From 03f96bcd2afb72dc5fc4674d8a70d7cabd78bec1 Mon Sep 17 00:00:00 2001 From: xXJSONDeruloXx Date: Fri, 11 Jul 2025 07:08:42 -0400 Subject: initial commit --- src/index.tsx | 256 ++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 187 insertions(+), 69 deletions(-) (limited to 'src') diff --git a/src/index.tsx b/src/index.tsx index 16cd6cb..1ab6f62 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -2,114 +2,232 @@ import { ButtonItem, PanelSection, PanelSectionRow, - Navigation, staticClasses } from "@decky/ui"; import { - addEventListener, - removeEventListener, callable, definePlugin, toaster, - // routerHook } from "@decky/api" -import { useState } from "react"; -import { FaShip } from "react-icons/fa"; +import { useState, useEffect } from "react"; +import { FaDownload, FaTrash } from "react-icons/fa"; +import { GiPlasticDuck } from "react-icons/gi"; -// import logo from "../assets/logo.png"; +// Function to install lsfg-vk +const installLsfgVk = callable<[], { success: boolean; error?: string; message?: string }>("install_lsfg_vk"); -// This function calls the python function "add", which takes in two numbers and returns their sum (as a number) -// Note the type annotations: -// the first one: [first: number, second: number] is for the arguments -// the second one: number is for the return value -const add = callable<[first: number, second: number], number>("add"); +// Function to uninstall lsfg-vk +const uninstallLsfgVk = callable<[], { success: boolean; error?: string; message?: string; removed_files?: string[] }>("uninstall_lsfg_vk"); -// This function calls the python function "start_timer", which takes in no arguments and returns nothing. -// It starts a (python) timer which eventually emits the event 'timer_event' -const startTimer = callable<[], void>("start_timer"); +// Function to check if lsfg-vk is installed +const checkLsfgVkInstalled = callable<[], { installed: boolean; lib_exists: boolean; json_exists: boolean; lib_path: string; json_path: string; error?: string }>("check_lsfg_vk_installed"); + +// Function to check if Lossless Scaling DLL is available +const checkLosslessScalingDll = callable<[], { detected: boolean; path?: string; source?: string; message?: string; error?: string }>("check_lossless_scaling_dll"); function Content() { - const [result, setResult] = useState(); + const [isInstalled, setIsInstalled] = useState(false); + const [isInstalling, setIsInstalling] = useState(false); + const [isUninstalling, setIsUninstalling] = useState(false); + const [installationStatus, setInstallationStatus] = useState(""); + const [dllDetected, setDllDetected] = useState(false); + const [dllDetectionStatus, setDllDetectionStatus] = useState(""); + + // Check installation status on component mount + useEffect(() => { + const checkInstallation = async () => { + try { + const status = await checkLsfgVkInstalled(); + setIsInstalled(status.installed); + if (status.installed) { + setInstallationStatus("lsfg-vk is installed"); + } else { + setInstallationStatus("lsfg-vk is not installed"); + } + } catch (error) { + setInstallationStatus("Error checking installation status"); + } + }; + + const checkDllDetection = async () => { + try { + const result = await checkLosslessScalingDll(); + setDllDetected(result.detected); + if (result.detected) { + setDllDetectionStatus(`Lossless Scaling App detected (${result.source})`); + } else { + setDllDetectionStatus(result.message || "Lossless Scaling App not detected"); + } + } catch (error) { + setDllDetectionStatus("Error checking Lossless Scaling App"); + } + }; + + checkInstallation(); + checkDllDetection(); + }, []); + + const handleInstall = async () => { + setIsInstalling(true); + setInstallationStatus("Installing lsfg-vk..."); + + try { + const result = await installLsfgVk(); + if (result.success) { + setIsInstalled(true); + setInstallationStatus("lsfg-vk installed successfully!"); + toaster.toast({ + title: "Installation Complete", + body: "lsfg-vk has been installed successfully" + }); + } else { + setInstallationStatus(`Installation failed: ${result.error}`); + toaster.toast({ + title: "Installation Failed", + body: result.error || "Unknown error occurred" + }); + } + } catch (error) { + setInstallationStatus(`Installation failed: ${error}`); + toaster.toast({ + title: "Installation Failed", + body: `Error: ${error}` + }); + } finally { + setIsInstalling(false); + } + }; - const onClick = async () => { - const result = await add(Math.random(), Math.random()); - setResult(result); + const handleUninstall = async () => { + setIsUninstalling(true); + setInstallationStatus("Uninstalling lsfg-vk..."); + + try { + const result = await uninstallLsfgVk(); + if (result.success) { + setIsInstalled(false); + setInstallationStatus("lsfg-vk uninstalled successfully!"); + toaster.toast({ + title: "Uninstallation Complete", + body: result.message || "lsfg-vk has been uninstalled successfully" + }); + } else { + setInstallationStatus(`Uninstallation failed: ${result.error}`); + toaster.toast({ + title: "Uninstallation Failed", + body: result.error || "Unknown error occurred" + }); + } + } catch (error) { + setInstallationStatus(`Uninstallation failed: ${error}`); + toaster.toast({ + title: "Uninstallation Failed", + body: `Error: ${error}` + }); + } finally { + setIsUninstalling(false); + } }; return ( - + - - {result ?? "Add two numbers via Python"} - +
+
+ {dllDetectionStatus} +
+
+ Status: {installationStatus} +
+
+ startTimer()} + onClick={isInstalled ? handleUninstall : handleInstall} + disabled={isInstalling || isUninstalling} > - {"Start Python timer"} + {isInstalling ? ( +
+
Installing...
+
+ ) : isUninstalling ? ( +
+
Uninstalling...
+
+ ) : isInstalled ? ( +
+ +
Uninstall lsfg-vk
+
+ ) : ( +
+ +
Install lsfg-vk
+
+ )}
- - {/* -
- + + +
+
+ Usage Instructions: +
+
+ Add to your game's launch options in Steam: +
+
+ ENABLE_LSFG=1 LSFG_MULTIPLIER=2 %COMMAND% +
+
+ • ENABLE_LSFG=1 - Enables frame generation +
+ • LSFG_MULTIPLIER=2-4 - FPS multiplier (start with 2) +
+ • LSFG_FLOW_SCALE=1.0 - Flow scale (optional, for performance) +
-
*/} - - {/* - { - Navigation.Navigate("/decky-plugin-test"); - Navigation.CloseSideMenus(); - }} - > - Router - - */} + ); }; export default definePlugin(() => { - console.log("Template plugin initializing, this is called once on frontend startup") - - // serverApi.routerHook.addRoute("/decky-plugin-test", DeckyPluginRouterTest, { - // exact: true, - // }); - - // Add an event listener to the "timer_event" event from the backend - const listener = addEventListener<[ - test1: string, - test2: boolean, - test3: number - ]>("timer_event", (test1, test2, test3) => { - console.log("Template got timer_event with:", test1, test2, test3) - toaster.toast({ - title: "template got timer_event", - body: `${test1}, ${test2}, ${test3}` - }); - }); + console.log("lsfg-vk Installer plugin initializing") return { // The name shown in various decky menus - name: "Test Plugin", + name: "lsfg-vk Installer", // The element displayed at the top of your plugin's menu - titleView:
Decky Example Plugin
, + titleView:
lsfg-vk Installer
, // The content of your plugin's menu content: , // The icon displayed in the plugin list - icon: , + icon: , // The function triggered when your plugin unloads onDismount() { - console.log("Unloading") - removeEventListener("timer_event", listener); - // serverApi.routerHook.removeRoute("/decky-plugin-test"); + console.log("lsfg-vk Installer unloading") }, }; }); -- cgit v1.2.3