@poolse/react-native 2.1.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +106 -123
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.js +102 -123
- package/dist/index.js.map +1 -1
- package/package.json +3 -9
package/dist/index.d.cts
CHANGED
|
@@ -578,7 +578,7 @@ interface AttachmentPickerProps {
|
|
|
578
578
|
* Override to plug in custom storage / transcoding. Default reads
|
|
579
579
|
* from `expo-image-picker` / `expo-document-picker`.
|
|
580
580
|
*/
|
|
581
|
-
onPickInputs?: (kind: 'image' | 'document') => Promise<{
|
|
581
|
+
onPickInputs?: (kind: 'image' | 'document' | 'camera') => Promise<{
|
|
582
582
|
body: {
|
|
583
583
|
uri: string;
|
|
584
584
|
name: string;
|
|
@@ -588,6 +588,14 @@ interface AttachmentPickerProps {
|
|
|
588
588
|
byteSize: number;
|
|
589
589
|
filename?: string;
|
|
590
590
|
}[]>;
|
|
591
|
+
/**
|
|
592
|
+
* Show the Camera item alongside Photo and File. Defaults true.
|
|
593
|
+
* Disable if your app explicitly doesn't want camera access (some
|
|
594
|
+
* App Store reviewers require an explicit usage description even
|
|
595
|
+
* for the picker entry). Add `NSCameraUsageDescription` to your
|
|
596
|
+
* iOS Info.plist when leaving this on.
|
|
597
|
+
*/
|
|
598
|
+
camera?: boolean;
|
|
591
599
|
}
|
|
592
600
|
/**
|
|
593
601
|
* Picker sheet wrapping `expo-image-picker` and `expo-document-picker`.
|
|
@@ -596,7 +604,7 @@ interface AttachmentPickerProps {
|
|
|
596
604
|
* declared as optional peers because consumers who pass
|
|
597
605
|
* `attachments={false}` to ConversationView never render this file.
|
|
598
606
|
*/
|
|
599
|
-
declare function AttachmentPicker({ visible, onClose, onPickInputs }: AttachmentPickerProps): react_jsx_runtime.JSX.Element;
|
|
607
|
+
declare function AttachmentPicker({ visible, onClose, onPickInputs, camera, }: AttachmentPickerProps): react_jsx_runtime.JSX.Element;
|
|
600
608
|
|
|
601
609
|
interface ImageMosaicProps {
|
|
602
610
|
images: Attachment[];
|
|
@@ -633,6 +641,10 @@ declare const ICONS: {
|
|
|
633
641
|
readonly vb: "0 0 24 24";
|
|
634
642
|
readonly d: "<path d=\"M6 9.2a6 6 0 0 1 12 0c0 4.8 1.4 6.3 1.9 6.8H4.1C4.6 15.5 6 14 6 9.2Z\"/><path d=\"M9.6 19.8a2.5 2.5 0 0 0 4.8 0\"/>";
|
|
635
643
|
};
|
|
644
|
+
readonly camera: {
|
|
645
|
+
readonly vb: "0 0 24 24";
|
|
646
|
+
readonly d: "<path d=\"M3 8.5a2 2 0 0 1 2-2h2.4l1.4-2h6.4l1.4 2H19a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-9Z\"/><circle cx=\"12\" cy=\"13\" r=\"3.5\"/>";
|
|
647
|
+
};
|
|
636
648
|
readonly 'check-double': {
|
|
637
649
|
readonly vb: "0 0 24 24";
|
|
638
650
|
readonly d: "<path d=\"M2.5 12.8 6.9 17 15.4 7.6\"/><path d=\"M11.4 16.4 12.3 17.2 21 7.6\"/>";
|
package/dist/index.d.ts
CHANGED
|
@@ -578,7 +578,7 @@ interface AttachmentPickerProps {
|
|
|
578
578
|
* Override to plug in custom storage / transcoding. Default reads
|
|
579
579
|
* from `expo-image-picker` / `expo-document-picker`.
|
|
580
580
|
*/
|
|
581
|
-
onPickInputs?: (kind: 'image' | 'document') => Promise<{
|
|
581
|
+
onPickInputs?: (kind: 'image' | 'document' | 'camera') => Promise<{
|
|
582
582
|
body: {
|
|
583
583
|
uri: string;
|
|
584
584
|
name: string;
|
|
@@ -588,6 +588,14 @@ interface AttachmentPickerProps {
|
|
|
588
588
|
byteSize: number;
|
|
589
589
|
filename?: string;
|
|
590
590
|
}[]>;
|
|
591
|
+
/**
|
|
592
|
+
* Show the Camera item alongside Photo and File. Defaults true.
|
|
593
|
+
* Disable if your app explicitly doesn't want camera access (some
|
|
594
|
+
* App Store reviewers require an explicit usage description even
|
|
595
|
+
* for the picker entry). Add `NSCameraUsageDescription` to your
|
|
596
|
+
* iOS Info.plist when leaving this on.
|
|
597
|
+
*/
|
|
598
|
+
camera?: boolean;
|
|
591
599
|
}
|
|
592
600
|
/**
|
|
593
601
|
* Picker sheet wrapping `expo-image-picker` and `expo-document-picker`.
|
|
@@ -596,7 +604,7 @@ interface AttachmentPickerProps {
|
|
|
596
604
|
* declared as optional peers because consumers who pass
|
|
597
605
|
* `attachments={false}` to ConversationView never render this file.
|
|
598
606
|
*/
|
|
599
|
-
declare function AttachmentPicker({ visible, onClose, onPickInputs }: AttachmentPickerProps): react_jsx_runtime.JSX.Element;
|
|
607
|
+
declare function AttachmentPicker({ visible, onClose, onPickInputs, camera, }: AttachmentPickerProps): react_jsx_runtime.JSX.Element;
|
|
600
608
|
|
|
601
609
|
interface ImageMosaicProps {
|
|
602
610
|
images: Attachment[];
|
|
@@ -633,6 +641,10 @@ declare const ICONS: {
|
|
|
633
641
|
readonly vb: "0 0 24 24";
|
|
634
642
|
readonly d: "<path d=\"M6 9.2a6 6 0 0 1 12 0c0 4.8 1.4 6.3 1.9 6.8H4.1C4.6 15.5 6 14 6 9.2Z\"/><path d=\"M9.6 19.8a2.5 2.5 0 0 0 4.8 0\"/>";
|
|
635
643
|
};
|
|
644
|
+
readonly camera: {
|
|
645
|
+
readonly vb: "0 0 24 24";
|
|
646
|
+
readonly d: "<path d=\"M3 8.5a2 2 0 0 1 2-2h2.4l1.4-2h6.4l1.4 2H19a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-9Z\"/><circle cx=\"12\" cy=\"13\" r=\"3.5\"/>";
|
|
647
|
+
};
|
|
636
648
|
readonly 'check-double': {
|
|
637
649
|
readonly vb: "0 0 24 24";
|
|
638
650
|
readonly d: "<path d=\"M2.5 12.8 6.9 17 15.4 7.6\"/><path d=\"M11.4 16.4 12.3 17.2 21 7.6\"/>";
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { useUser, useMe, useConversations, useAttachmentUpload, useConversation, useMembers, usePresence, useMessages, useTyping, useRealtimeStatus, computeGroupPosition, formatDayLabel, useReactions, sameDay, useThread, useAttachmentUrl, usePoolse } from '@poolse/react';
|
|
2
2
|
import { createContext, forwardRef, useRef, useState, useEffect, useImperativeHandle, useMemo, useCallback, useContext, createElement } from 'react';
|
|
3
|
-
import { StyleSheet, Platform, Keyboard, View, Pressable, TextInput, Text, useWindowDimensions, Animated, Easing, PanResponder, Image, ScrollView, ActivityIndicator, FlatList, AppState, KeyboardAvoidingView, Modal,
|
|
3
|
+
import { StyleSheet, Platform, Keyboard, View, Pressable, TextInput, Text, useWindowDimensions, Animated, Easing, PanResponder, Image, ScrollView, ActivityIndicator, FlatList, AppState, KeyboardAvoidingView, Modal, Dimensions, Linking } from 'react-native';
|
|
4
4
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import { SvgXml, Svg, Path, Circle, G } from 'react-native-svg';
|
|
6
6
|
import * as ImagePicker from 'expo-image-picker';
|
|
7
7
|
import * as DocumentPicker from 'expo-document-picker';
|
|
8
8
|
import { manipulateAsync, SaveFormat } from 'expo-image-manipulator';
|
|
9
|
+
import * as Clipboard from 'expo-clipboard';
|
|
10
|
+
import Markdown from 'react-native-markdown-display';
|
|
9
11
|
|
|
10
12
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
11
13
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
@@ -293,6 +295,10 @@ var ICONS = {
|
|
|
293
295
|
vb: "0 0 24 24",
|
|
294
296
|
d: '<path d="M6 9.2a6 6 0 0 1 12 0c0 4.8 1.4 6.3 1.9 6.8H4.1C4.6 15.5 6 14 6 9.2Z"/><path d="M9.6 19.8a2.5 2.5 0 0 0 4.8 0"/>'
|
|
295
297
|
},
|
|
298
|
+
camera: {
|
|
299
|
+
vb: "0 0 24 24",
|
|
300
|
+
d: '<path d="M3 8.5a2 2 0 0 1 2-2h2.4l1.4-2h6.4l1.4 2H19a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-9Z"/><circle cx="12" cy="13" r="3.5"/>'
|
|
301
|
+
},
|
|
296
302
|
"check-double": {
|
|
297
303
|
vb: "0 0 24 24",
|
|
298
304
|
d: '<path d="M2.5 12.8 6.9 17 15.4 7.6"/><path d="M11.4 16.4 12.3 17.2 21 7.6"/>'
|
|
@@ -1112,7 +1118,12 @@ function useUploadPreview() {
|
|
|
1112
1118
|
getPreview: ctx?.getPreview ?? (() => null)
|
|
1113
1119
|
};
|
|
1114
1120
|
}
|
|
1115
|
-
function AttachmentPicker({
|
|
1121
|
+
function AttachmentPicker({
|
|
1122
|
+
visible,
|
|
1123
|
+
onClose,
|
|
1124
|
+
onPickInputs,
|
|
1125
|
+
camera = true
|
|
1126
|
+
}) {
|
|
1116
1127
|
const theme = usePoolseTheme();
|
|
1117
1128
|
const upload = useSharedUpload();
|
|
1118
1129
|
const { setPreview } = useUploadPreview();
|
|
@@ -1146,8 +1157,12 @@ function AttachmentPicker({ visible, onClose, onPickInputs }) {
|
|
|
1146
1157
|
theme.shadows.lg
|
|
1147
1158
|
],
|
|
1148
1159
|
children: [
|
|
1160
|
+
camera ? /* @__PURE__ */ jsxs(Pressable, { style: styles6.item, onPress: () => pickFromKind("camera"), children: [
|
|
1161
|
+
/* @__PURE__ */ jsx(PoolseIcon, { name: "camera", size: 20, color: theme.colors.ink2 }),
|
|
1162
|
+
/* @__PURE__ */ jsx(Text, { style: [styles6.itemText, { color: theme.colors.ink }], children: "Camera" })
|
|
1163
|
+
] }) : null,
|
|
1149
1164
|
/* @__PURE__ */ jsxs(Pressable, { style: styles6.item, onPress: () => pickFromKind("image"), children: [
|
|
1150
|
-
/* @__PURE__ */ jsx(PoolseIcon, { name: "
|
|
1165
|
+
/* @__PURE__ */ jsx(PoolseIcon, { name: "image", size: 20, color: theme.colors.ink2 }),
|
|
1151
1166
|
/* @__PURE__ */ jsx(Text, { style: [styles6.itemText, { color: theme.colors.ink }], children: "Photo or video" })
|
|
1152
1167
|
] }),
|
|
1153
1168
|
/* @__PURE__ */ jsxs(Pressable, { style: styles6.item, onPress: () => pickFromKind("document"), children: [
|
|
@@ -1206,7 +1221,52 @@ async function compressImage({
|
|
|
1206
1221
|
filename: `${base}.webp`
|
|
1207
1222
|
};
|
|
1208
1223
|
}
|
|
1224
|
+
async function assetsToInputs(assets) {
|
|
1225
|
+
return Promise.all(
|
|
1226
|
+
assets.map(async (asset) => {
|
|
1227
|
+
try {
|
|
1228
|
+
const compressed = await compressImage({
|
|
1229
|
+
uri: asset.uri,
|
|
1230
|
+
width: asset.width,
|
|
1231
|
+
height: asset.height,
|
|
1232
|
+
filename: asset.fileName ?? `image-${Date.now()}`
|
|
1233
|
+
});
|
|
1234
|
+
return {
|
|
1235
|
+
body: compressed.blob,
|
|
1236
|
+
contentType: compressed.contentType,
|
|
1237
|
+
byteSize: compressed.blob.size,
|
|
1238
|
+
filename: compressed.filename,
|
|
1239
|
+
_previewUri: asset.uri
|
|
1240
|
+
};
|
|
1241
|
+
} catch (err) {
|
|
1242
|
+
console.warn("[poolse/picker] image compression failed, sending original:", err);
|
|
1243
|
+
const blob = await uriToBlob(asset.uri);
|
|
1244
|
+
const contentType = asset.mimeType ?? blob.type ?? "image/jpeg";
|
|
1245
|
+
return {
|
|
1246
|
+
body: blob,
|
|
1247
|
+
contentType,
|
|
1248
|
+
byteSize: asset.fileSize ?? blob.size,
|
|
1249
|
+
filename: asset.fileName ?? `image-${Date.now()}.jpg`,
|
|
1250
|
+
_previewUri: asset.uri
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
})
|
|
1254
|
+
);
|
|
1255
|
+
}
|
|
1209
1256
|
async function defaultAdapter(kind) {
|
|
1257
|
+
if (kind === "camera") {
|
|
1258
|
+
const perm = await ImagePicker.requestCameraPermissionsAsync();
|
|
1259
|
+
if (!perm.granted) {
|
|
1260
|
+
console.warn("[poolse/picker] camera permission denied");
|
|
1261
|
+
return [];
|
|
1262
|
+
}
|
|
1263
|
+
const res2 = await ImagePicker.launchCameraAsync({
|
|
1264
|
+
mediaTypes: "images",
|
|
1265
|
+
quality: 1
|
|
1266
|
+
});
|
|
1267
|
+
if (res2.canceled) return [];
|
|
1268
|
+
return assetsToInputs(res2.assets);
|
|
1269
|
+
}
|
|
1210
1270
|
if (kind === "image") {
|
|
1211
1271
|
const res2 = await ImagePicker.launchImageLibraryAsync({
|
|
1212
1272
|
mediaTypes: "images",
|
|
@@ -1216,36 +1276,7 @@ async function defaultAdapter(kind) {
|
|
|
1216
1276
|
quality: 1
|
|
1217
1277
|
});
|
|
1218
1278
|
if (res2.canceled) return [];
|
|
1219
|
-
return
|
|
1220
|
-
res2.assets.map(async (asset) => {
|
|
1221
|
-
try {
|
|
1222
|
-
const compressed = await compressImage({
|
|
1223
|
-
uri: asset.uri,
|
|
1224
|
-
width: asset.width,
|
|
1225
|
-
height: asset.height,
|
|
1226
|
-
filename: asset.fileName ?? `image-${Date.now()}`
|
|
1227
|
-
});
|
|
1228
|
-
return {
|
|
1229
|
-
body: compressed.blob,
|
|
1230
|
-
contentType: compressed.contentType,
|
|
1231
|
-
byteSize: compressed.blob.size,
|
|
1232
|
-
filename: compressed.filename,
|
|
1233
|
-
_previewUri: asset.uri
|
|
1234
|
-
};
|
|
1235
|
-
} catch (err) {
|
|
1236
|
-
console.warn("[poolse/picker] image compression failed, sending original:", err);
|
|
1237
|
-
const blob = await uriToBlob(asset.uri);
|
|
1238
|
-
const contentType = asset.mimeType ?? blob.type ?? "image/jpeg";
|
|
1239
|
-
return {
|
|
1240
|
-
body: blob,
|
|
1241
|
-
contentType,
|
|
1242
|
-
byteSize: asset.fileSize ?? blob.size,
|
|
1243
|
-
filename: asset.fileName ?? `image-${Date.now()}.jpg`,
|
|
1244
|
-
_previewUri: asset.uri
|
|
1245
|
-
};
|
|
1246
|
-
}
|
|
1247
|
-
})
|
|
1248
|
-
);
|
|
1279
|
+
return assetsToInputs(res2.assets);
|
|
1249
1280
|
}
|
|
1250
1281
|
const res = await DocumentPicker.getDocumentAsync({
|
|
1251
1282
|
copyToCacheDirectory: true,
|
|
@@ -2580,31 +2611,7 @@ var styles14 = StyleSheet.create({
|
|
|
2580
2611
|
borderRadius: 20
|
|
2581
2612
|
}
|
|
2582
2613
|
});
|
|
2583
|
-
var MarkdownModule;
|
|
2584
|
-
var warned = false;
|
|
2585
|
-
function loadMarkdown() {
|
|
2586
|
-
if (MarkdownModule === void 0) {
|
|
2587
|
-
try {
|
|
2588
|
-
MarkdownModule = __require("react-native-markdown-display");
|
|
2589
|
-
} catch {
|
|
2590
|
-
MarkdownModule = null;
|
|
2591
|
-
}
|
|
2592
|
-
}
|
|
2593
|
-
const fn = MarkdownModule?.default;
|
|
2594
|
-
if (!fn) {
|
|
2595
|
-
if (!warned) {
|
|
2596
|
-
warned = true;
|
|
2597
|
-
console.warn(
|
|
2598
|
-
"[@poolse/react-native] Markdown rendering requires `react-native-markdown-display`. Install it to enable bold/italic/code/links in message bubbles. Falling back to plain text."
|
|
2599
|
-
);
|
|
2600
|
-
}
|
|
2601
|
-
return null;
|
|
2602
|
-
}
|
|
2603
|
-
return fn;
|
|
2604
|
-
}
|
|
2605
2614
|
function renderMarkdown(body, args) {
|
|
2606
|
-
const Markdown = loadMarkdown();
|
|
2607
|
-
if (!Markdown) return null;
|
|
2608
2615
|
const baseText = {
|
|
2609
2616
|
color: args.textColor,
|
|
2610
2617
|
fontFamily: args.fontFamily,
|
|
@@ -2747,53 +2754,46 @@ function MessageBubble({
|
|
|
2747
2754
|
) : null,
|
|
2748
2755
|
renderAttachments && images.length > 0 ? /* @__PURE__ */ jsx(ImageMosaic, { images, maxWidth: contentMaxWidth }) : null,
|
|
2749
2756
|
renderAttachments && files.length > 0 ? /* @__PURE__ */ jsx(View, { style: { gap: theme.spacing.xs, marginBottom: theme.spacing.xs }, children: files.map((att) => /* @__PURE__ */ jsx(AttachmentPreview, { attachment: att, maxWidth: contentMaxWidth }, att.id)) }) : null,
|
|
2750
|
-
body.length > 0 ?
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2757
|
+
body.length > 0 ? isDeleted ? /* @__PURE__ */ jsx(
|
|
2758
|
+
Text,
|
|
2759
|
+
{
|
|
2760
|
+
style: [
|
|
2761
|
+
styles15.body,
|
|
2754
2762
|
{
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
fontSize: theme.type.bodySize,
|
|
2761
|
-
lineHeight: theme.type.lineHeight,
|
|
2762
|
-
fontStyle: "italic"
|
|
2763
|
-
}
|
|
2764
|
-
],
|
|
2765
|
-
children: "Message deleted"
|
|
2763
|
+
color: theme.colors.ink3,
|
|
2764
|
+
fontFamily: theme.type.fontBody,
|
|
2765
|
+
fontSize: theme.type.bodySize,
|
|
2766
|
+
lineHeight: theme.type.lineHeight,
|
|
2767
|
+
fontStyle: "italic"
|
|
2766
2768
|
}
|
|
2767
|
-
|
|
2769
|
+
],
|
|
2770
|
+
children: "Message deleted"
|
|
2768
2771
|
}
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
}
|
|
2795
|
-
);
|
|
2796
|
-
})() : null,
|
|
2772
|
+
) : markdown ? renderMarkdown(truncated, {
|
|
2773
|
+
textColor,
|
|
2774
|
+
linkColor: isSelf ? theme.colors.onBrand : theme.colors.brand,
|
|
2775
|
+
fontFamily: theme.type.fontBody,
|
|
2776
|
+
fontSize: theme.type.bodySize,
|
|
2777
|
+
lineHeight: theme.type.lineHeight,
|
|
2778
|
+
onLinkPress: (url) => {
|
|
2779
|
+
void Linking.openURL(url).catch(() => void 0);
|
|
2780
|
+
return false;
|
|
2781
|
+
}
|
|
2782
|
+
}) : /* @__PURE__ */ jsx(
|
|
2783
|
+
Text,
|
|
2784
|
+
{
|
|
2785
|
+
style: [
|
|
2786
|
+
styles15.body,
|
|
2787
|
+
{
|
|
2788
|
+
color: textColor,
|
|
2789
|
+
fontFamily: theme.type.fontBody,
|
|
2790
|
+
fontSize: theme.type.bodySize,
|
|
2791
|
+
lineHeight: theme.type.lineHeight
|
|
2792
|
+
}
|
|
2793
|
+
],
|
|
2794
|
+
children: truncated
|
|
2795
|
+
}
|
|
2796
|
+
) : null,
|
|
2797
2797
|
maxBodyLength > 0 && body.length > maxBodyLength ? /* @__PURE__ */ jsx(Pressable, { onPress: () => setExpanded((e) => !e), children: /* @__PURE__ */ jsx(
|
|
2798
2798
|
Text,
|
|
2799
2799
|
{
|
|
@@ -3330,7 +3330,7 @@ function MessageRow({
|
|
|
3330
3330
|
...msg.body && !msg.deleted_at ? {
|
|
3331
3331
|
onCopy: () => {
|
|
3332
3332
|
setActionsOpen(false);
|
|
3333
|
-
void
|
|
3333
|
+
void Clipboard.setStringAsync(msg.body ?? "");
|
|
3334
3334
|
}
|
|
3335
3335
|
} : {},
|
|
3336
3336
|
...onStartEdit ? {
|
|
@@ -3422,27 +3422,6 @@ var styles17 = StyleSheet.create({
|
|
|
3422
3422
|
marginTop: 2
|
|
3423
3423
|
}
|
|
3424
3424
|
});
|
|
3425
|
-
var clipboardModule;
|
|
3426
|
-
var clipboardWarned = false;
|
|
3427
|
-
async function copyToClipboard(text) {
|
|
3428
|
-
if (clipboardModule === void 0) {
|
|
3429
|
-
try {
|
|
3430
|
-
clipboardModule = __require("expo-clipboard");
|
|
3431
|
-
} catch {
|
|
3432
|
-
clipboardModule = null;
|
|
3433
|
-
}
|
|
3434
|
-
}
|
|
3435
|
-
if (!clipboardModule?.setStringAsync) {
|
|
3436
|
-
if (!clipboardWarned) {
|
|
3437
|
-
clipboardWarned = true;
|
|
3438
|
-
console.warn(
|
|
3439
|
-
"[@poolse/react-native] Copy action requires `expo-clipboard`. Install it to enable copy-to-clipboard."
|
|
3440
|
-
);
|
|
3441
|
-
}
|
|
3442
|
-
return;
|
|
3443
|
-
}
|
|
3444
|
-
await clipboardModule.setStringAsync(text);
|
|
3445
|
-
}
|
|
3446
3425
|
var SHEET_HEIGHT_FRACTION = 0.88;
|
|
3447
3426
|
function ThreadView({
|
|
3448
3427
|
visible,
|