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
---
 src/components/SmartClipboardButton.tsx | 128 ++++++++++++++++++++++++++++++++
 1 file changed, 128 insertions(+)
 create mode 100644 src/components/SmartClipboardButton.tsx

(limited to 'src/components/SmartClipboardButton.tsx')

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 (
+    <PanelSectionRow>
+      <ButtonItem
+        layout="below"
+        onClick={copyToClipboard}
+        disabled={isLoading}
+      >
+        <div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
+          {isLoading ? (
+            <FaClipboard style={{ 
+              animation: "pulse 1s ease-in-out infinite",
+              opacity: 0.7 
+            }} />
+          ) : (
+            <FaClipboard />
+          )}
+          <div>{isLoading ? "Copying..." : buttonText}</div>
+        </div>
+      </ButtonItem>
+      <style>{`
+        @keyframes pulse {
+          0% { opacity: 0.7; }
+          50% { opacity: 1; }
+          100% { opacity: 0.7; }
+        }
+      `}</style>
+    </PanelSectionRow>
+  );
+}
-- 
cgit v1.2.3

