@@ -5,6 +5,8 @@ import type { PluginStatus, CompileTarget, CompiledCode } from '../types';
55export interface AnalysisApplicability {
66 applicable : boolean ;
77 reason ?: string ;
8+ /** True while applicability check is in progress */
9+ loading ?: boolean ;
810}
911
1012interface PluginStore {
@@ -14,6 +16,9 @@ interface PluginStore {
1416 /** Analysis applicability per game: gameId -> analysisName -> status */
1517 applicabilityByGame : Record < string , Record < string , AnalysisApplicability > > ;
1618
19+ /** Games currently being checked for applicability: gameId -> true */
20+ loadingApplicability : Record < string , boolean > ;
21+
1722 /** Compiled code per game: gameId -> targetId -> CompiledCode */
1823 compiledCodeByGame : Record < string , Record < string , CompiledCode > > ;
1924
@@ -26,6 +31,7 @@ interface PluginStore {
2631 // Actions
2732 fetchPluginStatus : ( ) => Promise < void > ;
2833 fetchApplicability : ( gameId : string ) => Promise < void > ;
34+ isApplicabilityLoading : ( gameId : string ) => boolean ;
2935 getApplicability : ( gameId : string , analysisName : string ) => AnalysisApplicability ;
3036 compile : ( gameId : string , sourceCode : string , pluginName : string , target : CompileTarget ) => Promise < void > ;
3137 clearCompiledCode : ( gameId : string , targetId ?: string ) => void ;
@@ -35,6 +41,7 @@ interface PluginStore {
3541export const usePluginStore = create < PluginStore > ( ( set , get ) => ( {
3642 plugins : [ ] ,
3743 applicabilityByGame : { } ,
44+ loadingApplicability : { } ,
3845 compiledCodeByGame : { } ,
3946 compilingByGame : { } ,
4047 compileErrorByGame : { } ,
@@ -54,29 +61,54 @@ export const usePluginStore = create<PluginStore>((set, get) => ({
5461 } ,
5562
5663 fetchApplicability : async ( gameId : string ) => {
64+ // Mark as loading
65+ set ( ( state ) => ( {
66+ loadingApplicability : { ...state . loadingApplicability , [ gameId ] : true } ,
67+ } ) ) ;
68+
5769 try {
5870 const response = await fetch ( `/api/plugins/check-applicable/${ gameId } ` ) ;
5971 if ( ! response . ok ) {
6072 console . error ( 'Failed to fetch applicability:' , response . status ) ;
73+ // On error, remove loading state but don't set data (will use fallback)
74+ set ( ( state ) => {
75+ const { [ gameId ] : _ , ...rest } = state . loadingApplicability ;
76+ return { loadingApplicability : rest } ;
77+ } ) ;
6178 return ;
6279 }
6380 const data = await response . json ( ) ;
64- set ( ( state ) => ( {
65- applicabilityByGame : {
66- ...state . applicabilityByGame ,
67- [ gameId ] : data . analyses || { } ,
68- } ,
69- } ) ) ;
81+ set ( ( state ) => {
82+ const { [ gameId ] : _ , ...restLoading } = state . loadingApplicability ;
83+ return {
84+ applicabilityByGame : {
85+ ...state . applicabilityByGame ,
86+ [ gameId ] : data . analyses || { } ,
87+ } ,
88+ loadingApplicability : restLoading ,
89+ } ;
90+ } ) ;
7091 } catch ( error ) {
7192 console . error ( 'Failed to fetch applicability:' , error ) ;
93+ // On error, remove loading state
94+ set ( ( state ) => {
95+ const { [ gameId ] : _ , ...rest } = state . loadingApplicability ;
96+ return { loadingApplicability : rest } ;
97+ } ) ;
7298 }
7399 } ,
74100
101+ isApplicabilityLoading : ( gameId : string ) => {
102+ return ! ! get ( ) . loadingApplicability [ gameId ] ;
103+ } ,
104+
75105 getApplicability : ( gameId : string , analysisName : string ) => {
106+ const isLoading = ! ! get ( ) . loadingApplicability [ gameId ] ;
76107 const gameApplicability = get ( ) . applicabilityByGame [ gameId ] ;
77- if ( ! gameApplicability ) {
78- // Not yet fetched, assume applicable
79- return { applicable : true } ;
108+
109+ if ( isLoading || ! gameApplicability ) {
110+ // Still loading or not yet fetched - disable until we know for sure
111+ return { applicable : false , loading : true , reason : 'Checking...' } ;
80112 }
81113 return gameApplicability [ analysisName ] || { applicable : true } ;
82114 } ,
0 commit comments