From 75d0e1d0a74f6e46f479701d786939c290da95f0 Mon Sep 17 00:00:00 2001 From: adityavardhansharma Date: Wed, 29 Jul 2026 13:08:30 +0100 Subject: [PATCH] fix(mobile): support Android clipboard image paste --- .../src/native/T3ComposerEditor.native.tsx | 117 +++++++++--------- 1 file changed, 61 insertions(+), 56 deletions(-) diff --git a/apps/mobile/src/native/T3ComposerEditor.native.tsx b/apps/mobile/src/native/T3ComposerEditor.native.tsx index 84d1c22084f..e78f90a7db9 100644 --- a/apps/mobile/src/native/T3ComposerEditor.native.tsx +++ b/apps/mobile/src/native/T3ComposerEditor.native.tsx @@ -1,5 +1,6 @@ import { collectComposerInlineTokens } from "@t3tools/shared/composerInlineTokens"; import { requireNativeView } from "expo"; +import { TextInputWrapper } from "expo-paste-input"; import { useCallback, useEffect, @@ -9,12 +10,13 @@ import { useState, type Ref, } from "react"; -import type { NativeSyntheticEvent, StyleProp, ViewProps, ViewStyle } from "react-native"; +import type { NativeSyntheticEvent, ViewProps } from "react-native"; import { Image, StyleSheet } from "react-native"; import { markdownFileIconSource } from "@t3tools/mobile-markdown-text/file-icons"; import { resolveMarkdownFileIcon } from "@t3tools/mobile-markdown-text/links"; import { MOBILE_TYPOGRAPHY } from "../lib/typography"; +import { useNativePaste } from "../lib/useNativePaste"; import { useFontFamily } from "../lib/useFontFamily"; import { useThemeColor } from "../lib/useThemeColor"; import { @@ -117,6 +119,7 @@ export function ComposerEditor({ const skillBorder = useThemeColor("--color-inline-skill-border"); const skillText = useThemeColor("--color-inline-skill-foreground"); const fileTint = useThemeColor("--color-icon-muted"); + const handlePaste = useNativePaste((uris) => onPasteImages?.(uris)); useImperativeHandle( ref, @@ -221,61 +224,63 @@ export function ComposerEditor({ const resolvedTextStyle = StyleSheet.flatten(textStyle) ?? {}; const regularFontFamily = useFontFamily("regular"); return ( - } - onComposerChange={(event) => { - const acknowledgedEventCount = acceptNativeEvent( - event.nativeEvent.eventCount, - event.nativeEvent.value, - event.nativeEvent.selection, - ); - if (acknowledgedEventCount === false) return; - onChangeText(event.nativeEvent.value); - onSelectionChange?.(event.nativeEvent.selection); - setMostRecentEventCount(acknowledgedEventCount); - setNativeEventSequence((sequence) => sequence + 1); - }} - onComposerSelectionChange={(event) => { - const acknowledgedEventCount = acceptNativeEvent( - event.nativeEvent.eventCount, - event.nativeEvent.value, - event.nativeEvent.selection, - ); - if (acknowledgedEventCount === false) return; - onSelectionChange?.(event.nativeEvent.selection); - setMostRecentEventCount(acknowledgedEventCount); - setNativeEventSequence((sequence) => sequence + 1); - }} - onComposerPasteImages={(event) => onPasteImages?.(event.nativeEvent.uris)} - onComposerFocus={onFocus} - onComposerBlur={onBlur} - /> + + { + const acknowledgedEventCount = acceptNativeEvent( + event.nativeEvent.eventCount, + event.nativeEvent.value, + event.nativeEvent.selection, + ); + if (acknowledgedEventCount === false) return; + onChangeText(event.nativeEvent.value); + onSelectionChange?.(event.nativeEvent.selection); + setMostRecentEventCount(acknowledgedEventCount); + setNativeEventSequence((sequence) => sequence + 1); + }} + onComposerSelectionChange={(event) => { + const acknowledgedEventCount = acceptNativeEvent( + event.nativeEvent.eventCount, + event.nativeEvent.value, + event.nativeEvent.selection, + ); + if (acknowledgedEventCount === false) return; + onSelectionChange?.(event.nativeEvent.selection); + setMostRecentEventCount(acknowledgedEventCount); + setNativeEventSequence((sequence) => sequence + 1); + }} + onComposerPasteImages={(event) => onPasteImages?.(event.nativeEvent.uris)} + onComposerFocus={onFocus} + onComposerBlur={onBlur} + /> + ); }