From a45edcc9b5ae444b0cb4f50a20ecd63dcc1d5093 Mon Sep 17 00:00:00 2001 From: Denozordec Date: Mon, 30 Mar 2026 15:11:54 +0700 Subject: [PATCH] Enhance copy functionality in user pages - Updated the copy function to handle clipboard operations more robustly, including a fallback method for unsupported environments. - Improved user interaction by ensuring that copy actions are properly managed and errors are gracefully handled. - Refactored the copy event handling in the UI to prevent event propagation, enhancing the overall user experience. --- .../routes/servers/[alias]/users/+page.svelte | 26 +++++++++++++- web/src/routes/users/+page.svelte | 36 +++++++++++++++++-- web/src/routes/users/[username]/+page.svelte | 26 +++++++++++++- 3 files changed, 83 insertions(+), 5 deletions(-) diff --git a/web/src/routes/servers/[alias]/users/+page.svelte b/web/src/routes/servers/[alias]/users/+page.svelte index 95ec4b6..ae0cbde 100644 --- a/web/src/routes/servers/[alias]/users/+page.svelte +++ b/web/src/routes/servers/[alias]/users/+page.svelte @@ -163,7 +163,31 @@ } function copy(text: string) { - void navigator.clipboard.writeText(text); + const value = String(text ?? ''); + if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) { + void navigator.clipboard.writeText(value).catch(() => fallbackCopy(value)); + } else { + fallbackCopy(value); + } + } + + function fallbackCopy(value: string) { + if (typeof document === 'undefined') return; + const ta = document.createElement('textarea'); + ta.value = value; + ta.setAttribute('readonly', ''); + ta.style.position = 'fixed'; + ta.style.left = '-9999px'; + ta.style.top = '0'; + document.body.appendChild(ta); + ta.select(); + try { + document.execCommand('copy'); + } catch { + // ignore + } finally { + ta.remove(); + } } diff --git a/web/src/routes/users/+page.svelte b/web/src/routes/users/+page.svelte index 1700719..ce3e1b1 100644 --- a/web/src/routes/users/+page.svelte +++ b/web/src/routes/users/+page.svelte @@ -34,7 +34,12 @@ onMount(load); function copy(text: string) { - void navigator.clipboard.writeText(text); + const value = String(text ?? ''); + if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) { + void navigator.clipboard.writeText(value).catch(() => fallbackCopy(value)); + } else { + fallbackCopy(value); + } } function openUser(username: string | null | undefined) { @@ -42,6 +47,25 @@ if (!u) return; void goto(`/users/${encodeURIComponent(u)}`); } + + function fallbackCopy(value: string) { + if (typeof document === 'undefined') return; + const ta = document.createElement('textarea'); + ta.value = value; + ta.setAttribute('readonly', ''); + ta.style.position = 'fixed'; + ta.style.left = '-9999px'; + ta.style.top = '0'; + document.body.appendChild(ta); + ta.select(); + try { + document.execCommand('copy'); + } catch { + // ignore + } finally { + ta.remove(); + } + }
@@ -113,7 +137,10 @@ variant="outline" size="xs" class="h-7 gap-1 px-2 text-xs" - onclick|stopPropagation={() => copy(link)} + onclick={(e: MouseEvent) => { + e.stopPropagation(); + void copy(link); + }} > TLS @@ -124,7 +151,10 @@ variant="outline" size="xs" class="h-7 gap-1 px-2 text-xs" - onclick|stopPropagation={() => copy(link)} + onclick={(e: MouseEvent) => { + e.stopPropagation(); + void copy(link); + }} > t.me diff --git a/web/src/routes/users/[username]/+page.svelte b/web/src/routes/users/[username]/+page.svelte index 9bed675..fcf6f25 100644 --- a/web/src/routes/users/[username]/+page.svelte +++ b/web/src/routes/users/[username]/+page.svelte @@ -56,7 +56,31 @@ onMount(load); function copy(text: string) { - void navigator.clipboard.writeText(text); + const value = String(text ?? ''); + if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) { + void navigator.clipboard.writeText(value).catch(() => fallbackCopy(value)); + } else { + fallbackCopy(value); + } + } + + function fallbackCopy(value: string) { + if (typeof document === 'undefined') return; + const ta = document.createElement('textarea'); + ta.value = value; + ta.setAttribute('readonly', ''); + ta.style.position = 'fixed'; + ta.style.left = '-9999px'; + ta.style.top = '0'; + document.body.appendChild(ta); + ta.select(); + try { + document.execCommand('copy'); + } catch { + // ignore + } finally { + ta.remove(); + } } let ipsForUser = $derived.by(() => {