diff options
Diffstat (limited to 'src/utils')
| -rw-r--r-- | src/utils/clipboardUtils.ts | 70 | ||||
| -rw-r--r-- | src/utils/toastUtils.ts | 115 |
2 files changed, 185 insertions, 0 deletions
diff --git a/src/utils/clipboardUtils.ts b/src/utils/clipboardUtils.ts new file mode 100644 index 0000000..2d480fc --- /dev/null +++ b/src/utils/clipboardUtils.ts @@ -0,0 +1,70 @@ +/** + * Clipboard utilities for reliable copy operations across different environments + */ + +/** + * Reliably copy text to clipboard using multiple fallback methods + * This is especially important in gaming mode where clipboard APIs may behave differently + */ +export async function copyToClipboard(text: string): Promise<boolean> { + // 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); + + try { + // 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); + } + } + + return copySuccess; + } finally { + // Clean up + document.body.removeChild(tempInput); + } +} + +/** + * Verify that text was successfully copied to clipboard + */ +export async function verifyCopy(expectedText: string): Promise<boolean> { + try { + const readBack = await navigator.clipboard.readText(); + return readBack === expectedText; + } catch (e) { + // Verification not available, assume success + return true; + } +} + +/** + * Copy text with verification and return success status + */ +export async function copyWithVerification(text: string): Promise<{ success: boolean; verified: boolean }> { + const copySuccess = await copyToClipboard(text); + + if (!copySuccess) { + return { success: false, verified: false }; + } + + const verified = await verifyCopy(text); + return { success: true, verified }; +} diff --git a/src/utils/toastUtils.ts b/src/utils/toastUtils.ts new file mode 100644 index 0000000..dce0a59 --- /dev/null +++ b/src/utils/toastUtils.ts @@ -0,0 +1,115 @@ +/** + * Centralized toast notification utilities + * Provides consistent success/error messaging patterns + */ + +import { toaster } from "@decky/api"; + +export interface ToastOptions { + title: string; + body: string; +} + +/** + * Show a success toast notification + */ +export function showSuccessToast(title: string, body: string): void { + toaster.toast({ + title, + body + }); +} + +/** + * Show an error toast notification + */ +export function showErrorToast(title: string, body: string): void { + toaster.toast({ + title, + body + }); +} + +/** + * Standard success messages for common operations + */ +export const ToastMessages = { + INSTALL_SUCCESS: { + title: "Installation Complete", + body: "lsfg-vk has been installed successfully" + }, + INSTALL_ERROR: { + title: "Installation Failed", + body: "Unknown error occurred" + }, + UNINSTALL_SUCCESS: { + title: "Uninstallation Complete", + body: "lsfg-vk has been uninstalled successfully" + }, + UNINSTALL_ERROR: { + title: "Uninstallation Failed", + body: "Unknown error occurred" + }, + CONFIG_UPDATE_ERROR: { + title: "Update Failed", + body: "Failed to update configuration" + }, + CLIPBOARD_SUCCESS: { + title: "Copied to Clipboard!", + body: "Launch option ready to paste" + }, + CLIPBOARD_ERROR: { + title: "Copy Failed", + body: "Unable to copy to clipboard" + } +} as const; + +/** + * Show a toast with dynamic error message + */ +export function showErrorToastWithMessage(title: string, error: unknown): void { + const errorMessage = error instanceof Error ? error.message : String(error); + showErrorToast(title, errorMessage); +} + +/** + * Show installation success toast + */ +export function showInstallSuccessToast(): void { + showSuccessToast(ToastMessages.INSTALL_SUCCESS.title, ToastMessages.INSTALL_SUCCESS.body); +} + +/** + * Show installation error toast + */ +export function showInstallErrorToast(error?: string): void { + showErrorToast(ToastMessages.INSTALL_ERROR.title, error || ToastMessages.INSTALL_ERROR.body); +} + +/** + * Show uninstallation success toast + */ +export function showUninstallSuccessToast(): void { + showSuccessToast(ToastMessages.UNINSTALL_SUCCESS.title, ToastMessages.UNINSTALL_SUCCESS.body); +} + +/** + * Show uninstallation error toast + */ +export function showUninstallErrorToast(error?: string): void { + showErrorToast(ToastMessages.UNINSTALL_ERROR.title, error || ToastMessages.UNINSTALL_ERROR.body); +} + +/** + * Show clipboard success toast + */ +export function showClipboardSuccessToast(): void { + showSuccessToast(ToastMessages.CLIPBOARD_SUCCESS.title, ToastMessages.CLIPBOARD_SUCCESS.body); +} + +/** + * Show clipboard error toast + */ +export function showClipboardErrorToast(): void { + showErrorToast(ToastMessages.CLIPBOARD_ERROR.title, ToastMessages.CLIPBOARD_ERROR.body); +} |
