From 77494457e2a4f5c80c3a2f7acb054b12d918d8ad Mon Sep 17 00:00:00 2001 From: xXJSONDeruloXx Date: Sun, 13 Jul 2025 00:04:54 -0400 Subject: restructure for maintainability --- src/components/ConfigurationSection.tsx | 115 ++++++++++++++++++++++++++++++++ src/components/Content.tsx | 108 ++++++++++++++++++++++++++++++ src/components/InstallationButton.tsx | 64 ++++++++++++++++++ src/components/StatusDisplay.tsx | 38 +++++++++++ src/components/UsageInstructions.tsx | 68 +++++++++++++++++++ src/components/index.ts | 5 ++ 6 files changed, 398 insertions(+) create mode 100644 src/components/ConfigurationSection.tsx create mode 100644 src/components/Content.tsx create mode 100644 src/components/InstallationButton.tsx create mode 100644 src/components/StatusDisplay.tsx create mode 100644 src/components/UsageInstructions.tsx create mode 100644 src/components/index.ts (limited to 'src/components') diff --git a/src/components/ConfigurationSection.tsx b/src/components/ConfigurationSection.tsx new file mode 100644 index 0000000..707ad2a --- /dev/null +++ b/src/components/ConfigurationSection.tsx @@ -0,0 +1,115 @@ +import { PanelSectionRow, ToggleField, SliderField } from "@decky/ui"; + +interface LsfgConfig { + enableLsfg: boolean; + multiplier: number; + flowScale: number; + hdr: boolean; + perfMode: boolean; + immediateMode: boolean; +} + +interface ConfigurationSectionProps { + config: LsfgConfig; + onEnableLsfgChange: (value: boolean) => Promise; + onMultiplierChange: (value: number) => Promise; + onFlowScaleChange: (value: number) => Promise; + onHdrChange: (value: boolean) => Promise; + onPerfModeChange: (value: boolean) => Promise; + onImmediateModeChange: (value: boolean) => Promise; +} + +export function ConfigurationSection({ + config, + onEnableLsfgChange, + onMultiplierChange, + onFlowScaleChange, + onHdrChange, + onPerfModeChange, + onImmediateModeChange +}: ConfigurationSectionProps) { + return ( + <> + +
+ LSFG Configuration +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/src/components/Content.tsx b/src/components/Content.tsx new file mode 100644 index 0000000..cecb142 --- /dev/null +++ b/src/components/Content.tsx @@ -0,0 +1,108 @@ +import { useEffect } from "react"; +import { PanelSection } from "@decky/ui"; +import { useInstallationStatus, useDllDetection, useLsfgConfig } from "../hooks/useLsfgHooks"; +import { useInstallationActions } from "../hooks/useInstallationActions"; +import { StatusDisplay } from "./StatusDisplay"; +import { InstallationButton } from "./InstallationButton"; +import { ConfigurationSection } from "./ConfigurationSection"; +import { UsageInstructions } from "./UsageInstructions"; + +export function Content() { + const { + isInstalled, + installationStatus, + setIsInstalled, + setInstallationStatus + } = useInstallationStatus(); + + const { dllDetected, dllDetectionStatus } = useDllDetection(); + + const { + config, + setters, + loadLsfgConfig, + updateConfig + } = useLsfgConfig(); + + const { isInstalling, isUninstalling, handleInstall, handleUninstall } = useInstallationActions(); + + // Reload config when installation status changes + useEffect(() => { + if (isInstalled) { + loadLsfgConfig(); + } + }, [isInstalled, loadLsfgConfig]); + + // Configuration change handlers + const handleEnableLsfgChange = async (value: boolean) => { + setters.setEnableLsfg(value); + await updateConfig(value, config.multiplier, config.flowScale, config.hdr, config.perfMode, config.immediateMode); + }; + + const handleMultiplierChange = async (value: number) => { + setters.setMultiplier(value); + await updateConfig(config.enableLsfg, value, config.flowScale, config.hdr, config.perfMode, config.immediateMode); + }; + + const handleFlowScaleChange = async (value: number) => { + setters.setFlowScale(value); + await updateConfig(config.enableLsfg, config.multiplier, value, config.hdr, config.perfMode, config.immediateMode); + }; + + const handleHdrChange = async (value: boolean) => { + setters.setHdr(value); + await updateConfig(config.enableLsfg, config.multiplier, config.flowScale, value, config.perfMode, config.immediateMode); + }; + + const handlePerfModeChange = async (value: boolean) => { + setters.setPerfMode(value); + await updateConfig(config.enableLsfg, config.multiplier, config.flowScale, config.hdr, value, config.immediateMode); + }; + + const handleImmediateModeChange = async (value: boolean) => { + setters.setImmediateMode(value); + await updateConfig(config.enableLsfg, config.multiplier, config.flowScale, config.hdr, config.perfMode, value); + }; + + const onInstall = () => { + handleInstall(setIsInstalled, setInstallationStatus, loadLsfgConfig); + }; + + const onUninstall = () => { + handleUninstall(setIsInstalled, setInstallationStatus); + }; + + return ( + + + + + + {/* Configuration Section - only show if installed */} + {isInstalled && ( + + )} + + + + ); +} diff --git a/src/components/InstallationButton.tsx b/src/components/InstallationButton.tsx new file mode 100644 index 0000000..7892678 --- /dev/null +++ b/src/components/InstallationButton.tsx @@ -0,0 +1,64 @@ +import { ButtonItem, PanelSectionRow } from "@decky/ui"; +import { FaDownload, FaTrash } from "react-icons/fa"; + +interface InstallationButtonProps { + isInstalled: boolean; + isInstalling: boolean; + isUninstalling: boolean; + onInstall: () => void; + onUninstall: () => void; +} + +export function InstallationButton({ + isInstalled, + isInstalling, + isUninstalling, + onInstall, + onUninstall +}: InstallationButtonProps) { + const renderButtonContent = () => { + if (isInstalling) { + return ( +
+
Installing...
+
+ ); + } + + if (isUninstalling) { + return ( +
+
Uninstalling...
+
+ ); + } + + if (isInstalled) { + return ( +
+ +
Uninstall lsfg-vk
+
+ ); + } + + return ( +
+ +
Install lsfg-vk
+
+ ); + }; + + return ( + + + {renderButtonContent()} + + + ); +} diff --git a/src/components/StatusDisplay.tsx b/src/components/StatusDisplay.tsx new file mode 100644 index 0000000..8eecd42 --- /dev/null +++ b/src/components/StatusDisplay.tsx @@ -0,0 +1,38 @@ +import { PanelSectionRow } from "@decky/ui"; + +interface StatusDisplayProps { + dllDetected: boolean; + dllDetectionStatus: string; + isInstalled: boolean; + installationStatus: string; +} + +export function StatusDisplay({ + dllDetected, + dllDetectionStatus, + isInstalled, + installationStatus +}: StatusDisplayProps) { + return ( + +
+
+ {dllDetectionStatus} +
+
+ Status: {installationStatus} +
+
+
+ ); +} diff --git a/src/components/UsageInstructions.tsx b/src/components/UsageInstructions.tsx new file mode 100644 index 0000000..712d4c1 --- /dev/null +++ b/src/components/UsageInstructions.tsx @@ -0,0 +1,68 @@ +import { PanelSectionRow } from "@decky/ui"; + +interface UsageInstructionsProps { + multiplier: number; +} + +export function UsageInstructions({ multiplier }: UsageInstructionsProps) { + return ( + +
+
+ Usage Instructions: +
+
+ Option 1: Use the lsfg script (recommended): +
+
+ ~/lsfg %COMMAND% +
+
+ Option 2: Manual environment variables: +
+
+ ENABLE_LSFG=1 LSFG_MULTIPLIER={multiplier} %COMMAND% +
+
+ The lsfg script uses your current configuration settings. +
+ • ENABLE_LSFG=1 - Enables frame generation +
+ • LSFG_MULTIPLIER=2-4 - FPS multiplier (start with 2) +
+ • LSFG_FLOW_SCALE=0.25-1.0 - Flow scale (for performance) +
+ • LSFG_HDR=1 - HDR mode (only if using HDR) +
+ • MESA_VK_WSI_PRESENT_MODE=immediate - Disable vsync +
+
+
+ ); +} diff --git a/src/components/index.ts b/src/components/index.ts new file mode 100644 index 0000000..77f11d4 --- /dev/null +++ b/src/components/index.ts @@ -0,0 +1,5 @@ +export { Content } from "./Content"; +export { StatusDisplay } from "./StatusDisplay"; +export { InstallationButton } from "./InstallationButton"; +export { ConfigurationSection } from "./ConfigurationSection"; +export { UsageInstructions } from "./UsageInstructions"; -- cgit v1.2.3