From ca0d5f0ec1f4ba21f4bf51f0f773d2b6bad45c93 Mon Sep 17 00:00:00 2001
From: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com>
Date: Thu, 17 Jul 2025 08:49:12 -0400
Subject: reorganize for readability and DRY (#115)

* reorganize for readability and DRY

* rm backup files

* ver bump
---
 src/components/FGModInstallerSection.tsx | 103 +++++++++++++++++++++++++++++++
 1 file changed, 103 insertions(+)
 create mode 100644 src/components/FGModInstallerSection.tsx

(limited to 'src/components/FGModInstallerSection.tsx')

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>
+  );
+}
-- 
cgit v1.2.3

