summaryrefslogtreecommitdiff
path: root/src/components/OptiScalerControls.tsx
diff options
context:
space:
mode:
authorKurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com>2025-07-29 07:53:45 -0700
committerGitHub <noreply@github.com>2025-07-29 10:53:45 -0400
commit0b5e71fe916e92ef9ecf7de91ca43371c4bd6d25 (patch)
tree30793600da162d9d8fcc63cddeebb1e5a0b058cb /src/components/OptiScalerControls.tsx
parent526e4e590bb0125f7f7a08e214986afec73e7439 (diff)
downloadDecky-Framegen-0b5e71fe916e92ef9ecf7de91ca43371c4bd6d25.tar.gz
Decky-Framegen-0b5e71fe916e92ef9ecf7de91ca43371c4bd6d25.zip
wording and layout tweaks (#125)v0.11.8
* wording and layout tweaks * red in remove button * reorganize frontend components * fix ld preload permissions issue for decky 3.1.10 * bump ver
Diffstat (limited to 'src/components/OptiScalerControls.tsx')
-rw-r--r--src/components/OptiScalerControls.tsx92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/components/OptiScalerControls.tsx b/src/components/OptiScalerControls.tsx
new file mode 100644
index 0000000..7b2db0e
--- /dev/null
+++ b/src/components/OptiScalerControls.tsx
@@ -0,0 +1,92 @@
+import { useState, useEffect } from "react";
+import { PanelSection } from "@decky/ui";
+import { runInstallFGMod, runUninstallFGMod } from "../api";
+import { OperationResult } from "./ResultDisplay";
+import { createAutoCleanupTimer } from "../utils";
+import { TIMEOUTS } from "../utils/constants";
+import { InstallationStatus } from "./InstallationStatus";
+import { OptiScalerHeader } from "./OptiScalerHeader";
+import { ClipboardCommands } from "./ClipboardCommands";
+import { InstructionCard } from "./InstructionCard";
+import { OptiScalerWiki } from "./OptiScalerWiki";
+import { UninstallButton } from "./UninstallButton";
+
+interface OptiScalerControlsProps {
+ pathExists: boolean | null;
+ setPathExists: (exists: boolean | null) => void;
+}
+
+export function OptiScalerControls({ pathExists, setPathExists }: 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);
+
+ 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);
+ if (result.status === "success") {
+ setPathExists(true);
+ }
+ } catch (e) {
+ console.error(e);
+ } finally {
+ setInstalling(false);
+ }
+ };
+
+ const handleUninstallClick = async () => {
+ try {
+ setUninstalling(true);
+ const result = await runUninstallFGMod();
+ setUninstallResult(result);
+ if (result.status === "success") {
+ setPathExists(false);
+ }
+ } catch (e) {
+ console.error(e);
+ } finally {
+ setUninstalling(false);
+ }
+ };
+
+ return (
+ <PanelSection>
+ <InstallationStatus
+ pathExists={pathExists}
+ installing={installing}
+ onInstallClick={handleInstallClick}
+ />
+
+ <OptiScalerHeader pathExists={pathExists} />
+
+ <ClipboardCommands pathExists={pathExists} />
+
+ <InstructionCard pathExists={pathExists} />
+
+ <OptiScalerWiki pathExists={pathExists} />
+
+ <UninstallButton
+ pathExists={pathExists}
+ uninstalling={uninstalling}
+ onUninstallClick={handleUninstallClick}
+ />
+ </PanelSection>
+ );
+}