@@ -21,13 +21,8 @@ export const atomGameLibrarySorting = atomWithTauriStore<SortType, false>(
2121 { initialValue : SortType . NONE } ,
2222) ;
2323
24- export const atomGameLibrary = atom < {
25- indexing : boolean ;
26- games : GameRow [ ] ;
27- } > ( {
28- indexing : false ,
29- games : [ ] ,
30- } ) ;
24+ export const atomGameLibraryIsIndexing = atom ( false ) ;
25+ export const atomGameLibrary = atom < GameRow [ ] > ( [ ] ) ;
3126
3227async function loadGameData ( path : string ) : Promise < GameRow > {
3328 try {
@@ -83,53 +78,60 @@ async function loadGameData(path: string): Promise<GameRow> {
8378 }
8479}
8580
86- async function registerGamePath ( path : string ) {
87- console . debug ( `Loading game from ${ path } ` ) ;
88- const gameData = await loadGameData ( path ) ;
89- if ( ! ( "error" in gameData ) ) {
90- db . addGame ( gameData ) ;
81+ const gameRegisterQueue : string [ ] = [ ] ;
82+ let gameRegisterQueueIsUse = false ;
83+
84+ async function registerGamePath ( workPath : string ) {
85+ console . debug ( `Loading game from ${ workPath } ` ) ;
86+ gameRegisterQueue . push ( workPath ) ;
87+ if ( gameRegisterQueueIsUse ) {
88+ return ;
89+ }
90+ gameRegisterQueueIsUse = true ;
91+ while ( gameRegisterQueue . length > 0 ) {
92+ const path = gameRegisterQueue . shift ( ) ;
93+ if ( ! path ) {
94+ break ;
95+ }
96+ const gameData = await loadGameData ( path ) ;
97+ if ( ! ( "error" in gameData ) ) {
98+ db . addGame ( gameData ) ;
99+ }
100+ defaultStore . set ( atomGameLibrary , ( prev ) =>
101+ prev . filter ( ( e ) => e . path !== path ) . concat ( gameData ) ,
102+ ) ;
91103 }
92- defaultStore . set ( atomGameLibrary , ( prev ) => ( {
93- ...prev ,
94- games : prev . games . filter ( ( e ) => e . path !== path ) . concat ( gameData ) ,
95- } ) ) ;
104+ gameRegisterQueueIsUse = false ;
96105}
97106
98107async function unregisterGamePathPrefix (
99108 pathPrefix : string ,
100109 knownPaths : Set < string > ,
101110) {
102- defaultStore . set ( atomGameLibrary , ( prev ) => {
103- return {
104- ...prev ,
105- games : prev . games . filter ( ( e ) => {
106- const toRemove = e . path . startsWith ( pathPrefix ) ;
107- if ( toRemove ) {
108- knownPaths . delete ( e . path ) ;
109- db . removeGame ( e . path ) ;
110- }
111- return ! toRemove ;
112- } ) ,
113- } ;
114- } ) ;
111+ defaultStore . set ( atomGameLibrary , ( prev ) =>
112+ prev . filter ( ( e ) => {
113+ const toRemove = e . path . startsWith ( pathPrefix ) ;
114+ if ( toRemove ) {
115+ knownPaths . delete ( e . path ) ;
116+ db . removeGame ( e . path ) ;
117+ }
118+ return ! toRemove ;
119+ } ) ,
120+ ) ;
115121}
116122
117123async function isGame ( path : string ) {
118124 const eBootPath = await join ( path , "eboot.bin" ) ;
119125 return await exists ( eBootPath ) ;
120126}
121127
122- let indexingCount = 0 ;
123-
124128async function scanDirectory (
125129 path : string ,
126130 knownPaths : Set < string > ,
127131 signal : AbortSignal ,
128132 recursionLevel : number ,
129133) {
130134 try {
131- indexingCount ++ ;
132-
133135 if ( recursionLevel > 3 || signal . aborted ) {
134136 return ;
135137 }
@@ -140,14 +142,14 @@ async function scanDirectory(
140142 return ;
141143 }
142144 if ( await isGame ( path ) ) {
143- setTimeout ( ( ) => registerGamePath ( path ) , 1 ) ;
145+ void registerGamePath ( path ) ;
144146 return ;
145147 }
146148 const children = await readDir ( path ) ;
147149 for ( const c of children ) {
148150 if ( c . isDirectory ) {
149151 const childPath = await join ( path , c . name ) ;
150- scanDirectory (
152+ await scanDirectory (
151153 childPath ,
152154 knownPaths ,
153155 signal ,
@@ -157,54 +159,47 @@ async function scanDirectory(
157159 }
158160 } catch ( e : unknown ) {
159161 console . error ( `Error discovering game at "${ path } "` , e ) ;
160- } finally {
161- indexingCount -- ;
162- if ( indexingCount === 0 ) {
163- defaultStore . set ( atomGameLibrary , ( prev ) => ( {
164- ...prev ,
165- indexing : false ,
166- } ) ) ;
167- }
168162 }
169163}
170164
171165( async ( ) => {
172166 const cachedGames = await db . listGames ( ) ;
173- defaultStore . set ( atomGameLibrary , {
174- indexing : true ,
175- games : cachedGames ,
176- } ) ;
167+ defaultStore . set ( atomGameLibraryIsIndexing , true ) ;
168+ defaultStore . set ( atomGameLibrary , cachedGames ) ;
177169
178170 const knownPaths = new Set < string > ( ) ;
179171
180172 for ( const e of cachedGames ) {
181173 knownPaths . add ( e . path ) ;
182174 }
183175
184- let first = true ;
185-
176+ let prevPath : string | null = null ;
186177 let cancel : ( ( ) => void ) | undefined ;
178+
187179 defaultStore . sub ( atomGamesPath , async ( ) => {
188180 cancel ?.( ) ;
189181 cancel = undefined ;
190182
191183 try {
192- if ( ! first ) {
193- first = false ;
194- defaultStore . set ( atomGameLibrary , {
195- indexing : true ,
196- games : [ ] ,
197- } ) ;
184+ const path = defaultStore . get ( atomGamesPath ) ;
185+ if ( prevPath != null && prevPath !== path ) {
186+ await db . removeAllGames ( ) ;
187+ defaultStore . set ( atomGameLibraryIsIndexing , true ) ;
188+ defaultStore . set ( atomGameLibrary , [ ] ) ;
198189 knownPaths . clear ( ) ;
199190 }
200- indexingCount = 0 ;
201- const path = defaultStore . get ( atomGamesPath ) ;
191+ prevPath = path ;
202192 if ( path ) {
203193 if ( ! ( await exists ( path ) ) ) {
204194 await mkdir ( path , { recursive : true } ) ;
205195 }
206196 const abortController = new AbortController ( ) ;
207- scanDirectory ( path , knownPaths , abortController . signal , 0 ) ;
197+ await scanDirectory (
198+ path ,
199+ knownPaths ,
200+ abortController . signal ,
201+ 0 ,
202+ ) ;
208203 const unsub = await watch ( path , async ( e ) => {
209204 if ( typeof e . type === "object" ) {
210205 if ( "create" in e . type ) {
@@ -220,12 +215,20 @@ async function scanDirectory(
220215 return ;
221216 }
222217 }
223- scanDirectory (
218+ defaultStore . set (
219+ atomGameLibraryIsIndexing ,
220+ true ,
221+ ) ;
222+ await scanDirectory (
224223 newPath ,
225224 knownPaths ,
226225 abortController . signal ,
227226 1 ,
228227 ) ;
228+ defaultStore . set (
229+ atomGameLibraryIsIndexing ,
230+ false ,
231+ ) ;
229232 }
230233 } else if ( "remove" in e . type ) {
231234 const newPath = e . paths [ 0 ] ;
@@ -235,6 +238,7 @@ async function scanDirectory(
235238 }
236239 }
237240 } ) ;
241+ defaultStore . set ( atomGameLibraryIsIndexing , false ) ;
238242 cancel = ( ) => {
239243 unsub ( ) ;
240244 abortController . abort ( ) ;
0 commit comments