summaryrefslogtreecommitdiff
path: root/src/components/Content.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/Content.tsx')
-rw-r--r--src/components/Content.tsx181
1 files changed, 117 insertions, 64 deletions
diff --git a/src/components/Content.tsx b/src/components/Content.tsx
index 1d7d2d1..ce3c018 100644
--- a/src/components/Content.tsx
+++ b/src/components/Content.tsx
@@ -1,81 +1,118 @@
import { Tabs } from "@decky/ui";
import { useEffect, useRef, useState } from "react";
-import { FaFileAlt, FaGamepad, FaLayerGroup, FaList, FaTools } from "react-icons/fa";
+import { FaCube, FaFileAlt, FaGamepad, FaList, FaTools } from "react-icons/fa";
import { ConfigurationData } from "../config/configSchema";
-import { tabStyles } from "../styles";
+import { useFlatpakConfiguration } from "../hooks/useFlatpakConfiguration";
import { useGameConfiguration } from "../hooks/useGameConfiguration";
-import { useInstallationActions } from "../hooks/useInstallationActions";
-import { useInstallationStatus } from "../hooks/useLsfgHooks";
+import { useInstallation } from "../hooks/useLsfgHooks";
+import { tabStyles } from "../styles";
import { ConfigFileTab } from "./ConfigFileTab";
import { ConfigurationTab } from "./ConfigurationTab";
-import { FlatpaksTab } from "./FlatpaksTab";
+import { FlatpakNowPlayingTab } from "./FlatpakNowPlayingTab";
+import { FlatpakTab } from "./FlatpakTab";
import { NowPlayingTab } from "./NowPlayingTab";
import { SetupTab } from "./SetupTab";
const tabIcons = {
nowPlaying: <FaGamepad size={18} />,
- configuration: <FaList size={18} />,
- flatpak: <FaLayerGroup size={18} />,
+ games: <FaList size={18} />,
+ flatpak: <FaCube size={18} />,
configFile: <FaFileAlt size={18} />,
setup: <FaTools size={18} />,
};
+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 {}
+ }, [key, value]);
+
+ return [value, setValue] as const;
+}
+
export function Content() {
const {
- isInstalled,
- installationStatus,
- setIsInstalled,
- setInstallationStatus,
- losslessScalingInstalled,
- losslessScalingStatus,
- steamBranchStatus,
- checkInstallation,
- } = useInstallationStatus();
- const {
config,
+ runningConfig,
targets,
runningGame,
setSelectedAppId,
save,
+ saveFor,
enable,
enableAll,
+ repair,
resetSelected,
resetAll,
reload,
} = useGameConfiguration();
- const { isInstalling, isUninstalling, handleInstall, handleUninstall } = useInstallationActions();
- const [tab, setTab] = useState("Setup");
+ const {
+ isInstalled,
+ installationStatus,
+ losslessScalingInstalled,
+ losslessScalingStatus,
+ steamBranchStatus,
+ isInstalling,
+ isUninstalling,
+ install,
+ uninstall,
+ } = useInstallation(reload);
const setupComplete =
isInstalled &&
losslessScalingInstalled &&
steamBranchStatus?.success === true &&
steamBranchStatus.installed &&
!steamBranchStatus.needs_switch;
- const previousRunningState = useRef<{ appid: string; configured: boolean } | null>(null);
+ const flatpak = useFlatpakConfiguration(setupComplete);
+ const [tab, setTab] = useState("Setup");
+ const [showDebugTab, setShowDebugTab] = usePersistentBoolean(DEBUG_TAB_VISIBILITY_KEY, true);
+ const previousRunningWorkload = useRef<string | null>(null);
+ const runningFlatpak = flatpak.runningApp;
+ const hasNowPlaying = Boolean(runningGame?.configured || runningFlatpak);
+ const runningWorkload = runningGame?.configured
+ ? `steam:${runningGame.appid}`
+ : runningFlatpak ? `flatpak:${runningFlatpak.app_id}` : null;
useEffect(() => {
if (!setupComplete) {
setTab("Setup");
return;
}
- setTab((current) => current === "Setup" ? (runningGame?.configured ? "NowPlaying" : "Configuration") : current);
- }, [runningGame?.configured, setupComplete]);
+ setTab((current) => current === "Setup" ? (hasNowPlaying ? "NowPlaying" : "Games") : current);
+ }, [hasNowPlaying, setupComplete]);
useEffect(() => {
if (!setupComplete) return;
- const current = runningGame ? { appid: runningGame.appid, configured: runningGame.configured } : null;
- const previous = previousRunningState.current;
- previousRunningState.current = current;
- if (current?.appid && (current.appid !== previous?.appid || current.configured !== previous?.configured)) {
- setTab(current.configured ? "NowPlaying" : "Configuration");
- } else if (!current && previous) {
- setTab((currentTab) => currentTab === "NowPlaying" ? "Configuration" : currentTab);
+ const previous = previousRunningWorkload.current;
+ previousRunningWorkload.current = runningWorkload;
+ if (runningWorkload && runningWorkload !== previous) setTab("NowPlaying");
+ else if (!runningWorkload && previous) {
+ setTab((current) => current === "NowPlaying" ? "Games" : current);
+ }
+ }, [runningWorkload, setupComplete]);
+
+ useEffect(() => {
+ if (isInstalled) {
+ void reload();
+ void flatpak.reload();
}
- }, [runningGame?.appid, runningGame?.configured, setupComplete]);
+ }, [isInstalled, reload, flatpak.reload]);
useEffect(() => {
- if (isInstalled) void reload();
- }, [isInstalled, reload]);
+ if (!showDebugTab && tab === "ConfigFile") setTab("Games");
+ }, [showDebugTab, tab]);
const handleConfigChange = async (
fieldName: keyof ConfigurationData,
@@ -85,15 +122,7 @@ export function Content() {
await save({ ...config, [fieldName]: value }, cleanupLaunchOptions);
};
- const onInstall = () => {
- void handleInstall(setIsInstalled, setInstallationStatus, reload, checkInstallation);
- };
-
- const onUninstall = () => {
- void handleUninstall(setIsInstalled, setInstallationStatus, checkInstallation);
- };
-
- const setupContent = (
+ const setup = (
<SetupTab
isInstalled={isInstalled}
installationStatus={installationStatus}
@@ -102,48 +131,72 @@ export function Content() {
steamBranchStatus={steamBranchStatus}
isInstalling={isInstalling}
isUninstalling={isUninstalling}
- onInstall={onInstall}
- onUninstall={onUninstall}
+ onInstall={() => void install()}
+ onUninstall={() => void uninstall()}
/>
);
+ const nowPlaying = runningGame?.configured ? (
+ <NowPlayingTab
+ game={runningGame}
+ config={runningConfig}
+ onConfigChange={async (field, value) => {
+ await saveFor(runningGame.appid, { ...runningConfig, [field]: value }, true);
+ }}
+ />
+ ) : runningFlatpak ? (
+ <FlatpakNowPlayingTab
+ app={runningFlatpak}
+ busy={flatpak.busyAppId === runningFlatpak.app_id}
+ onConfigChange={flatpak.updateConfig}
+ onWorkaroundChange={flatpak.updateWorkarounds}
+ />
+ ) : null;
+
const tabs = setupComplete
? [
- ...(runningGame?.configured ? [{
- id: "NowPlaying",
- title: tabIcons.nowPlaying,
- content: (
- <NowPlayingTab
- game={runningGame}
- config={config}
- onConfigChange={(fieldName, value) => handleConfigChange(fieldName, value)}
- />
- ),
- }] : []),
+ ...(nowPlaying ? [{ id: "NowPlaying", title: tabIcons.nowPlaying, content: nowPlaying }] : []),
{
- id: "Configuration",
- title: tabIcons.configuration,
+ id: "Games",
+ title: tabIcons.games,
content: (
<ConfigurationTab
config={config}
targets={targets}
runningGame={runningGame}
+ showDebugTab={showDebugTab}
+ onShowDebugTabChange={setShowDebugTab}
onSelect={setSelectedAppId}
- onConfigChange={(fieldName, value) => handleConfigChange(fieldName, value, true)}
+ onConfigChange={(field, value) => handleConfigChange(field, value, true)}
onEnable={enable}
onEnableAll={enableAll}
+ onRepair={repair}
onReset={resetSelected}
onResetAll={resetAll}
/>
),
},
- { id: "Flatpak", title: tabIcons.flatpak, content: <FlatpaksTab /> },
- { id: "ConfigFile", title: tabIcons.configFile, content: <ConfigFileTab /> }, // comment out for prod
- { id: "Setup", title: tabIcons.setup, content: setupContent },
+ {
+ id: "Flatpak",
+ title: tabIcons.flatpak,
+ content: (
+ <FlatpakTab
+ apps={flatpak.apps}
+ runningApp={runningFlatpak}
+ loading={flatpak.loading}
+ busyAppId={flatpak.busyAppId}
+ onRefresh={flatpak.reload}
+ onEnable={flatpak.enableApp}
+ onRemove={flatpak.removeApp}
+ onConfigChange={flatpak.updateConfig}
+ onWorkaroundChange={flatpak.updateWorkarounds}
+ />
+ ),
+ },
+ ...(showDebugTab ? [{ id: "ConfigFile", title: tabIcons.configFile, content: <ConfigFileTab /> }] : []),
+ { id: "Setup", title: tabIcons.setup, content: setup },
]
- : [
- { id: "Setup", title: tabIcons.setup, content: setupContent },
- ];
+ : [{ id: "Setup", title: tabIcons.setup, content: setup }];
return (
<div
@@ -151,7 +204,7 @@ export function Content() {
style={{ height: "95%", width: "300px", position: "fixed", marginTop: "-12px", overflow: "hidden" }}
>
<style>{tabStyles}</style>
- <Tabs activeTab={tab} onShowTab={setTab} tabs={tabs} />
+ <Tabs activeTab={!showDebugTab && tab === "ConfigFile" ? "Games" : tab} onShowTab={setTab} tabs={tabs} />
</div>
);
}