From e662500c2f29bea871689662c6d39a7c0ac04213 Mon Sep 17 00:00:00 2001 From: Ivan Sekovanikj Date: Thu, 6 Aug 2026 17:16:43 +0200 Subject: [PATCH] fix: expo clipboard handling on v8 --- .../setClipboardString.ts | 30 ++++++++++++++++--- .../setClipboardString.ts | 12 ++++++-- package/src/native.ts | 4 ++- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/package/expo-package/src/optionalDependencies/setClipboardString.ts b/package/expo-package/src/optionalDependencies/setClipboardString.ts index bfd4ba37b8..62befb266f 100644 --- a/package/expo-package/src/optionalDependencies/setClipboardString.ts +++ b/package/expo-package/src/optionalDependencies/setClipboardString.ts @@ -1,4 +1,9 @@ -let Clipboard: { setString: (string: string) => void } | undefined; +let Clipboard: + | { + setString?: (text: string) => void; + setStringAsync?: (text: string) => Promise; + } + | undefined; try { Clipboard = require('expo-clipboard'); @@ -12,6 +17,23 @@ if (!Clipboard) { ); } -export const setClipboardString = Clipboard - ? (string: string) => Clipboard?.setString(string) - : null; +export const setClipboardString = + Clipboard && (Clipboard.setStringAsync || Clipboard.setString) + ? (text: string) => { + try { + // `expo-clipboard` removed the synchronous `setString` in favour of + // the async API. Keep this handler synchronous (void return, like the + // legacy `setString`) and fire the async write without awaiting. Fall + // back to `setString` for older versions. + if (Clipboard?.setStringAsync) { + Clipboard.setStringAsync(text).catch((error: unknown) => { + console.log('Copying to clipboard failed...', error); + }); + } else { + Clipboard?.setString?.(text); + } + } catch (error) { + console.log('Copying to clipboard failed...', error); + } + } + : null; diff --git a/package/native-package/src/optionalDependencies/setClipboardString.ts b/package/native-package/src/optionalDependencies/setClipboardString.ts index 030609cc87..8a66cb6d68 100644 --- a/package/native-package/src/optionalDependencies/setClipboardString.ts +++ b/package/native-package/src/optionalDependencies/setClipboardString.ts @@ -1,4 +1,4 @@ -let Clipboard: { setString: (string: string) => void } | undefined; +let Clipboard: { setString?: (text: string) => void } | undefined; try { Clipboard = require('@react-native-clipboard/clipboard').default; @@ -7,6 +7,12 @@ try { console.log('@react-native-clipboard/clipboard is not installed'); } -export const setClipboardString = Clipboard - ? (string: string) => (Clipboard ? Clipboard.setString(string) : {}) +export const setClipboardString = Clipboard?.setString + ? (text: string) => { + try { + Clipboard?.setString?.(text); + } catch (error) { + console.log('Copying to clipboard failed...', error); + } + } : null; diff --git a/package/src/native.ts b/package/src/native.ts index cfcb627e5f..1bbd764512 100644 --- a/package/src/native.ts +++ b/package/src/native.ts @@ -62,7 +62,9 @@ type SaveFileOptions = { }; type SaveFile = (options: SaveFileOptions) => Promise | never; -type SetClipboardString = (text: string) => Promise | never; +// Kept synchronous (void return) for backwards compatibility. The expo +// implementation fires the async clipboard write without awaiting it. +type SetClipboardString = (text: string) => void; type ShareOptions = { type?: string;