From 485ebb748185391e28764f48c39322b3cbdac65c Mon Sep 17 00:00:00 2001 From: xXJSONDeruloXx Date: Thu, 10 Sep 2026 16:26:17 -0400 Subject: refactor: remove Flatpak support --- src/api/lsfgApi.ts | 44 +--------- src/components/ConfigurationTab.tsx | 22 +---- src/components/Content.tsx | 1 - src/components/GameConfigurationControls.tsx | 3 +- src/components/GameConfigurationSelector.tsx | 3 +- src/components/NowPlayingTab.tsx | 36 +------- src/components/WorkaroundsSection.tsx | 6 +- src/hooks/useGameConfiguration.ts | 44 ++-------- src/hooks/usePerAppWorkarounds.ts | 35 ++------ src/i18n/languages.json | 81 +----------------- src/types.d.ts | 2 - src/utils/steamLaunchOptions.ts | 121 ++------------------------- 12 files changed, 30 insertions(+), 368 deletions(-) (limited to 'src') 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({ )} - {selectedTarget?.configured && selectedTarget.transport.kind === "flatpak" && selectedTarget.flatpakSupport?.support_status !== "ready" && ( - - - void onRepair(selectedTarget.appid)} - > - Repair Flatpak support - - - - )} {selectedTarget?.configured && ( 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; + workaroundTarget?: Pick; onRepairWorkaround?: () => Promise; } @@ -36,7 +36,6 @@ export function GameConfigurationControls({ )} 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( 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; - onRepair: (appid: string) => Promise; } 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 ( @@ -47,21 +28,6 @@ export function NowPlayingTab({ - {supportNeedsRepair && ( - - - - - - void handleRepair()}> - {busy ? "Repairing..." : "Repair Flatpak support"} - - - - )} Promise; } @@ -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 { 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(() => { 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 => { - 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 => { 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 => { 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 => { 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>, - 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 { let integration: Awaited> | 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("loading"); const [snapshot, setSnapshot] = useState(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; SetShortcutLaunchOptions(appId: number, options: string): void | Promise; - SetShortcutExe(appId: number, executable: string): void | Promise; TerminateApp(appId: string, param1: boolean): void; GetAllShortcuts?(): Promise; } 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>(); @@ -325,18 +295,16 @@ async function writeVerified( previous: string, next: string, write: (value: string) => Promise, - read: (value: SteamLaunchOptionsSnapshot) => string, message: string, ): Promise { - 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 { 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 { - 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 { 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 { 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", ); }); -- cgit v1.2.3