From b0621d15c675b7b8c1615b0699cc85ea1430a728 Mon Sep 17 00:00:00 2001
From: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com>
Date: Mon, 21 Jul 2025 13:50:23 -0400
Subject: hooking clipboard automation button, hide plugin wiki for now (#118)
* hooking clipboard automation button, hide plugin wiki for now
* add direct copy to clip buttons for patch and unpatch
---
justfile | 2 +-
package.json | 2 +-
src/components/DocumentationButton.tsx | 2 +
src/components/FGModInstallerSection.tsx | 17 ++++
src/components/SmartClipboardButton.tsx | 128 +++++++++++++++++++++++++++++++
src/utils/constants.ts | 2 +-
6 files changed, 150 insertions(+), 3 deletions(-)
create mode 100644 src/components/SmartClipboardButton.tsx
diff --git a/justfile b/justfile
index 4e9a17a..9fa9cfb 100644
--- a/justfile
+++ b/justfile
@@ -5,7 +5,7 @@ build:
sudo rm -rf node_modules && .vscode/build.sh
test:
- scp "/Users/kurt/Developer/FG-plugins/Decky-Framegen/out/Decky-Framegen.zip" deck@192.168.0.6:~/Desktop
+ scp "out/Decky-Framegen.zip" deck@192.168.0.6:~/Desktop
clean:
rm -rf node_modules dist
\ No newline at end of file
diff --git a/package.json b/package.json
index fba3228..b614bc4 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "decky-framegen",
- "version": "0.11.2",
+ "version": "0.11.3",
"description": "plugin to install OptiScaler bleeding-edge and enable upscaling and framegen in a large variety of games.",
"type": "module",
"scripts": {
diff --git a/src/components/DocumentationButton.tsx b/src/components/DocumentationButton.tsx
index 4125fd3..7069bc2 100644
--- a/src/components/DocumentationButton.tsx
+++ b/src/components/DocumentationButton.tsx
@@ -12,6 +12,7 @@ export function DocumentationButton() {
return (
+ {/*
+ */}
) : null}
+
+ {pathExists === true ? (
+
+ ) : null}
+
+ {pathExists === true ? (
+
+ ) : null}
);
}
diff --git a/src/components/SmartClipboardButton.tsx b/src/components/SmartClipboardButton.tsx
new file mode 100644
index 0000000..7d250f5
--- /dev/null
+++ b/src/components/SmartClipboardButton.tsx
@@ -0,0 +1,128 @@
+import { useState } from "react";
+import { PanelSectionRow, ButtonItem } from "@decky/ui";
+import { FaClipboard } from "react-icons/fa";
+import { toaster } from "@decky/api";
+
+interface SmartClipboardButtonProps {
+ command?: string;
+ buttonText?: string;
+ successMessage?: string;
+}
+
+export function SmartClipboardButton({
+ command = "~/fgmod/fgmod %command%",
+ buttonText = "Copy Launch Command",
+ successMessage = "Launch option ready to paste"
+}: SmartClipboardButtonProps) {
+ const [isLoading, setIsLoading] = useState(false);
+
+ const getLaunchOptionText = (): string => {
+ return command;
+ };
+
+ const copyToClipboard = async () => {
+ if (isLoading) return;
+
+ setIsLoading(true);
+ try {
+ const text = getLaunchOptionText();
+
+ // Use the proven input simulation method
+ const tempInput = document.createElement('input');
+ tempInput.value = text;
+ tempInput.style.position = 'absolute';
+ tempInput.style.left = '-9999px';
+ document.body.appendChild(tempInput);
+
+ // Focus and select the text
+ tempInput.focus();
+ tempInput.select();
+
+ // Try copying using execCommand first (most reliable in gaming mode)
+ let copySuccess = false;
+ try {
+ if (document.execCommand('copy')) {
+ copySuccess = true;
+ }
+ } catch (e) {
+ // If execCommand fails, try navigator.clipboard as fallback
+ try {
+ await navigator.clipboard.writeText(text);
+ copySuccess = true;
+ } catch (clipboardError) {
+ console.error('Both copy methods failed:', e, clipboardError);
+ }
+ }
+
+ // Clean up
+ document.body.removeChild(tempInput);
+
+ if (copySuccess) {
+ // Verify the copy worked by reading back
+ try {
+ const readBack = await navigator.clipboard.readText();
+ if (readBack === text) {
+ toaster.toast({
+ title: "Copied to Clipboard!",
+ body: successMessage
+ });
+ } else {
+ // Copy worked but verification failed - still consider it success
+ toaster.toast({
+ title: "Copied to Clipboard!",
+ body: "Launch option copied (verification unavailable)"
+ });
+ }
+ } catch (e) {
+ // Verification failed but copy likely worked
+ toaster.toast({
+ title: "Copied to Clipboard!",
+ body: "Launch option copied successfully"
+ });
+ }
+ } else {
+ toaster.toast({
+ title: "Copy Failed",
+ body: "Unable to copy to clipboard"
+ });
+ }
+
+ } catch (error) {
+ toaster.toast({
+ title: "Copy Failed",
+ body: `Error: ${String(error)}`
+ });
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ return (
+
+
+
+ {isLoading ? (
+
+ ) : (
+
+ )}
+
{isLoading ? "Copying..." : buttonText}
+
+
+
+
+ );
+}
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index c949521..3e39067 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -62,5 +62,5 @@ export const MESSAGES = {
installSuccess: "✅ OptiScaler mod installed successfully!",
uninstallSuccess: "✅ OptiScaler mod removed successfully.",
instructionTitle: "How to Use:",
- instructionText: "Select and patch a game below to enable frame generation (or use clipboard button to copy and paste into launch options)\n\nIn-game: Enable DLSS in graphics settings, or assign a back button to keyboard's 'Insert' key for extended OptiScaler options"
+ instructionText: "Select and patch a game below to enable frame generation, or use the Copy Patch/Unpatch Command buttons for manual setup.\n\nIn-game: Enable DLSS in graphics settings, or assign a back button to keyboard's 'Insert' key for extended OptiScaler options"
};
--
cgit v1.2.3