summaryrefslogtreecommitdiff
path: root/src/components/OptiScalerControls.tsx
diff options
context:
space:
mode:
authorxXJSONDeruloXx <danielhimebauch@gmail.com>2026-05-19 14:26:39 -0400
committerxXJSONDeruloXx <danielhimebauch@gmail.com>2026-05-19 14:26:39 -0400
commit19e5aefa2f41ebd4389bf27136adacf3e75d3502 (patch)
treec7f2228aa45fd4325a68de6fe6f32864f383791c /src/components/OptiScalerControls.tsx
parent9e12c11b6189972ea04de454dad5c8554efe657a (diff)
downloadDecky-Framegen-feat/asset-manifest-fsr4-variants.tar.gz
Decky-Framegen-feat/asset-manifest-fsr4-variants.zip
feat: add fsr4 runtime manifestsfeat/asset-manifest-fsr4-variants
Diffstat (limited to 'src/components/OptiScalerControls.tsx')
-rw-r--r--src/components/OptiScalerControls.tsx106
1 files changed, 97 insertions, 9 deletions
diff --git a/src/components/OptiScalerControls.tsx b/src/components/OptiScalerControls.tsx
index f88e8f9..2167fcd 100644
--- a/src/components/OptiScalerControls.tsx
+++ b/src/components/OptiScalerControls.tsx
@@ -1,9 +1,9 @@
import { useState, useEffect } from "react";
-import { DropdownItem, PanelSection, PanelSectionRow } from "@decky/ui";
-import { runInstallFGMod, runUninstallFGMod } from "../api";
+import { DropdownItem, Field, PanelSection, PanelSectionRow, ToggleField } from "@decky/ui";
+import { runInstallFGMod, runUninstallFGMod, setDefaultFsr4Variant } from "../api";
import { OperationResult } from "./ResultDisplay";
import { createAutoCleanupTimer } from "../utils";
-import { TIMEOUTS, PROXY_DLL_OPTIONS, DEFAULT_PROXY_DLL } from "../utils/constants";
+import { TIMEOUTS, PROXY_DLL_OPTIONS, DEFAULT_PROXY_DLL, FSR4_VARIANT_OPTIONS, DEFAULT_FSR4_VARIANT } from "../utils/constants";
import { InstallationStatus } from "./InstallationStatus";
import { OptiScalerHeader } from "./OptiScalerHeader";
import { ClipboardCommands } from "./ClipboardCommands";
@@ -13,18 +13,31 @@ import { UninstallButton } from "./UninstallButton";
import { ManualPatchControls } from "./CustomPathOverride";
import { SteamGamePatcher } from "./SteamGamePatcher";
+interface FgmodInfo {
+ exists: boolean;
+ version?: string | null;
+ selected_fsr4_variant?: string | null;
+ selected_fsr4_variant_label?: string | null;
+ install_manifest_present?: boolean;
+}
+
interface OptiScalerControlsProps {
pathExists: boolean | null;
setPathExists: (exists: boolean | null) => void;
+ fgmodInfo?: FgmodInfo | null;
}
-export function OptiScalerControls({ pathExists, setPathExists }: OptiScalerControlsProps) {
+export function OptiScalerControls({ pathExists, setPathExists, fgmodInfo }: OptiScalerControlsProps) {
const [installing, setInstalling] = useState(false);
const [uninstalling, setUninstalling] = useState(false);
const [installResult, setInstallResult] = useState<OperationResult | null>(null);
const [uninstallResult, setUninstallResult] = useState<OperationResult | null>(null);
- const [manualModeEnabled, setManualModeEnabled] = useState(false);
+ const [advancedModeEnabled, setAdvancedModeEnabled] = useState(false);
+ const [manualClipboardModeEnabled, setManualClipboardModeEnabled] = useState(false);
const [dllName, setDllName] = useState<string>(DEFAULT_PROXY_DLL);
+ const [fsr4Variant, setFsr4Variant] = useState<string>(DEFAULT_FSR4_VARIANT);
+ const [fsr4VariantTouched, setFsr4VariantTouched] = useState(false);
+ const [switchingVariant, setSwitchingVariant] = useState(false);
useEffect(() => {
if (installResult) {
return createAutoCleanupTimer(() => setInstallResult(null), TIMEOUTS.resultDisplay);
@@ -39,10 +52,17 @@ export function OptiScalerControls({ pathExists, setPathExists }: OptiScalerCont
return () => {}; // Ensure a cleanup function is always returned
}, [uninstallResult]);
+ useEffect(() => {
+ const installedVariant = fgmodInfo?.selected_fsr4_variant;
+ if (!fsr4VariantTouched && installedVariant && FSR4_VARIANT_OPTIONS.some((option) => option.value === installedVariant)) {
+ setFsr4Variant(installedVariant);
+ }
+ }, [fgmodInfo?.selected_fsr4_variant, fsr4VariantTouched]);
+
const handleInstallClick = async () => {
try {
setInstalling(true);
- const result = await runInstallFGMod();
+ const result = await runInstallFGMod(fsr4Variant);
setInstallResult(result);
if (result.status === "success") {
setPathExists(true);
@@ -69,6 +89,31 @@ export function OptiScalerControls({ pathExists, setPathExists }: OptiScalerCont
}
};
+ const handleFsr4VariantChange = async (nextVariant: string) => {
+ const previousVariant = fsr4Variant;
+ setFsr4Variant(nextVariant);
+ setFsr4VariantTouched(true);
+
+ if (pathExists !== true) return;
+
+ try {
+ setSwitchingVariant(true);
+ const result = await setDefaultFsr4Variant(nextVariant);
+ if (result.status !== "success") {
+ throw new Error(result.message || result.output || "Failed to switch default FSR4 runtime.");
+ }
+ setFsr4Variant(result.selected_default_variant || nextVariant);
+ setFsr4VariantTouched(false);
+ } catch (error) {
+ console.error(error);
+ setFsr4Variant(previousVariant);
+ } finally {
+ setSwitchingVariant(false);
+ }
+ };
+
+ const installedVariantLabel = fgmodInfo?.selected_fsr4_variant_label || FSR4_VARIANT_OPTIONS.find((option) => option.value === fsr4Variant)?.label;
+
return (
<PanelSection>
<InstallationStatus
@@ -79,6 +124,28 @@ export function OptiScalerControls({ pathExists, setPathExists }: OptiScalerCont
<OptiScalerHeader pathExists={pathExists} />
+ <PanelSectionRow>
+ <DropdownItem
+ label="Default FSR4 runtime"
+ description={FSR4_VARIANT_OPTIONS.find((option) => option.value === fsr4Variant)?.hint}
+ menuLabel="Default FSR4 runtime"
+ selectedOption={fsr4Variant}
+ rgOptions={FSR4_VARIANT_OPTIONS.map((option) => ({ data: option.value, label: option.label }))}
+ disabled={installing || uninstalling || switchingVariant}
+ onChange={(option) => {
+ void handleFsr4VariantChange(String(option.data));
+ }}
+ />
+ </PanelSectionRow>
+
+ {pathExists === true && fgmodInfo?.version && installedVariantLabel && (
+ <PanelSectionRow>
+ <Field label="Installed bundle" description={`OptiScaler ${fgmodInfo.version}`}>
+ {installedVariantLabel}
+ </Field>
+ </PanelSectionRow>
+ )}
+
{pathExists === true && (
<PanelSectionRow>
<DropdownItem
@@ -93,18 +160,39 @@ export function OptiScalerControls({ pathExists, setPathExists }: OptiScalerCont
)}
{pathExists === true && (
- <SteamGamePatcher dllName={dllName} />
+ <SteamGamePatcher dllName={dllName} fsr4Variant={fsr4Variant} />
)}
<ClipboardCommands pathExists={pathExists} dllName={dllName} />
+ {pathExists === true && (
+ <PanelSectionRow>
+ <ToggleField
+ label="Manual Mode"
+ description="Show wrapper command clipboard buttons for patching and unpatching through ~/fgmod scripts."
+ checked={manualClipboardModeEnabled}
+ onChange={setManualClipboardModeEnabled}
+ />
+ </PanelSectionRow>
+ )}
+
+ {pathExists === true && manualClipboardModeEnabled ? (
+ <ClipboardCommands
+ pathExists={pathExists}
+ dllName={dllName}
+ manualModeEnabled
+ showLaunchOptions={false}
+ />
+ ) : null}
+
<ManualPatchControls
isAvailable={pathExists === true}
- onManualModeChange={setManualModeEnabled}
+ onManualModeChange={setAdvancedModeEnabled}
dllName={dllName}
+ fsr4Variant={fsr4Variant}
/>
- {!manualModeEnabled && (
+ {!advancedModeEnabled && (
<InstructionCard pathExists={pathExists} />
)}
<OptiScalerWiki pathExists={pathExists} />