summaryrefslogtreecommitdiff
path: root/src/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/clipboardUtils.ts70
-rw-r--r--src/utils/toastUtils.ts115
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);
+}