From 9573344450de451b8f9c7295c11318010d67f1d5 Mon Sep 17 00:00:00 2001 From: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com> Date: Mon, 21 Jul 2025 10:05:39 -0400 Subject: Refresh UI (#117) * initial visual refinement * rm dupe status pops * hide other menus if uninstalled opti * bump ver * fix ver bump --- src/components/FGModInstallerSection.tsx | 58 ++++++++++++++++---------------- src/components/InstalledGamesSection.tsx | 29 +++++++++------- src/components/ResultDisplay.tsx | 31 ++++++++++------- 3 files changed, 63 insertions(+), 55 deletions(-) (limited to 'src/components') diff --git a/src/components/FGModInstallerSection.tsx b/src/components/FGModInstallerSection.tsx index f9f905e..1e347c0 100644 --- a/src/components/FGModInstallerSection.tsx +++ b/src/components/FGModInstallerSection.tsx @@ -1,30 +1,20 @@ import { useState, useEffect } from "react"; import { PanelSection, PanelSectionRow, ButtonItem } from "@decky/ui"; -import { checkFGModPath, runInstallFGMod, runUninstallFGMod } from "../api"; -import { ResultDisplay, OperationResult } from "./ResultDisplay"; -import { createAutoCleanupTimer, safeAsyncOperation } from "../utils"; -import { TIMEOUTS, MESSAGES } from "../utils/constants"; +import { runInstallFGMod, runUninstallFGMod } from "../api"; +import { OperationResult } from "./ResultDisplay"; +import { createAutoCleanupTimer } from "../utils"; +import { TIMEOUTS, MESSAGES, STYLES } from "../utils/constants"; -export function FGModInstallerSection() { +interface FGModInstallerSectionProps { + pathExists: boolean | null; + setPathExists: (exists: boolean | null) => void; +} + +export function FGModInstallerSection({ pathExists, setPathExists }: FGModInstallerSectionProps) { const [installing, setInstalling] = useState(false); const [uninstalling, setUninstalling] = useState(false); const [installResult, setInstallResult] = useState(null); const [uninstallResult, setUninstallResult] = useState(null); - const [pathExists, setPathExists] = useState(null); - - useEffect(() => { - const checkPath = async () => { - const result = await safeAsyncOperation( - async () => await checkFGModPath(), - 'useEffect -> checkPath' - ); - if (result) setPathExists(result.exists); - }; - - checkPath(); // Initial check - const intervalId = setInterval(checkPath, TIMEOUTS.pathCheck); // Check every 3 seconds - return () => clearInterval(intervalId); // Cleanup interval on component unmount - }, []); useEffect(() => { if (installResult) { @@ -45,6 +35,9 @@ export function FGModInstallerSection() { setInstalling(true); const result = await runInstallFGMod(); setInstallResult(result); + if (result.status === "success") { + setPathExists(true); + } } catch (e) { console.error(e); } finally { @@ -57,6 +50,9 @@ export function FGModInstallerSection() { setUninstalling(true); const result = await runUninstallFGMod(); setUninstallResult(result); + if (result.status === "success") { + setPathExists(false); + } } catch (e) { console.error(e); } finally { @@ -68,7 +64,7 @@ export function FGModInstallerSection() { {pathExists !== null ? ( -
+
{pathExists ? MESSAGES.modInstalled : MESSAGES.modNotInstalled}
@@ -90,14 +86,18 @@ export function FGModInstallerSection() { ) : null} - - - - -
- {MESSAGES.instructionText} -
-
+ {pathExists === true ? ( + +
+
+ {MESSAGES.instructionTitle} +
+
+ {MESSAGES.instructionText} +
+
+
+ ) : null} ); } diff --git a/src/components/InstalledGamesSection.tsx b/src/components/InstalledGamesSection.tsx index 30ca2a4..71278d7 100644 --- a/src/components/InstalledGamesSection.tsx +++ b/src/components/InstalledGamesSection.tsx @@ -40,19 +40,19 @@ export function InstalledGamesSection() { // Show confirmation modal showModal( { try { await SteamClient.Apps.SetAppLaunchOptions(selectedGame.appid, '~/fgmod/fgmod %COMMAND%'); - setResult(`Launch options set for ${selectedGame.name}. You can now select DLSS in the game's menu, and access OptiScaler with Insert key.`); + setResult(`✓ Frame generation enabled for ${selectedGame.name}. Launch the game, enable DLSS in graphics settings, then press Insert to access OptiScaler options.`); } catch (error) { logError('handlePatchClick: ' + String(error)); - setResult(error instanceof Error ? `Error setting launch options: ${error.message}` : 'Error setting launch options'); + setResult(error instanceof Error ? `Error: ${error.message}` : 'Error enabling frame generation'); } }} /> @@ -64,15 +64,15 @@ export function InstalledGamesSection() { try { await SteamClient.Apps.SetAppLaunchOptions(selectedGame.appid, '~/fgmod/fgmod-uninstaller.sh %COMMAND%'); - setResult(`OptiScaler will uninstall on next launch of ${selectedGame.name}.`); + setResult(`✓ Frame generation will be disabled on next launch of ${selectedGame.name}.`); } catch (error) { logError('handleUnpatchClick: ' + String(error)); - setResult(error instanceof Error ? `Error clearing launch options: ${error.message}` : 'Error clearing launch options'); + setResult(error instanceof Error ? `Error: ${error.message}` : 'Error disabling frame generation'); } }; return ( - + ({ @@ -85,15 +85,18 @@ export function InstalledGamesSection() { setSelectedGame(game || null); setResult(''); }} - strDefaultLabel="Select a game..." + strDefaultLabel="Choose a game" menuLabel="Installed Games" /> {result ? ( -
- {result} +
+ {result.includes('Error') ? '❌' : '✅'} {result}
) : null} @@ -105,7 +108,7 @@ export function InstalledGamesSection() { layout="below" onClick={handlePatchClick} > - Patch + Enable Frame Generation @@ -113,7 +116,7 @@ export function InstalledGamesSection() { layout="below" onClick={handleUnpatchClick} > - Unpatch + Disable Frame Generation diff --git a/src/components/ResultDisplay.tsx b/src/components/ResultDisplay.tsx index 0f58f0e..bcd66c0 100644 --- a/src/components/ResultDisplay.tsx +++ b/src/components/ResultDisplay.tsx @@ -12,25 +12,30 @@ interface ResultDisplayProps { export const ResultDisplay: FC = ({ result }) => { if (!result) return null; + const isSuccess = result.status === "success"; + return ( -
- Status:{" "} - - {result.status === "success" ? "Success" : "Error"} - -
- {result.output ? ( +
+ {isSuccess ? ( <> - Output: -
{result.output}
+ ✅ {result.output?.includes("uninstall") || result.output?.includes("remov") + ? "OptiScaler mod removed successfully" + : "OptiScaler mod installed successfully"} - ) : null} - {result.message ? ( + ) : ( <> - Error: {result.message} + ❌ Error: {result.message || "Operation failed"} - ) : null} + )} + {result.output && !isSuccess && ( +
+ View Details +
+              {result.output}
+            
+
+ )}
); -- cgit v1.2.3