Skip to content

Commit e8a1050

Browse files
committed
refactor: Simplify LAUNCH_GAME error bubbling
refactor: Add an easy use error dialog to most user-initiated API errors
1 parent 4a087df commit e8a1050

13 files changed

Lines changed: 68 additions & 88 deletions

File tree

src/back/download.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,26 @@ export async function downloadGameData(gameDataId: number, state: BackState, abo
1111
onProgress?: (percent: number) => void, onDetails?: (details: DownloadDetails) => void): Promise<void> {
1212
const gameData = await fpDatabase.findGameDataById(gameDataId);
1313
log.debug('Game Launcher', `Checking ${state.preferences.gameDataSources.length} Sources for this GameData...`);
14+
const errors = [];
1415
if (gameData) {
1516
for (const source of state.preferences.gameDataSources) {
16-
let success = false;
1717
for (const provider of state.registry.dataSources.values()) {
1818
log.debug('Launcher', `testing ${provider.name}`);
1919
const dataPacksFullPath = path.join(state.config.flashpointPath, state.preferences.dataPacksFolderPath);
2020
try {
21-
success = await provider.downloadGame(source, gameData, dataPacksFullPath, abortSignal, onProgress, onDetails);
21+
const success = await provider.downloadGame(source, gameData, dataPacksFullPath, abortSignal, onProgress, onDetails);
2222
if (success) {
2323
return;
2424
}
2525
} catch (err) {
26+
errors.push(`Error from source ${provider.name} (${provider.id}) - ${err}`);
2627
log.error('Launcher', `Error from source ${provider.name} (${provider.id}) - ${err}`);
27-
success = false;
2828
}
2929
}
3030
}
3131
}
32-
throw new Error('No working Sources available for this GameData.');
32+
const errorMsg = `No working Sources available for this GameData.${errors.length > 0 ? '\n' + errors.join('\n') : ''}`;
33+
throw new Error(errorMsg);
3334
}
3435

3536
export async function importGameDataSkipHash(gameId: string, filePath: string, dataPacksFolderPath: string, sha256: string,

src/back/flashpoint/WebgameContentRunner.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export async function downloadGameDataRes(state: BackState, gameData: GameData)
8888
}
8989
}
9090

91-
export async function ensureGameDataDownloaded(state: BackState, game: Game) {
91+
export async function ensureGameDataDownloaded(state: BackState, game: Game): Promise<boolean> {
9292
const showDialogFunc = state.socketServer.showMessageBoxBack(state);
9393
if (game.activeDataId && game.gameData) {
9494
log.debug('Launcher', 'Found active game data');
@@ -146,18 +146,13 @@ export async function ensureGameDataDownloaded(state: BackState, game: Game) {
146146
// Make sure we didn't choose to swap game data during the user dialog above
147147
log.debug('Game Launcher', 'Downloading Game Data for ' + getGameDataFilename(gameData) || 'UNKNOWN');
148148
// Download GameData
149-
try {
150-
await downloadGameDataRes(state, gameData);
151-
gameData = (await fpDatabase.findGameDataById(gameData.id)) as GameData;
152-
} catch (error: any) {
153-
state.socketServer.broadcast(BackOut.OPEN_ALERT, error);
154-
log.info('Game Launcher', `Game Launch Aborted: ${error}`);
155-
return false;
156-
}
149+
await downloadGameDataRes(state, gameData);
150+
gameData = (await fpDatabase.findGameDataById(gameData.id)) as GameData;
157151
}
158152
broadcastGameUpdate(state, game.id);
159153
}
160154
}
155+
return true;
161156
}
162157

163158
export async function configureServer(state: BackState, requestedServer?: string) {

src/back/index.ts

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1809,19 +1809,13 @@ export async function checkAndDownloadGameData(activeDataId: number) {
18091809
state.socketServer.broadcast(BackOut.SET_PLACEHOLDER_DOWNLOAD_PERCENT, percent);
18101810
};
18111811
state.socketServer.broadcast(BackOut.OPEN_PLACEHOLDER_DOWNLOAD_DIALOG);
1812-
try {
1813-
await downloadGameData(gameData.id, state, state.downloadController.signal(), onProgress, onDetails)
1814-
.finally(() => {
1815-
// Close PLACEHOLDER download dialog on client, cosmetic delay to look nice
1816-
setTimeout(() => {
1817-
state.socketServer.broadcast(BackOut.CLOSE_PLACEHOLDER_DOWNLOAD_DIALOG);
1818-
}, 250);
1819-
});
1820-
} catch (error: any) {
1821-
state.socketServer.broadcast(BackOut.OPEN_ALERT, error);
1822-
log.info('Game Launcher', `Game Launch Aborted: ${error}`);
1823-
return;
1824-
}
1812+
await downloadGameData(gameData.id, state, state.downloadController.signal(), onProgress, onDetails)
1813+
.finally(() => {
1814+
// Close PLACEHOLDER download dialog on client, cosmetic delay to look nice
1815+
setTimeout(() => {
1816+
state.socketServer.broadcast(BackOut.CLOSE_PLACEHOLDER_DOWNLOAD_DIALOG);
1817+
}, 250);
1818+
});
18251819
}
18261820
}
18271821

