summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorxXJSONDeruloXx <danielhimebauch@gmail.com>2026-09-10 16:26:17 -0400
committerxXJSONDeruloXx <danielhimebauch@gmail.com>2026-09-10 16:26:17 -0400
commit485ebb748185391e28764f48c39322b3cbdac65c (patch)
tree9b03047ed842e14d9c800bcdfa16cad322733cf4 /src
parentde74f0d2499159ed1cf8f628a166302146ae1f13 (diff)
downloaddecky-lsfg-vk-485ebb748185391e28764f48c39322b3cbdac65c.tar.gz
decky-lsfg-vk-485ebb748185391e28764f48c39322b3cbdac65c.zip
refactor: remove Flatpak supportv2-flatpakless
Diffstat (limited to 'src')
-rw-r--r--src/api/lsfgApi.ts44
-rw-r--r--src/components/ConfigurationTab.tsx22
-rw-r--r--src/components/Content.tsx1
-rw-r--r--src/components/GameConfigurationControls.tsx3
-rw-r--r--src/components/GameConfigurationSelector.tsx3
-rw-r--r--src/components/NowPlayingTab.tsx36
-rw-r--r--src/components/WorkaroundsSection.tsx6
-rw-r--r--src/hooks/useGameConfiguration.ts44
-rw-r--r--src/hooks/usePerAppWorkarounds.ts35
-rw-r--r--src/i18n/languages.json81
-rw-r--r--src/types.d.ts2
-rw-r--r--src/utils/steamLaunchOptions.ts121
12 files changed, 30 insertions, 368 deletions
diff --git a/src/api/lsfgApi.ts b/src/api/lsfgApi.ts
index 567e1ae..f8ef765 100644
--- a/src/api/lsfgApi.ts
+++ b/src/api/lsfgApi.ts
@@ -30,10 +30,6 @@ export interface SteamBranchStatus extends ApiResult {
}
export type LsfgConfig = ConfigurationData;
-export type TargetTransport =
- | { kind: "host" }
- | { kind: "flatpak"; flatpakAppId: string };
-export type FlatpakTargetSupportStatus = "ready" | "needs-runtime" | "unsupported" | "error";
export interface GameConfigEntry {
appid: string;
@@ -45,11 +41,9 @@ export interface InstalledGame {
appid: string;
name: string;
nonSteam: boolean;
- transport: TargetTransport;
executable?: string;
arguments?: string;
startDir?: string;
- flatpakSupport?: FlatpakTargetSupport;
}
export interface GlobalConfig {
@@ -57,15 +51,6 @@ export interface GlobalConfig {
no_fp16: boolean;
}
-export interface FlatpakTargetSupport extends ApiResult {
- flatpak_app_id?: string;
- runtime?: string | null;
- runtime_branch?: string | null;
- support_status: FlatpakTargetSupportStatus;
- extension_installed: boolean;
- installed_branches: string[];
-}
-
export interface WorkaroundState {
dxvkFrameRate: number;
disableGamescopeWsi: boolean;
@@ -80,9 +65,7 @@ export interface WorkaroundStateResult extends ApiResult {
state?: WorkaroundState | null;
wrapper_path?: string;
wrapper_owned?: boolean;
- shortcut_exe?: string | null;
command_token_added?: boolean;
- transport?: TargetTransport | null;
}
export interface GameConfigsResult extends ApiResult {
@@ -118,42 +101,17 @@ export interface DebugFileContentsResult extends ApiResult {
files?: DebugFileContent[];
}
-export interface FlatpakExtensionStatus extends ApiResult {
- message: string;
- available: boolean;
- extension_id: string;
- supported_branches: string[];
- installed_branches: string[];
-}
-
-export interface FlatpakExtensionToggleResult extends ApiResult {
- message: string;
- runtime_branch: string;
- enabled: boolean;
- installed: boolean;
-}
-
export const installLsfgVk = callable<[], InstallationResult>("install_lsfg_vk");
export const uninstallLsfgVk = callable<[], InstallationResult>("uninstall_lsfg_vk");
export const checkLsfgVkInstalled = callable<[], InstallationStatus>("check_lsfg_vk_installed");
export const getLosslessScalingBranchStatus = callable<[], SteamBranchStatus>("get_lossless_scaling_branch_status");
export const getConfigFileContent = callable<[], FileContentResult>("get_config_file_content");
-export const getFlatpakSupportStatus = callable<[], FlatpakExtensionStatus>("get_flatpak_support_status");
-export const ensureFlatpakSupport = callable<[string], FlatpakTargetSupport>("ensure_flatpak_support");
-export const repairFlatpakSupport = callable<[string], FlatpakTargetSupport>("repair_flatpak_support");
-export const setFlatpakExtensionEnabled = callable<[string, boolean], FlatpakExtensionToggleResult>("set_flatpak_extension_enabled");
export const getGameConfigs = callable<[], GameConfigsResult>("get_game_configs");
export const getInstalledGames = callable<[], InstalledGamesResult>("get_installed_games");
export const updateGameConfig = callable<[string, string, LsfgConfig], GameConfigResult>("update_game_config");
export const resetGameConfig = callable<[string], GameConfigResult>("reset_game_config");
export const resetAllGameConfigs = callable<[], GameConfigsResult>("reset_all_game_configs");
export const getWorkaroundState = callable<[string], WorkaroundStateResult>("get_workaround_state");
-export const setWorkaroundState = callable<[
- string,
- WorkaroundState,
- string | null | undefined,
- boolean,
- TargetTransport | null | undefined,
-], WorkaroundStateResult>("set_workaround_state");
+export const setWorkaroundState = callable<[string, WorkaroundState, boolean?], WorkaroundStateResult>("set_workaround_state");
export const removeWorkaroundState = callable<[string], WorkaroundStateResult>("remove_workaround_state");
export const getDebugFileContents = callable<[], DebugFileContentsResult>("get_debug_file_contents");
diff --git a/src/components/ConfigurationTab.tsx b/src/components/ConfigurationTab.tsx
index 4e2d93d..957f697 100644
--- a/src/components/ConfigurationTab.tsx
+++ b/src/components/ConfigurationTab.tsx
@@ -99,13 +99,11 @@ export function ConfigurationTab({
}
const profileLabel = selectedTarget?.name || "Game profile";
- const profileTransport = selectedTarget
- ? selectedTarget.transport.kind === "flatpak"
- ? "Non-Steam · Flatpak"
- : selectedTarget.nonSteam ? "Non-Steam" : "Steam"
+ const profileType = selectedTarget
+ ? selectedTarget.nonSteam ? "Non-Steam" : "Steam"
: "Game";
const profileDescription = selectedTarget
- ? `${profileTransport} · App ID ${selectedTarget.appid} · ${selectedTarget.configured ? "LSFG-VK Enabled" : "LSFG-VK not enabled"}`
+ ? `${profileType} · App ID ${selectedTarget.appid} · ${selectedTarget.configured ? "LSFG-VK Enabled" : "LSFG-VK not enabled"}`
: "Game is no longer available";
const enableProfile = async (appid: string, quitRunningGame = false) => {
if (!(await onEnable(appid))) return;
@@ -120,9 +118,7 @@ export function ConfigurationTab({
} else if (detailAppId) {
const isRunningUnconfigured = runningGame?.appid === detailAppId
&& runningGame.nonSteam === false
- && runningGame.transport.kind === "host"
&& selectedTarget?.nonSteam === false
- && selectedTarget?.transport.kind === "host"
&& !runningGame.configured;
if (isRunningUnconfigured) {
showModal(
@@ -182,18 +178,6 @@ export function ConfigurationTab({
</PanelSectionRow>
)}
</PanelSection>
- {selectedTarget?.configured && selectedTarget.transport.kind === "flatpak" && selectedTarget.flatpakSupport?.support_status !== "ready" && (
- <PanelSection>
- <PanelSectionRow>
- <ButtonItem
- layout="below"
- onClick={() => void onRepair(selectedTarget.appid)}
- >
- Repair Flatpak support
- </ButtonItem>
- </PanelSectionRow>
- </PanelSection>
- )}
{selectedTarget?.configured && (
<GameConfigurationControls
config={config}
diff --git a/src/components/Content.tsx b/src/components/Content.tsx
index 43720c0..480a3e3 100644
--- a/src/components/Content.tsx
+++ b/src/components/Content.tsx
@@ -132,7 +132,6 @@ export function Content() {
game={runningGame}
config={config}
onConfigChange={(field, value) => handleConfigChange(field, value)}
- onRepair={repair}
/>
),
}] : []),
diff --git a/src/components/GameConfigurationControls.tsx b/src/components/GameConfigurationControls.tsx
index 6bea2e0..7025f78 100644
--- a/src/components/GameConfigurationControls.tsx
+++ b/src/components/GameConfigurationControls.tsx
@@ -10,7 +10,7 @@ interface Props {
autoFocusFpsMultiplier?: boolean;
onFpsMultiplierFocused?: () => void;
showWorkarounds?: boolean;
- workaroundTarget?: Pick<GameTarget, "appid" | "nonSteam" | "transport">;
+ workaroundTarget?: Pick<GameTarget, "appid" | "nonSteam">;
onRepairWorkaround?: () => Promise<boolean>;
}
@@ -36,7 +36,6 @@ export function GameConfigurationControls({
<WorkaroundsSection
appId={workaroundTarget.appid}
nonSteam={workaroundTarget.nonSteam}
- transport={workaroundTarget.transport}
onRepair={onRepairWorkaround}
/>
)}
diff --git a/src/components/GameConfigurationSelector.tsx b/src/components/GameConfigurationSelector.tsx
index 92eacba..e407919 100644
--- a/src/components/GameConfigurationSelector.tsx
+++ b/src/components/GameConfigurationSelector.tsx
@@ -37,7 +37,6 @@ function usePersistentCollapsed(key: string) {
}
function targetDescription(game: GameTarget): string {
- if (game.transport.kind === "flatpak") return "Non-Steam · Flatpak";
return game.nonSteam ? "Non-Steam" : "Steam";
}
@@ -137,7 +136,7 @@ export function GameConfigurationSelector({
showModal(
<ConfirmModal
strTitle="Enable all available games?"
- strDescription="Create individual LSFG-VK profiles for every available game using the plugin defaults. Flatpak targets will be provisioned as needed."
+ strDescription="Create individual LSFG-VK profiles for every available game using the plugin defaults."
strOKButtonText="Enable all"
strCancelButtonText="Cancel"
onOK={() => void onEnableAll()}
diff --git a/src/components/NowPlayingTab.tsx b/src/components/NowPlayingTab.tsx
index 57858db..c067dc0 100644
--- a/src/components/NowPlayingTab.tsx
+++ b/src/components/NowPlayingTab.tsx
@@ -1,5 +1,4 @@
-import { ButtonItem, Field, Focusable, PanelSection, PanelSectionRow } from "@decky/ui";
-import { useState } from "react";
+import { Field, Focusable, PanelSection, PanelSectionRow } from "@decky/ui";
import { ConfigurationData } from "../config/configSchema";
import { GameTarget } from "../hooks/useGameConfiguration";
import { GameConfigurationControls } from "./GameConfigurationControls";
@@ -11,11 +10,9 @@ interface Props {
fieldName: keyof ConfigurationData,
value: boolean | number | string | string[],
) => Promise<void>;
- onRepair: (appid: string) => Promise<boolean>;
}
function targetDescription(game: GameTarget): string {
- if (game.transport.kind === "flatpak") return "Non-Steam · Flatpak";
return game.nonSteam ? "Non-Steam" : "Steam";
}
@@ -23,23 +20,7 @@ export function NowPlayingTab({
game,
config,
onConfigChange,
- onRepair,
}: Props) {
- const [busy, setBusy] = useState(false);
- const supportNeedsRepair =
- game.transport.kind === "flatpak" &&
- game.flatpakSupport?.support_status !== "ready";
-
- const handleRepair = async () => {
- if (busy) return;
- setBusy(true);
- try {
- await onRepair(game.appid);
- } finally {
- setBusy(false);
- }
- };
-
return (
<Focusable>
<PanelSection title="Now Playing">
@@ -47,21 +28,6 @@ export function NowPlayingTab({
<Field label={game.name} description={targetDescription(game)} />
</PanelSectionRow>
</PanelSection>
- {supportNeedsRepair && (
- <PanelSection>
- <PanelSectionRow>
- <Field
- label="Flatpak support needs repair"
- description={game.flatpakSupport?.error || "The target runtime extension is not ready."}
- />
- </PanelSectionRow>
- <PanelSectionRow>
- <ButtonItem layout="below" disabled={busy} onClick={() => void handleRepair()}>
- {busy ? "Repairing..." : "Repair Flatpak support"}
- </ButtonItem>
- </PanelSectionRow>
- </PanelSection>
- )}
<GameConfigurationControls
config={config}
onConfigChange={onConfigChange}
diff --git a/src/components/WorkaroundsSection.tsx b/src/components/WorkaroundsSection.tsx
index 5587392..dbdd6a3 100644
--- a/src/components/WorkaroundsSection.tsx
+++ b/src/components/WorkaroundsSection.tsx
@@ -1,7 +1,6 @@
import { ButtonItem, Field, PanelSectionRow, SliderField, ToggleField } from "@decky/ui";
import { useEffect, useState } from "react";
import { RiArrowDownSFill, RiArrowUpSFill } from "react-icons/ri";
-import type { TargetTransport } from "../api/lsfgApi";
import { usePerAppWorkarounds } from "../hooks/usePerAppWorkarounds";
import t from "../i18n/i18n";
import type { WorkaroundField } from "../hooks/usePerAppWorkarounds";
@@ -9,7 +8,6 @@ import type { WorkaroundField } from "../hooks/usePerAppWorkarounds";
interface WorkaroundsSectionProps {
appId: string;
nonSteam: boolean;
- transport: TargetTransport;
onRepair?: () => Promise<boolean>;
}
@@ -81,9 +79,9 @@ function usePersistentCollapsed() {
return [collapsed, () => setCollapsed((value) => !value)] as const;
}
-export function WorkaroundsSection({ appId, nonSteam, transport, onRepair }: WorkaroundsSectionProps) {
+export function WorkaroundsSection({ appId, nonSteam, onRepair }: WorkaroundsSectionProps) {
const [collapsed, toggleCollapsed] = usePersistentCollapsed();
- const { status, snapshot, refresh, update, error } = usePerAppWorkarounds(appId, nonSteam, transport);
+ const { status, snapshot, refresh, update, error } = usePerAppWorkarounds(appId, nonSteam);
const [repairing, setRepairing] = useState(false);
const state = snapshot?.state;
const controlsDisabled = status !== "ready" || state === undefined || snapshot?.wrapperOwned !== true || snapshot.integrationInstalled !== true;
diff --git a/src/hooks/useGameConfiguration.ts b/src/hooks/useGameConfiguration.ts
index 3260019..e94ce42 100644
--- a/src/hooks/useGameConfiguration.ts
+++ b/src/hooks/useGameConfiguration.ts
@@ -1,7 +1,7 @@
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useQuickAccessVisible } from "@decky/api";
import { Router } from "@decky/ui";
-import { ensureFlatpakSupport, getGameConfigs, getInstalledGames, getWorkaroundState, removeWorkaroundState, repairFlatpakSupport, resetGameConfig, resetAllGameConfigs, setWorkaroundState, updateGameConfig, type GameConfigEntry, type GlobalConfig, type InstalledGame, type WorkaroundState } from "../api/lsfgApi";
+import { getGameConfigs, getInstalledGames, getWorkaroundState, removeWorkaroundState, resetGameConfig, resetAllGameConfigs, setWorkaroundState, updateGameConfig, type GameConfigEntry, type GlobalConfig, type InstalledGame, type WorkaroundState } from "../api/lsfgApi";
import { ConfigurationData, getDefaults } from "../config/configSchema";
import { getDefaultWrapperPath, installWrapperIntegration, removeWrapperIntegration } from "../utils/steamLaunchOptions";
import { showErrorToast } from "../utils/toastUtils";
@@ -23,7 +23,6 @@ async function getSteamShortcuts(): Promise<InstalledGame[]> {
appid: String(appid >>> 0),
name,
nonSteam: true,
- transport: { kind: "host" },
}];
});
} catch {
@@ -90,7 +89,7 @@ export function useGameConfiguration() {
const name = app.display_name || installed?.name;
if (!name) return setRunningGame(null);
setRunningGame((current) => current?.appid === appid ? current : {
- ...(installed || { appid, name, nonSteam: false, transport: { kind: "host" } }),
+ ...(installed || { appid, name, nonSteam: false }),
name,
configured: games.some((game) => game.appid === appid),
});
@@ -109,26 +108,13 @@ export function useGameConfiguration() {
const targets = useMemo<GameTarget[]>(() => {
const configured = installedGames.map((game) => ({ ...game, configured: games.some((item) => item.appid === game.appid) }));
- for (const game of games) if (!configured.some((item) => item.appid === game.appid)) configured.push({ appid: game.appid, name: game.profile, nonSteam: false, transport: { kind: "host" }, configured: true });
+ for (const game of games) if (!configured.some((item) => item.appid === game.appid)) configured.push({ appid: game.appid, name: game.profile, nonSteam: false, configured: true });
if (runningGame && !configured.some((game) => game.appid === runningGame.appid)) configured.unshift(runningGame);
return configured;
}, [games, installedGames, runningGame]);
const template = useMemo(() => ({ ...getDefaults(), ...globalConfig }), [globalConfig]);
const config = games.find((game) => game.appid === selectedAppId)?.config || template;
- const ensureTargetFlatpakSupport = useCallback(async (target: GameTarget): Promise<boolean> => {
- if (target.transport.kind !== "flatpak") return true;
- const result = await ensureFlatpakSupport(target.transport.flatpakAppId);
- if (!result.success || result.support_status !== "ready") {
- showErrorToast(
- "Flatpak support unavailable",
- result.error || result.message || "The required Flatpak runtime extension is not ready",
- );
- return false;
- }
- return true;
- }, []);
-
const ensureTargetWorkarounds = useCallback(async (target: GameTarget): Promise<boolean> => {
if (!installedGames.some((game) => game.appid === target.appid)) return true;
const appId = Number(target.appid);
@@ -148,16 +134,12 @@ export function useGameConfiguration() {
target.nonSteam,
wrapperPath,
commandTokenAdded,
- target.transport,
- target.transport.kind === "flatpak" ? existing.shortcut_exe || undefined : undefined,
);
stateWriteAttempted = true;
const saved = await setWorkaroundState(
target.appid,
state,
- integration.originalExecutable ?? null,
integration.commandTokenAdded,
- target.transport,
);
if (!saved.success) throw new Error(saved.error || "Could not save workaround state");
return true;
@@ -169,9 +151,7 @@ export function useGameConfiguration() {
appId,
target.nonSteam,
wrapperPath,
- integration.originalExecutable,
integration.commandTokenAdded,
- target.transport,
);
} catch (rollbackError) {
showErrorToast("Workaround rollback failed", asError(rollbackError).message);
@@ -201,9 +181,7 @@ export function useGameConfiguration() {
appId,
target.nonSteam,
wrapperPath,
- target.transport.kind === "flatpak" ? existing.shortcut_exe || undefined : undefined,
existing.command_token_added === true,
- target.transport,
);
const removed = await removeWorkaroundState(target.appid);
if (!removed.success) throw new Error(removed.error || "Could not remove workaround state");
@@ -228,19 +206,17 @@ export function useGameConfiguration() {
const enable = useCallback(async (appid: string) => {
const target = targets.find((item) => item.appid === appid);
if (!target?.name) return false;
- if (!(await ensureTargetFlatpakSupport(target))) return false;
if (!(await ensureTargetWorkarounds(target))) return false;
const result = await updateGameConfig(appid, target.name, template);
if (result.success) await load();
else await removeTargetWorkarounds(target);
return result.success;
- }, [ensureTargetFlatpakSupport, ensureTargetWorkarounds, load, removeTargetWorkarounds, targets, template]);
+ }, [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) {
@@ -253,20 +229,10 @@ export function useGameConfiguration() {
}
}
await load();
- }, [ensureTargetFlatpakSupport, ensureTargetWorkarounds, load, removeTargetWorkarounds, targets, template]);
+ }, [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;
- if (target.transport.kind === "flatpak") {
- const support = await repairFlatpakSupport(target.transport.flatpakAppId);
- if (!support.success || support.support_status !== "ready") {
- showErrorToast(
- "Flatpak support unavailable",
- support.error || support.message || "The required Flatpak runtime extension is not ready",
- );
- return false;
- }
- }
const success = await ensureTargetWorkarounds(target);
if (success) await load();
return success;
diff --git a/src/hooks/usePerAppWorkarounds.ts b/src/hooks/usePerAppWorkarounds.ts
index 29e1181..63ebdb9 100644
--- a/src/hooks/usePerAppWorkarounds.ts
+++ b/src/hooks/usePerAppWorkarounds.ts
@@ -3,11 +3,9 @@ import {
getWorkaroundState,
removeWorkaroundState,
setWorkaroundState,
- type TargetTransport,
type WorkaroundState,
} from "../api/lsfgApi";
import {
- assertKnownShortcutTarget,
getDefaultWrapperPath,
installWrapperIntegration,
isWrapperIntegrationInstalled,
@@ -45,8 +43,6 @@ export interface WorkaroundSnapshot {
wrapperOwned: boolean;
integrationInstalled: boolean;
commandTokenAdded: boolean;
- shortcutExe?: string | null;
- transport: TargetTransport;
}
interface PerAppWorkarounds {
@@ -64,30 +60,22 @@ function asError(error: unknown): Error {
function makeSnapshot(
steam: SteamLaunchOptionsSnapshot,
result: Awaited<ReturnType<typeof getWorkaroundState>>,
- nonSteam: boolean,
- transport: TargetTransport,
): WorkaroundSnapshot {
if (!result.state) throw new Error("Workaround state is not initialized for this profile");
const wrapperPath = result.wrapper_path || getDefaultWrapperPath();
- const selectedTransport = result.transport || transport;
- const shortcutExe = selectedTransport.kind === "flatpak" ? result.shortcut_exe : undefined;
- assertKnownShortcutTarget(steam, nonSteam, selectedTransport, wrapperPath, shortcutExe);
return {
steam,
state: result.state,
wrapperPath,
wrapperOwned: result.wrapper_owned === true,
- integrationInstalled: isWrapperIntegrationInstalled(steam, nonSteam, selectedTransport, wrapperPath),
+ integrationInstalled: isWrapperIntegrationInstalled(steam, wrapperPath),
commandTokenAdded: result.command_token_added === true,
- shortcutExe,
- transport: selectedTransport,
};
}
async function adoptWorkaroundState(
appId: string,
nonSteam: boolean,
- transport: TargetTransport,
wrapperPath: string,
): Promise<WorkaroundSnapshot> {
let integration: Awaited<ReturnType<typeof installWrapperIntegration>> | null = null;
@@ -97,17 +85,14 @@ async function adoptWorkaroundState(
nonSteam,
wrapperPath,
false,
- transport,
);
const finalized = await setWorkaroundState(
appId,
DEFAULT_WORKAROUND_STATE,
- integration.originalExecutable ?? null,
integration.commandTokenAdded,
- transport,
);
if (!finalized.success) throw new Error(finalized.error || "Could not finalize workaround state");
- return makeSnapshot(integration.snapshot, finalized, nonSteam, transport);
+ return makeSnapshot(integration.snapshot, finalized);
} catch (error) {
let rollbackSucceeded = true;
if (integration?.changed) {
@@ -116,9 +101,7 @@ async function adoptWorkaroundState(
Number(appId),
nonSteam,
wrapperPath,
- integration.originalExecutable,
integration.commandTokenAdded,
- transport,
);
} catch {
// Leave the owned integration in place rather than guessing at cleanup.
@@ -136,7 +119,6 @@ async function adoptWorkaroundState(
export function usePerAppWorkarounds(
appId: string,
nonSteam: boolean,
- transport: TargetTransport = { kind: "host" },
): PerAppWorkarounds {
const [status, setStatus] = useState<WorkaroundLoadStatus>("loading");
const [snapshot, setSnapshot] = useState<WorkaroundSnapshot | null>(null);
@@ -154,12 +136,11 @@ export function usePerAppWorkarounds(
return adoptWorkaroundState(
appId,
nonSteam,
- transport,
result.wrapper_path || getDefaultWrapperPath(),
);
}
- return makeSnapshot(steam, result, nonSteam, transport);
- }, [appId, nonSteam, numericAppId, transport]);
+ return makeSnapshot(steam, result);
+ }, [appId, nonSteam, numericAppId]);
const applySnapshot = useCallback((next: WorkaroundSnapshot) => {
setSnapshot(next);
@@ -194,7 +175,7 @@ export function usePerAppWorkarounds(
setSnapshot((current) => current ? {
...current,
steam,
- integrationInstalled: isWrapperIntegrationInstalled(steam, nonSteam, current.transport, current.wrapperPath),
+ integrationInstalled: isWrapperIntegrationInstalled(steam, current.wrapperPath),
} : current);
},
(subscriptionError) => {
@@ -229,24 +210,18 @@ export function usePerAppWorkarounds(
setError(null);
const nextState = { ...current.state, [field]: value } as WorkaroundState;
try {
- const shortcutExe = current.transport.kind === "flatpak" ? current.shortcutExe ?? null : null;
const result = await setWorkaroundState(
appId,
nextState,
- shortcutExe,
current.commandTokenAdded,
- current.transport,
);
if (!result.success || !result.state) throw new Error(result.error || "Could not save workaround state");
- const selectedTransport = result.transport || current.transport;
applySnapshot({
...current,
state: result.state,
wrapperPath: result.wrapper_path || current.wrapperPath,
wrapperOwned: result.wrapper_owned === true,
- shortcutExe: selectedTransport.kind === "flatpak" ? result.shortcut_exe : undefined,
commandTokenAdded: result.command_token_added === true,
- transport: selectedTransport,
});
return true;
} catch (updateError) {
diff --git a/src/i18n/languages.json b/src/i18n/languages.json
index 7e5676b..0ee539a 100644
--- a/src/i18n/languages.json
+++ b/src/i18n/languages.json
@@ -2,7 +2,6 @@
"ja": {
"CONTENT_FPS_MULTIPLIER": "FPS倍率",
"CONTENT_NERD_STUFF": "詳細情報",
- "CONTENT_FLATPAK_SETUP": "Flatpak設定",
"MULTIPLIER_OFF": "オフ",
"CONFIG_SECTION_TITLE": "設定",
"CONFIG_WORKAROUNDS_TITLE": "互換性設定",
@@ -22,9 +21,7 @@
"CONFIG_ENABLE_WSI": "WSIを有効化",
"CONFIG_ENABLE_WSI_DESC": "Gamescope WSIレイヤーを再有効化します。ゲームの再起動が必要。",
"CONFIG_DISABLE_GAMESCOPE_WSI": "Gamescope WSIを無効化",
- "CONFIG_DISABLE_GAMESCOPE_WSI_DESC": "ENABLE_GAMESCOPE_WSI=0を追加します。ゲームの再起動が必要です。",
- "CONFIG_DISABLE_HDR": "HDRを無効化",
- "CONFIG_DISABLE_HDR_DESC": "DXVKがゲームにHDRを公開しないようにします。ゲームの再起動が必要です。",
+ "CONFIG_DISABLE_GAMESCOPE_WSI_DESC": "HDRを変更せずENABLE_GAMESCOPE_WSI=0を追加します。ゲームの再起動が必要です。",
"CONFIG_DISABLE_STEAMDECK_MODE": "Steam Deckモードを無効化",
"CONFIG_DISABLE_STEAMDECK_MODE_DESC": "ゲーム固有のSteam Deck互換スイッチを無効化します。ゲームの再起動が必要です。",
"CONFIG_DISABLE_VKBASALT": "vkBasaltを無効化",
@@ -35,28 +32,6 @@
"INSTALL_UNINSTALLING": "アンインストール中...",
"INSTALL_UNINSTALL_BTN": "LSFG-VKをアンインストール",
"INSTALL_INSTALL_BTN": "LSFG-VKをインストール",
- "FLATPAK_MODAL_TITLE": "Flatpak拡張",
- "FLATPAK_RUNTIME_INSTALLER": "ランタイム拡張インストーラー",
- "FLATPAK_RUNTIME_23": "ランタイム 23.08",
- "FLATPAK_RUNTIME_24": "ランタイム 24.08",
- "FLATPAK_RUNTIME_25": "ランタイム 25.08",
- "FLATPAK_INSTALLED": "インストール済み",
- "FLATPAK_NOT_INSTALLED": "未インストール",
- "FLATPAK_UNINSTALL_TITLE": "ランタイム拡張をアンインストール",
- "FLATPAK_UNINSTALL_CONFIRM_PREFIX": "本当に",
- "FLATPAK_UNINSTALL_CONFIRM_SUFFIX": "ランタイム拡張をアンインストールしますか?",
- "FLATPAK_UNINSTALL_BTN": "アンインストール",
- "FLATPAK_INSTALL_BTN": "インストール",
- "FLATPAK_APPS_TITLE": "Flatpakアプリケーション",
- "FLATPAK_NO_APPS": "Flatpakアプリなし",
- "FLATPAK_NO_APPS_DESC": "現在インストールされているFlatpakアプリケーションはありません",
- "FLATPAK_STATUS_CONFIGURED": "設定済み",
- "FLATPAK_STATUS_PARTIAL": "部分設定",
- "FLATPAK_STATUS_NO_OVERRIDES": "オーバーライドなし",
- "FLATPAK_ERROR": "エラー",
- "FLATPAK_ERROR_STATUS": "拡張ステータスの確認に失敗しました",
- "FLATPAK_ERROR_APPS": "Flatpakアプリケーションの読み込みに失敗しました",
- "FLATPAK_CLOSE": "閉じる",
"NERD_LOADING": "情報を読み込み中...",
"NERD_DLL_PATH": "DLLパス",
"NERD_NOT_AVAILABLE": "利用不可",
@@ -91,7 +66,6 @@
"ko": {
"CONTENT_FPS_MULTIPLIER": "FPS 배율",
"CONTENT_NERD_STUFF": "상세 정보",
- "CONTENT_FLATPAK_SETUP": "Flatpak 설정",
"MULTIPLIER_OFF": "끄기",
"CONFIG_SECTION_TITLE": "설정",
"CONFIG_WORKAROUNDS_TITLE": "호환성 설정",
@@ -111,9 +85,7 @@
"CONFIG_ENABLE_WSI": "WSI 활성화",
"CONFIG_ENABLE_WSI_DESC": "Gamescope WSI 레이어를 다시 활성화합니다. 게임 재시작 필요.",
"CONFIG_DISABLE_GAMESCOPE_WSI": "Gamescope WSI 비활성화",
- "CONFIG_DISABLE_GAMESCOPE_WSI_DESC": "ENABLE_GAMESCOPE_WSI=0을 추가합니다. 게임 재시작 필요.",
- "CONFIG_DISABLE_HDR": "HDR 비활성화",
- "CONFIG_DISABLE_HDR_DESC": "DXVK가 게임에 HDR을 노출하지 않도록 합니다. 게임 재시작 필요.",
+ "CONFIG_DISABLE_GAMESCOPE_WSI_DESC": "HDR을 변경하지 않고 ENABLE_GAMESCOPE_WSI=0을 추가합니다. 게임 재시작 필요.",
"CONFIG_DISABLE_STEAMDECK_MODE": "Steam Deck 모드 비활성화",
"CONFIG_DISABLE_STEAMDECK_MODE_DESC": "게임별 Steam Deck 호환 스위치를 비활성화합니다. 게임 재시작 필요.",
"CONFIG_DISABLE_VKBASALT": "vkBasalt 비활성화",
@@ -124,28 +96,6 @@
"INSTALL_UNINSTALLING": "제거 중...",
"INSTALL_UNINSTALL_BTN": "LSFG-VK 제거",
"INSTALL_INSTALL_BTN": "LSFG-VK 설치",
- "FLATPAK_MODAL_TITLE": "Flatpak 확장",
- "FLATPAK_RUNTIME_INSTALLER": "런타임 확장 설치",
- "FLATPAK_RUNTIME_23": "런타임 23.08",
- "FLATPAK_RUNTIME_24": "런타임 24.08",
- "FLATPAK_RUNTIME_25": "런타임 25.08",
- "FLATPAK_INSTALLED": "설치됨",
- "FLATPAK_NOT_INSTALLED": "설치 안 됨",
- "FLATPAK_UNINSTALL_TITLE": "런타임 확장 제거",
- "FLATPAK_UNINSTALL_CONFIRM_PREFIX": "정말로",
- "FLATPAK_UNINSTALL_CONFIRM_SUFFIX": "런타임 확장을 제거하시겠습니까?",
- "FLATPAK_UNINSTALL_BTN": "제거",
- "FLATPAK_INSTALL_BTN": "설치",
- "FLATPAK_APPS_TITLE": "Flatpak 애플리케이션",
- "FLATPAK_NO_APPS": "Flatpak 앱 없음",
- "FLATPAK_NO_APPS_DESC": "현재 설치된 Flatpak 애플리케이션이 없습니다",
- "FLATPAK_STATUS_CONFIGURED": "설정됨",
- "FLATPAK_STATUS_PARTIAL": "부분 설정",
- "FLATPAK_STATUS_NO_OVERRIDES": "오버라이드 없음",
- "FLATPAK_ERROR": "오류",
- "FLATPAK_ERROR_STATUS": "확장 상태 확인 실패",
- "FLATPAK_ERROR_APPS": "Flatpak 애플리케이션 로드 실패",
- "FLATPAK_CLOSE": "닫기",
"NERD_LOADING": "정보 불러오는 중...",
"NERD_DLL_PATH": "DLL 경로",
"NERD_NOT_AVAILABLE": "사용 불가",
@@ -208,7 +158,6 @@
"template": {
"CONTENT_FPS_MULTIPLIER": "FPS Multiplier",
"CONTENT_NERD_STUFF": "Nerd Stuff",
- "CONTENT_FLATPAK_SETUP": "Flatpak Setup",
"MULTIPLIER_OFF": "OFF",
"CONFIG_SECTION_TITLE": "Config",
"CONFIG_WORKAROUNDS_TITLE": "Workarounds",
@@ -228,9 +177,7 @@
"CONFIG_ENABLE_WSI": "Enable WSI",
"CONFIG_ENABLE_WSI_DESC": "Re-Enable Gamescope WSI Layer. Requires game restart to apply.",
"CONFIG_DISABLE_GAMESCOPE_WSI": "Disable Gamescope WSI",
- "CONFIG_DISABLE_GAMESCOPE_WSI_DESC": "Adds ENABLE_GAMESCOPE_WSI=0. Requires game restart to apply.",
- "CONFIG_DISABLE_HDR": "Disable HDR",
- "CONFIG_DISABLE_HDR_DESC": "Prevents DXVK from exposing HDR to the game. Requires game restart to apply.",
+ "CONFIG_DISABLE_GAMESCOPE_WSI_DESC": "Adds ENABLE_GAMESCOPE_WSI=0 without changing HDR. Requires game restart to apply.",
"CONFIG_DISABLE_STEAMDECK_MODE": "Disable Steam Deck Mode",
"CONFIG_DISABLE_STEAMDECK_MODE_DESC": "Disables a game-specific Steam Deck compatibility switch. Requires game restart to apply.",
"CONFIG_DISABLE_VKBASALT": "Disable vkBasalt",
@@ -241,28 +188,6 @@
"INSTALL_UNINSTALLING": "Uninstalling...",
"INSTALL_UNINSTALL_BTN": "Uninstall LSFG-VK",
"INSTALL_INSTALL_BTN": "Install LSFG-VK",
- "FLATPAK_MODAL_TITLE": "Flatpak Extensions",
- "FLATPAK_RUNTIME_INSTALLER": "Runtime Extension Installer",
- "FLATPAK_RUNTIME_23": "Runtime 23.08",
- "FLATPAK_RUNTIME_24": "Runtime 24.08",
- "FLATPAK_RUNTIME_25": "Runtime 25.08",
- "FLATPAK_INSTALLED": "Installed",
- "FLATPAK_NOT_INSTALLED": "Not installed",
- "FLATPAK_UNINSTALL_TITLE": "Uninstall Runtime Extension",
- "FLATPAK_UNINSTALL_CONFIRM_PREFIX": "Are you sure you want to uninstall the",
- "FLATPAK_UNINSTALL_CONFIRM_SUFFIX": "runtime extension?",
- "FLATPAK_UNINSTALL_BTN": "Uninstall",
- "FLATPAK_INSTALL_BTN": "Install",
- "FLATPAK_APPS_TITLE": "Flatpak Applications",
- "FLATPAK_NO_APPS": "No Flatpak Apps Found",
- "FLATPAK_NO_APPS_DESC": "No Flatpak applications are currently installed",
- "FLATPAK_STATUS_CONFIGURED": "Configured",
- "FLATPAK_STATUS_PARTIAL": "Partial",
- "FLATPAK_STATUS_NO_OVERRIDES": "No overrides",
- "FLATPAK_ERROR": "Error",
- "FLATPAK_ERROR_STATUS": "Failed to check extension status",
- "FLATPAK_ERROR_APPS": "Failed to load Flatpak applications",
- "FLATPAK_CLOSE": "Close",
"NERD_LOADING": "Loading information...",
"NERD_DLL_PATH": "DLL Path",
"NERD_NOT_AVAILABLE": "Not available",
diff --git a/src/types.d.ts b/src/types.d.ts
index e5db40d..ebcf32c 100644
--- a/src/types.d.ts
+++ b/src/types.d.ts
@@ -16,7 +16,6 @@ declare module "*.jpg" {
interface SteamAppDetails {
strLaunchOptions?: string;
strShortcutLaunchOptions?: string;
- strShortcutExe?: string;
strShortcutStartDir?: string;
}
@@ -31,7 +30,6 @@ interface SteamApps {
): SteamAppDetailsRegistration;
SetAppLaunchOptions(appId: number, options: string): void | Promise<void>;
SetShortcutLaunchOptions(appId: number, options: string): void | Promise<void>;
- SetShortcutExe(appId: number, executable: string): void | Promise<void>;
TerminateApp(appId: string, param1: boolean): void;
GetAllShortcuts?(): Promise<unknown[]>;
}
diff --git a/src/utils/steamLaunchOptions.ts b/src/utils/steamLaunchOptions.ts
index 82cf116..662f060 100644
--- a/src/utils/steamLaunchOptions.ts
+++ b/src/utils/steamLaunchOptions.ts
@@ -1,5 +1,3 @@
-import type { TargetTransport } from "../api/lsfgApi";
-
const DEFAULT_WRAPPER_PATH = "~/.lsfg";
const COMMAND_TOKEN = "%command%";
@@ -26,12 +24,10 @@ export interface SteamLaunchOptionsSnapshot {
appId: number;
nonSteam: boolean;
options: string;
- target: string;
details: SteamAppDetails;
}
export interface WrapperIntegrationResult {
snapshot: SteamLaunchOptionsSnapshot;
- originalExecutable?: string;
commandTokenAdded: boolean;
changed: boolean;
}
@@ -61,7 +57,6 @@ function snapshot(appId: number, nonSteam: boolean, details: SteamAppDetails): S
appId,
nonSteam,
options: nonSteam ? details.strShortcutLaunchOptions || "" : details.strLaunchOptions || "",
- target: nonSteam ? details.strShortcutExe || "" : "",
details,
};
}
@@ -162,15 +157,6 @@ const commandIndex = (tokens: readonly LaunchToken[]) => tokens.findIndex((token
const isAssignment = (token: LaunchToken) => /^[A-Za-z_][A-Za-z0-9_]*=/.test(token.value);
const isLegacyToken = (value: string) => LEGACY_WRAPPER_TOKENS.has(value) || LEGACY_ABSOLUTE_WRAPPER.test(value);
const isWrapperToken = (value: string, wrapperPath: string) => decodeToken(value) === wrapperPath || isLegacyWrapperToken(value);
-const usesShortcutTarget = (nonSteam: boolean, transport: TargetTransport) => nonSteam && transport.kind === "flatpak";
-
-function selectFlatpakExecutable(transport: TargetTransport, candidate?: string | null): string | undefined {
- if (transport.kind !== "flatpak") return 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));
export const isLegacyWrapperToken = (value: string) => isLegacyToken(decodeToken(value));
@@ -267,25 +253,9 @@ export function hasWrapperLaunchIntegration(options: string, wrapperPath = DEFAU
export function isWrapperIntegrationInstalled(
steam: SteamLaunchOptionsSnapshot,
- nonSteam: boolean,
- transport: TargetTransport,
wrapperPath = DEFAULT_WRAPPER_PATH,
): boolean {
- return usesShortcutTarget(nonSteam, transport)
- ? steam.target === wrapperPath
- : hasWrapperLaunchIntegration(steam.options, wrapperPath);
-}
-
-export function assertKnownShortcutTarget(
- steam: SteamLaunchOptionsSnapshot,
- nonSteam: boolean,
- transport: TargetTransport,
- wrapperPath: string,
- originalExecutable?: string | null,
-): void {
- if (usesShortcutTarget(nonSteam, transport) && steam.target === wrapperPath && !originalExecutable) {
- throw new Error("Managed shortcut Target has no saved original executable");
- }
+ return hasWrapperLaunchIntegration(steam.options, wrapperPath);
}
const queues = new Map<string, Promise<unknown>>();
@@ -325,18 +295,16 @@ async function writeVerified(
previous: string,
next: string,
write: (value: string) => Promise<void>,
- read: (value: SteamLaunchOptionsSnapshot) => string,
message: string,
): Promise<SteamLaunchOptionsSnapshot> {
- const normalized = read === readOptions ? normalizeLaunchOptions : (value: string) => value;
try {
await write(next);
- return await waitFor(appId, nonSteam, (value) => normalized(read(value)) === normalized(next), message);
+ return await waitFor(appId, nonSteam, (value) => normalizeLaunchOptions(value.options) === normalizeLaunchOptions(next), message);
} catch (error) {
const failure = asError(error);
try {
await write(previous);
- await waitFor(appId, nonSteam, (value) => normalized(read(value)) === normalized(previous), `Steam did not restore the previous ${read === readOptions ? "launch options" : "shortcut Target"}`);
+ await waitFor(appId, nonSteam, (value) => normalizeLaunchOptions(value.options) === normalizeLaunchOptions(previous), "Steam did not restore the previous launch options");
} catch (rollback) {
throw new Error(`${failure.message}; rollback also failed: ${asError(rollback).message}`);
}
@@ -344,19 +312,11 @@ async function writeVerified(
}
}
-const readOptions = (value: SteamLaunchOptionsSnapshot) => value.options;
-const readTarget = (value: SteamLaunchOptionsSnapshot) => value.target;
-
function writeOptions(appId: number, nonSteam: boolean, value: string): Promise<void> {
const setter = nonSteam ? apps()?.SetShortcutLaunchOptions : apps()?.SetAppLaunchOptions;
if (!setter) return Promise.reject(new Error(`Steam ${nonSteam ? "shortcut " : ""}launch options API is unavailable`));
return Promise.resolve(setter.call(apps(), appId, value));
}
-function writeTarget(appId: number, value: string): Promise<void> {
- const setter = apps()?.SetShortcutExe;
- if (!setter) return Promise.reject(new Error("Steam shortcut Target API is unavailable"));
- return Promise.resolve(setter.call(apps(), appId, value));
-}
export function updateSteamLaunchOptions(
appId: number,
@@ -368,7 +328,7 @@ export function updateSteamLaunchOptions(
const next = transform(current.options);
return next === current.options ? current : writeVerified(
appId, nonSteam, current.options, next,
- (value) => writeOptions(appId, nonSteam, value), readOptions,
+ (value) => writeOptions(appId, nonSteam, value),
"Steam did not accept the launch options",
);
});
@@ -379,52 +339,16 @@ export function installWrapperIntegration(
nonSteam: boolean,
wrapperPath: string,
commandTokenAdded = false,
- transport: TargetTransport = { kind: "host" },
- originalExecutable?: string,
): Promise<WrapperIntegrationResult> {
return queued(appId, nonSteam, async () => {
- let current = await readSteamLaunchOptions(appId, nonSteam);
- if (usesShortcutTarget(nonSteam, transport)) {
- if (!current.target) throw new Error("Steam shortcut Target is empty; refusing to replace it");
- if (current.target !== wrapperPath && isWrapperToken(current.target, wrapperPath)) {
- throw new Error("The shortcut Target points to a legacy frame-generation wrapper; restore it first");
- }
- const cleaned = cleanupPluginLaunchOptions(current.options, wrapperPath);
- const launchOptionsChanged = cleaned !== current.options;
- if (launchOptionsChanged) {
- current = await writeVerified(
- appId, true, current.options, cleaned,
- (value) => writeOptions(appId, true, value), readOptions,
- "Steam did not accept shortcut launch options",
- );
- }
- const savedOriginal = selectFlatpakExecutable(transport, originalExecutable);
- if (current.target === wrapperPath) {
- if (!savedOriginal) throw new Error("Managed shortcut Target has no saved original executable");
- return { snapshot: current, originalExecutable: savedOriginal, commandTokenAdded: false, changed: launchOptionsChanged };
- }
- if (savedOriginal && selectFlatpakExecutable(transport, current.target) !== savedOriginal) {
- 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,
- "Steam did not accept the shortcut Target",
- );
- return { snapshot: value, originalExecutable: currentOriginal, commandTokenAdded: false, changed: true };
- }
-
+ const current = await readSteamLaunchOptions(appId, nonSteam);
const cleaned = cleanupPluginAssignments(cleanupLegacyLaunchOptions(current.options));
const alreadyInstalled = hasWrapperLaunchIntegration(current.options, wrapperPath);
const rewrite = installLaunchOption(cleaned, wrapperPath, nonSteam);
if (rewrite.options === current.options) return { snapshot: current, commandTokenAdded, changed: false };
const value = await writeVerified(
appId, nonSteam, current.options, rewrite.options,
- (options) => writeOptions(appId, nonSteam, options), readOptions,
+ (options) => writeOptions(appId, nonSteam, options),
"Steam did not accept the launch options",
);
return { snapshot: value, commandTokenAdded: alreadyInstalled ? commandTokenAdded : rewrite.commandTokenAdded, changed: true };
@@ -435,43 +359,14 @@ export function removeWrapperIntegration(
appId: number,
nonSteam: boolean,
wrapperPath: string,
- originalExecutable?: string,
commandTokenAdded = false,
- transport: TargetTransport = { kind: "host" },
): Promise<SteamLaunchOptionsSnapshot> {
return queued(appId, nonSteam, async () => {
- let current = await readSteamLaunchOptions(appId, nonSteam);
- if (usesShortcutTarget(nonSteam, transport)) {
- const cleaned = cleanupPluginLaunchOptions(current.options, wrapperPath);
- if (cleaned !== current.options) {
- current = await writeVerified(
- appId, true, current.options, cleaned,
- (value) => writeOptions(appId, true, value), readOptions,
- "Steam did not clean shortcut launch options",
- );
- }
- if (current.target !== wrapperPath) {
- if (isWrapperToken(current.target, wrapperPath)) {
- throw new Error("Original shortcut Target is unavailable; refusing to overwrite the current Target");
- }
- if (originalExecutable && selectFlatpakExecutable(transport, current.target) !== selectFlatpakExecutable(transport, originalExecutable)) {
- throw new Error("Shortcut Target changed externally; refusing to restore it");
- }
- return current;
- }
- if (!originalExecutable || isWrapperToken(originalExecutable, wrapperPath)) {
- throw new Error("Original shortcut Target is unavailable; refusing to overwrite the current Target");
- }
- return writeVerified(
- appId, true, wrapperPath, originalExecutable,
- (target) => writeTarget(appId, target), readTarget,
- "Steam did not restore the shortcut Target",
- );
- }
+ const current = await readSteamLaunchOptions(appId, nonSteam);
const next = cleanupPluginAssignments(removeWrapperLaunchOption(current.options, wrapperPath, commandTokenAdded));
return next === current.options ? current : writeVerified(
appId, nonSteam, current.options, next,
- (options) => writeOptions(appId, nonSteam, options), readOptions,
+ (options) => writeOptions(appId, nonSteam, options),
"Steam did not clean the launch options",
);
});