From de74f0d2499159ed1cf8f628a166302146ae1f13 Mon Sep 17 00:00:00 2001 From: xXJSONDeruloXx Date: Thu, 10 Sep 2026 12:58:44 -0400 Subject: fix flatpak disable leftovers --- src/api/lsfgApi.ts | 14 +++++ src/components/ConfigFileTab.tsx | 119 +++++++++++++++++++++++++++++------- src/components/ConfigurationTab.tsx | 50 +++++++++------ src/components/Content.tsx | 34 ++++++++++- 4 files changed, 177 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/api/lsfgApi.ts b/src/api/lsfgApi.ts index b96acec..567e1ae 100644 --- a/src/api/lsfgApi.ts +++ b/src/api/lsfgApi.ts @@ -105,6 +105,19 @@ export interface FileContentResult extends ApiResult { path?: string; } +export interface DebugFileContent { + id: string; + label: string; + path: string; + exists: boolean; + content?: string | null; + error?: string | null; +} + +export interface DebugFileContentsResult extends ApiResult { + files?: DebugFileContent[]; +} + export interface FlatpakExtensionStatus extends ApiResult { message: string; available: boolean; @@ -143,3 +156,4 @@ export const setWorkaroundState = callable<[ TargetTransport | null | undefined, ], 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/ConfigFileTab.tsx b/src/components/ConfigFileTab.tsx index e3cc09d..07408d7 100644 --- a/src/components/ConfigFileTab.tsx +++ b/src/components/ConfigFileTab.tsx @@ -1,13 +1,79 @@ +import { ButtonItem, Field, PanelSection, PanelSectionRow, Spinner } from "@decky/ui"; import { useEffect, useState } from "react"; -import { Field, PanelSection, PanelSectionRow, Spinner } from "@decky/ui"; -import { getConfigFileContent, FileContentResult } from "../api/lsfgApi"; +import { RiArrowDownSFill, RiArrowUpSFill } from "react-icons/ri"; +import { getDebugFileContents, type DebugFileContent, type DebugFileContentsResult } from "../api/lsfgApi"; import t from "../i18n/i18n"; +function usePersistentCollapsed(key: string) { + const [collapsed, setCollapsed] = useState(() => { + try { + return localStorage.getItem(key) !== "false"; + } catch { + return true; + } + }); + + useEffect(() => { + try { + localStorage.setItem(key, String(collapsed)); + } catch { + // Persisting the view preference is optional. + } + }, [collapsed, key]); + + return [collapsed, () => setCollapsed((value) => !value)] as const; +} + +function DebugFileSection({ file }: { file: DebugFileContent }) { + const [collapsed, toggleCollapsed] = usePersistentCollapsed(`lsfg-debug-file-${file.id}-collapsed-v1`); + const status = file.exists ? "Present" : "Not present"; + + return ( + <> + + + + +
+ + {collapsed ? : } + +
+
+ {!collapsed && ( + + {file.exists && file.content !== null && file.content !== undefined ? ( +
+              {file.content}
+            
+ ) : ( + + )} +
+ )} + + ); +} + export function ConfigFileTab() { - const [result, setResult] = useState(null); + const [result, setResult] = useState(null); useEffect(() => { - getConfigFileContent().then(setResult).catch((error) => { + getDebugFileContents().then(setResult).catch((error) => { setResult({ success: false, error: String(error) }); }); }, []); @@ -23,24 +89,35 @@ export function ConfigFileTab() { } return ( - - {result.error && ( - - - - )} - {result.success && result.content && ( - <> - - - + <> + + + {result.error && ( -
-              {result.content}
-            
+
- - )} -
+ )} + {result.success && result.files?.map((file) => ( + + ))} +
+ ); } diff --git a/src/components/ConfigurationTab.tsx b/src/components/ConfigurationTab.tsx index 5ae4a87..4e2d93d 100644 --- a/src/components/ConfigurationTab.tsx +++ b/src/components/ConfigurationTab.tsx @@ -1,4 +1,4 @@ -import { ButtonItem, ConfirmModal, DialogButton, Focusable, PanelSection, PanelSectionRow, gamepadDialogClasses, showModal } from "@decky/ui"; +import { ButtonItem, ConfirmModal, DialogButton, Focusable, PanelSection, PanelSectionRow, ToggleField, gamepadDialogClasses, showModal } from "@decky/ui"; import { useCallback, useEffect, useRef, useState } from "react"; import { FaArrowLeft } from "react-icons/fa"; import { ConfigurationData } from "../config/configSchema"; @@ -11,6 +11,8 @@ interface ConfigurationTabProps { config: ConfigurationData; targets: GameTarget[]; runningGame: GameTarget | null; + showDebugTab: boolean; + onShowDebugTabChange: (value: boolean) => void; onSelect: (appid: string) => void; onConfigChange: (fieldName: keyof ConfigurationData, value: boolean | number | string | string[]) => Promise; onEnable: (appid: string) => Promise; @@ -24,6 +26,8 @@ export function ConfigurationTab({ config, targets, runningGame, + showDebugTab, + onShowDebugTabChange, onSelect, onConfigChange, onEnable, @@ -63,22 +67,34 @@ export function ConfigurationTab({ if (detailAppId === null) { return ( - - { - setFocusConfiguredToggle(false); - setFocusDetailAction(targets.find((target) => target.appid === appid)?.configured ? "fps" : "enable"); - onSelect(appid); - setDetailAppId(appid); - }} - onEnableAll={onEnableAll} - onResetAll={onResetAll} - focusConfiguredToggle={focusConfiguredToggle} - onConfiguredToggleFocused={clearConfiguredToggleFocusRequest} - /> - + <> + + { + setFocusConfiguredToggle(false); + setFocusDetailAction(targets.find((target) => target.appid === appid)?.configured ? "fps" : "enable"); + onSelect(appid); + setDetailAppId(appid); + }} + onEnableAll={onEnableAll} + onResetAll={onResetAll} + focusConfiguredToggle={focusConfiguredToggle} + onConfiguredToggleFocused={clearConfiguredToggleFocusRequest} + /> + + + + + + + ); } diff --git a/src/components/Content.tsx b/src/components/Content.tsx index 578f984..43720c0 100644 --- a/src/components/Content.tsx +++ b/src/components/Content.tsx @@ -17,6 +17,29 @@ const tabIcons = { setup: , }; +const DEBUG_TAB_VISIBILITY_KEY = "lsfg-debug-tab-visible-v1"; + +function usePersistentBoolean(key: string, defaultValue: boolean) { + const [value, setValue] = useState(() => { + try { + const stored = localStorage.getItem(key); + return stored === null ? defaultValue : stored === "true"; + } catch { + return defaultValue; + } + }); + + useEffect(() => { + try { + localStorage.setItem(key, String(value)); + } catch { + // Persisting the visibility preference is optional. + } + }, [key, value]); + + return [value, setValue] as const; +} + export function Content() { const { config, @@ -43,6 +66,7 @@ export function Content() { uninstall, } = useInstallation(reload); const [tab, setTab] = useState("Setup"); + const [showDebugTab, setShowDebugTab] = usePersistentBoolean(DEBUG_TAB_VISIBILITY_KEY, true); const previousRunningAppId = useRef(null); const setupComplete = isInstalled && @@ -74,6 +98,10 @@ export function Content() { if (isInstalled) void reload(); }, [isInstalled, reload]); + useEffect(() => { + if (!showDebugTab && tab === "ConfigFile") setTab("Games"); + }, [showDebugTab, tab]); + const handleConfigChange = async ( fieldName: keyof ConfigurationData, value: boolean | number | string | string[], @@ -116,6 +144,8 @@ export function Content() { config={config} targets={targets} runningGame={runningGame} + showDebugTab={showDebugTab} + onShowDebugTabChange={setShowDebugTab} onSelect={setSelectedAppId} onConfigChange={(field, value) => handleConfigChange(field, value, true)} onEnable={enable} @@ -126,7 +156,7 @@ export function Content() { /> ), }, - { id: "ConfigFile", title: tabIcons.configFile, content: }, + ...(showDebugTab ? [{ id: "ConfigFile", title: tabIcons.configFile, content: }] : []), { id: "Setup", title: tabIcons.setup, content: setup }, ] : [{ id: "Setup", title: tabIcons.setup, content: setup }]; @@ -137,7 +167,7 @@ export function Content() { style={{ height: "95%", width: "300px", position: "fixed", marginTop: "-12px", overflow: "hidden" }} > - + ); } -- cgit v1.2.3