summaryrefslogtreecommitdiff
path: root/src/components/FGModInstallerSection.tsx
diff options
context:
space:
mode:
authorKurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com>2025-07-17 08:49:12 -0400
committerGitHub <noreply@github.com>2025-07-17 08:49:12 -0400
commitca0d5f0ec1f4ba21f4bf51f0f773d2b6bad45c93 (patch)
tree8374652b65877b10bce3ea6e073165a02b6af0ba /src/components/FGModInstallerSection.tsx
parent74ac6e7b7a18c2ae969b08242a5919f903d294e2 (diff)
downloadDecky-Framegen-ca0d5f0ec1f4ba21f4bf51f0f773d2b6bad45c93.tar.gz
Decky-Framegen-ca0d5f0ec1f4ba21f4bf51f0f773d2b6bad45c93.zip
reorganize for readability and DRY (#115)v0.10.1
* reorganize for readability and DRY * rm backup files * ver bump
Diffstat (limited to 'src/components/FGModInstallerSection.tsx')
-rw-r--r--src/components/FGModInstallerSection.tsx103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/components/FGModInstallerSection.tsx b/src/components/FGModInstallerSection.tsx
new file mode 100644
index 0000000..f9f905e
--- /dev/null
+++ b/src/components/FGModInstallerSection.tsx
@@ -0,0 +1,103 @@
+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";
+
+export function FGModInstallerSection() {
+ 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 [pathExists, setPathExists] = useState<boolean | null>(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) {
+ return createAutoCleanupTimer(() => setInstallResult(null), TIMEOUTS.resultDisplay);
+ }
+ return () => {}; // Ensure a cleanup function is always returned
+ }, [installResult]);
+
+ useEffect(() => {
+ if (uninstallResult) {
+ return createAutoCleanupTimer(() => setUninstallResult(null), TIMEOUTS.resultDisplay);
+ }
+ return () => {}; // Ensure a cleanup function is always returned
+ }, [uninstallResult]);
+
+ const handleInstallClick = async () => {
+ try {
+ setInstalling(true);
+ const result = await runInstallFGMod();
+ setInstallResult(result);
+ } catch (e) {
+ console.error(e);
+ } finally {
+ setInstalling(false);
+ }
+ };
+
+ const handleUninstallClick = async () => {
+ try {
+ setUninstalling(true);
+ const result = await runUninstallFGMod();
+ setUninstallResult(result);
+ } catch (e) {
+ console.error(e);
+ } finally {
+ setUninstalling(false);
+ }
+ };
+
+ return (
+ <PanelSection>
+ {pathExists !== null ? (
+ <PanelSectionRow>
+ <div style={{ color: pathExists ? "green" : "red" }}>
+ {pathExists ? MESSAGES.modInstalled : MESSAGES.modNotInstalled}
+ </div>
+ </PanelSectionRow>
+ ) : null}
+
+ {pathExists === false ? (
+ <PanelSectionRow>
+ <ButtonItem layout="below" onClick={handleInstallClick} disabled={installing}>
+ {installing ? MESSAGES.installing : MESSAGES.installButton}
+ </ButtonItem>
+ </PanelSectionRow>
+ ) : null}
+
+ {pathExists === true ? (
+ <PanelSectionRow>
+ <ButtonItem layout="below" onClick={handleUninstallClick} disabled={uninstalling}>
+ {uninstalling ? MESSAGES.uninstalling : MESSAGES.uninstallButton}
+ </ButtonItem>
+ </PanelSectionRow>
+ ) : null}
+
+ <ResultDisplay result={installResult} />
+ <ResultDisplay result={uninstallResult} />
+
+ <PanelSectionRow>
+ <div>
+ {MESSAGES.instructionText}
+ </div>
+ </PanelSectionRow>
+ </PanelSection>
+ );
+}