summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorxXJSONDeruloXx <danielhimebauch@gmail.com>2025-07-11 07:08:42 -0400
committerxXJSONDeruloXx <danielhimebauch@gmail.com>2025-07-11 07:08:42 -0400
commit03f96bcd2afb72dc5fc4674d8a70d7cabd78bec1 (patch)
treea79b38f1485f8b80f1517bbaf1fbb3c875bac406 /src
parentfb4516cabb652774ce60e0683bda1af88cc2d09f (diff)
downloaddecky-lsfg-vk-03f96bcd2afb72dc5fc4674d8a70d7cabd78bec1.tar.gz
decky-lsfg-vk-03f96bcd2afb72dc5fc4674d8a70d7cabd78bec1.zip
initial commit
Diffstat (limited to 'src')
-rwxr-xr-xsrc/index.tsx256
1 files changed, 187 insertions, 69 deletions
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<number | undefined>();
+ const [isInstalled, setIsInstalled] = useState<boolean>(false);
+ const [isInstalling, setIsInstalling] = useState<boolean>(false);
+ const [isUninstalling, setIsUninstalling] = useState<boolean>(false);
+ const [installationStatus, setInstallationStatus] = useState<string>("");
+ const [dllDetected, setDllDetected] = useState<boolean>(false);
+ const [dllDetectionStatus, setDllDetectionStatus] = useState<string>("");
+
+ // 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 (
- <PanelSection title="Panel Section">
+ <PanelSection title="lsfg-vk Installation">
<PanelSectionRow>
- <ButtonItem
- layout="below"
- onClick={onClick}
- >
- {result ?? "Add two numbers via Python"}
- </ButtonItem>
+ <div style={{ marginBottom: "8px", fontSize: "14px" }}>
+ <div style={{
+ color: dllDetected ? "#4CAF50" : "#F44336",
+ fontWeight: "bold",
+ marginBottom: "4px"
+ }}>
+ {dllDetectionStatus}
+ </div>
+ <div style={{
+ color: isInstalled ? "#4CAF50" : "#FF9800"
+ }}>
+ Status: {installationStatus}
+ </div>
+ </div>
</PanelSectionRow>
+
<PanelSectionRow>
<ButtonItem
layout="below"
- onClick={() => startTimer()}
+ onClick={isInstalled ? handleUninstall : handleInstall}
+ disabled={isInstalling || isUninstalling}
>
- {"Start Python timer"}
+ {isInstalling ? (
+ <div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
+ <div>Installing...</div>
+ </div>
+ ) : isUninstalling ? (
+ <div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
+ <div>Uninstalling...</div>
+ </div>
+ ) : isInstalled ? (
+ <div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
+ <FaTrash />
+ <div>Uninstall lsfg-vk</div>
+ </div>
+ ) : (
+ <div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
+ <FaDownload />
+ <div>Install lsfg-vk</div>
+ </div>
+ )}
</ButtonItem>
</PanelSectionRow>
-
- {/* <PanelSectionRow>
- <div style={{ display: "flex", justifyContent: "center" }}>
- <img src={logo} />
+
+ <PanelSectionRow>
+ <div style={{
+ fontSize: "13px",
+ marginTop: "12px",
+ padding: "8px",
+ backgroundColor: "rgba(255, 255, 255, 0.05)",
+ borderRadius: "4px"
+ }}>
+ <div style={{ fontWeight: "bold", marginBottom: "6px" }}>
+ Usage Instructions:
+ </div>
+ <div style={{ marginBottom: "4px" }}>
+ Add to your game's launch options in Steam:
+ </div>
+ <div style={{
+ fontFamily: "monospace",
+ backgroundColor: "rgba(0, 0, 0, 0.3)",
+ padding: "4px",
+ borderRadius: "2px",
+ fontSize: "12px",
+ marginBottom: "6px"
+ }}>
+ ENABLE_LSFG=1 LSFG_MULTIPLIER=2 %COMMAND%
+ </div>
+ <div style={{ fontSize: "11px", opacity: 0.8 }}>
+ • ENABLE_LSFG=1 - Enables frame generation
+ <br />
+ • LSFG_MULTIPLIER=2-4 - FPS multiplier (start with 2)
+ <br />
+ • LSFG_FLOW_SCALE=1.0 - Flow scale (optional, for performance)
+ </div>
</div>
- </PanelSectionRow> */}
-
- {/*<PanelSectionRow>
- <ButtonItem
- layout="below"
- onClick={() => {
- Navigation.Navigate("/decky-plugin-test");
- Navigation.CloseSideMenus();
- }}
- >
- Router
- </ButtonItem>
- </PanelSectionRow>*/}
+ </PanelSectionRow>
</PanelSection>
);
};
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: <div className={staticClasses.Title}>Decky Example Plugin</div>,
+ titleView: <div className={staticClasses.Title}>lsfg-vk Installer</div>,
// The content of your plugin's menu
content: <Content />,
// The icon displayed in the plugin list
- icon: <FaShip />,
+ icon: <GiPlasticDuck />,
// 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")
},
};
});