mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
fix(ui): report clipboard write failures instead of rejecting (#50292)
Closes DOCS-1390 ## Problem Sentry [DOCS-AA](https://supabase.sentry.io/issues/7727380816/) reports `NotAllowedError: Failed to execute 'write' on 'Clipboard': Write permission denied.` as an unhandled promise rejection. The error names `write`, not `writeText`, which places it in the `ClipboardItem` branch of `copyToClipboard`. That branch has two problems: - The write runs inside a `setTimeout`, so the surrounding `try/catch` has already returned by the time it executes. A denied write routes to the promise's `reject`. - No caller attaches a `catch`. All call sites either fire-and-forget or `await` inside an async handler with no `try/catch`, so the rejection surfaces as an unhandled rejection. The user-visible effect is worse than the Sentry noise. On that branch the copy fails with no feedback at all, because the `toast.error` in the outer `catch` is unreachable from inside the `setTimeout`. The `writeText` branch does show the toast, so the two paths disagree. The issue is filed against auth docs, where it surfaced, but the fix belongs in `packages/ui`. The same branch runs in Studio and www. ## Solution - Handle the failure inside the `setTimeout`, where it happens: report it and resolve. - `copyToClipboard` no longer rejects on either path, matching what the `writeText` branch already did. No caller relied on rejection. - Add regression tests for a denied write on both branches. ## Manual testing 1. Run the unit tests. Four `copyToClipboard` cases pass, including the two new denial cases. ``` pnpm --filter studio exec vitest run lib/helpers.test.ts -t copyToClipboard ``` 2. Confirm the new test is a real guard. Revert `clipboard.ts` and rerun. The write case fails with `promise rejected ... instead of resolving`. 3. Confirm the ratchet is unchanged. ``` pnpm --filter studio run lint:ratchet ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Clipboard write failures now display an error notification instead of causing an unhandled rejection. * Copy operations resolve consistently when clipboard access is denied or unavailable, including Safari clipboard support. * Failed copy attempts no longer trigger completion callbacks, preventing misleading success behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
1 parent
cf5bf65361
commit
91b7df64c2
2 files changed
+32
-14
No files matched your search
@@ -30,20 +30,9 @@ export const copyToClipboard = async (str: ClipboardText, callback = noop) => {
|
||||
'text/plain': Promise.resolve(str).then((text) => new Blob([text], { type: 'text/plain' })),
|
||||
})
|
||||
|
||||
let resolve = () => {}
|
||||
let reject = () => {}
|
||||
const promise = new Promise<void>((res, rej) => {
|
||||
resolve = res
|
||||
reject = rej
|
||||
})
|
||||
// Safari also seems to require that the promise resolve soon after the
|
||||
// clipboard write call, adding a setTimeout with 0 delay seems to work.
|
||||
// Returning the promise to ensure the caller can await the clipboard
|
||||
// copy operation intuitively.
|
||||
setTimeout(() => {
|
||||
navigator.clipboard.write([text]).then(callback).then(resolve).catch(reject)
|
||||
}, 0)
|
||||
return promise
|
||||
await navigator.clipboard.write([text])
|
||||
callback()
|
||||
return
|
||||
}
|
||||
|
||||
// NOTE: Firefox has support for ClipboardItem and navigator.clipboard.write,
|
||||
|
||||
Reference in new issue
Block a user