From 0668428a5ebc221d39b907f251dc0dc43e30a2df Mon Sep 17 00:00:00 2001 From: xXJSONDeruloXx Date: Mon, 21 Jul 2025 12:28:36 -0400 Subject: testing alt keyboard copy methods --- src/components/SmartClipboardButton.tsx | 245 ++++++++++++++++++++++++++++++++ 1 file changed, 245 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..229560d --- /dev/null +++ b/src/components/SmartClipboardButton.tsx @@ -0,0 +1,245 @@ +import { useState } from "react"; +import { PanelSectionRow, ButtonItem } from "@decky/ui"; +import { FaClipboard, FaRocket } from "react-icons/fa"; +import { toaster } from "@decky/api"; +import { getLaunchOption, copyToSystemClipboard } from "../api/lsfgApi"; + +export function SmartClipboardButton() { + const [isLoading, setIsLoading] = useState(false); + + const getLaunchOptionText = async (): Promise => { + try { + const result = await getLaunchOption(); + return result.launch_option || "~/lsfg %command%"; + } catch (error) { + return "~/lsfg %command%"; + } + }; + + const copyToClipboard = async () => { + if (isLoading) return; + + setIsLoading(true); + try { + const text = await getLaunchOptionText(); + + // Strategy 1: Try direct navigator.clipboard first (fastest) + let directSuccess = false; + try { + await navigator.clipboard.writeText(text); + // Verify it worked + const readBack = await navigator.clipboard.readText(); + directSuccess = readBack === text; + } catch (e) { + // Direct clipboard failed, will try alternatives + } + + if (directSuccess) { + toaster.toast({ + title: "Copied to Clipboard!", + body: "Launch option ready to paste" + }); + return; + } + + // Strategy 2: Try backend system clipboard + try { + const result = await copyToSystemClipboard(text); + if (result.success) { + toaster.toast({ + title: "Copied to Clipboard!", + body: `Using ${result.method || "system clipboard"}` + }); + return; + } + } catch (e) { + // Backend failed, fall back to browser + } + + // Strategy 3: Fall back to optimized browser window + const htmlContent = ` + + + + + Quick Copy - Steam Deck Clipboard Helper + + + +
+

🚀 Steam Deck Clipboard Helper

+
Copy this launch option for your Steam games:
+
${text}
+
⏳ Copying to clipboard...
+
+ + +
+
+
+ + + + `; + + const dataUrl = 'data:text/html;charset=utf-8,' + encodeURIComponent(htmlContent); + window.open(dataUrl, '_blank', 'width=600,height=400,scrollbars=no,resizable=yes'); + + toaster.toast({ + title: "Browser Helper Opened", + body: "Clipboard helper window opened with auto-copy" + }); + + } catch (error) { + toaster.toast({ + title: "Copy Failed", + body: `Error: ${String(error)}` + }); + } finally { + setIsLoading(false); + } + }; + + return ( + + +
+ {isLoading ? : } +
{isLoading ? "Copying..." : "Smart Clipboard Copy"}
+
+
+ +
+ ); +} -- cgit v1.2.3 From 404b01b1acd5bd66e009176a71c21c29275fb6b9 Mon Sep 17 00:00:00 2001 From: xXJSONDeruloXx Date: Mon, 21 Jul 2025 12:48:36 -0400 Subject: rm the other clipboard tests --- src/components/SmartClipboardButton.tsx | 253 +++++++++----------------------- 1 file changed, 66 insertions(+), 187 deletions(-) (limited to 'src/components/SmartClipboardButton.tsx') diff --git a/src/components/SmartClipboardButton.tsx b/src/components/SmartClipboardButton.tsx index 229560d..81223bd 100644 --- a/src/components/SmartClipboardButton.tsx +++ b/src/components/SmartClipboardButton.tsx @@ -1,8 +1,8 @@ import { useState } from "react"; import { PanelSectionRow, ButtonItem } from "@decky/ui"; -import { FaClipboard, FaRocket } from "react-icons/fa"; +import { FaClipboard } from "react-icons/fa"; import { toaster } from "@decky/api"; -import { getLaunchOption, copyToSystemClipboard } from "../api/lsfgApi"; +import { getLaunchOption } from "../api/lsfgApi"; export function SmartClipboardButton() { const [isLoading, setIsLoading] = useState(false); @@ -23,195 +23,66 @@ export function SmartClipboardButton() { try { const text = await getLaunchOptionText(); - // Strategy 1: Try direct navigator.clipboard first (fastest) - let directSuccess = false; + // 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 { - await navigator.clipboard.writeText(text); - // Verify it worked - const readBack = await navigator.clipboard.readText(); - directSuccess = readBack === text; + if (document.execCommand('copy')) { + copySuccess = true; + } } catch (e) { - // Direct clipboard failed, will try alternatives - } - - if (directSuccess) { - toaster.toast({ - title: "Copied to Clipboard!", - body: "Launch option ready to paste" - }); - return; + // 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); + } } - - // Strategy 2: Try backend system clipboard - try { - const result = await copyToSystemClipboard(text); - if (result.success) { + + // 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: "Launch option ready to paste" + }); + } 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: `Using ${result.method || "system clipboard"}` + body: "Launch option copied successfully" }); - return; } - } catch (e) { - // Backend failed, fall back to browser + } else { + toaster.toast({ + title: "Copy Failed", + body: "Unable to copy to clipboard" + }); } - // Strategy 3: Fall back to optimized browser window - const htmlContent = ` - - - - - Quick Copy - Steam Deck Clipboard Helper - - - -
-

🚀 Steam Deck Clipboard Helper

-
Copy this launch option for your Steam games:
-
${text}
-
⏳ Copying to clipboard...
-
- - -
-
-
- - - - `; - - const dataUrl = 'data:text/html;charset=utf-8,' + encodeURIComponent(htmlContent); - window.open(dataUrl, '_blank', 'width=600,height=400,scrollbars=no,resizable=yes'); - - toaster.toast({ - title: "Browser Helper Opened", - body: "Clipboard helper window opened with auto-copy" - }); - } catch (error) { toaster.toast({ title: "Copy Failed", @@ -230,14 +101,22 @@ export function SmartClipboardButton() { disabled={isLoading} >
- {isLoading ? : } -
{isLoading ? "Copying..." : "Smart Clipboard Copy"}
+ {isLoading ? ( + + ) : ( + + )} +
{isLoading ? "Copying..." : "Copy Launch Option"}
-- cgit v1.2.3