From 9902135e53be129bd6096d51d5e510ab298c1ae2 Mon Sep 17 00:00:00 2001 From: xXJSONDeruloXx Date: Thu, 10 Sep 2026 12:19:40 -0400 Subject: fix: handle bare Flatpak shortcut targets --- py_modules/lsfg_vk/steam_service.py | 2 +- src/utils/steamLaunchOptions.ts | 9 +++++++-- tests/steamLaunchOptions.test.ts | 17 +++++++++-------- tests/test_steam_service.py | 7 +++++++ 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/py_modules/lsfg_vk/steam_service.py b/py_modules/lsfg_vk/steam_service.py index 201441e..a952fcb 100644 --- a/py_modules/lsfg_vk/steam_service.py +++ b/py_modules/lsfg_vk/steam_service.py @@ -35,7 +35,7 @@ def classify_shortcut_transport(executable: Optional[str], launch_options: Optio option_tokens = _split_command(launch_options) if executable_tokens is None or option_tokens is None or not executable_tokens: return {"kind": "host"} - direct_flatpak = executable_tokens[0] == "/usr/bin/flatpak" + direct_flatpak = executable_tokens[0] in {"flatpak", "/usr/bin/flatpak"} managed_wrapper = len(executable_tokens) == 1 and _is_managed_wrapper(executable_tokens[0]) if not direct_flatpak and not managed_wrapper: return {"kind": "host"} diff --git a/src/utils/steamLaunchOptions.ts b/src/utils/steamLaunchOptions.ts index 959ce9e..82cf116 100644 --- a/src/utils/steamLaunchOptions.ts +++ b/src/utils/steamLaunchOptions.ts @@ -166,8 +166,10 @@ const usesShortcutTarget = (nonSteam: boolean, transport: TargetTransport) => no function selectFlatpakExecutable(transport: TargetTransport, candidate?: string | null): string | undefined { if (transport.kind !== "flatpak") return undefined; - const value = candidate?.trim(); - return value ? (value.startsWith("/") ? value : "/usr/bin/flatpak") : undefined; + const value = candidate?.trim() ? decodeToken(candidate.trim()) : ""; + if (value === "flatpak") return "/usr/bin/flatpak"; + if (value === "/usr/bin/flatpak") return value; + return undefined; } export const normalizeLaunchOptions = (options: string) => serialize(tokenize(options)); @@ -405,6 +407,9 @@ export function installWrapperIntegration( throw new Error("Shortcut Target changed externally; refusing to replace it"); } const currentOriginal = selectFlatpakExecutable(transport, current.target); + if (!currentOriginal || (originalExecutable && !savedOriginal)) { + throw new Error("Flatpak shortcut Target is not a supported executable"); + } const value = await writeVerified( appId, true, current.target, wrapperPath, (target) => writeTarget(appId, target), readTarget, diff --git a/tests/steamLaunchOptions.test.ts b/tests/steamLaunchOptions.test.ts index 456d9d0..c799907 100644 --- a/tests/steamLaunchOptions.test.ts +++ b/tests/steamLaunchOptions.test.ts @@ -83,7 +83,7 @@ test("reads the matching app-details field and installs/removes Steam integratio const previousSteamClient = (globalThis as Record).SteamClient; let appOptions = "FOO=bar %command%"; let shortcutOptions = "--windowed"; - let shortcutTarget = "/usr/bin/example-game"; + let shortcutTarget = '"flatpak"'; const appWrites: string[] = []; const shortcutWrites: string[] = []; const targetWrites: string[] = []; @@ -123,12 +123,12 @@ test("reads the matching app-details field and installs/removes Steam integratio assert.equal(shortcutWrites.length, 0); const shortcut = await installWrapperIntegration(43, true, wrapper, false, { kind: "flatpak", flatpakAppId: "com.example.Game" }); - assert.equal(shortcut.originalExecutable, "/usr/bin/example-game"); + assert.equal(shortcut.originalExecutable, "/usr/bin/flatpak"); assert.equal(shortcut.snapshot.target, wrapper); assert.deepEqual(targetWrites, [wrapper]); const restored = await removeWrapperIntegration(43, true, wrapper, shortcut.originalExecutable, false, { kind: "flatpak", flatpakAppId: "com.example.Game" }); - assert.equal(restored.target, "/usr/bin/example-game"); - assert.deepEqual(targetWrites, [wrapper, "/usr/bin/example-game"]); + assert.equal(restored.target, "/usr/bin/flatpak"); + assert.deepEqual(targetWrites, [wrapper, "/usr/bin/flatpak"]); assert.equal(shortcutWrites.length, 0); const cleaned = await removeWrapperIntegration(42, false, wrapper, undefined, installed.commandTokenAdded); @@ -198,12 +198,13 @@ test("fails closed when shortcut Target ownership or setters are unavailable", a (globalThis as Record).SteamClient = { Apps: { RegisterForAppDetails(_appId: number, callback: (details: SteamAppDetails) => void) { - callback({ strShortcutExe: "/usr/bin/other", strShortcutLaunchOptions: "" }); + callback({ strShortcutExe: _appId === 99 ? "/usr/bin/flatpak" : "garbage", strShortcutLaunchOptions: "" }); return { unregister() {} }; }, }, }; try { + await assert.rejects(installWrapperIntegration(98, true, wrapper, false, { kind: "flatpak", flatpakAppId: "com.example.Game" }), /supported executable/); await assert.rejects(installWrapperIntegration(99, true, wrapper, false, { kind: "flatpak", flatpakAppId: "com.example.Game" }), /Target API is unavailable/); await assert.rejects(removeWrapperIntegration(99, true, wrapper, "/usr/bin/original", false, { kind: "flatpak", flatpakAppId: "com.example.Game" }), /Target changed externally/); } finally { @@ -218,7 +219,7 @@ test("restores launch options and shortcut Target when a setter fails after chan const previousWindow = (globalThis as Record).window; const previousSteamClient = (globalThis as Record).SteamClient; let appOptions = "FOO=bar %command%"; - let shortcutTarget = "/usr/bin/original"; + let shortcutTarget = "/usr/bin/flatpak"; const appWrites: string[] = []; const targetWrites: string[] = []; const apps = { @@ -247,8 +248,8 @@ test("restores launch options and shortcut Target when a setter fails after chan assert.deepEqual(appWrites, [`FOO=bar ${wrapper} %command%`, "FOO=bar %command%"]); await assert.rejects(installWrapperIntegration(43, true, wrapper, false, { kind: "flatpak", flatpakAppId: "com.example.Game" }), /simulated Target write failure/); - assert.equal(shortcutTarget, "/usr/bin/original"); - assert.deepEqual(targetWrites, [wrapper, "/usr/bin/original"]); + assert.equal(shortcutTarget, "/usr/bin/flatpak"); + assert.deepEqual(targetWrites, [wrapper, "/usr/bin/flatpak"]); } finally { if (previousWindow === undefined) delete (globalThis as Record).window; else (globalThis as Record).window = previousWindow; diff --git a/tests/test_steam_service.py b/tests/test_steam_service.py index 9924186..636c87f 100644 --- a/tests/test_steam_service.py +++ b/tests/test_steam_service.py @@ -23,6 +23,13 @@ class SteamTransportTests(unittest.TestCase): ), {"kind": "flatpak", "flatpakAppId": "com.example.PCSX2"}, ) + self.assertEqual( + classify_shortcut_transport( + "flatpak", + "run com.example.PCSX2 --fullscreen", + ), + {"kind": "flatpak", "flatpakAppId": "com.example.PCSX2"}, + ) self.assertEqual( classify_shortcut_transport( "/usr/bin/flatpak run com.example.PCSX2", -- cgit v1.2.3