diff --git a/src/main/services/achievements/achievement-watcher-manager.ts b/src/main/services/achievements/achievement-watcher-manager.ts index b862abbe..dd65165a 100644 --- a/src/main/services/achievements/achievement-watcher-manager.ts +++ b/src/main/services/achievements/achievement-watcher-manager.ts @@ -167,6 +167,8 @@ export class AchievementWatcherManager { shop: GameShop, objectId: string ) { + if (shop === "custom") return; + const gameKey = levelKeys.game(shop, objectId); if (this.alreadySyncedGames.get(gameKey)) return; diff --git a/src/main/services/library-sync/create-game.ts b/src/main/services/library-sync/create-game.ts index a346d3b4..e9ec9612 100644 --- a/src/main/services/library-sync/create-game.ts +++ b/src/main/services/library-sync/create-game.ts @@ -3,6 +3,10 @@ import { HydraApi } from "../hydra-api"; import { gamesSublevel, levelKeys } from "@main/level"; export const createGame = async (game: Game) => { + if (game.shop === "custom") { + return; + } + return HydraApi.post(`/profile/games`, { objectId: game.objectId, playTimeInMilliseconds: Math.trunc(game.playTimeInMilliseconds ?? 0), diff --git a/src/main/services/library-sync/update-game-playtime.ts b/src/main/services/library-sync/update-game-playtime.ts index 3689b302..b53ebebc 100644 --- a/src/main/services/library-sync/update-game-playtime.ts +++ b/src/main/services/library-sync/update-game-playtime.ts @@ -6,6 +6,10 @@ export const updateGamePlaytime = async ( deltaInMillis: number, lastTimePlayed: Date ) => { + if (game.shop === "custom") { + return; + } + return HydraApi.put(`/profile/games/${game.remoteId}`, { playTimeDeltaInSeconds: Math.trunc(deltaInMillis / 1000), lastTimePlayed, diff --git a/src/main/services/process-watcher.ts b/src/main/services/process-watcher.ts index 6408c30d..a1449255 100644 --- a/src/main/services/process-watcher.ts +++ b/src/main/services/process-watcher.ts @@ -198,11 +198,6 @@ export const watchProcesses = async () => { function onOpenGame(game: Game) { const now = performance.now(); - AchievementWatcherManager.firstSyncWithRemoteIfNeeded( - game.shop, - game.objectId - ); - gamesPlaytime.set(levelKeys.game(game.shop, game.objectId), { lastTick: now, firstTick: now, @@ -220,6 +215,13 @@ function onOpenGame(game: Game) { }) .catch(() => {}); + if (game.shop === "custom") return; + + AchievementWatcherManager.firstSyncWithRemoteIfNeeded( + game.shop, + game.objectId + ); + if (game.remoteId) { updateGamePlaytime( game, @@ -255,18 +257,20 @@ function onTickGame(game: Game) { const delta = now - gamePlaytime.lastTick; - gamesSublevel.put(levelKeys.game(game.shop, game.objectId), { + const updatedGame: Game = { ...game, playTimeInMilliseconds: (game.playTimeInMilliseconds ?? 0) + delta, lastTimePlayed: new Date(), - }); + }; + + gamesSublevel.put(levelKeys.game(game.shop, game.objectId), updatedGame); gamesPlaytime.set(levelKeys.game(game.shop, game.objectId), { ...gamePlaytime, lastTick: now, }); - if (currentTick % TICKS_TO_UPDATE_API === 0) { + if (currentTick % TICKS_TO_UPDATE_API === 0 && game.shop !== "custom") { const deltaToSync = now - gamePlaytime.lastSyncTick + @@ -279,19 +283,20 @@ function onTickGame(game: Game) { gamePromise .then(() => { gamesSublevel.put(levelKeys.game(game.shop, game.objectId), { - ...game, + ...updatedGame, unsyncedDeltaPlayTimeInMilliseconds: 0, }); }) .catch(() => { gamesSublevel.put(levelKeys.game(game.shop, game.objectId), { - ...game, + ...updatedGame, unsyncedDeltaPlayTimeInMilliseconds: deltaToSync, }); }) .finally(() => { gamesPlaytime.set(levelKeys.game(game.shop, game.objectId), { ...gamePlaytime, + lastTick: now, lastSyncTick: now, }); }); @@ -299,11 +304,24 @@ function onTickGame(game: Game) { } const onCloseGame = (game: Game) => { + const now = performance.now(); const gamePlaytime = gamesPlaytime.get( levelKeys.game(game.shop, game.objectId) )!; gamesPlaytime.delete(levelKeys.game(game.shop, game.objectId)); + const delta = now - gamePlaytime.lastTick; + + const updatedGame: Game = { + ...game, + playTimeInMilliseconds: (game.playTimeInMilliseconds ?? 0) + delta, + lastTimePlayed: new Date(), + }; + + gamesSublevel.put(levelKeys.game(game.shop, game.objectId), updatedGame); + + if (game.shop === "custom") return; + if (game.remoteId) { if (game.automaticCloudSync) { CloudSync.uploadSaveGame( @@ -315,20 +333,20 @@ const onCloseGame = (game: Game) => { } const deltaToSync = - performance.now() - + now - gamePlaytime.lastSyncTick + (game.unsyncedDeltaPlayTimeInMilliseconds ?? 0); return updateGamePlaytime(game, deltaToSync, game.lastTimePlayed!) .then(() => { return gamesSublevel.put(levelKeys.game(game.shop, game.objectId), { - ...game, + ...updatedGame, unsyncedDeltaPlayTimeInMilliseconds: 0, }); }) .catch(() => { return gamesSublevel.put(levelKeys.game(game.shop, game.objectId), { - ...game, + ...updatedGame, unsyncedDeltaPlayTimeInMilliseconds: deltaToSync, }); }); diff --git a/src/renderer/src/context/game-details/game-details.context.tsx b/src/renderer/src/context/game-details/game-details.context.tsx index c5b88607..bc1a6351 100644 --- a/src/renderer/src/context/game-details/game-details.context.tsx +++ b/src/renderer/src/context/game-details/game-details.context.tsx @@ -293,6 +293,8 @@ export function GameDetailsContextProvider({ }, [objectId, shop, userDetails]); useEffect(() => { + if (shop === "custom") return; + const fetchDownloadSources = async () => { try { const sources = await window.electron.getDownloadSources(); diff --git a/src/renderer/src/pages/settings/settings-download-sources.tsx b/src/renderer/src/pages/settings/settings-download-sources.tsx index 75f0cc73..675919e3 100644 --- a/src/renderer/src/pages/settings/settings-download-sources.tsx +++ b/src/renderer/src/pages/settings/settings-download-sources.tsx @@ -89,7 +89,7 @@ export function SettingsDownloadSources() { try { await window.electron.removeDownloadSource(false, downloadSource.id); const sources = await window.electron.getDownloadSources(); - setDownloadSources(sources as DownloadSource[]); + setDownloadSources(sources); showSuccessToast(t("removed_download_source")); } catch (error) { logger.error("Failed to remove download source:", error); @@ -104,7 +104,7 @@ export function SettingsDownloadSources() { try { await window.electron.removeDownloadSource(true); const sources = await window.electron.getDownloadSources(); - setDownloadSources(sources as DownloadSource[]); + setDownloadSources(sources); showSuccessToast(t("removed_all_download_sources")); } catch (error) { logger.error("Failed to remove all download sources:", error); @@ -117,7 +117,7 @@ export function SettingsDownloadSources() { const handleAddDownloadSource = async () => { try { const sources = await window.electron.getDownloadSources(); - setDownloadSources(sources as DownloadSource[]); + setDownloadSources(sources); } catch (error) { logger.error("Failed to refresh download sources:", error); } @@ -128,7 +128,7 @@ export function SettingsDownloadSources() { try { await window.electron.syncDownloadSources(); const sources = await window.electron.getDownloadSources(); - setDownloadSources(sources as DownloadSource[]); + setDownloadSources(sources); showSuccessToast(t("download_sources_synced_successfully")); } finally {