src/back/responses.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -643,13 +643,7 @@ export function registerRequestCallbacks(state: BackState, init: () => Promise<v
643643
gameData = await fpDatabase.findGameDataById(parentGame.activeDataId);
644644
if (gameData && !gameData.presentOnDisk) {
645645
// Download GameData
646-
try {
647-
await downloadGameDataRes(state, gameData);
648-
} catch (error: any) {
649-
state.socketServer.broadcast(BackOut.OPEN_ALERT, error);
650-
log.info('Game Launcher', `Add App Launch Aborted: ${error}`);
651-
return;
652-
}
646+
await downloadGameDataRes(state, gameData);
653647
}
654648
}
655649
await state.apiEmitters.games.onWillLaunchAddApp.fireAlert(state, addApp, event.client, 'Error during add app launch api event');
@@ -1055,10 +1049,7 @@ export function registerRequestCallbacks(state: BackState, init: () => Promise<v
10551049
state.socketServer.register(BackIn.DOWNLOAD_GAME_DATA, async (event, gameDataId) => {
10561050
const gameData = await fpDatabase.findGameDataById(gameDataId);
10571051
if (gameData) {
1058-
await downloadGameDataRes(state, gameData)
1059-
.catch((err) => {
1060-
throw 'Failed to download';
1061-
});
1052+
await downloadGameDataRes(state, gameData);
10621053
} else {
10631054
log.error('Launcher', `Game Data not found (ID=${gameDataId})`);
10641055
throw new Error(`Game Data not found (ID=${gameDataId})`);

src/renderer/Util.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ import { Paths } from '@shared/Paths';
55
import { getFileServerURL } from '@shared/Util';
66
import { getGameDataFilename } from '@shared/utils/misc';
77
import _axios from 'axios';
8-
import { Game, GameLaunchOverride, Playlist, TagFilterGroup } from 'flashpoint-launcher';
8+
import { Game, Playlist, TagFilterGroup } from 'flashpoint-launcher';
99
import * as path from 'node:path';
1010
import { GameGridItem } from './components/GameGridItem';
1111
import { GameListItem } from './components/GameListItem';
1212
import { GameOrderChangeEvent } from './components/GameOrder';
1313
import { GameDragEventData } from './components/pages/BrowsePage';
14+
import { createErrorDialog } from './dialog';
1415
import { markGameBusy, unmarkGameBusy } from './store/main/slice';
1516
import { AppDispatch } from './store/store';
1617

@@ -358,13 +359,11 @@ export function createDataDownload(blob: Blob, name: string) {
358359
URL.revokeObjectURL(url);
359360
}
360361

361-
export async function launchGame(dispatch: AppDispatch, gameId: string, override: GameLaunchOverride) {
362+
export async function launchGame(dispatch: AppDispatch, gameId: string, owner: string) {
362363
log.debug('Launcher', 'Launching Game - ' + gameId);
363364
dispatch(markGameBusy(gameId));
364-
await window.Shared.back.request(BackIn.LAUNCH_GAME, gameId, 'flashpoint-archive')
365-
.catch((error) => {
366-
log.error('Launcher', `Failed to launch game - ${gameId} - ERROR: ${error}`);
367-
})
365+
await window.Shared.back.request(BackIn.LAUNCH_GAME, gameId, owner)
366+
.catch(createErrorDialog)
368367
.finally(() => {
369368
dispatch(unmarkGameBusy(gameId));
370369
});

src/renderer/components/BrowsePageDisplay.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { useAppDispatch, useAppSelector } from '@renderer/hooks/useAppSelector';
33
import { useLocalization } from '@renderer/hooks/useLocalization';
44
import { requestRange, selectGame, setGridScroll, setListScroll } from '@renderer/store/search/slice';
5-
import { gameDragDataType, getPlatformIconURL } from '@renderer/Util';
5+
import { gameDragDataType, getPlatformIconURL, launchGame } from '@renderer/Util';
66
import { BackIn } from '@shared/back/types';
77
import { calcScale } from '@shared/Util';
88
import { isGame } from '@shared/utils/misc';
@@ -18,12 +18,13 @@ import { GameDragData, GameDragEventData } from './pages/BrowsePage';
1818
import { Spinner } from './Spinner';
1919

2020
export function WebgameBrowsePageDisplayGrid(props: BrowsePageDisplayProps<Game>) {
21+
const dispatch = useAppDispatch();
2122
const getContentIcons = (game: Content | Game) => {
2223
return isGame(game) ? game.platforms.slice(0, 5).map(p => getPlatformIconURL(p, props.logoVersion)) : [];
2324
};
2425

2526
const onContentRun = async (gameId: string): Promise<void> => {
26-
await window.Shared.back.request(BackIn.LAUNCH_GAME, gameId, 'flashpoint-archive');
27+
launchGame(dispatch, gameId, 'flashpoint-archive');
2728
};
2829

2930
return (
@@ -35,8 +36,10 @@ export function WebgameBrowsePageDisplayGrid(props: BrowsePageDisplayProps<Game>
3536
}
3637

3738
export function WebgameBrowsePageDisplayList(props: BrowsePageDisplayProps<Game>) {
39+
const dispatch = useAppDispatch();
40+
3841
const onContentRun = async (gameId: string): Promise<void> => {
39-
await window.Shared.back.request(BackIn.LAUNCH_GAME, gameId, 'flashpoint-archive');
42+
launchGame(dispatch, gameId, 'flashpoint-archive');
4043
};
4144

4245
return (

src/renderer/components/RightBrowseSidebar.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { getPointer } from '@renderer/context/MenuContext';
2+
import { createErrorDialogWithPrefix } from '@renderer/dialog';
23
import { useAppDispatch, useAppSelector } from '@renderer/hooks/useAppSelector';
34
import { useConfirmDialog } from '@renderer/hooks/useConfirmDialog';
45
import { useContextMenu } from '@renderer/hooks/useContextMenu';
@@ -156,7 +157,7 @@ export function RightBrowseSidebarView({ view }: RightBrowseSidebarViewProps) {
156157
}
157158

158159
const onGameLaunch = async (gameId: string, override: GameLaunchOverride) => {
159-
launchGame(dispatch, gameId, override);
160+
launchGame(dispatch, gameId, 'flashpoint-archive');
160161
};
161162

162163
const onDeleteSelectedGame = async () => {
@@ -481,7 +482,6 @@ export function RightBrowseSidebar(props: RightBrowseSidebarProps) {
481482
type: 'button',
482483
label: strings.uninstallGame,
483484
onClick: async () => {
484-
console.log('literally kys');
485485
const res = await openConfirmDialog({
486486
message: allStrings.dialog.uninstallGame,
487487
buttons: [allStrings.misc.yes, allStrings.misc.no],
@@ -490,9 +490,7 @@ export function RightBrowseSidebar(props: RightBrowseSidebarProps) {
490490
if (res === 0 && game.gameData !== undefined) {
491491
for (const gameData of game.gameData) {
492492
await window.Shared.back.request(BackIn.UNINSTALL_GAME_DATA, gameData.id)
493-
.catch(() => {
494-
alert(allStrings.dialog.unableToUninstallGameData);
495-
});
493+
.catch(createErrorDialogWithPrefix(allStrings.dialog.unableToUninstallGameData));
496494
}
497495
}
498496
}

src/renderer/components/pages/BrowsePage.tsx

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { createSelector } from '@reduxjs/toolkit';
22
import { SearchBar } from '@renderer/components/SearchBar';
33
import { getPointer } from '@renderer/context/MenuContext';
4-
import { createNewDialog } from '@renderer/dialog';
4+
import { createErrorDialogWithPrefix } from '@renderer/dialog';
55
import { useAppDispatch, useAppSelector } from '@renderer/hooks/useAppSelector';
66
import { useContextMenu } from '@renderer/hooks/useContextMenu';
77
import { useLocalization } from '@renderer/hooks/useLocalization';
@@ -383,13 +383,7 @@ export function BrowsePage(props: BrowsePageProps) {
383383

384384
const onDownloadPlaylistContents = (playlistId: string): void => {
385385
window.Shared.back.request(BackIn.DOWNLOAD_PLAYLIST_CONTENTS, playlistId)
386-
.catch((error) => {
387-
createNewDialog(dispatch, {
388-
largeMessage: true,
389-
message: `Failed to download playlist - ${error}`,
390-
buttons: ['Ok']
391-
});
392-
});
386+
.catch(createErrorDialogWithPrefix('Failed to download playlist'));
393387
};
394388

395389
const onExportPlaylist = (playlistId: string): void => {
@@ -439,9 +433,7 @@ export function BrowsePage(props: BrowsePageProps) {
439433
window.Shared.back.request(BackIn.GET_PLAYLIST, playlistId)
440434
.then(playlist => {
441435
window.Shared.back.request(BackIn.RUN_COMMAND, contextButton.command, playlist)
442-
.catch((error) => {
443-
log.error('Launcher', `Failed to run Ext Playlist command '${contextButton.command}': ${error}`);
444-
});
436+
.catch(createErrorDialogWithPrefix(`Failed to run Ext Playlist command '${contextButton.command}`));
445437
});
446438
}
447439
});

src/renderer/components/pages/ConfigPage.tsx

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
22
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
3-
import { createNewDialog } from '@renderer/dialog';
3+
import { createErrorDialog, createErrorDialogWithPrefix, createNewDialog } from '@renderer/dialog';
44
import { useAppDispatch, useAppSelector } from '@renderer/hooks/useAppSelector';
55
import { useLocalization } from '@renderer/hooks/useLocalization';
66
import { cancelDialog } from '@renderer/store/main/slice';
@@ -216,9 +216,7 @@ export function ConfigPage() {
216216
.then(() => {
217217
dispatch(removeTagFilterGroup(index));
218218
})
219-
.catch((error) => {
220-
alert('Failed to nuke tags: ' + error);
221-
})
219+
.catch(createErrorDialogWithPrefix('Failed to nuke tags'))
222220
.finally(() => {
223221
dispatch(cancelDialog(dialogId));
224222
});
@@ -345,9 +343,7 @@ export function ConfigPage() {
345343

346344
const onOptimizeDatabase = () => {
347345
window.Shared.back.request(BackIn.OPTIMIZE_DATABASE)
348-
.catch((err) => {
349-
alert('Error: ' + err);
350-
});
346+
.catch(createErrorDialog);
351347
};
352348

353349
const onRegisterProtocol = (isChecked: boolean): void => {
@@ -712,9 +708,7 @@ export function ConfigPage() {
712708
.then(() => {
713709
toast('Images Deleted');
714710
})
715-
.catch((err) => {
716-
alert('Error: ' + err);
717-
});
711+
.catch(createErrorDialogWithPrefix('Failed to delete images'));
718712
}}/>
719713
</ConfigBox>
720714
{/* Playtime Tracking */}
@@ -1010,9 +1004,7 @@ function renderExtConfigProp(key: string, prop: ExtConfigurationProp, value: any
10101004
value='Run'
10111005
onClick={() => {
10121006
window.Shared.back.request(BackIn.RUN_COMMAND, prop.command || '')
1013-
.catch((error) => {
1014-
log.error('Launcher', `Failed to run Ext Config command '${prop.command}': ${error}`);
1015-
});
1007+
.catch(createErrorDialogWithPrefix(`Failed to run Ext Config command '${prop.command}'`));
10161008
}}/>
10171009
);
10181010
}

src/renderer/components/pages/CuratePage.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { CurateBox } from '@renderer/components/CurateBox';
2+
import { createErrorDialogWithPrefix } from '@renderer/dialog';
23
import { useAppSelector } from '@renderer/hooks/useAppSelector';
34
import { useLocalization } from '@renderer/hooks/useLocalization';
45
import * as curateActions from '@renderer/store/curate/slice';
@@ -415,9 +416,7 @@ export function CuratePage() {
415416

416417
const runExtCommand = (command: string) => {
417418
window.Shared.back.request(BackIn.RUN_COMMAND, command, curation, curate.selected)
418-
.catch((error) => {
419-
log.error('Launcher', `Failed to run Ext Curate command '${command}': ${error}`);
420-
});
419+
.catch(createErrorDialogWithPrefix(`Failed to run Ext Curate Command ${command}`));
421420
};
422421

423422
// Gen extension buttons

0 commit comments

Comments
 (0)