summaryrefslogtreecommitdiff
path: root/src/hooks
diff options
context:
space:
mode:
authorxXJSONDeruloXx <danielhimebauch@gmail.com>2026-09-09 20:45:20 -0400
committerxXJSONDeruloXx <danielhimebauch@gmail.com>2026-09-09 20:45:20 -0400
commitfb4d053213bdbda271a54b517a11a89c4780f80a (patch)
treecf63819208ceb75c49c0ad08de8edd1b2b81082c /src/hooks
parentcc1e6f47dd9838b066822162a607d2859c043aff (diff)
downloaddecky-lsfg-vk-fb4d053213bdbda271a54b517a11a89c4780f80a.tar.gz
decky-lsfg-vk-fb4d053213bdbda271a54b517a11a89c4780f80a.zip
fix: restore profile and Flatpak controls
Diffstat (limited to 'src/hooks')
-rw-r--r--src/hooks/useGameConfiguration.ts65
-rw-r--r--src/hooks/usePerAppWorkarounds.ts24
2 files changed, 82 insertions, 7 deletions
diff --git a/src/hooks/useGameConfiguration.ts b/src/hooks/useGameConfiguration.ts
index b59d592..c70d589 100644
--- a/src/hooks/useGameConfiguration.ts
+++ b/src/hooks/useGameConfiguration.ts
@@ -40,6 +40,23 @@ function mergeInstalledGames(backendGames: InstalledGame[], shortcutGames: Insta
return Array.from(games.values());
}
+function selectShortcutExecutable(
+ target: GameTarget,
+ ...candidates: Array<string | null | undefined>
+): string | undefined {
+ const absolute = candidates
+ .map((candidate) => candidate?.trim())
+ .find((candidate) => candidate && candidate.startsWith("/"));
+ if (absolute) return absolute;
+
+ // Steam's app-details API can report a Flatpak Target as just "flatpak"
+ // even when the shortcut's canonical VDF executable is /usr/bin/flatpak.
+ // Keep the stored original executable absolute so SetShortcutExe and the
+ // generated dispatcher agree on the same direct transport.
+ if (target.transport.kind === "flatpak") return "/usr/bin/flatpak";
+ return candidates.map((candidate) => candidate?.trim()).find(Boolean);
+}
+
const DEFAULT_WORKAROUND_STATE: WorkaroundState = {
dxvkFrameRate: 0,
disableGamescopeWsi: true,
@@ -151,7 +168,14 @@ export function useGameConfiguration() {
throw new Error("Shortcut Target is already the managed wrapper but its original Target is unknown");
}
const state = oldState || { ...DEFAULT_WORKAROUND_STATE };
- const originalExecutable = target.nonSteam ? (oldShortcutExe || current.target) : undefined;
+ const originalExecutable = target.nonSteam
+ ? selectShortcutExecutable(
+ target,
+ oldShortcutExe,
+ target.transport.kind === "flatpak" ? target.executable : undefined,
+ current.target,
+ )
+ : undefined;
const initialIntegration = target.nonSteam
? current.target === wrapperPath
: hasWrapperLaunchIntegration(current.options, wrapperPath);
@@ -170,7 +194,14 @@ export function useGameConfiguration() {
const finalStateResult = await setWorkaroundState(
target.appid,
state,
- target.nonSteam ? (integration.originalExecutable || originalExecutable || null) : null,
+ target.nonSteam
+ ? (selectShortcutExecutable(
+ target,
+ integration.originalExecutable,
+ originalExecutable,
+ target.transport.kind === "flatpak" ? target.executable : undefined,
+ ) || null)
+ : null,
integration.commandTokenAdded,
target.transport,
);
@@ -184,7 +215,14 @@ export function useGameConfiguration() {
appId,
target.nonSteam,
wrapperPath,
- target.nonSteam ? (integration?.originalExecutable || originalExecutable) : undefined,
+ target.nonSteam
+ ? (selectShortcutExecutable(
+ target,
+ integration?.originalExecutable,
+ originalExecutable,
+ target.transport.kind === "flatpak" ? target.executable : undefined,
+ ) || undefined)
+ : undefined,
integration?.commandTokenAdded ?? oldCommandTokenAdded,
);
} catch (rollbackError) {
@@ -264,6 +302,25 @@ export function useGameConfiguration() {
else await removeTargetWorkarounds(target);
return result.success;
}, [ensureTargetFlatpakSupport, ensureTargetWorkarounds, load, removeTargetWorkarounds, targets, template]);
+ const enableAll = useCallback(async (): Promise<void> => {
+ const available = targets.filter((target) => !target.configured && target.name);
+ if (available.length === 0) return;
+
+ for (const target of available) {
+ if (!(await ensureTargetFlatpakSupport(target))) return;
+ if (!(await ensureTargetWorkarounds(target))) return;
+ const result = await updateGameConfig(target.appid, target.name, template);
+ if (!result.success) {
+ await removeTargetWorkarounds(target);
+ showErrorToast(
+ "Could not enable all games",
+ result.error || `Could not create a profile for ${target.name}`,
+ );
+ return;
+ }
+ }
+ await load();
+ }, [ensureTargetFlatpakSupport, ensureTargetWorkarounds, load, removeTargetWorkarounds, targets, template]);
const repair = useCallback(async (appid: string): Promise<boolean> => {
const target = targets.find((item) => item.appid === appid);
if (!target) return false;
@@ -306,5 +363,5 @@ export function useGameConfiguration() {
}
}, [load, removeTargetWorkarounds, targets]);
- return { config, games, targets, runningGame, selectedAppId, setSelectedAppId, save, enable, repair, resetSelected, resetAll, reload: load };
+ return { config, games, targets, runningGame, selectedAppId, setSelectedAppId, save, enable, enableAll, repair, resetSelected, resetAll, reload: load };
}
diff --git a/src/hooks/usePerAppWorkarounds.ts b/src/hooks/usePerAppWorkarounds.ts
index c7413b0..e9e44e1 100644
--- a/src/hooks/usePerAppWorkarounds.ts
+++ b/src/hooks/usePerAppWorkarounds.ts
@@ -61,6 +61,18 @@ function asError(error: unknown): Error {
return error instanceof Error ? error : new Error(String(error));
}
+function selectShortcutExecutable(
+ transport: TargetTransport,
+ ...candidates: Array<string | null | undefined>
+): string | undefined {
+ const absolute = candidates
+ .map((candidate) => candidate?.trim())
+ .find((candidate) => candidate && candidate.startsWith("/"));
+ if (absolute) return absolute;
+ if (transport.kind === "flatpak") return "/usr/bin/flatpak";
+ return candidates.map((candidate) => candidate?.trim()).find(Boolean);
+}
+
function integrationIsInstalled(
steam: SteamLaunchOptionsSnapshot,
nonSteam: boolean,
@@ -101,7 +113,9 @@ async function adoptWorkaroundState(
if (nonSteam && (!steam.target || steam.target === wrapperPath || isLegacyWrapperToken(steam.target))) {
throw new Error("Shortcut Target is a wrapper but its original Target is unknown");
}
- const originalExecutable = nonSteam ? steam.target : null;
+ const originalExecutable = nonSteam
+ ? selectShortcutExecutable(transport, steam.target)
+ : null;
const initial = await setWorkaroundState(
appId,
DEFAULT_WORKAROUND_STATE,
@@ -120,7 +134,9 @@ async function adoptWorkaroundState(
const finalized = await setWorkaroundState(
appId,
DEFAULT_WORKAROUND_STATE,
- nonSteam ? (integration.originalExecutable || originalExecutable) : null,
+ nonSteam
+ ? (selectShortcutExecutable(transport, integration.originalExecutable, originalExecutable) || null)
+ : null,
integration.commandTokenAdded,
transport,
);
@@ -134,7 +150,9 @@ async function adoptWorkaroundState(
Number(appId),
nonSteam,
wrapperPath,
- nonSteam ? (integration?.originalExecutable || originalExecutable || undefined) : undefined,
+ nonSteam
+ ? (selectShortcutExecutable(transport, integration?.originalExecutable, originalExecutable) || undefined)
+ : undefined,
integration?.commandTokenAdded ?? false,
);
} catch {