diff --git a/src/main/events/library/create-steam-shortcut.ts b/src/main/events/library/create-steam-shortcut.ts index b702bc08..436d4ac1 100644 --- a/src/main/events/library/create-steam-shortcut.ts +++ b/src/main/events/library/create-steam-shortcut.ts @@ -5,7 +5,7 @@ import { composeSteamShortcut, getSteamLocation, getSteamShortcuts, - getSteamUserId, + getSteamUsersIds, HydraApi, logger, SystemPath, @@ -54,77 +54,79 @@ const createSteamShortcut = async ( `/games/stats?objectId=${objectId}&shop=${shop}` ); - const steamUserId = await getSteamUserId(); + const steamUserIds = await getSteamUsersIds(); - if (!steamUserId) { + if (!steamUserIds.length) { logger.error("No Steam user ID found"); return; } - logger.info("Got Steam user id", steamUserId); + for (const steamUserId of steamUserIds) { + logger.info("Adding shortcut for Steam user", steamUserId); - const steamShortcuts = await getSteamShortcuts(steamUserId); + const steamShortcuts = await getSteamShortcuts(steamUserId); - if ( - steamShortcuts.some( - (shortcut) => - shortcut.Exe === game.executablePath && - shortcut.appname === game.title - ) - ) { - return; + if ( + steamShortcuts.some( + (shortcut) => + shortcut.Exe === game.executablePath && + shortcut.appname === game.title + ) + ) { + continue; + } + + const icon = await downloadAsset( + path.join( + SystemPath.getPath("userData"), + "Icons", + `${game.shop}-${game.objectId}.ico` + ), + assets?.iconUrl + ); + + const newShortcut = composeSteamShortcut( + game.title, + game.executablePath, + icon + ); + + const gridPath = path.join( + await getSteamLocation(), + "userdata", + steamUserId.toString(), + "config", + "grid" + ); + + fs.mkdirSync(gridPath, { recursive: true }); + + await Promise.allSettled([ + downloadAsset( + path.join(gridPath, `${newShortcut.appid}_hero.jpg`), + assets?.libraryHeroImageUrl + ), + downloadAsset( + path.join(gridPath, `${newShortcut.appid}_logo.png`), + assets?.logoImageUrl + ), + downloadAsset( + path.join(gridPath, `${newShortcut.appid}p.jpg`), + assets?.coverImageUrl + ), + downloadAsset( + path.join(gridPath, `${newShortcut.appid}.jpg`), + assets?.libraryImageUrl + ), + ]); + + steamShortcuts.push(newShortcut); + + logger.info(newShortcut); + logger.info("Writing Steam shortcuts", steamShortcuts); + + await writeSteamShortcuts(steamUserId, steamShortcuts); } - - const icon = await downloadAsset( - path.join( - SystemPath.getPath("userData"), - "Icons", - `${game.shop}-${game.objectId}.ico` - ), - assets?.iconUrl - ); - - const newShortcut = composeSteamShortcut( - game.title, - game.executablePath, - icon - ); - - const gridPath = path.join( - await getSteamLocation(), - "userdata", - steamUserId.toString(), - "config", - "grid" - ); - - fs.mkdirSync(gridPath, { recursive: true }); - - await Promise.allSettled([ - downloadAsset( - path.join(gridPath, `${newShortcut.appid}_hero.jpg`), - assets?.libraryHeroImageUrl - ), - downloadAsset( - path.join(gridPath, `${newShortcut.appid}_logo.png`), - assets?.logoImageUrl - ), - downloadAsset( - path.join(gridPath, `${newShortcut.appid}p.jpg`), - assets?.coverImageUrl - ), - downloadAsset( - path.join(gridPath, `${newShortcut.appid}.jpg`), - assets?.libraryImageUrl - ), - ]); - - steamShortcuts.push(newShortcut); - - logger.info(newShortcut); - logger.info("Writing Steam shortcuts", steamShortcuts); - - return writeSteamShortcuts(steamUserId, steamShortcuts); } }; diff --git a/src/main/services/steam.ts b/src/main/services/steam.ts index d805de4b..3b655b1a 100644 --- a/src/main/services/steam.ts +++ b/src/main/services/steam.ts @@ -77,34 +77,33 @@ export const getSteamAppDetails = async ( }); }; -export const getSteamUserId = async () => { +export const getSteamUsersIds = async () => { const userDataPath = await getSteamLocation(); const userIds = fs.readdirSync(path.join(userDataPath, "userdata"), { withFileTypes: true, }); - const [steamUserId] = userIds.filter((dir) => dir.isDirectory()); - if (!steamUserId) { - return null; - } - - return Number(steamUserId.name); + return userIds + .filter((dir) => dir.isDirectory()) + .map((dir) => Number(dir.name)); }; export const getSteamShortcuts = async (steamUserId: number) => { - const shortcuts = parseBuffer( - fs.readFileSync( - path.join( - await getSteamLocation(), - "userdata", - steamUserId.toString(), - "config", - "shortcuts.vdf" - ) - ) + const shortcutsPath = path.join( + await getSteamLocation(), + "userdata", + steamUserId.toString(), + "config", + "shortcuts.vdf" ); + if (!fs.existsSync(shortcutsPath)) { + return []; + } + + const shortcuts = parseBuffer(fs.readFileSync(shortcutsPath)); + return shortcuts.shortcuts as SteamShortcut[]; }; @@ -126,8 +125,8 @@ export const composeSteamShortcut = ( return { appid: generateSteamShortcutAppId(executablePath, title), appname: title, - Exe: executablePath, - StartDir: path.dirname(executablePath), + Exe: `"${executablePath}"`, + StartDir: `"${path.dirname(executablePath)}"`, icon: iconPath ?? "", ShortcutPath: "", LaunchOptions: "", diff --git a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx index c178d0c1..764ec92a 100644 --- a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx +++ b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx @@ -47,6 +47,7 @@ export function GameOptionsModal({ const [automaticCloudSync, setAutomaticCloudSync] = useState( game.automaticCloudSync ?? false ); + const [creatingSteamShortcut, setCreatingSteamShortcut] = useState(false); const { removeGameInstaller, @@ -111,6 +112,7 @@ export function GameOptionsModal({ const handleCreateSteamShortcut = async () => { try { + setCreatingSteamShortcut(true); await window.electron.createSteamShortcut(game.shop, game.objectId); showSuccessToast( @@ -120,6 +122,8 @@ export function GameOptionsModal({ } catch (error: unknown) { logger.error("Failed to create Steam shortcut", error); showErrorToast(t("create_shortcut_error")); + } finally { + setCreatingSteamShortcut(false); } };