From 56eac1ac74e9f32bbf2541929e80b79cdb6cbcb1 Mon Sep 17 00:00:00 2001
From: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com>
Date: Mon, 28 Jul 2025 07:21:34 -0700
Subject: refined copy to clipboard ui feedback (#122)

* copy feedback

* add opti logo and update wording

* branding updates

* hide check mark when installed
---
 src/components/SmartClipboardButton.tsx | 62 ++++++++++++++++++---------------
 1 file changed, 34 insertions(+), 28 deletions(-)

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

diff --git a/src/components/SmartClipboardButton.tsx b/src/components/SmartClipboardButton.tsx
index 7d250f5..095da15 100644
--- a/src/components/SmartClipboardButton.tsx
+++ b/src/components/SmartClipboardButton.tsx
@@ -1,31 +1,37 @@
-import { useState } from "react";
+import { useState, useEffect } from "react";
 import { PanelSectionRow, ButtonItem } from "@decky/ui";
-import { FaClipboard } from "react-icons/fa";
+import { FaClipboard, FaCheck } 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"
+  buttonText = "Copy Launch Command"
 }: SmartClipboardButtonProps) {
   const [isLoading, setIsLoading] = useState(false);
+  const [showSuccess, setShowSuccess] = useState(false);
 
-  const getLaunchOptionText = (): string => {
-    return command;
-  };
+  // 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) return;
+    if (isLoading || showSuccess) return;
     
     setIsLoading(true);
     try {
-      const text = getLaunchOptionText();
+      const text = command;
       
       // Use the proven input simulation method
       const tempInput = document.createElement('input');
@@ -58,27 +64,18 @@ export function SmartClipboardButton({
       document.body.removeChild(tempInput);
       
       if (copySuccess) {
+        // Show success feedback in the button instead of toast
+        setShowSuccess(true);
         // 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)"
-            });
+          if (readBack !== text) {
+            // Copy worked but verification failed - still show success
+            console.log('Copy verification failed but copy likely worked');
           }
         } catch (e) {
           // Verification failed but copy likely worked
-          toaster.toast({
-            title: "Copied to Clipboard!",
-            body: "Launch option copied successfully"
-          });
+          console.log('Copy verification unavailable but copy likely worked');
         }
       } else {
         toaster.toast({
@@ -102,10 +99,14 @@ export function SmartClipboardButton({
       <ButtonItem
         layout="below"
         onClick={copyToClipboard}
-        disabled={isLoading}
+        disabled={isLoading || showSuccess}
       >
         <div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
-          {isLoading ? (
+          {showSuccess ? (
+            <FaCheck style={{ 
+              color: "#4CAF50" // Green color for success
+            }} />
+          ) : isLoading ? (
             <FaClipboard style={{ 
               animation: "pulse 1s ease-in-out infinite",
               opacity: 0.7 
@@ -113,7 +114,12 @@ export function SmartClipboardButton({
           ) : (
             <FaClipboard />
           )}
-          <div>{isLoading ? "Copying..." : buttonText}</div>
+          <div style={{ 
+            color: showSuccess ? "#4CAF50" : "inherit",
+            fontWeight: showSuccess ? "bold" : "normal"
+          }}>
+            {showSuccess ? "Copied to clipboard" : isLoading ? "Copying..." : buttonText}
+          </div>
         </div>
       </ButtonItem>
       <style>{`
-- 
cgit v1.2.3

