From bac59e55e319d871de5ac70c47199eb209fee66e Mon Sep 17 00:00:00 2001 From: xXJSONDeruloXx Date: Wed, 17 Sep 2025 14:57:02 -0400 Subject: add deckyfg combo launch option clipboard --- src/api/lsfgApi.ts | 8 +++ src/components/Content.tsx | 11 +++- src/components/FgmodClipboardButton.tsx | 109 ++++++++++++++++++++++++++++++++ src/components/index.ts | 1 + 4 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 src/components/FgmodClipboardButton.tsx (limited to 'src') diff --git a/src/api/lsfgApi.ts b/src/api/lsfgApi.ts index 6c535af..8db0c82 100644 --- a/src/api/lsfgApi.ts +++ b/src/api/lsfgApi.ts @@ -89,6 +89,13 @@ export interface FileContentResult { error?: string; } +export interface FgmodCheckResult { + success: boolean; + exists: boolean; + path?: string; + error?: string; +} + // Profile management interfaces export interface ProfilesResult { success: boolean; @@ -116,6 +123,7 @@ export const getConfigSchema = callable<[], ConfigSchemaResult>("get_config_sche export const getLaunchOption = callable<[], LaunchOptionResult>("get_launch_option"); export const getConfigFileContent = callable<[], FileContentResult>("get_config_file_content"); export const getLaunchScriptContent = callable<[], FileContentResult>("get_launch_script_content"); +export const checkFgmodDirectory = callable<[], FgmodCheckResult>("check_fgmod_directory"); // Updated config function using object-based configuration (single source of truth) export const updateLsfgConfig = callable< diff --git a/src/components/Content.tsx b/src/components/Content.tsx index e0adf3f..e870dda 100644 --- a/src/components/Content.tsx +++ b/src/components/Content.tsx @@ -11,6 +11,7 @@ import { UsageInstructions } from "./UsageInstructions"; import { WikiButton } from "./WikiButton"; import { ClipboardButton } from "./ClipboardButton"; import { SmartClipboardButton } from "./SmartClipboardButton"; +import { FgmodClipboardButton } from "./FgmodClipboardButton"; import { PluginUpdateChecker } from "./PluginUpdateChecker"; import { NerdStuffModal } from "./NerdStuffModal"; import { ConfigurationData } from "../config/configSchema"; @@ -96,7 +97,13 @@ export function Content() { )} - + {/* Clipboard buttons - only show if installed */} + {isInstalled && ( + <> + + + + )} {/* Profile Management - only show if installed */} {isInstalled && ( @@ -117,8 +124,10 @@ export function Content() { /> )} + {/* Usage instructions - always visible for user guidance */} + {/* Wiki and clipboard buttons - always available for documentation */} diff --git a/src/components/FgmodClipboardButton.tsx b/src/components/FgmodClipboardButton.tsx new file mode 100644 index 0000000..6f65955 --- /dev/null +++ b/src/components/FgmodClipboardButton.tsx @@ -0,0 +1,109 @@ +import { useState, useEffect } from "react"; +import { PanelSectionRow, ButtonItem } from "@decky/ui"; +import { FaClipboard, FaCheck } from "react-icons/fa"; +import { checkFgmodDirectory } from "../api/lsfgApi"; +import { showClipboardErrorToast } from "../utils/toastUtils"; +import { copyWithVerification } from "../utils/clipboardUtils"; + +export function FgmodClipboardButton() { + const [isLoading, setIsLoading] = useState(false); + const [showSuccess, setShowSuccess] = useState(false); + const [fgmodExists, setFgmodExists] = useState(false); + const [checkingFgmod, setCheckingFgmod] = useState(true); + + // Check for fgmod directory on component mount + useEffect(() => { + const checkFgmod = async () => { + try { + const result = await checkFgmodDirectory(); + setFgmodExists(result.exists); + } catch (error) { + console.error("Error checking fgmod directory:", error); + setFgmodExists(false); + } finally { + setCheckingFgmod(false); + } + }; + + checkFgmod(); + }, []); + + // Reset success state after 3 seconds + useEffect(() => { + if (showSuccess) { + const timer = setTimeout(() => { + setShowSuccess(false); + }, 3000); + return () => clearTimeout(timer); + } + return undefined; + }, [showSuccess]); + + const copyToClipboard = async () => { + if (isLoading || showSuccess) return; + + setIsLoading(true); + try { + const text = "~/fgmod/fgmod ~/lsfg %command%"; + const { success, verified } = await copyWithVerification(text); + + if (success) { + // Show success feedback in the button instead of toast + setShowSuccess(true); + if (!verified) { + // Copy worked but verification failed - still show success + console.log('Copy verification failed but copy likely worked'); + } + } else { + showClipboardErrorToast(); + } + } catch (error) { + showClipboardErrorToast(); + } finally { + setIsLoading(false); + } + }; + + // Don't render if fgmod directory doesn't exist or we're still checking + if (checkingFgmod || !fgmodExists) { + return null; + } + + return ( + + +
+ {showSuccess ? ( + + ) : isLoading ? ( + + ) : ( + + )} +
+ {showSuccess ? "Copied to clipboard" : isLoading ? "Copying..." : "LSFG + DeckyFG"} +
+
+
+ +
+ ); +} diff --git a/src/components/index.ts b/src/components/index.ts index bf60423..32bbb31 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -6,6 +6,7 @@ export { FpsMultiplierControl } from "./FpsMultiplierControl"; export { UsageInstructions } from "./UsageInstructions"; export { WikiButton } from "./WikiButton"; export { SmartClipboardButton } from "./SmartClipboardButton"; +export { FgmodClipboardButton } from "./FgmodClipboardButton"; export { PluginUpdateChecker } from "./PluginUpdateChecker"; export { NerdStuffModal } from "./NerdStuffModal"; export { ProfileManagement } from "./ProfileManagement"; -- cgit v1.2.3