@@ -181,6 +181,11 @@ function Settings() {
181
181
const [ autoSyncSaves , setAutoSyncSaves ] = useState ( false )
182
182
const [ altWine , setAltWine ] = useState ( [ ] as WineInstallation [ ] )
183
183
184
+ const [ configLoaded , setConfigLoaded ] = useState ( false )
185
+ const [ settingsToSave , setSettingsToSave ] = useState < AppSettings > (
186
+ { } as AppSettings
187
+ )
188
+
184
189
const { appName = '' , type = '' } = useParams ( )
185
190
const isDefault = appName === 'default'
186
191
const isGeneralSettings = type === 'general'
@@ -190,79 +195,162 @@ function Settings() {
190
195
const isLogSettings = type === 'log'
191
196
const isAdvancedSetting = type === 'advanced' && isDefault
192
197
198
+ // Load Heroic's or game's config, only if not loaded already
193
199
useEffect ( ( ) => {
194
200
const getSettings = async ( ) => {
195
- const config : AppSettings = await ipcRenderer . invoke (
196
- 'requestSettings' ,
197
- appName
198
- )
199
- setAutoSyncSaves ( config . autoSyncSaves )
200
- setUseGameMode ( config . useGameMode )
201
- setShowFps ( config . showFps )
202
- setShowOffline ( config . offlineMode )
203
- setAudioFix ( config . audioFix )
204
- setShowMangoHud ( config . showMangohud )
205
- setDefaultInstallPath ( config . defaultInstallPath )
206
- setWineVersion ( config . wineVersion )
207
- setWinePrefix ( config . winePrefix )
208
- setWineCrossoverBottle ( config . wineCrossoverBottle )
209
- setOtherOptions ( config . otherOptions )
210
- setLauncherArgs ( config . launcherArgs )
211
- setUseNvidiaPrime ( config . nvidiaPrime )
212
- setEgsLinkedPath ( config . egsLinkedPath || '' )
213
- setEgsPath ( config . egsLinkedPath || '' )
214
- setExitToTray ( config . exitToTray )
215
- setStartInTray ( config . startInTray )
216
- setMinimizeOnLaunch ( config . minimizeOnLaunch )
217
- setDarkTrayIcon ( config . darkTrayIcon )
218
- setDiscordRPC ( config . discordRPC )
219
- setAutoInstallDxvk ( config . autoInstallDxvk )
220
- setAutoInstallVkd3d ( config . autoInstallVkd3d )
221
- setEnableEsync ( config . enableEsync )
222
- setEnableFsync ( config . enableFsync )
223
- setEnableFSR ( config . enableFSR )
224
- setFsrSharpness ( config . maxSharpness || 2 )
225
- setResizableBar ( config . enableResizableBar )
226
- setSavesPath ( config . savesPath || '' )
227
- setMaxWorkers ( config . maxWorkers ?? 0 )
228
- setMaxRecentGames ( config . maxRecentGames ?? 5 )
229
- setCustomWinePaths ( config . customWinePaths || [ ] )
230
- setAddDesktopShortcuts ( config . addDesktopShortcuts )
231
- setAddGamesToStartMenu ( config . addStartMenuShortcuts )
232
- setCustomWinePaths ( config . customWinePaths || [ ] )
233
- setTargetExe ( config . targetExe || '' )
234
- setAltLegendaryBin ( config . altLegendaryBin || '' )
235
- setAltGogdlBin ( config . altGogdlBin || '' )
236
- setShowUnrealMarket ( config . showUnrealMarket )
237
- setDefaultWinePrefix ( config . defaultWinePrefix )
238
- setUseSteamRuntime ( config . useSteamRuntime )
239
- setDisableController ( config . disableController || false )
201
+ if ( ! configLoaded ) {
202
+ const config : AppSettings = await ipcRenderer . invoke (
203
+ 'requestSettings' ,
204
+ appName
205
+ )
206
+ setAutoSyncSaves ( config . autoSyncSaves )
207
+ setUseGameMode ( config . useGameMode )
208
+ setShowFps ( config . showFps )
209
+ setShowOffline ( config . offlineMode )
210
+ setAudioFix ( config . audioFix )
211
+ setShowMangoHud ( config . showMangohud )
212
+ setDefaultInstallPath ( config . defaultInstallPath )
213
+ setWineVersion ( config . wineVersion )
214
+ setWinePrefix ( config . winePrefix )
215
+ setWineCrossoverBottle ( config . wineCrossoverBottle )
216
+ setOtherOptions ( config . otherOptions )
217
+ setLauncherArgs ( config . launcherArgs )
218
+ setUseNvidiaPrime ( config . nvidiaPrime )
219
+ setEgsLinkedPath ( config . egsLinkedPath || '' )
220
+ setEgsPath ( config . egsLinkedPath || '' )
221
+ setExitToTray ( config . exitToTray )
222
+ setStartInTray ( config . startInTray )
223
+ setMinimizeOnLaunch ( config . minimizeOnLaunch )
224
+ setDarkTrayIcon ( config . darkTrayIcon )
225
+ setDiscordRPC ( config . discordRPC )
226
+ setAutoInstallDxvk ( config . autoInstallDxvk )
227
+ setAutoInstallVkd3d ( config . autoInstallVkd3d )
228
+ setEnableEsync ( config . enableEsync )
229
+ setEnableFsync ( config . enableFsync )
230
+ setEnableFSR ( config . enableFSR )
231
+ setFsrSharpness ( config . maxSharpness || 2 )
232
+ setResizableBar ( config . enableResizableBar )
233
+ setSavesPath ( config . savesPath || '' )
234
+ setMaxWorkers ( config . maxWorkers ?? 0 )
235
+ setMaxRecentGames ( config . maxRecentGames ?? 5 )
236
+ setCustomWinePaths ( config . customWinePaths || [ ] )
237
+ setAddDesktopShortcuts ( config . addDesktopShortcuts )
238
+ setAddGamesToStartMenu ( config . addStartMenuShortcuts )
239
+ setCustomWinePaths ( config . customWinePaths || [ ] )
240
+ setTargetExe ( config . targetExe || '' )
241
+ setAltLegendaryBin ( config . altLegendaryBin || '' )
242
+ setAltGogdlBin ( config . altGogdlBin || '' )
243
+ setShowUnrealMarket ( config . showUnrealMarket )
244
+ setDefaultWinePrefix ( config . defaultWinePrefix )
245
+ setUseSteamRuntime ( config . useSteamRuntime )
246
+ setDisableController ( config . disableController || false )
247
+
248
+ if ( ! isDefault ) {
249
+ setLanguageCode ( config . language )
250
+ const { title : gameTitle , canRunOffline : can_run_offline } =
251
+ await getGameInfo ( appName , runner )
252
+ setCanRunOffline ( can_run_offline )
253
+ setTitle ( gameTitle )
254
+ } else {
255
+ setTitle ( t ( 'globalSettings' , 'Global Settings' ) )
256
+ }
240
257
241
- if ( ! isDefault ) {
242
- setLanguageCode ( config . language )
243
- const { title : gameTitle , canRunOffline : can_run_offline } =
244
- await getGameInfo ( appName , runner )
245
- setCanRunOffline ( can_run_offline )
246
- setTitle ( gameTitle )
247
- } else {
248
- setTitle ( t ( 'globalSettings' , 'Global Settings' ) )
258
+ setSettingsToSaveState ( )
249
259
}
250
260
}
251
261
getSettings ( )
262
+ } , [ appName , type , isDefault , i18n . language ] )
263
+
264
+ let returnPath = '/'
252
265
253
- return ( ) => {
254
- ipcRenderer . removeAllListeners ( 'requestSettings' )
266
+ if ( ! fromGameCard ) {
267
+ returnPath = `/gamepage/${ appName } `
268
+ if ( returnPath === '/gamepage/default' ) {
269
+ returnPath = '/'
255
270
}
256
- } , [ appName , type , isDefault , i18n . language ] )
271
+ }
272
+
273
+ // Helper function to update the `settingsToSave` state
274
+ const setSettingsToSaveState = ( ) => {
275
+ const GlobalSettings = {
276
+ altLegendaryBin,
277
+ altGogdlBin,
278
+ addDesktopShortcuts,
279
+ addStartMenuShortcuts,
280
+ audioFix,
281
+ autoInstallDxvk,
282
+ autoInstallVkd3d,
283
+ customWinePaths,
284
+ darkTrayIcon,
285
+ defaultInstallPath,
286
+ defaultWinePrefix,
287
+ disableController,
288
+ discordRPC,
289
+ egsLinkedPath,
290
+ enableEsync,
291
+ enableFsync,
292
+ exitToTray,
293
+ maxRecentGames,
294
+ maxWorkers,
295
+ minimizeOnLaunch,
296
+ nvidiaPrime,
297
+ otherOptions,
298
+ showFps,
299
+ showMangohud,
300
+ showUnrealMarket,
301
+ startInTray,
302
+ useGameMode,
303
+ wineCrossoverBottle,
304
+ winePrefix,
305
+ wineVersion,
306
+ enableFSR,
307
+ enableResizableBar
308
+ } as AppSettings
309
+
310
+ const GameSettings = {
311
+ audioFix,
312
+ autoInstallDxvk,
313
+ autoInstallVkd3d,
314
+ autoSyncSaves,
315
+ enableEsync,
316
+ enableFSR,
317
+ enableFsync,
318
+ maxSharpness,
319
+ enableResizableBar,
320
+ language : languageCode ,
321
+ launcherArgs,
322
+ nvidiaPrime,
323
+ offlineMode,
324
+ otherOptions,
325
+ savesPath,
326
+ showFps,
327
+ showMangohud,
328
+ targetExe,
329
+ useGameMode,
330
+ wineCrossoverBottle,
331
+ winePrefix,
332
+ wineVersion,
333
+ useSteamRuntime
334
+ } as AppSettings
257
335
258
- const GlobalSettings = {
336
+ setSettingsToSave ( isDefault ? GlobalSettings : GameSettings )
337
+ }
338
+
339
+ // update the settingsToSave state when any of the configurations changes
340
+ // but only after the configuration was loaded
341
+ useEffect ( ( ) => {
342
+ if ( configLoaded ) {
343
+ setSettingsToSaveState ( )
344
+ }
345
+ } , [
259
346
altLegendaryBin ,
260
347
altGogdlBin ,
261
348
addDesktopShortcuts ,
262
349
addStartMenuShortcuts ,
263
350
audioFix ,
264
351
autoInstallDxvk ,
265
352
autoInstallVkd3d ,
353
+ autoSyncSaves ,
266
354
customWinePaths ,
267
355
darkTrayIcon ,
268
356
defaultInstallPath ,
@@ -275,6 +363,7 @@ function Settings() {
275
363
exitToTray ,
276
364
maxRecentGames ,
277
365
maxWorkers ,
366
+ maxSharpness ,
278
367
minimizeOnLaunch ,
279
368
nvidiaPrime ,
280
369
otherOptions ,
@@ -287,48 +376,26 @@ function Settings() {
287
376
winePrefix ,
288
377
wineVersion ,
289
378
enableFSR ,
290
- enableResizableBar
291
- } as AppSettings
292
-
293
- const GameSettings = {
294
- audioFix,
295
- autoInstallDxvk,
296
- autoInstallVkd3d,
297
- autoSyncSaves,
298
- enableEsync,
299
- enableFSR,
300
- enableFsync,
301
- maxSharpness,
302
379
enableResizableBar ,
303
- language : languageCode ,
380
+ languageCode ,
304
381
launcherArgs ,
305
- nvidiaPrime,
306
382
offlineMode ,
307
- otherOptions,
308
383
savesPath ,
309
- showFps,
310
- showMangohud,
311
384
targetExe ,
312
- useGameMode,
313
- wineCrossoverBottle,
314
- winePrefix,
315
- wineVersion,
316
385
useSteamRuntime
317
- } as AppSettings
318
-
319
- const settingsToSave = isDefault ? GlobalSettings : GameSettings
320
- let returnPath = '/'
321
-
322
- if ( ! fromGameCard ) {
323
- returnPath = `/gamepage/${ appName } `
324
- if ( returnPath === '/gamepage/default' ) {
325
- returnPath = '/'
326
- }
327
- }
386
+ ] )
328
387
388
+ // when the settingsToSave state changes:
389
+ // - write the config if it completed loading before
390
+ // - set the `configLoaded` state to ensure it can only be written after loaded
329
391
useEffect ( ( ) => {
330
- writeConfig ( [ appName , settingsToSave ] )
331
- } , [ GlobalSettings , GameSettings , appName ] )
392
+ if ( configLoaded ) {
393
+ writeConfig ( [ appName , settingsToSave ] )
394
+ } else {
395
+ // initial state is {}, consider loaded when the object has keys in it
396
+ setConfigLoaded ( Object . keys ( settingsToSave ) . length > 0 )
397
+ }
398
+ } , [ settingsToSave ] )
332
399
333
400
if ( ! title ) {
334
401
return < UpdateComponent />
0 commit comments