summaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
authorKurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com>2026-09-10 07:24:05 -0400
committerKurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com>2026-09-10 07:24:05 -0400
commit450d3e5e6612d467a00bb937538fded640c66ecb (patch)
tree3c07ceac1474e8e2211f64928a01f6a3aaa67bda /src/components
parent28ebc17785a8cca52f289b74261d1f310fd35904 (diff)
downloaddecky-lsfg-vk-450d3e5e6612d467a00bb937538fded640c66ecb.tar.gz
decky-lsfg-vk-450d3e5e6612d467a00bb937538fded640c66ecb.zip
refactor: simplify migration implementation
Diffstat (limited to 'src/components')
-rw-r--r--src/components/Content.tsx73
-rw-r--r--src/components/InstallationButton.tsx38
-rw-r--r--src/components/SetupTab.tsx145
-rw-r--r--src/components/StatusDisplay.tsx41
-rw-r--r--src/components/index.ts2
5 files changed, 111 insertions, 188 deletions
diff --git a/src/components/Content.tsx b/src/components/Content.tsx
index d4f54e9..d92ef86 100644
--- a/src/components/Content.tsx
+++ b/src/components/Content.tsx
@@ -2,12 +2,11 @@ import { Tabs } from "@decky/ui";
import { useEffect, useRef, useState } from "react";
import { FaFileAlt, FaGamepad, FaList, FaTools } from "react-icons/fa";
import { ConfigurationData } from "../config/configSchema";
-import { tabStyles } from "../styles";
import { useGameConfiguration } from "../hooks/useGameConfiguration";
-import { useInstallationActions } from "../hooks/useInstallationActions";
-import { useInstallationStatus } from "../hooks/useLsfgHooks";
-import { ConfigurationTab } from "./ConfigurationTab";
+import { useInstallation } from "../hooks/useLsfgHooks";
+import { tabStyles } from "../styles";
import { ConfigFileTab } from "./ConfigFileTab";
+import { ConfigurationTab } from "./ConfigurationTab";
import { NowPlayingTab } from "./NowPlayingTab";
import { SetupTab } from "./SetupTab";
@@ -20,16 +19,6 @@ const tabIcons = {
export function Content() {
const {
- isInstalled,
- installationStatus,
- setIsInstalled,
- setInstallationStatus,
- losslessScalingInstalled,
- losslessScalingStatus,
- steamBranchStatus,
- checkInstallation,
- } = useInstallationStatus();
- const {
config,
targets,
runningGame,
@@ -42,15 +31,25 @@ export function Content() {
resetAll,
reload,
} = useGameConfiguration();
- const { isInstalling, isUninstalling, handleInstall, handleUninstall } = useInstallationActions();
+ const {
+ isInstalled,
+ installationStatus,
+ losslessScalingInstalled,
+ losslessScalingStatus,
+ steamBranchStatus,
+ isInstalling,
+ isUninstalling,
+ install,
+ uninstall,
+ } = useInstallation(reload);
const [tab, setTab] = useState("Setup");
+ const previousRunningAppId = useRef<string | null>(null);
const setupComplete =
isInstalled &&
losslessScalingInstalled &&
steamBranchStatus?.success === true &&
steamBranchStatus.installed &&
!steamBranchStatus.needs_switch;
- const previousRunningAppId = useRef<string | null>(null);
useEffect(() => {
if (!setupComplete) {
@@ -65,10 +64,9 @@ export function Content() {
const appid = runningGame?.appid || null;
const previous = previousRunningAppId.current;
previousRunningAppId.current = appid;
- if (appid && appid !== previous) {
- setTab("NowPlaying");
- } else if (!appid && previous) {
- setTab((currentTab) => currentTab === "NowPlaying" ? "Games" : currentTab);
+ if (appid && appid !== previous) setTab("NowPlaying");
+ else if (!appid && previous) {
+ setTab((current) => current === "NowPlaying" ? "Games" : current);
}
}, [runningGame?.appid, runningGame?.configured, setupComplete]);
@@ -80,19 +78,9 @@ export function Content() {
fieldName: keyof ConfigurationData,
value: boolean | number | string | string[],
cleanupLaunchOptions = false,
- ) => {
- await save({ ...config, [fieldName]: value }, cleanupLaunchOptions);
- };
-
- const onInstall = () => {
- void handleInstall(setIsInstalled, setInstallationStatus, reload, checkInstallation);
- };
-
- const onUninstall = () => {
- void handleUninstall(setIsInstalled, setInstallationStatus, checkInstallation);
- };
+ ) => save({ ...config, [fieldName]: value }, cleanupLaunchOptions);
- const setupContent = (
+ const setup = (
<SetupTab
isInstalled={isInstalled}
installationStatus={installationStatus}
@@ -101,8 +89,9 @@ export function Content() {
steamBranchStatus={steamBranchStatus}
isInstalling={isInstalling}
isUninstalling={isUninstalling}
- onInstall={onInstall}
- onUninstall={onUninstall}
+ onInstall={() => void install()}
+ onUninstall={() => void uninstall()}
+ flatpakRelevant={targets.some((target) => target.transport.kind === "flatpak")}
/>
);
@@ -115,7 +104,7 @@ export function Content() {
<NowPlayingTab
game={runningGame}
config={config}
- onConfigChange={(fieldName, value) => handleConfigChange(fieldName, value)}
+ onConfigChange={(field, value) => handleConfigChange(field, value)}
onEnable={enable}
onRepair={repair}
/>
@@ -130,7 +119,7 @@ export function Content() {
targets={targets}
runningGame={runningGame}
onSelect={setSelectedAppId}
- onConfigChange={(fieldName, value) => handleConfigChange(fieldName, value, true)}
+ onConfigChange={(field, value) => handleConfigChange(field, value, true)}
onEnable={enable}
onEnableAll={enableAll}
onRepair={repair}
@@ -139,16 +128,10 @@ export function Content() {
/>
),
},
- {
- id: "ConfigFile",
- title: tabIcons.configFile,
- content: <ConfigFileTab />,
- },
- { id: "Setup", title: tabIcons.setup, content: setupContent },
+ { 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
diff --git a/src/components/InstallationButton.tsx b/src/components/InstallationButton.tsx
deleted file mode 100644
index 1bf10ac..0000000
--- a/src/components/InstallationButton.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import { ButtonItem, PanelSectionRow } from "@decky/ui";
-import t from '../i18n/i18n';
-
-interface InstallationButtonProps {
- isInstalled: boolean;
- isInstalling: boolean;
- isUninstalling: boolean;
- onInstall: () => void;
- onUninstall: () => void;
-}
-
-export function InstallationButton({
- isInstalled,
- isInstalling,
- isUninstalling,
- onInstall,
- onUninstall
-}: InstallationButtonProps) {
- const label = isInstalling
- ? t('INSTALL_INSTALLING', 'Installing...')
- : isUninstalling
- ? t('INSTALL_UNINSTALLING', 'Uninstalling...')
- : isInstalled
- ? t('INSTALL_UNINSTALL_BTN', 'Uninstall LSFG-VK')
- : t('INSTALL_INSTALL_BTN', 'Install LSFG-VK');
-
- return (
- <PanelSectionRow>
- <ButtonItem
- layout="below"
- onClick={isInstalled ? onUninstall : onInstall}
- disabled={isInstalling || isUninstalling}
- >
- {label}
- </ButtonItem>
- </PanelSectionRow>
- );
-}
diff --git a/src/components/SetupTab.tsx b/src/components/SetupTab.tsx
index 6bf1fad..e936049 100644
--- a/src/components/SetupTab.tsx
+++ b/src/components/SetupTab.tsx
@@ -1,4 +1,4 @@
-import { Field, PanelSection, PanelSectionRow, ToggleField } from "@decky/ui";
+import { ButtonItem, Field, PanelSection, PanelSectionRow, ToggleField } from "@decky/ui";
import { useEffect, useState } from "react";
import {
getFlatpakSupportStatus,
@@ -6,8 +6,7 @@ import {
type FlatpakExtensionStatus,
type SteamBranchStatus,
} from "../api/lsfgApi";
-import { InstallationButton } from "./InstallationButton";
-import { StatusDisplay } from "./StatusDisplay";
+import t from "../i18n/i18n";
import { showErrorToast } from "../utils/toastUtils";
interface SetupTabProps {
@@ -20,10 +19,12 @@ interface SetupTabProps {
isUninstalling: boolean;
onInstall: () => void;
onUninstall: () => void;
+ flatpakRelevant: boolean;
}
-function FlatpakSupportDiagnostics() {
+function FlatpakSupportDiagnostics({ relevant }: { relevant: boolean }) {
const [status, setStatus] = useState<FlatpakExtensionStatus | null>(null);
+ const [advanced, setAdvanced] = useState(false);
const [operation, setOperation] = useState<string | null>(null);
const refresh = async () => {
@@ -43,16 +44,15 @@ function FlatpakSupportDiagnostics() {
};
useEffect(() => {
- void refresh();
- }, []);
+ if (relevant) void refresh();
+ }, [relevant]);
- if (!status?.available) return null;
+ if (!relevant || !status?.available) return null;
- const runExtensionOperation = async (version: string, enabled: boolean) => {
- const operationKey = `${enabled ? "enable" : "disable"}-${version}`;
- setOperation(operationKey);
+ const setEnabled = async (branch: string, enabled: boolean) => {
+ setOperation(`${enabled ? "enable" : "disable"}-${branch}`);
try {
- const result = await setFlatpakExtensionEnabled(version, enabled);
+ const result = await setFlatpakExtensionEnabled(branch, enabled);
if (!result.success) throw new Error(result.error || result.message || "Flatpak runtime update failed");
await refresh();
} catch (error) {
@@ -62,70 +62,91 @@ function FlatpakSupportDiagnostics() {
}
};
- const handleExtensionToggle = (version: string, enabled: boolean) => {
- void runExtensionOperation(version, enabled);
- };
-
return (
- <PanelSection title="Flatpak runtimes">
+ <PanelSection title="Flatpak support">
<PanelSectionRow>
<Field
- label="LSFG-VK runtime extensions"
- description={status.message || "Toggle a branch to install or uninstall it."}
+ label="Runtime extension support"
+ description={status.message || "Flatpak is available for classified targets."}
/>
</PanelSectionRow>
- {status.supported_branches.map((branch) => (
- <PanelSectionRow key={branch}>
- <ToggleField
- label={branch}
- description={
- operation === `enable-${branch}`
- ? "Installing..."
- : operation === `disable-${branch}`
- ? "Uninstalling..."
- : status.installed_branches.includes(branch)
- ? "Installed"
- : "Not installed"
- }
- checked={status.installed_branches.includes(branch)}
- onChange={(enabled) => handleExtensionToggle(branch, enabled)}
- disabled={operation !== null}
- />
- </PanelSectionRow>
- ))}
+ <PanelSectionRow>
+ <ButtonItem layout="below" onClick={() => setAdvanced((value) => !value)}>
+ {advanced ? "Hide runtime details" : "Show runtime details"}
+ </ButtonItem>
+ </PanelSectionRow>
+ {advanced && status.supported_branches.map((branch) => {
+ const installed = status.installed_branches.includes(branch);
+ const pending = operation?.endsWith(`-${branch}`);
+ return (
+ <PanelSectionRow key={branch}>
+ <ToggleField
+ label={branch}
+ description={pending ? (operation?.startsWith("enable") ? "Installing..." : "Uninstalling...") : installed ? "Installed" : "Not installed"}
+ checked={installed}
+ onChange={(enabled) => void setEnabled(branch, enabled)}
+ disabled={operation !== null}
+ />
+ </PanelSectionRow>
+ );
+ })}
</PanelSection>
);
}
-export function SetupTab({
- isInstalled,
- installationStatus,
- losslessScalingInstalled,
- losslessScalingStatus,
- steamBranchStatus,
- isInstalling,
- isUninstalling,
- onInstall,
- onUninstall,
-}: SetupTabProps) {
+export function SetupTab(props: SetupTabProps) {
+ const {
+ isInstalled,
+ installationStatus,
+ losslessScalingInstalled,
+ losslessScalingStatus,
+ steamBranchStatus,
+ isInstalling,
+ isUninstalling,
+ onInstall,
+ onUninstall,
+ flatpakRelevant,
+ } = props;
+ const losslessScalingAppInstalled = losslessScalingInstalled || steamBranchStatus?.installed === true;
+ const buttonLabel = isInstalling
+ ? t("INSTALL_INSTALLING", "Installing...")
+ : isUninstalling
+ ? t("INSTALL_UNINSTALLING", "Uninstalling...")
+ : isInstalled
+ ? t("INSTALL_UNINSTALL_BTN", "Uninstall LSFG-VK")
+ : t("INSTALL_INSTALL_BTN", "Install LSFG-VK");
+
return (
<>
<PanelSection title="Setup">
- <StatusDisplay
- installationStatus={installationStatus}
- losslessScalingInstalled={losslessScalingInstalled}
- losslessScalingStatus={losslessScalingStatus}
- steamBranchStatus={steamBranchStatus}
- />
- <InstallationButton
- isInstalled={isInstalled}
- isInstalling={isInstalling}
- isUninstalling={isUninstalling}
- onInstall={onInstall}
- onUninstall={onUninstall}
- />
+ <PanelSectionRow>
+ <Field
+ label="Lossless Scaling"
+ description={losslessScalingAppInstalled ? "Installed" : losslessScalingStatus || "Not installed"}
+ />
+ </PanelSectionRow>
+ <PanelSectionRow>
+ <Field label="LSFG-VK" description={installationStatus} />
+ </PanelSectionRow>
+ {steamBranchStatus?.installed && (
+ <PanelSectionRow>
+ <Field
+ label="Steam branch"
+ description={`${steamBranchStatus.current_branch || "public"}${steamBranchStatus.needs_switch ? ` - ${steamBranchStatus.message}` : ""}`}
+ />
+ </PanelSectionRow>
+ )}
+ <PanelSectionRow>
+ <ButtonItem
+ layout="below"
+ onClick={isInstalled ? onUninstall : onInstall}
+ disabled={isInstalling || isUninstalling}
+ >
+ {buttonLabel}
+ </ButtonItem>
+ </PanelSectionRow>
</PanelSection>
- <FlatpakSupportDiagnostics />
+ <FlatpakSupportDiagnostics relevant={flatpakRelevant} />
</>
);
}
diff --git a/src/components/StatusDisplay.tsx b/src/components/StatusDisplay.tsx
deleted file mode 100644
index b1a98e5..0000000
--- a/src/components/StatusDisplay.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-import { Field, PanelSectionRow } from "@decky/ui";
-import type { SteamBranchStatus } from "../api/lsfgApi";
-
-interface StatusDisplayProps {
- installationStatus: string;
- losslessScalingInstalled: boolean;
- losslessScalingStatus: string;
- steamBranchStatus: SteamBranchStatus | null;
-}
-
-export function StatusDisplay({
- installationStatus,
- losslessScalingInstalled,
- losslessScalingStatus,
- steamBranchStatus
-}: StatusDisplayProps) {
- const losslessScalingAppInstalled = losslessScalingInstalled || steamBranchStatus?.installed === true;
-
- return (
- <>
- <PanelSectionRow>
- <Field
- label="Lossless Scaling"
- description={losslessScalingAppInstalled ? "Installed" : losslessScalingStatus || "Not installed"}
- />
- </PanelSectionRow>
- <PanelSectionRow>
- <Field label="LSFG-VK" description={installationStatus} />
- </PanelSectionRow>
-
- {steamBranchStatus?.installed && (
- <PanelSectionRow>
- <Field
- label="Steam branch"
- description={`${steamBranchStatus.current_branch || "public"}${steamBranchStatus.needs_switch ? ` - ${steamBranchStatus.message}` : ""}`}
- />
- </PanelSectionRow>
- )}
- </>
- );
-}
diff --git a/src/components/index.ts b/src/components/index.ts
index 6856e76..bca6f6f 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -1,6 +1,4 @@
export { Content } from "./Content";
-export { StatusDisplay } from "./StatusDisplay";
-export { InstallationButton } from "./InstallationButton";
export { ConfigurationSection } from "./ConfigurationSection";
export { FpsMultiplierControl } from "./FpsMultiplierControl";
export { ConfigurationTab } from "./ConfigurationTab";