@poolse/react-native 2.9.0 → 2.10.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.js CHANGED
@@ -1,7 +1,7 @@
1
- import { useUser, useMe, useConversations, useAttachmentUpload, useConversation, useMembers, usePresence, useMessages, useTyping, useRealtimeStatus, computeGroupPosition, formatDayLabel, useReactions, sameDay, useThread, useAttachmentUrl, usePoolse, useVoiceRoom, useCalls } from '@poolse/react';
2
- import { createContext, forwardRef, useRef, useState, useEffect, useImperativeHandle, useMemo, useCallback, useContext, createElement } from 'react';
3
1
  import { StyleSheet, Platform, Keyboard, View, Pressable, TextInput, Text, useWindowDimensions, Animated, Easing, PanResponder, Image, ScrollView, ActivityIndicator, FlatList, AppState, KeyboardAvoidingView, Modal, Dimensions, Linking } from 'react-native';
2
+ import { createContext, forwardRef, useRef, useState, useEffect, useImperativeHandle, useMemo, useCallback, useContext, createElement } from 'react';
4
3
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
+ import { useUser, useMe, useConversations, useAttachmentUpload, useConversation, useMembers, usePresence, useMessages, useTyping, useRealtimeStatus, computeGroupPosition, formatDayLabel, useReactions, sameDay, useThread, useAttachmentUrl, usePoolse, useVoiceRoom, useCalls, useCallRoom } from '@poolse/react';
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';
@@ -179,6 +179,79 @@ function PoolseTheme({ mode, theme, children }) {
179
179
  function usePoolseTheme() {
180
180
  return useContext(ThemeContext) ?? defaultLightTheme;
181
181
  }
182
+ function CallVideoGrid({ participants, livekitReactNative, labelFor }) {
183
+ const theme = usePoolseTheme();
184
+ const label = labelFor ?? ((id) => `User ${id.slice(0, 6)}`);
185
+ const VideoTrack = livekitReactNative?.VideoTrack;
186
+ if (participants.length === 0) return null;
187
+ const columns = participants.length <= 1 ? 1 : 2;
188
+ const basis = columns === 1 ? "100%" : "48%";
189
+ return /* @__PURE__ */ jsx(View, { style: styles.grid, children: participants.map((participant) => /* @__PURE__ */ jsxs(
190
+ View,
191
+ {
192
+ style: [
193
+ styles.tile,
194
+ {
195
+ flexBasis: basis,
196
+ backgroundColor: theme.colors.surface,
197
+ // A ring rather than a badge: it reads at a glance in a
198
+ // grid, and doesn't cover a face.
199
+ borderColor: participant.speaking ? theme.colors.brand : "transparent"
200
+ }
201
+ ],
202
+ children: [
203
+ participant.videoTrackRef && VideoTrack ? /* @__PURE__ */ jsx(
204
+ VideoTrack,
205
+ {
206
+ trackRef: participant.videoTrackRef,
207
+ style: styles.video,
208
+ objectFit: "cover",
209
+ mirror: participant.isSelf,
210
+ zOrder: participant.isSelf ? 1 : 0
211
+ }
212
+ ) : /* @__PURE__ */ jsx(View, { style: styles.placeholder, children: /* @__PURE__ */ jsx(Text, { style: [styles.initial, { color: theme.colors.ink3 }], children: label(participant.userId).slice(0, 1).toUpperCase() }) }),
213
+ /* @__PURE__ */ jsxs(View, { style: styles.caption, children: [
214
+ /* @__PURE__ */ jsx(Text, { numberOfLines: 1, style: [styles.name, { color: theme.colors.onBrand }], children: participant.isSelf ? "You" : participant.name ?? label(participant.userId) }),
215
+ !participant.micEnabled && // Muted is worth showing even for yourself — it is the
216
+ // answer to "why can nobody hear me".
217
+ /* @__PURE__ */ jsx(Text, { style: [styles.muted, { color: theme.colors.onBrand }], children: "muted" })
218
+ ] })
219
+ ]
220
+ },
221
+ participant.userId
222
+ )) });
223
+ }
224
+ var styles = StyleSheet.create({
225
+ grid: {
226
+ flex: 1,
227
+ flexDirection: "row",
228
+ flexWrap: "wrap",
229
+ justifyContent: "center",
230
+ alignContent: "center",
231
+ gap: 8
232
+ },
233
+ tile: {
234
+ aspectRatio: 3 / 4,
235
+ borderRadius: 16,
236
+ borderWidth: 2,
237
+ overflow: "hidden",
238
+ justifyContent: "flex-end"
239
+ },
240
+ video: { ...StyleSheet.absoluteFillObject },
241
+ placeholder: { ...StyleSheet.absoluteFillObject, alignItems: "center", justifyContent: "center" },
242
+ initial: { fontSize: 48, fontWeight: "600" },
243
+ caption: {
244
+ flexDirection: "row",
245
+ alignItems: "center",
246
+ gap: 6,
247
+ paddingHorizontal: 10,
248
+ paddingVertical: 6,
249
+ // Legible over both a bright video frame and a flat placeholder.
250
+ backgroundColor: "rgba(0,0,0,0.45)"
251
+ },
252
+ name: { flexShrink: 1, fontSize: 13, fontWeight: "600" },
253
+ muted: { fontSize: 11, opacity: 0.85 }
254
+ });
182
255
 
183
256
  // src/primitives/userColor.ts
184
257
  var PALETTE = [
@@ -217,7 +290,7 @@ function Avatar({ src, name, seed, online, size = "md" }) {
217
290
  View,
218
291
  {
219
292
  style: [
220
- styles.root,
293
+ styles2.root,
221
294
  {
222
295
  width: dim,
223
296
  height: dim,
@@ -251,7 +324,7 @@ function Avatar({ src, name, seed, online, size = "md" }) {
251
324
  View,
252
325
  {
253
326
  style: [
254
- styles.presence,
327
+ styles2.presence,
255
328
  {
256
329
  backgroundColor: theme.colors.presence,
257
330
  borderColor: theme.colors.surface,
@@ -271,7 +344,7 @@ function computeInitials(name) {
271
344
  const parts = name.trim().split(/\s+/).slice(0, 2);
272
345
  return parts.map((p) => p.charAt(0).toUpperCase()).join("").slice(0, 2) || "?";
273
346
  }
274
- var styles = StyleSheet.create({
347
+ var styles2 = StyleSheet.create({
275
348
  root: {
276
349
  alignItems: "center",
277
350
  justifyContent: "center",
@@ -481,16 +554,16 @@ function MemberList({
481
554
  );
482
555
  const effectiveOnline = onlineExternalIds ?? presenceOnline;
483
556
  if (loading && members.length === 0) {
484
- return /* @__PURE__ */ jsx(View, { style: [styles2.placeholder, { backgroundColor: theme.colors.paper }], children: /* @__PURE__ */ jsx(ActivityIndicator, { color: theme.colors.brand }) });
557
+ return /* @__PURE__ */ jsx(View, { style: [styles3.placeholder, { backgroundColor: theme.colors.paper }], children: /* @__PURE__ */ jsx(ActivityIndicator, { color: theme.colors.brand }) });
485
558
  }
486
559
  if (error) {
487
- return /* @__PURE__ */ jsxs(View, { style: [styles2.placeholder, { backgroundColor: theme.colors.paper }], children: [
560
+ return /* @__PURE__ */ jsxs(View, { style: [styles3.placeholder, { backgroundColor: theme.colors.paper }], children: [
488
561
  /* @__PURE__ */ jsx(Text, { style: { color: theme.colors.error, fontFamily: theme.type.fontBody }, children: "Failed to load members." }),
489
- error.message ? /* @__PURE__ */ jsx(Text, { style: [styles2.errorDetail, { color: theme.colors.ink3 }], children: error.message }) : null
562
+ error.message ? /* @__PURE__ */ jsx(Text, { style: [styles3.errorDetail, { color: theme.colors.ink3 }], children: error.message }) : null
490
563
  ] });
491
564
  }
492
565
  if (members.length === 0) {
493
- return /* @__PURE__ */ jsx(View, { style: [styles2.placeholder, { backgroundColor: theme.colors.paper }], children: typeof emptyState === "string" || emptyState == null ? /* @__PURE__ */ jsx(Text, { style: { color: theme.colors.ink3, fontFamily: theme.type.fontBody }, children: emptyState ?? "No members." }) : emptyState });
566
+ return /* @__PURE__ */ jsx(View, { style: [styles3.placeholder, { backgroundColor: theme.colors.paper }], children: typeof emptyState === "string" || emptyState == null ? /* @__PURE__ */ jsx(Text, { style: { color: theme.colors.ink3, fontFamily: theme.type.fontBody }, children: emptyState ?? "No members." }) : emptyState });
494
567
  }
495
568
  return /* @__PURE__ */ jsx(
496
569
  FlatList,
@@ -529,23 +602,23 @@ function MemberRow({
529
602
  const resolved = useUser(externalId);
530
603
  const name = labelFor?.(externalId) ?? resolved.profile?.displayName ?? externalId;
531
604
  const avatarUrl = avatarFor?.(externalId) ?? resolved.profile?.avatarUrl ?? null;
532
- return /* @__PURE__ */ jsxs(View, { style: styles2.row, children: [
605
+ return /* @__PURE__ */ jsxs(View, { style: styles3.row, children: [
533
606
  /* @__PURE__ */ jsx(Avatar, { src: avatarUrl, name, seed: externalId, online, size: "md" }),
534
- /* @__PURE__ */ jsxs(View, { style: styles2.body, children: [
607
+ /* @__PURE__ */ jsxs(View, { style: styles3.body, children: [
535
608
  /* @__PURE__ */ jsx(
536
609
  Text,
537
610
  {
538
- style: [styles2.name, { color: theme.colors.ink, fontFamily: theme.type.fontBody }],
611
+ style: [styles3.name, { color: theme.colors.ink, fontFamily: theme.type.fontBody }],
539
612
  numberOfLines: 1,
540
613
  children: name
541
614
  }
542
615
  ),
543
- /* @__PURE__ */ jsx(Text, { style: [styles2.role, { color: theme.colors.ink3 }], children: role })
616
+ /* @__PURE__ */ jsx(Text, { style: [styles3.role, { color: theme.colors.ink3 }], children: role })
544
617
  ] }),
545
- onRemove ? /* @__PURE__ */ jsx(Pressable, { onPress: onRemove, hitSlop: 8, style: styles2.removeBtn, children: /* @__PURE__ */ jsx(PoolseIcon, { name: "close", size: 16, color: theme.colors.ink2 }) }) : null
618
+ onRemove ? /* @__PURE__ */ jsx(Pressable, { onPress: onRemove, hitSlop: 8, style: styles3.removeBtn, children: /* @__PURE__ */ jsx(PoolseIcon, { name: "close", size: 16, color: theme.colors.ink2 }) }) : null
546
619
  ] });
547
620
  }
548
- var styles2 = StyleSheet.create({
621
+ var styles3 = StyleSheet.create({
549
622
  placeholder: {
550
623
  flex: 1,
551
624
  alignItems: "center",
@@ -648,11 +721,11 @@ function GroupDetailsSheet({
648
721
  animationType: "slide",
649
722
  onRequestClose: onClose,
650
723
  statusBarTranslucent: true,
651
- children: /* @__PURE__ */ jsxs(View, { style: styles3.modalRoot, children: [
724
+ children: /* @__PURE__ */ jsxs(View, { style: styles4.modalRoot, children: [
652
725
  /* @__PURE__ */ jsx(
653
726
  Pressable,
654
727
  {
655
- style: styles3.backdrop,
728
+ style: styles4.backdrop,
656
729
  onPress: onClose,
657
730
  accessibilityLabel: "Close group details"
658
731
  }
@@ -661,7 +734,7 @@ function GroupDetailsSheet({
661
734
  Animated.View,
662
735
  {
663
736
  style: [
664
- styles3.sheet,
737
+ styles4.sheet,
665
738
  {
666
739
  backgroundColor: theme.colors.paper,
667
740
  borderTopLeftRadius: theme.radii.xl,
@@ -671,14 +744,14 @@ function GroupDetailsSheet({
671
744
  theme.shadows.lg
672
745
  ],
673
746
  children: [
674
- /* @__PURE__ */ jsx(View, { ...panHandlers, style: styles3.dragHandle, children: /* @__PURE__ */ jsx(View, { style: [styles3.dragPill, { backgroundColor: theme.colors.ink3 }] }) }),
675
- /* @__PURE__ */ jsxs(View, { style: styles3.headerRow, children: [
747
+ /* @__PURE__ */ jsx(View, { ...panHandlers, style: styles4.dragHandle, children: /* @__PURE__ */ jsx(View, { style: [styles4.dragPill, { backgroundColor: theme.colors.ink3 }] }) }),
748
+ /* @__PURE__ */ jsxs(View, { style: styles4.headerRow, children: [
676
749
  /* @__PURE__ */ jsx(
677
750
  Pressable,
678
751
  {
679
752
  onPress: onClose,
680
753
  hitSlop: 16,
681
- style: [styles3.closeBtn, { backgroundColor: theme.colors.surface2 }],
754
+ style: [styles4.closeBtn, { backgroundColor: theme.colors.surface2 }],
682
755
  accessibilityLabel: "Close",
683
756
  children: /* @__PURE__ */ jsx(PoolseIcon, { name: "close", size: 18, color: theme.colors.ink })
684
757
  }
@@ -687,34 +760,34 @@ function GroupDetailsSheet({
687
760
  Text,
688
761
  {
689
762
  style: [
690
- styles3.headerTitle,
763
+ styles4.headerTitle,
691
764
  { color: theme.colors.ink, fontFamily: theme.type.fontDisplay }
692
765
  ],
693
766
  children: "Group details"
694
767
  }
695
768
  )
696
769
  ] }),
697
- /* @__PURE__ */ jsxs(View, { style: styles3.summary, children: [
770
+ /* @__PURE__ */ jsxs(View, { style: styles4.summary, children: [
698
771
  /* @__PURE__ */ jsx(Avatar, { src: null, name: title, seed: conversationId, size: "lg" }),
699
772
  /* @__PURE__ */ jsx(
700
773
  Text,
701
774
  {
702
775
  style: [
703
- styles3.title,
776
+ styles4.title,
704
777
  { color: theme.colors.ink, fontFamily: theme.type.fontDisplay }
705
778
  ],
706
779
  numberOfLines: 1,
707
780
  children: title
708
781
  }
709
782
  ),
710
- /* @__PURE__ */ jsx(Text, { style: [styles3.subtitle, { color: theme.colors.ink3 }], children: subtitle })
783
+ /* @__PURE__ */ jsx(Text, { style: [styles4.subtitle, { color: theme.colors.ink3 }], children: subtitle })
711
784
  ] }),
712
- /* @__PURE__ */ jsx(View, { style: [styles3.divider, { backgroundColor: theme.colors.border }] }),
713
- /* @__PURE__ */ jsx(View, { style: styles3.sectionLabelRow, children: /* @__PURE__ */ jsx(
785
+ /* @__PURE__ */ jsx(View, { style: [styles4.divider, { backgroundColor: theme.colors.border }] }),
786
+ /* @__PURE__ */ jsx(View, { style: styles4.sectionLabelRow, children: /* @__PURE__ */ jsx(
714
787
  Text,
715
788
  {
716
789
  style: [
717
- styles3.sectionLabel,
790
+ styles4.sectionLabel,
718
791
  { color: theme.colors.ink2, fontFamily: theme.type.fontBody }
719
792
  ],
720
793
  children: "Members"
@@ -737,7 +810,7 @@ function GroupDetailsSheet({
737
810
  }
738
811
  );
739
812
  }
740
- var styles3 = StyleSheet.create({
813
+ var styles4 = StyleSheet.create({
741
814
  modalRoot: {
742
815
  flex: 1,
743
816
  justifyContent: "flex-end"
@@ -831,7 +904,7 @@ function ChatHeader({
831
904
  View,
832
905
  {
833
906
  style: [
834
- styles4.root,
907
+ styles5.root,
835
908
  {
836
909
  backgroundColor: theme.colors.surface,
837
910
  borderBottomColor: theme.colors.border
@@ -856,32 +929,32 @@ function ChatHeader({
856
929
  {
857
930
  ...headerOnPress ? { onPress: headerOnPress } : {},
858
931
  style: [
859
- styles4.root,
932
+ styles5.root,
860
933
  {
861
934
  backgroundColor: theme.colors.surface,
862
935
  borderBottomColor: theme.colors.border
863
936
  }
864
937
  ],
865
938
  children: [
866
- onBack ? /* @__PURE__ */ jsx(Pressable, { onPress: onBack, hitSlop: 12, style: styles4.backBtn, accessibilityLabel: "Back", children: /* @__PURE__ */ jsx(PoolseIcon, { name: "reply", size: 20, color: theme.colors.ink }) }) : null,
939
+ onBack ? /* @__PURE__ */ jsx(Pressable, { onPress: onBack, hitSlop: 12, style: styles5.backBtn, accessibilityLabel: "Back", children: /* @__PURE__ */ jsx(PoolseIcon, { name: "reply", size: 20, color: theme.colors.ink }) }) : null,
867
940
  /* @__PURE__ */ jsx(Avatar, { src: avatarUrl, name: title, seed: avatarSeed, online: isOnline, size: "md" }),
868
- /* @__PURE__ */ jsxs(View, { style: styles4.titleCol, children: [
941
+ /* @__PURE__ */ jsxs(View, { style: styles5.titleCol, children: [
869
942
  /* @__PURE__ */ jsx(
870
943
  Text,
871
944
  {
872
- style: [styles4.title, { color: theme.colors.ink, fontFamily: theme.type.fontDisplay }],
945
+ style: [styles5.title, { color: theme.colors.ink, fontFamily: theme.type.fontDisplay }],
873
946
  numberOfLines: 1,
874
947
  children: title
875
948
  }
876
949
  ),
877
- subtitle ? /* @__PURE__ */ jsx(Text, { style: [styles4.subtitle, { color: theme.colors.ink3 }], numberOfLines: 1, children: subtitle }) : null
950
+ subtitle ? /* @__PURE__ */ jsx(Text, { style: [styles5.subtitle, { color: theme.colors.ink3 }], numberOfLines: 1, children: subtitle }) : null
878
951
  ] }),
879
952
  onMembersPress ? /* @__PURE__ */ jsx(
880
953
  Pressable,
881
954
  {
882
955
  onPress: onMembersPress,
883
956
  hitSlop: 12,
884
- style: styles4.actionBtn,
957
+ style: styles5.actionBtn,
885
958
  accessibilityLabel: "Show members",
886
959
  children: /* @__PURE__ */ jsx(PoolseIcon, { name: "users", size: 20, color: theme.colors.ink2 })
887
960
  }
@@ -901,7 +974,7 @@ function ChatHeader({
901
974
  ) : null
902
975
  ] });
903
976
  }
904
- var styles4 = StyleSheet.create({
977
+ var styles5 = StyleSheet.create({
905
978
  root: {
906
979
  flexDirection: "row",
907
980
  alignItems: "center",
@@ -959,13 +1032,13 @@ function ConversationList({
959
1032
  const error = isControlled ? controlledError ?? null : auto.error;
960
1033
  const counts = unreadCounts ?? (isControlled ? void 0 : auto.unreadCounts);
961
1034
  if (loading && conversations.length === 0) {
962
- return /* @__PURE__ */ jsx(View, { style: [styles5.placeholder, { backgroundColor: theme.colors.paper }], children: /* @__PURE__ */ jsx(ActivityIndicator, { color: theme.colors.brand }) });
1035
+ return /* @__PURE__ */ jsx(View, { style: [styles6.placeholder, { backgroundColor: theme.colors.paper }], children: /* @__PURE__ */ jsx(ActivityIndicator, { color: theme.colors.brand }) });
963
1036
  }
964
1037
  if (error) {
965
- return /* @__PURE__ */ jsx(View, { style: [styles5.placeholder, { backgroundColor: theme.colors.paper }], children: /* @__PURE__ */ jsx(Text, { style: { color: theme.colors.error, fontFamily: theme.type.fontBody }, children: "Failed to load conversations." }) });
1038
+ return /* @__PURE__ */ jsx(View, { style: [styles6.placeholder, { backgroundColor: theme.colors.paper }], children: /* @__PURE__ */ jsx(Text, { style: { color: theme.colors.error, fontFamily: theme.type.fontBody }, children: "Failed to load conversations." }) });
966
1039
  }
967
1040
  if (conversations.length === 0) {
968
- return /* @__PURE__ */ jsx(View, { style: [styles5.placeholder, { backgroundColor: theme.colors.paper }], children: typeof emptyState === "string" || emptyState == null ? /* @__PURE__ */ jsx(Text, { style: { color: theme.colors.ink3, fontFamily: theme.type.fontBody }, children: emptyState ?? "No conversations yet." }) : emptyState });
1041
+ return /* @__PURE__ */ jsx(View, { style: [styles6.placeholder, { backgroundColor: theme.colors.paper }], children: typeof emptyState === "string" || emptyState == null ? /* @__PURE__ */ jsx(Text, { style: { color: theme.colors.ink3, fontFamily: theme.type.fontBody }, children: emptyState ?? "No conversations yet." }) : emptyState });
969
1042
  }
970
1043
  return /* @__PURE__ */ jsx(
971
1044
  FlatList,
@@ -1015,25 +1088,25 @@ function ConversationRow({
1015
1088
  {
1016
1089
  onPress: () => onSelect?.(conv),
1017
1090
  style: [
1018
- styles5.row,
1091
+ styles6.row,
1019
1092
  {
1020
1093
  backgroundColor: selected ? theme.colors.surface2 : "transparent"
1021
1094
  }
1022
1095
  ],
1023
1096
  children: [
1024
- avatarUrl ? /* @__PURE__ */ jsx(Image, { source: { uri: avatarUrl }, style: styles5.rowAvatar }) : /* @__PURE__ */ jsx(Avatar, { src: null, name: title, seed: avatarSeed, size: "md" }),
1025
- /* @__PURE__ */ jsxs(View, { style: styles5.body, children: [
1097
+ avatarUrl ? /* @__PURE__ */ jsx(Image, { source: { uri: avatarUrl }, style: styles6.rowAvatar }) : /* @__PURE__ */ jsx(Avatar, { src: null, name: title, seed: avatarSeed, size: "md" }),
1098
+ /* @__PURE__ */ jsxs(View, { style: styles6.body, children: [
1026
1099
  /* @__PURE__ */ jsx(
1027
1100
  Text,
1028
1101
  {
1029
- style: [styles5.name, { color: theme.colors.ink, fontFamily: theme.type.fontBody }],
1102
+ style: [styles6.name, { color: theme.colors.ink, fontFamily: theme.type.fontBody }],
1030
1103
  numberOfLines: 1,
1031
1104
  children: title
1032
1105
  }
1033
1106
  ),
1034
- conv.last_message_preview ? /* @__PURE__ */ jsx(Text, { style: [styles5.preview, { color: theme.colors.ink3 }], numberOfLines: 1, children: conv.last_message_preview }) : conv.last_message_at ? /* @__PURE__ */ jsx(Text, { style: [styles5.preview, { color: theme.colors.ink3 }], numberOfLines: 1, children: formatRelative(conv.last_message_at) }) : null
1107
+ conv.last_message_preview ? /* @__PURE__ */ jsx(Text, { style: [styles6.preview, { color: theme.colors.ink3 }], numberOfLines: 1, children: conv.last_message_preview }) : conv.last_message_at ? /* @__PURE__ */ jsx(Text, { style: [styles6.preview, { color: theme.colors.ink3 }], numberOfLines: 1, children: formatRelative(conv.last_message_at) }) : null
1035
1108
  ] }),
1036
- unread > 0 ? /* @__PURE__ */ jsx(View, { style: [styles5.unreadPill, { backgroundColor: theme.colors.unreadPill }], children: /* @__PURE__ */ jsx(Text, { style: [styles5.unreadText, { color: theme.colors.unreadPillText }], children: unread > 99 ? "99+" : String(unread) }) }) : null
1109
+ unread > 0 ? /* @__PURE__ */ jsx(View, { style: [styles6.unreadPill, { backgroundColor: theme.colors.unreadPill }], children: /* @__PURE__ */ jsx(Text, { style: [styles6.unreadText, { color: theme.colors.unreadPillText }], children: unread > 99 ? "99+" : String(unread) }) }) : null
1037
1110
  ]
1038
1111
  }
1039
1112
  );
@@ -1051,7 +1124,7 @@ function formatRelative(iso) {
1051
1124
  return "";
1052
1125
  }
1053
1126
  }
1054
- var styles5 = StyleSheet.create({
1127
+ var styles6 = StyleSheet.create({
1055
1128
  placeholder: {
1056
1129
  flex: 1,
1057
1130
  alignItems: "center",
@@ -1144,11 +1217,11 @@ function AttachmentPicker({
1144
1217
  onClose();
1145
1218
  }
1146
1219
  };
1147
- return /* @__PURE__ */ jsx(Modal, { visible, transparent: true, animationType: "slide", onRequestClose: onClose, children: /* @__PURE__ */ jsx(Pressable, { style: styles6.backdrop, onPress: onClose, children: /* @__PURE__ */ jsxs(
1220
+ return /* @__PURE__ */ jsx(Modal, { visible, transparent: true, animationType: "slide", onRequestClose: onClose, children: /* @__PURE__ */ jsx(Pressable, { style: styles7.backdrop, onPress: onClose, children: /* @__PURE__ */ jsxs(
1148
1221
  View,
1149
1222
  {
1150
1223
  style: [
1151
- styles6.sheet,
1224
+ styles7.sheet,
1152
1225
  {
1153
1226
  backgroundColor: theme.colors.surface,
1154
1227
  borderTopLeftRadius: theme.radii.lg,
@@ -1157,19 +1230,19 @@ function AttachmentPicker({
1157
1230
  theme.shadows.lg
1158
1231
  ],
1159
1232
  children: [
1160
- camera ? /* @__PURE__ */ jsxs(Pressable, { style: styles6.item, onPress: () => pickFromKind("camera"), children: [
1233
+ camera ? /* @__PURE__ */ jsxs(Pressable, { style: styles7.item, onPress: () => pickFromKind("camera"), children: [
1161
1234
  /* @__PURE__ */ jsx(PoolseIcon, { name: "camera", size: 20, color: theme.colors.ink2 }),
1162
- /* @__PURE__ */ jsx(Text, { style: [styles6.itemText, { color: theme.colors.ink }], children: "Camera" })
1235
+ /* @__PURE__ */ jsx(Text, { style: [styles7.itemText, { color: theme.colors.ink }], children: "Camera" })
1163
1236
  ] }) : null,
1164
- /* @__PURE__ */ jsxs(Pressable, { style: styles6.item, onPress: () => pickFromKind("image"), children: [
1237
+ /* @__PURE__ */ jsxs(Pressable, { style: styles7.item, onPress: () => pickFromKind("image"), children: [
1165
1238
  /* @__PURE__ */ jsx(PoolseIcon, { name: "image", size: 20, color: theme.colors.ink2 }),
1166
- /* @__PURE__ */ jsx(Text, { style: [styles6.itemText, { color: theme.colors.ink }], children: "Photo or video" })
1239
+ /* @__PURE__ */ jsx(Text, { style: [styles7.itemText, { color: theme.colors.ink }], children: "Photo or video" })
1167
1240
  ] }),
1168
- /* @__PURE__ */ jsxs(Pressable, { style: styles6.item, onPress: () => pickFromKind("document"), children: [
1241
+ /* @__PURE__ */ jsxs(Pressable, { style: styles7.item, onPress: () => pickFromKind("document"), children: [
1169
1242
  /* @__PURE__ */ jsx(PoolseIcon, { name: "attachment", size: 20, color: theme.colors.ink2 }),
1170
- /* @__PURE__ */ jsx(Text, { style: [styles6.itemText, { color: theme.colors.ink }], children: "File" })
1243
+ /* @__PURE__ */ jsx(Text, { style: [styles7.itemText, { color: theme.colors.ink }], children: "File" })
1171
1244
  ] }),
1172
- /* @__PURE__ */ jsx(Pressable, { style: styles6.cancel, onPress: onClose, children: /* @__PURE__ */ jsx(Text, { style: [styles6.itemText, { color: theme.colors.brand }], children: "Cancel" }) })
1245
+ /* @__PURE__ */ jsx(Pressable, { style: styles7.cancel, onPress: onClose, children: /* @__PURE__ */ jsx(Text, { style: [styles7.itemText, { color: theme.colors.brand }], children: "Cancel" }) })
1173
1246
  ]
1174
1247
  }
1175
1248
  ) }) });
@@ -1315,7 +1388,7 @@ async function defaultAdapter(kind) {
1315
1388
  })
1316
1389
  );
1317
1390
  }
1318
- var styles6 = StyleSheet.create({
1391
+ var styles7 = StyleSheet.create({
1319
1392
  backdrop: {
1320
1393
  flex: 1,
1321
1394
  backgroundColor: "rgba(0,0,0,0.35)",
@@ -1345,11 +1418,11 @@ var styles6 = StyleSheet.create({
1345
1418
  });
1346
1419
  function DaySeparator({ label }) {
1347
1420
  const theme = usePoolseTheme();
1348
- return /* @__PURE__ */ jsx(View, { style: styles7.wrap, children: /* @__PURE__ */ jsx(
1421
+ return /* @__PURE__ */ jsx(View, { style: styles8.wrap, children: /* @__PURE__ */ jsx(
1349
1422
  View,
1350
1423
  {
1351
1424
  style: [
1352
- styles7.chip,
1425
+ styles8.chip,
1353
1426
  {
1354
1427
  backgroundColor: theme.colors.surface2,
1355
1428
  borderColor: theme.colors.border
@@ -1359,7 +1432,7 @@ function DaySeparator({ label }) {
1359
1432
  Text,
1360
1433
  {
1361
1434
  style: [
1362
- styles7.label,
1435
+ styles8.label,
1363
1436
  {
1364
1437
  color: theme.colors.ink2,
1365
1438
  fontFamily: theme.type.fontBody
@@ -1371,7 +1444,7 @@ function DaySeparator({ label }) {
1371
1444
  }
1372
1445
  ) });
1373
1446
  }
1374
- var styles7 = StyleSheet.create({
1447
+ var styles8 = StyleSheet.create({
1375
1448
  wrap: {
1376
1449
  alignItems: "center",
1377
1450
  marginVertical: 8
@@ -1398,8 +1471,8 @@ function UploadQueueStrip() {
1398
1471
  {
1399
1472
  horizontal: true,
1400
1473
  showsHorizontalScrollIndicator: false,
1401
- contentContainerStyle: styles8.scroll,
1402
- style: [styles8.scrollStyle, { marginBottom: 8 }],
1474
+ contentContainerStyle: styles9.scroll,
1475
+ style: [styles9.scrollStyle, { marginBottom: 8 }],
1403
1476
  children: upload.queue.map((item) => {
1404
1477
  const isError = item.status === "error";
1405
1478
  const isUploading = item.status === "uploading" || item.status === "pending";
@@ -1410,7 +1483,7 @@ function UploadQueueStrip() {
1410
1483
  if (item.status === "ready" || isError) upload.remove(item.localId);
1411
1484
  else upload.cancel(item.localId);
1412
1485
  };
1413
- return /* @__PURE__ */ jsxs(View, { style: styles8.tileWrap, children: [
1486
+ return /* @__PURE__ */ jsxs(View, { style: styles9.tileWrap, children: [
1414
1487
  isImage && previewUri ? /* @__PURE__ */ jsx(ImageTile, { uri: previewUri, uploading: isUploading, error: isError }) : /* @__PURE__ */ jsx(
1415
1488
  FileTile,
1416
1489
  {
@@ -1425,13 +1498,13 @@ function UploadQueueStrip() {
1425
1498
  {
1426
1499
  onPress: handleClose,
1427
1500
  hitSlop: 8,
1428
- style: styles8.closeBtn,
1501
+ style: styles9.closeBtn,
1429
1502
  accessibilityLabel: isError ? "Remove failed upload" : "Cancel upload",
1430
1503
  children: /* @__PURE__ */ jsx(PoolseIcon, { name: "close", size: 11, color: "#fff" })
1431
1504
  }
1432
1505
  ) : null,
1433
- isUploading ? /* @__PURE__ */ jsx(View, { style: styles8.progressOverlay, children: /* @__PURE__ */ jsx(View, { style: [styles8.spinner, { borderColor: theme.colors.onBrand }] }) }) : null,
1434
- isError ? /* @__PURE__ */ jsx(View, { style: [styles8.errorOverlay, { backgroundColor: "rgba(229,72,77,0.85)" }], children: /* @__PURE__ */ jsx(Text, { style: [styles8.errorText, { color: "#fff" }], children: "Failed" }) }) : null
1506
+ isUploading ? /* @__PURE__ */ jsx(View, { style: styles9.progressOverlay, children: /* @__PURE__ */ jsx(View, { style: [styles9.spinner, { borderColor: theme.colors.onBrand }] }) }) : null,
1507
+ isError ? /* @__PURE__ */ jsx(View, { style: [styles9.errorOverlay, { backgroundColor: "rgba(229,72,77,0.85)" }], children: /* @__PURE__ */ jsx(Text, { style: [styles9.errorText, { color: "#fff" }], children: "Failed" }) }) : null
1435
1508
  ] }, item.localId);
1436
1509
  })
1437
1510
  }
@@ -1444,7 +1517,7 @@ function ImageTile({ uri, uploading, error }) {
1444
1517
  {
1445
1518
  source: { uri },
1446
1519
  style: [
1447
- styles8.imageTile,
1520
+ styles9.imageTile,
1448
1521
  {
1449
1522
  backgroundColor: theme.colors.surface2,
1450
1523
  borderColor: error ? theme.colors.error : "transparent",
@@ -1466,24 +1539,24 @@ function FileTile({
1466
1539
  View,
1467
1540
  {
1468
1541
  style: [
1469
- styles8.fileTile,
1542
+ styles9.fileTile,
1470
1543
  {
1471
1544
  backgroundColor: theme.colors.surface2,
1472
1545
  borderColor: error ? theme.colors.error : uploading ? theme.colors.brand : theme.colors.border
1473
1546
  }
1474
1547
  ],
1475
1548
  children: [
1476
- /* @__PURE__ */ jsx(View, { style: [styles8.fileIconBox, { backgroundColor: theme.colors.brandSoft }], children: /* @__PURE__ */ jsx(PoolseIcon, { name: "attachment", size: 18, color: theme.colors.brand }) }),
1477
- /* @__PURE__ */ jsxs(View, { style: styles8.fileInfo, children: [
1549
+ /* @__PURE__ */ jsx(View, { style: [styles9.fileIconBox, { backgroundColor: theme.colors.brandSoft }], children: /* @__PURE__ */ jsx(PoolseIcon, { name: "attachment", size: 18, color: theme.colors.brand }) }),
1550
+ /* @__PURE__ */ jsxs(View, { style: styles9.fileInfo, children: [
1478
1551
  /* @__PURE__ */ jsx(
1479
1552
  Text,
1480
1553
  {
1481
- style: [styles8.fileName, { color: theme.colors.ink, fontFamily: theme.type.fontBody }],
1554
+ style: [styles9.fileName, { color: theme.colors.ink, fontFamily: theme.type.fontBody }],
1482
1555
  numberOfLines: 1,
1483
1556
  children: filename
1484
1557
  }
1485
1558
  ),
1486
- /* @__PURE__ */ jsx(Text, { style: [styles8.fileSize, { color: theme.colors.ink3 }], children: formatBytes(size) })
1559
+ /* @__PURE__ */ jsx(Text, { style: [styles9.fileSize, { color: theme.colors.ink3 }], children: formatBytes(size) })
1487
1560
  ] })
1488
1561
  ]
1489
1562
  }
@@ -1497,7 +1570,7 @@ function formatBytes(n) {
1497
1570
  return `${(n / 1024 / 1024 / 1024).toFixed(1)} GB`;
1498
1571
  }
1499
1572
  var TILE = 64;
1500
- var styles8 = StyleSheet.create({
1573
+ var styles9 = StyleSheet.create({
1501
1574
  scrollStyle: {
1502
1575
  overflow: "visible"
1503
1576
  },
@@ -1713,7 +1786,7 @@ var MessageComposer = forwardRef(
1713
1786
  View,
1714
1787
  {
1715
1788
  style: [
1716
- styles9.wrap,
1789
+ styles10.wrap,
1717
1790
  {
1718
1791
  backgroundColor: theme.colors.surface,
1719
1792
  borderTopColor: theme.colors.border,
@@ -1736,13 +1809,13 @@ var MessageComposer = forwardRef(
1736
1809
  }
1737
1810
  ) : null,
1738
1811
  attachments && !isEditing ? /* @__PURE__ */ jsx(UploadQueueStrip, {}) : null,
1739
- /* @__PURE__ */ jsxs(View, { style: styles9.row, children: [
1812
+ /* @__PURE__ */ jsxs(View, { style: styles10.row, children: [
1740
1813
  attachments && onAttachPress ? /* @__PURE__ */ jsx(
1741
1814
  Pressable,
1742
1815
  {
1743
1816
  onPress: onAttachPress,
1744
1817
  hitSlop: 8,
1745
- style: styles9.iconBtn,
1818
+ style: styles10.iconBtn,
1746
1819
  accessibilityLabel: "Attach file",
1747
1820
  children: /* @__PURE__ */ jsx(PoolseIcon, { name: "attachment", size: 22, color: theme.colors.ink2 })
1748
1821
  }
@@ -1761,7 +1834,7 @@ var MessageComposer = forwardRef(
1761
1834
  multiline: true,
1762
1835
  editable: !disabled,
1763
1836
  style: [
1764
- styles9.input,
1837
+ styles10.input,
1765
1838
  {
1766
1839
  color: theme.colors.ink,
1767
1840
  backgroundColor: theme.colors.surface2,
@@ -1778,7 +1851,7 @@ var MessageComposer = forwardRef(
1778
1851
  onPress: handleSend,
1779
1852
  disabled: submitDisabled,
1780
1853
  style: [
1781
- styles9.sendBtn,
1854
+ styles10.sendBtn,
1782
1855
  {
1783
1856
  backgroundColor: submitDisabled ? theme.colors.ink3 : theme.colors.brand,
1784
1857
  opacity: submitDisabled ? 0.6 : 1
@@ -1800,7 +1873,7 @@ function EditChip({ message, onCancel }) {
1800
1873
  View,
1801
1874
  {
1802
1875
  style: [
1803
- styles9.replyChip,
1876
+ styles10.replyChip,
1804
1877
  {
1805
1878
  backgroundColor: theme.colors.surface2,
1806
1879
  borderLeftColor: theme.colors.brand
@@ -1808,10 +1881,10 @@ function EditChip({ message, onCancel }) {
1808
1881
  ],
1809
1882
  children: [
1810
1883
  /* @__PURE__ */ jsxs(View, { style: { flex: 1 }, children: [
1811
- /* @__PURE__ */ jsx(Text, { style: [styles9.replyName, { color: theme.colors.brand }], children: "Editing message" }),
1812
- /* @__PURE__ */ jsx(Text, { style: [styles9.replyBody, { color: theme.colors.ink2 }], numberOfLines: 1, children: message.body ?? "\u2026" })
1884
+ /* @__PURE__ */ jsx(Text, { style: [styles10.replyName, { color: theme.colors.brand }], children: "Editing message" }),
1885
+ /* @__PURE__ */ jsx(Text, { style: [styles10.replyBody, { color: theme.colors.ink2 }], numberOfLines: 1, children: message.body ?? "\u2026" })
1813
1886
  ] }),
1814
- onCancel ? /* @__PURE__ */ jsx(Pressable, { onPress: onCancel, hitSlop: 8, style: styles9.replyCancel, children: /* @__PURE__ */ jsx(PoolseIcon, { name: "close", size: 16, color: theme.colors.ink2 }) }) : null
1887
+ onCancel ? /* @__PURE__ */ jsx(Pressable, { onPress: onCancel, hitSlop: 8, style: styles10.replyCancel, children: /* @__PURE__ */ jsx(PoolseIcon, { name: "close", size: 16, color: theme.colors.ink2 }) }) : null
1815
1888
  ]
1816
1889
  }
1817
1890
  );
@@ -1828,7 +1901,7 @@ function ReplyChip({
1828
1901
  View,
1829
1902
  {
1830
1903
  style: [
1831
- styles9.replyChip,
1904
+ styles10.replyChip,
1832
1905
  {
1833
1906
  backgroundColor: theme.colors.surface2,
1834
1907
  borderLeftColor: theme.colors.brand
@@ -1836,18 +1909,18 @@ function ReplyChip({
1836
1909
  ],
1837
1910
  children: [
1838
1911
  /* @__PURE__ */ jsxs(View, { style: { flex: 1 }, children: [
1839
- /* @__PURE__ */ jsxs(Text, { style: [styles9.replyName, { color: theme.colors.brand }], children: [
1912
+ /* @__PURE__ */ jsxs(Text, { style: [styles10.replyName, { color: theme.colors.brand }], children: [
1840
1913
  "Replying to ",
1841
1914
  senderName
1842
1915
  ] }),
1843
- /* @__PURE__ */ jsx(Text, { style: [styles9.replyBody, { color: theme.colors.ink2 }], numberOfLines: 1, children: message.body ?? "\u2026" })
1916
+ /* @__PURE__ */ jsx(Text, { style: [styles10.replyBody, { color: theme.colors.ink2 }], numberOfLines: 1, children: message.body ?? "\u2026" })
1844
1917
  ] }),
1845
- onCancel ? /* @__PURE__ */ jsx(Pressable, { onPress: onCancel, hitSlop: 8, style: styles9.replyCancel, children: /* @__PURE__ */ jsx(PoolseIcon, { name: "close", size: 16, color: theme.colors.ink2 }) }) : null
1918
+ onCancel ? /* @__PURE__ */ jsx(Pressable, { onPress: onCancel, hitSlop: 8, style: styles10.replyCancel, children: /* @__PURE__ */ jsx(PoolseIcon, { name: "close", size: 16, color: theme.colors.ink2 }) }) : null
1846
1919
  ]
1847
1920
  }
1848
1921
  );
1849
1922
  }
1850
- var styles9 = StyleSheet.create({
1923
+ var styles10 = StyleSheet.create({
1851
1924
  wrap: {
1852
1925
  borderTopWidth: StyleSheet.hairlineWidth,
1853
1926
  paddingTop: 8,
@@ -1944,11 +2017,11 @@ function MentionInput({ conversationId, onSend, ...composerProps }) {
1944
2017
  transparent: true,
1945
2018
  animationType: "slide",
1946
2019
  onRequestClose: () => setPickerOpen(false),
1947
- children: /* @__PURE__ */ jsx(Pressable, { style: styles10.backdrop, onPress: () => setPickerOpen(false), children: /* @__PURE__ */ jsxs(
2020
+ children: /* @__PURE__ */ jsx(Pressable, { style: styles11.backdrop, onPress: () => setPickerOpen(false), children: /* @__PURE__ */ jsxs(
1948
2021
  View,
1949
2022
  {
1950
2023
  style: [
1951
- styles10.sheet,
2024
+ styles11.sheet,
1952
2025
  {
1953
2026
  backgroundColor: theme.colors.surface,
1954
2027
  borderTopLeftRadius: theme.radii.lg,
@@ -1959,7 +2032,7 @@ function MentionInput({ conversationId, onSend, ...composerProps }) {
1959
2032
  /* @__PURE__ */ jsx(
1960
2033
  Text,
1961
2034
  {
1962
- style: [styles10.title, { color: theme.colors.ink, fontFamily: theme.type.fontBody }],
2035
+ style: [styles11.title, { color: theme.colors.ink, fontFamily: theme.type.fontBody }],
1963
2036
  children: "Mention a member"
1964
2037
  }
1965
2038
  ),
@@ -1990,12 +2063,12 @@ function MentionInput({ conversationId, onSend, ...composerProps }) {
1990
2063
  }
1991
2064
  function MentionRow({ member, onPress }) {
1992
2065
  const theme = usePoolseTheme();
1993
- return /* @__PURE__ */ jsxs(Pressable, { onPress, style: styles10.row, children: [
2066
+ return /* @__PURE__ */ jsxs(Pressable, { onPress, style: styles11.row, children: [
1994
2067
  /* @__PURE__ */ jsx(Avatar, { src: null, name: member.external_id, seed: member.external_id, size: "sm" }),
1995
- /* @__PURE__ */ jsx(Text, { style: [styles10.rowText, { color: theme.colors.ink, fontFamily: theme.type.fontBody }], children: member.external_id })
2068
+ /* @__PURE__ */ jsx(Text, { style: [styles11.rowText, { color: theme.colors.ink, fontFamily: theme.type.fontBody }], children: member.external_id })
1996
2069
  ] });
1997
2070
  }
1998
- var styles10 = StyleSheet.create({
2071
+ var styles11 = StyleSheet.create({
1999
2072
  backdrop: {
2000
2073
  flex: 1,
2001
2074
  backgroundColor: "rgba(0,0,0,0.35)",
@@ -2075,12 +2148,12 @@ function MessageList({
2075
2148
  [renderItem, data.length]
2076
2149
  );
2077
2150
  if (loading && messages.length === 0) {
2078
- return /* @__PURE__ */ jsx(View, { style: [styles11.placeholder, { backgroundColor: theme.colors.paper }], children: /* @__PURE__ */ jsx(ActivityIndicator, { color: theme.colors.brand }) });
2151
+ return /* @__PURE__ */ jsx(View, { style: [styles12.placeholder, { backgroundColor: theme.colors.paper }], children: /* @__PURE__ */ jsx(ActivityIndicator, { color: theme.colors.brand }) });
2079
2152
  }
2080
2153
  if (messages.length === 0) {
2081
- return /* @__PURE__ */ jsx(View, { style: [styles11.placeholder, { backgroundColor: theme.colors.paper }], children: typeof emptyState === "string" ? /* @__PURE__ */ jsx(Text, { style: { color: theme.colors.ink3, fontFamily: theme.type.fontBody }, children: emptyState }) : emptyState ?? null });
2154
+ return /* @__PURE__ */ jsx(View, { style: [styles12.placeholder, { backgroundColor: theme.colors.paper }], children: typeof emptyState === "string" ? /* @__PURE__ */ jsx(Text, { style: { color: theme.colors.ink3, fontFamily: theme.type.fontBody }, children: emptyState }) : emptyState ?? null });
2082
2155
  }
2083
- return /* @__PURE__ */ jsxs(View, { style: styles11.root, children: [
2156
+ return /* @__PURE__ */ jsxs(View, { style: styles12.root, children: [
2084
2157
  /* @__PURE__ */ jsx(
2085
2158
  FlatList,
2086
2159
  {
@@ -2107,7 +2180,7 @@ function MessageList({
2107
2180
  {
2108
2181
  onPress: scrollToBottom,
2109
2182
  style: [
2110
- styles11.jumpButton,
2183
+ styles12.jumpButton,
2111
2184
  {
2112
2185
  backgroundColor: theme.colors.brand
2113
2186
  },
@@ -2116,7 +2189,7 @@ function MessageList({
2116
2189
  accessibilityLabel: `${newCount} new ${newCount === 1 ? "message" : "messages"}, jump to latest`,
2117
2190
  children: [
2118
2191
  /* @__PURE__ */ jsx(PoolseIcon, { name: "chevron-down", size: 14, color: theme.colors.onBrand }),
2119
- /* @__PURE__ */ jsxs(Text, { style: [styles11.jumpText, { color: theme.colors.onBrand }], children: [
2192
+ /* @__PURE__ */ jsxs(Text, { style: [styles12.jumpText, { color: theme.colors.onBrand }], children: [
2120
2193
  newCount,
2121
2194
  " new ",
2122
2195
  newCount === 1 ? "message" : "messages"
@@ -2126,7 +2199,7 @@ function MessageList({
2126
2199
  ) : null
2127
2200
  ] });
2128
2201
  }
2129
- var styles11 = StyleSheet.create({
2202
+ var styles12 = StyleSheet.create({
2130
2203
  root: {
2131
2204
  flex: 1
2132
2205
  },
@@ -2177,11 +2250,11 @@ function MessageActions({
2177
2250
  if (isSelf && onDelete)
2178
2251
  items.push({ label: "Delete", icon: "trash", onPress: onDelete, danger: true });
2179
2252
  const showEmojiRow = !!onPickReaction && emojis.length > 0;
2180
- return /* @__PURE__ */ jsx(Modal, { visible, transparent: true, animationType: "fade", onRequestClose: onClose, children: /* @__PURE__ */ jsx(Pressable, { style: styles12.backdrop, onPress: onClose, children: /* @__PURE__ */ jsxs(
2253
+ return /* @__PURE__ */ jsx(Modal, { visible, transparent: true, animationType: "fade", onRequestClose: onClose, children: /* @__PURE__ */ jsx(Pressable, { style: styles13.backdrop, onPress: onClose, children: /* @__PURE__ */ jsxs(
2181
2254
  View,
2182
2255
  {
2183
2256
  style: [
2184
- styles12.sheet,
2257
+ styles13.sheet,
2185
2258
  {
2186
2259
  backgroundColor: theme.colors.surface,
2187
2260
  borderTopLeftRadius: theme.radii.lg,
@@ -2190,21 +2263,21 @@ function MessageActions({
2190
2263
  theme.shadows.lg
2191
2264
  ],
2192
2265
  children: [
2193
- showEmojiRow ? /* @__PURE__ */ jsx(View, { style: [styles12.emojiRow, { borderBottomColor: theme.colors.border }], children: emojis.map((emoji) => /* @__PURE__ */ jsx(
2266
+ showEmojiRow ? /* @__PURE__ */ jsx(View, { style: [styles13.emojiRow, { borderBottomColor: theme.colors.border }], children: emojis.map((emoji) => /* @__PURE__ */ jsx(
2194
2267
  Pressable,
2195
2268
  {
2196
2269
  onPress: () => {
2197
2270
  onPickReaction(emoji);
2198
2271
  onClose();
2199
2272
  },
2200
- style: styles12.emojiBtn,
2273
+ style: styles13.emojiBtn,
2201
2274
  hitSlop: 6,
2202
2275
  accessibilityLabel: `React with ${emoji}`,
2203
- children: /* @__PURE__ */ jsx(Text, { style: styles12.emoji, children: emoji })
2276
+ children: /* @__PURE__ */ jsx(Text, { style: styles13.emoji, children: emoji })
2204
2277
  },
2205
2278
  emoji
2206
2279
  )) }) : null,
2207
- items.map((item) => /* @__PURE__ */ jsxs(Pressable, { onPress: item.onPress, style: styles12.item, children: [
2280
+ items.map((item) => /* @__PURE__ */ jsxs(Pressable, { onPress: item.onPress, style: styles13.item, children: [
2208
2281
  /* @__PURE__ */ jsx(
2209
2282
  PoolseIcon,
2210
2283
  {
@@ -2217,7 +2290,7 @@ function MessageActions({
2217
2290
  Text,
2218
2291
  {
2219
2292
  style: [
2220
- styles12.itemText,
2293
+ styles13.itemText,
2221
2294
  {
2222
2295
  color: item.danger ? theme.colors.error : theme.colors.ink,
2223
2296
  fontFamily: theme.type.fontBody
@@ -2231,7 +2304,7 @@ function MessageActions({
2231
2304
  }
2232
2305
  ) }) });
2233
2306
  }
2234
- var styles12 = StyleSheet.create({
2307
+ var styles13 = StyleSheet.create({
2235
2308
  backdrop: {
2236
2309
  flex: 1,
2237
2310
  backgroundColor: "rgba(0,0,0,0.35)",
@@ -2296,7 +2369,7 @@ function AttachmentPreview({ attachment, onPress, maxWidth = 280 }) {
2296
2369
  View,
2297
2370
  {
2298
2371
  style: [
2299
- styles13.imagePlaceholder,
2372
+ styles14.imagePlaceholder,
2300
2373
  {
2301
2374
  width: maxWidth,
2302
2375
  height: 200,
@@ -2313,7 +2386,7 @@ function AttachmentPreview({ attachment, onPress, maxWidth = 280 }) {
2313
2386
  onPress,
2314
2387
  disabled: !onPress,
2315
2388
  style: [
2316
- styles13.fileCard,
2389
+ styles14.fileCard,
2317
2390
  {
2318
2391
  backgroundColor: theme.colors.surface2,
2319
2392
  borderColor: theme.colors.border,
@@ -2326,12 +2399,12 @@ function AttachmentPreview({ attachment, onPress, maxWidth = 280 }) {
2326
2399
  /* @__PURE__ */ jsx(
2327
2400
  Text,
2328
2401
  {
2329
- style: [styles13.fileName, { color: theme.colors.ink, fontFamily: theme.type.fontBody }],
2402
+ style: [styles14.fileName, { color: theme.colors.ink, fontFamily: theme.type.fontBody }],
2330
2403
  numberOfLines: 1,
2331
2404
  children: attachment.original_filename ?? "file"
2332
2405
  }
2333
2406
  ),
2334
- /* @__PURE__ */ jsx(Text, { style: [styles13.fileSize, { color: theme.colors.ink3 }], children: formatBytes2(attachment.byte_size) })
2407
+ /* @__PURE__ */ jsx(Text, { style: [styles14.fileSize, { color: theme.colors.ink3 }], children: formatBytes2(attachment.byte_size) })
2335
2408
  ] })
2336
2409
  ]
2337
2410
  }
@@ -2343,7 +2416,7 @@ function formatBytes2(n) {
2343
2416
  if (n < 1024 * 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MB`;
2344
2417
  return `${(n / 1024 / 1024 / 1024).toFixed(1)} GB`;
2345
2418
  }
2346
- var styles13 = StyleSheet.create({
2419
+ var styles14 = StyleSheet.create({
2347
2420
  imagePlaceholder: {},
2348
2421
  fileCard: {
2349
2422
  flexDirection: "row",
@@ -2372,7 +2445,7 @@ function ImageMosaic({ images, maxWidth, radius }) {
2372
2445
  View,
2373
2446
  {
2374
2447
  style: [
2375
- styles14.root,
2448
+ styles15.root,
2376
2449
  {
2377
2450
  borderRadius: r,
2378
2451
  ...maxWidth ? { maxWidth } : {}
@@ -2383,17 +2456,17 @@ function ImageMosaic({ images, maxWidth, radius }) {
2383
2456
  Tile,
2384
2457
  {
2385
2458
  attachment: visible[0],
2386
- style: styles14.tileFull,
2459
+ style: styles15.tileFull,
2387
2460
  onPress: () => setViewerIndex(0),
2388
2461
  overlay: null
2389
2462
  }
2390
2463
  ) : null,
2391
- n === 2 ? /* @__PURE__ */ jsxs(View, { style: styles14.rowEven, children: [
2464
+ n === 2 ? /* @__PURE__ */ jsxs(View, { style: styles15.rowEven, children: [
2392
2465
  /* @__PURE__ */ jsx(
2393
2466
  Tile,
2394
2467
  {
2395
2468
  attachment: visible[0],
2396
- style: styles14.tileHalfSquare,
2469
+ style: styles15.tileHalfSquare,
2397
2470
  onPress: () => setViewerIndex(0),
2398
2471
  overlay: null
2399
2472
  }
@@ -2402,7 +2475,7 @@ function ImageMosaic({ images, maxWidth, radius }) {
2402
2475
  Tile,
2403
2476
  {
2404
2477
  attachment: visible[1],
2405
- style: styles14.tileHalfSquare,
2478
+ style: styles15.tileHalfSquare,
2406
2479
  onPress: () => setViewerIndex(1),
2407
2480
  overlay: null
2408
2481
  }
@@ -2413,17 +2486,17 @@ function ImageMosaic({ images, maxWidth, radius }) {
2413
2486
  Tile,
2414
2487
  {
2415
2488
  attachment: visible[0],
2416
- style: styles14.tileHero,
2489
+ style: styles15.tileHero,
2417
2490
  onPress: () => setViewerIndex(0),
2418
2491
  overlay: null
2419
2492
  }
2420
2493
  ),
2421
- /* @__PURE__ */ jsxs(View, { style: [styles14.rowEven, { marginTop: 2 }], children: [
2494
+ /* @__PURE__ */ jsxs(View, { style: [styles15.rowEven, { marginTop: 2 }], children: [
2422
2495
  /* @__PURE__ */ jsx(
2423
2496
  Tile,
2424
2497
  {
2425
2498
  attachment: visible[1],
2426
- style: styles14.tileHalfSquare,
2499
+ style: styles15.tileHalfSquare,
2427
2500
  onPress: () => setViewerIndex(1),
2428
2501
  overlay: null
2429
2502
  }
@@ -2432,7 +2505,7 @@ function ImageMosaic({ images, maxWidth, radius }) {
2432
2505
  Tile,
2433
2506
  {
2434
2507
  attachment: visible[2],
2435
- style: styles14.tileHalfSquare,
2508
+ style: styles15.tileHalfSquare,
2436
2509
  onPress: () => setViewerIndex(2),
2437
2510
  overlay: null
2438
2511
  }
@@ -2440,12 +2513,12 @@ function ImageMosaic({ images, maxWidth, radius }) {
2440
2513
  ] })
2441
2514
  ] }) : null,
2442
2515
  n === 4 ? /* @__PURE__ */ jsxs(Fragment, { children: [
2443
- /* @__PURE__ */ jsxs(View, { style: styles14.rowEven, children: [
2516
+ /* @__PURE__ */ jsxs(View, { style: styles15.rowEven, children: [
2444
2517
  /* @__PURE__ */ jsx(
2445
2518
  Tile,
2446
2519
  {
2447
2520
  attachment: visible[0],
2448
- style: styles14.tileHalfSquare,
2521
+ style: styles15.tileHalfSquare,
2449
2522
  onPress: () => setViewerIndex(0),
2450
2523
  overlay: null
2451
2524
  }
@@ -2454,18 +2527,18 @@ function ImageMosaic({ images, maxWidth, radius }) {
2454
2527
  Tile,
2455
2528
  {
2456
2529
  attachment: visible[1],
2457
- style: styles14.tileHalfSquare,
2530
+ style: styles15.tileHalfSquare,
2458
2531
  onPress: () => setViewerIndex(1),
2459
2532
  overlay: null
2460
2533
  }
2461
2534
  )
2462
2535
  ] }),
2463
- /* @__PURE__ */ jsxs(View, { style: [styles14.rowEven, { marginTop: 2 }], children: [
2536
+ /* @__PURE__ */ jsxs(View, { style: [styles15.rowEven, { marginTop: 2 }], children: [
2464
2537
  /* @__PURE__ */ jsx(
2465
2538
  Tile,
2466
2539
  {
2467
2540
  attachment: visible[2],
2468
- style: styles14.tileHalfSquare,
2541
+ style: styles15.tileHalfSquare,
2469
2542
  onPress: () => setViewerIndex(2),
2470
2543
  overlay: null
2471
2544
  }
@@ -2474,7 +2547,7 @@ function ImageMosaic({ images, maxWidth, radius }) {
2474
2547
  Tile,
2475
2548
  {
2476
2549
  attachment: visible[3],
2477
- style: styles14.tileHalfSquare,
2550
+ style: styles15.tileHalfSquare,
2478
2551
  onPress: () => setViewerIndex(3),
2479
2552
  overlay: overflow > 0 ? `+${overflow}` : null
2480
2553
  }
@@ -2510,18 +2583,18 @@ function Tile({
2510
2583
  }) {
2511
2584
  const theme = usePoolseTheme();
2512
2585
  const { url } = useAttachmentUrl(attachment.id);
2513
- return /* @__PURE__ */ jsxs(Pressable, { onPress, style: [styles14.tileBase, style], children: [
2586
+ return /* @__PURE__ */ jsxs(Pressable, { onPress, style: [styles15.tileBase, style], children: [
2514
2587
  url ? /* @__PURE__ */ jsx(
2515
2588
  Image,
2516
2589
  {
2517
2590
  source: { uri: url },
2518
- style: [styles14.tileImage, { backgroundColor: theme.colors.surface2 }],
2591
+ style: [styles15.tileImage, { backgroundColor: theme.colors.surface2 }],
2519
2592
  resizeMode: "cover",
2520
2593
  accessible: true,
2521
2594
  accessibilityLabel: attachment.original_filename ?? "image"
2522
2595
  }
2523
- ) : /* @__PURE__ */ jsx(View, { style: [styles14.tileImage, { backgroundColor: theme.colors.surface2 }] }),
2524
- overlay ? /* @__PURE__ */ jsx(View, { style: styles14.overflow, children: /* @__PURE__ */ jsx(Text, { style: styles14.overflowText, children: overlay }) }) : null
2596
+ ) : /* @__PURE__ */ jsx(View, { style: [styles15.tileImage, { backgroundColor: theme.colors.surface2 }] }),
2597
+ overlay ? /* @__PURE__ */ jsx(View, { style: styles15.overflow, children: /* @__PURE__ */ jsx(Text, { style: styles15.overflowText, children: overlay }) }) : null
2525
2598
  ] });
2526
2599
  }
2527
2600
  function FullScreenViewer({
@@ -2530,7 +2603,7 @@ function FullScreenViewer({
2530
2603
  }) {
2531
2604
  const { url } = useAttachmentUrl(attachment.id);
2532
2605
  const { width, height } = Dimensions.get("window");
2533
- return /* @__PURE__ */ jsxs(Pressable, { style: styles14.viewer, onPress: onClose, children: [
2606
+ return /* @__PURE__ */ jsxs(Pressable, { style: styles15.viewer, onPress: onClose, children: [
2534
2607
  url ? /* @__PURE__ */ jsx(
2535
2608
  Image,
2536
2609
  {
@@ -2546,14 +2619,14 @@ function FullScreenViewer({
2546
2619
  {
2547
2620
  onPress: onClose,
2548
2621
  hitSlop: 12,
2549
- style: styles14.closeBtn,
2622
+ style: styles15.closeBtn,
2550
2623
  accessibilityLabel: "Close viewer",
2551
2624
  children: /* @__PURE__ */ jsx(PoolseIcon, { name: "close", size: 20, color: "#ffffff" })
2552
2625
  }
2553
2626
  )
2554
2627
  ] });
2555
2628
  }
2556
- var styles14 = StyleSheet.create({
2629
+ var styles15 = StyleSheet.create({
2557
2630
  root: {
2558
2631
  width: "100%",
2559
2632
  overflow: "hidden",
@@ -2708,7 +2781,7 @@ function MessageBubble({
2708
2781
  View,
2709
2782
  {
2710
2783
  style: [
2711
- styles15.wrap,
2784
+ styles16.wrap,
2712
2785
  {
2713
2786
  alignSelf: isSelf ? "flex-end" : "flex-start",
2714
2787
  // Pixel maxWidth (not percentage) so single-line and
@@ -2722,7 +2795,7 @@ function MessageBubble({
2722
2795
  View,
2723
2796
  {
2724
2797
  style: [
2725
- styles15.bubble,
2798
+ styles16.bubble,
2726
2799
  {
2727
2800
  backgroundColor: bubbleColor,
2728
2801
  borderColor: isSelf ? "transparent" : theme.colors.border,
@@ -2744,7 +2817,7 @@ function MessageBubble({
2744
2817
  theme.shadows.sm
2745
2818
  ],
2746
2819
  children: [
2747
- showSenderName && !isSelf && (groupPosition === "first" || groupPosition === "standalone") ? /* @__PURE__ */ jsx(Text, { style: [styles15.senderName, { color: senderTint, fontFamily: theme.type.fontBody }], children: senderLabel }) : null,
2820
+ showSenderName && !isSelf && (groupPosition === "first" || groupPosition === "standalone") ? /* @__PURE__ */ jsx(Text, { style: [styles16.senderName, { color: senderTint, fontFamily: theme.type.fontBody }], children: senderLabel }) : null,
2748
2821
  message.quoted_message ? /* @__PURE__ */ jsx(
2749
2822
  QuotedCard,
2750
2823
  {
@@ -2760,7 +2833,7 @@ function MessageBubble({
2760
2833
  Text,
2761
2834
  {
2762
2835
  style: [
2763
- styles15.body,
2836
+ styles16.body,
2764
2837
  {
2765
2838
  color: theme.colors.ink3,
2766
2839
  fontFamily: theme.type.fontBody,
@@ -2785,7 +2858,7 @@ function MessageBubble({
2785
2858
  Text,
2786
2859
  {
2787
2860
  style: [
2788
- styles15.body,
2861
+ styles16.body,
2789
2862
  {
2790
2863
  color: textColor,
2791
2864
  fontFamily: theme.type.fontBody,
@@ -2800,18 +2873,18 @@ function MessageBubble({
2800
2873
  Text,
2801
2874
  {
2802
2875
  style: [
2803
- styles15.readMore,
2876
+ styles16.readMore,
2804
2877
  { color: isSelf ? theme.colors.onBrand : theme.colors.brand }
2805
2878
  ],
2806
2879
  children: expanded ? "Show less" : "Read more"
2807
2880
  }
2808
2881
  ) }) : null,
2809
- /* @__PURE__ */ jsxs(View, { style: styles15.metaRow, children: [
2882
+ /* @__PURE__ */ jsxs(View, { style: styles16.metaRow, children: [
2810
2883
  isEdited ? /* @__PURE__ */ jsx(
2811
2884
  Text,
2812
2885
  {
2813
2886
  style: [
2814
- styles15.editedTag,
2887
+ styles16.editedTag,
2815
2888
  {
2816
2889
  color: isSelf ? theme.colors.onBrand : theme.colors.ink3,
2817
2890
  opacity: 0.7
@@ -2824,7 +2897,7 @@ function MessageBubble({
2824
2897
  Text,
2825
2898
  {
2826
2899
  style: [
2827
- styles15.meta,
2900
+ styles16.meta,
2828
2901
  {
2829
2902
  color: isSelf ? theme.colors.onBrand : theme.colors.ink3,
2830
2903
  opacity: isSelf ? 0.85 : 1
@@ -2833,7 +2906,7 @@ function MessageBubble({
2833
2906
  children: time
2834
2907
  }
2835
2908
  ),
2836
- isSelf && readState ? /* @__PURE__ */ jsx(View, { style: styles15.readTick, children: /* @__PURE__ */ jsx(
2909
+ isSelf && readState ? /* @__PURE__ */ jsx(View, { style: styles16.readTick, children: /* @__PURE__ */ jsx(
2837
2910
  PoolseIcon,
2838
2911
  {
2839
2912
  name: readState === "read" ? "check-double" : "check",
@@ -2842,7 +2915,7 @@ function MessageBubble({
2842
2915
  }
2843
2916
  ) }) : null
2844
2917
  ] }),
2845
- actionsTrigger ? /* @__PURE__ */ jsx(View, { style: styles15.actionsSlot, children: actionsTrigger }) : null
2918
+ actionsTrigger ? /* @__PURE__ */ jsx(View, { style: styles16.actionsSlot, children: actionsTrigger }) : null
2846
2919
  ]
2847
2920
  }
2848
2921
  )
@@ -2867,15 +2940,15 @@ function QuotedCard({
2867
2940
  onPress,
2868
2941
  disabled: !onPress,
2869
2942
  style: [
2870
- styles15.quoted,
2943
+ styles16.quoted,
2871
2944
  {
2872
2945
  backgroundColor: bg,
2873
2946
  borderLeftColor: accent
2874
2947
  }
2875
2948
  ],
2876
2949
  children: [
2877
- /* @__PURE__ */ jsx(Text, { style: [styles15.quotedSender, { color: accent }], children: senderName }),
2878
- /* @__PURE__ */ jsx(Text, { style: [styles15.quotedBody, { color: txt }], numberOfLines: 2, children: quoted.body ?? "\u2026" })
2950
+ /* @__PURE__ */ jsx(Text, { style: [styles16.quotedSender, { color: accent }], children: senderName }),
2951
+ /* @__PURE__ */ jsx(Text, { style: [styles16.quotedBody, { color: txt }], numberOfLines: 2, children: quoted.body ?? "\u2026" })
2879
2952
  ]
2880
2953
  }
2881
2954
  );
@@ -2907,7 +2980,7 @@ function formatTime(iso) {
2907
2980
  function isSameDay(a, b) {
2908
2981
  return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
2909
2982
  }
2910
- var styles15 = StyleSheet.create({
2983
+ var styles16 = StyleSheet.create({
2911
2984
  wrap: {
2912
2985
  marginBottom: 2
2913
2986
  },
@@ -2987,7 +3060,7 @@ function ReactionStrip({
2987
3060
  });
2988
3061
  const entries = Object.entries(reactions);
2989
3062
  if (entries.length === 0) return null;
2990
- return /* @__PURE__ */ jsx(View, { style: styles16.strip, children: entries.map(([emoji, userIds]) => {
3063
+ return /* @__PURE__ */ jsx(View, { style: styles17.strip, children: entries.map(([emoji, userIds]) => {
2991
3064
  const userArr = Array.isArray(userIds) ? userIds : [];
2992
3065
  const meReacted = meId !== null && userArr.includes(meId);
2993
3066
  return /* @__PURE__ */ jsxs(
@@ -2995,7 +3068,7 @@ function ReactionStrip({
2995
3068
  {
2996
3069
  onPress: () => meReacted ? removeReaction(emoji) : addReaction(emoji),
2997
3070
  style: [
2998
- styles16.chip,
3071
+ styles17.chip,
2999
3072
  {
3000
3073
  backgroundColor: meReacted ? theme.colors.brandSoft : theme.colors.surface2,
3001
3074
  borderColor: meReacted ? theme.colors.brand : theme.colors.border,
@@ -3004,12 +3077,12 @@ function ReactionStrip({
3004
3077
  }
3005
3078
  ],
3006
3079
  children: [
3007
- /* @__PURE__ */ jsx(Text, { style: styles16.emoji, children: emoji }),
3080
+ /* @__PURE__ */ jsx(Text, { style: styles17.emoji, children: emoji }),
3008
3081
  /* @__PURE__ */ jsx(
3009
3082
  Text,
3010
3083
  {
3011
3084
  style: [
3012
- styles16.count,
3085
+ styles17.count,
3013
3086
  {
3014
3087
  color: meReacted ? theme.colors.brand : theme.colors.ink2,
3015
3088
  fontWeight: meReacted ? "700" : "600"
@@ -3031,11 +3104,11 @@ function ReactionPicker({
3031
3104
  emojis = DEFAULT_EMOJIS
3032
3105
  }) {
3033
3106
  const theme = usePoolseTheme();
3034
- return /* @__PURE__ */ jsx(Modal, { visible, transparent: true, animationType: "fade", onRequestClose: onClose, children: /* @__PURE__ */ jsx(Pressable, { style: styles16.backdrop, onPress: onClose, children: /* @__PURE__ */ jsx(
3107
+ return /* @__PURE__ */ jsx(Modal, { visible, transparent: true, animationType: "fade", onRequestClose: onClose, children: /* @__PURE__ */ jsx(Pressable, { style: styles17.backdrop, onPress: onClose, children: /* @__PURE__ */ jsx(
3035
3108
  View,
3036
3109
  {
3037
3110
  style: [
3038
- styles16.sheet,
3111
+ styles17.sheet,
3039
3112
  {
3040
3113
  backgroundColor: theme.colors.surface,
3041
3114
  borderRadius: theme.radii.lg
@@ -3045,19 +3118,19 @@ function ReactionPicker({
3045
3118
  children: emojis.map((emoji) => /* @__PURE__ */ jsx(
3046
3119
  Pressable,
3047
3120
  {
3048
- style: styles16.emojiBtn,
3121
+ style: styles17.emojiBtn,
3049
3122
  onPress: () => {
3050
3123
  onPick(emoji);
3051
3124
  onClose();
3052
3125
  },
3053
- children: /* @__PURE__ */ jsx(Text, { style: styles16.bigEmoji, children: emoji })
3126
+ children: /* @__PURE__ */ jsx(Text, { style: styles17.bigEmoji, children: emoji })
3054
3127
  },
3055
3128
  emoji
3056
3129
  ))
3057
3130
  }
3058
3131
  ) }) });
3059
3132
  }
3060
- var styles16 = StyleSheet.create({
3133
+ var styles17 = StyleSheet.create({
3061
3134
  strip: {
3062
3135
  flexDirection: "row",
3063
3136
  flexWrap: "wrap",
@@ -3225,15 +3298,15 @@ function MessageRow({
3225
3298
  View,
3226
3299
  {
3227
3300
  style: [
3228
- styles17.row,
3301
+ styles18.row,
3229
3302
  { alignSelf: isSelf ? "flex-end" : "flex-start" },
3230
3303
  // Lift this row above the dim backdrop the parent renders
3231
3304
  // during edit mode. zIndex covers iOS / web; elevation does
3232
3305
  // the equivalent on Android.
3233
- isEditing ? styles17.rowEditing : null
3306
+ isEditing ? styles18.rowEditing : null
3234
3307
  ],
3235
3308
  children: [
3236
- showAvatarSlot ? /* @__PURE__ */ jsx(View, { style: styles17.avatarSlot, children: showAvatarRender ? /* @__PURE__ */ jsx(
3309
+ showAvatarSlot ? /* @__PURE__ */ jsx(View, { style: styles18.avatarSlot, children: showAvatarRender ? /* @__PURE__ */ jsx(
3237
3310
  Avatar,
3238
3311
  {
3239
3312
  src: avatarUrl ?? null,
@@ -3242,14 +3315,14 @@ function MessageRow({
3242
3315
  size: "sm"
3243
3316
  }
3244
3317
  ) : null }) : null,
3245
- /* @__PURE__ */ jsxs(View, { style: styles17.bubbleCol, children: [
3318
+ /* @__PURE__ */ jsxs(View, { style: styles18.bubbleCol, children: [
3246
3319
  swipeEnabled ? /* @__PURE__ */ jsx(
3247
3320
  Animated.View,
3248
3321
  {
3249
3322
  pointerEvents: "none",
3250
3323
  style: [
3251
- styles17.replyHint,
3252
- isSelf ? styles17.replyHintRight : styles17.replyHintLeft,
3324
+ styles18.replyHint,
3325
+ isSelf ? styles18.replyHintRight : styles18.replyHintLeft,
3253
3326
  {
3254
3327
  opacity: replyIconOpacity,
3255
3328
  transform: [{ scale: replyIconScale }],
@@ -3300,13 +3373,13 @@ function MessageRow({
3300
3373
  )
3301
3374
  }
3302
3375
  ),
3303
- threads && (msg.reply_count ?? 0) > 0 && onOpenThread ? /* @__PURE__ */ jsx(Pressable, { onPress: onOpenThread, style: styles17.threadPill, children: /* @__PURE__ */ jsxs(Text, { style: [styles17.threadPillText, { color: theme.colors.brand }], children: [
3376
+ threads && (msg.reply_count ?? 0) > 0 && onOpenThread ? /* @__PURE__ */ jsx(Pressable, { onPress: onOpenThread, style: styles18.threadPill, children: /* @__PURE__ */ jsxs(Text, { style: [styles18.threadPillText, { color: theme.colors.brand }], children: [
3304
3377
  "\u{1F4AC} ",
3305
3378
  msg.reply_count,
3306
3379
  " ",
3307
3380
  msg.reply_count === 1 ? "reply" : "replies"
3308
3381
  ] }) }) : null,
3309
- reactions ? /* @__PURE__ */ jsx(View, { style: [styles17.reactionsRow, { alignSelf: isSelf ? "flex-end" : "flex-start" }], children: /* @__PURE__ */ jsx(
3382
+ reactions ? /* @__PURE__ */ jsx(View, { style: [styles18.reactionsRow, { alignSelf: isSelf ? "flex-end" : "flex-start" }], children: /* @__PURE__ */ jsx(
3310
3383
  ReactionStrip,
3311
3384
  {
3312
3385
  messageId: msg.id,
@@ -3365,7 +3438,7 @@ function MessageRow({
3365
3438
  }
3366
3439
  );
3367
3440
  }
3368
- var styles17 = StyleSheet.create({
3441
+ var styles18 = StyleSheet.create({
3369
3442
  row: {
3370
3443
  flexDirection: "row",
3371
3444
  alignItems: "flex-end",
@@ -3525,13 +3598,13 @@ function ThreadSheet({
3525
3598
  ),
3526
3599
  [rootMessage, meId, labelFor, avatarFor]
3527
3600
  );
3528
- return /* @__PURE__ */ jsxs(View, { style: styles18.modalRoot, children: [
3529
- /* @__PURE__ */ jsx(Pressable, { style: styles18.backdrop, onPress: onClose, accessibilityLabel: "Close thread" }),
3601
+ return /* @__PURE__ */ jsxs(View, { style: styles19.modalRoot, children: [
3602
+ /* @__PURE__ */ jsx(Pressable, { style: styles19.backdrop, onPress: onClose, accessibilityLabel: "Close thread" }),
3530
3603
  /* @__PURE__ */ jsxs(
3531
3604
  Animated.View,
3532
3605
  {
3533
3606
  style: [
3534
- styles18.sheet,
3607
+ styles19.sheet,
3535
3608
  {
3536
3609
  height: sheetHeight,
3537
3610
  backgroundColor: theme.colors.paper,
@@ -3543,14 +3616,14 @@ function ThreadSheet({
3543
3616
  ],
3544
3617
  children: [
3545
3618
  /* @__PURE__ */ jsxs(View, { ...panHandlers, children: [
3546
- /* @__PURE__ */ jsx(View, { style: styles18.dragHandle, children: /* @__PURE__ */ jsx(View, { style: [styles18.dragPill, { backgroundColor: theme.colors.ink3 }] }) }),
3547
- /* @__PURE__ */ jsxs(View, { style: [styles18.header, { borderBottomColor: theme.colors.border }], children: [
3619
+ /* @__PURE__ */ jsx(View, { style: styles19.dragHandle, children: /* @__PURE__ */ jsx(View, { style: [styles19.dragPill, { backgroundColor: theme.colors.ink3 }] }) }),
3620
+ /* @__PURE__ */ jsxs(View, { style: [styles19.header, { borderBottomColor: theme.colors.border }], children: [
3548
3621
  /* @__PURE__ */ jsx(
3549
3622
  Pressable,
3550
3623
  {
3551
3624
  onPress: onClose,
3552
3625
  hitSlop: 16,
3553
- style: [styles18.closeBtn, { backgroundColor: theme.colors.surface2 }],
3626
+ style: [styles19.closeBtn, { backgroundColor: theme.colors.surface2 }],
3554
3627
  accessibilityLabel: "Close thread",
3555
3628
  children: /* @__PURE__ */ jsx(PoolseIcon, { name: "close", size: 18, color: theme.colors.ink })
3556
3629
  }
@@ -3559,7 +3632,7 @@ function ThreadSheet({
3559
3632
  Text,
3560
3633
  {
3561
3634
  style: [
3562
- styles18.title,
3635
+ styles19.title,
3563
3636
  { color: theme.colors.ink, fontFamily: theme.type.fontDisplay }
3564
3637
  ],
3565
3638
  children: "Thread"
@@ -3570,12 +3643,12 @@ function ThreadSheet({
3570
3643
  /* @__PURE__ */ jsxs(
3571
3644
  KeyboardAvoidingView,
3572
3645
  {
3573
- style: styles18.kavBody,
3646
+ style: styles19.kavBody,
3574
3647
  behavior: Platform.OS === "ios" ? "padding" : "height",
3575
3648
  keyboardVerticalOffset: Platform.OS === "ios" ? gutter : 0,
3576
3649
  children: [
3577
- /* @__PURE__ */ jsx(View, { style: [styles18.rootPreview, { backgroundColor: theme.colors.surface2 }], children: rootRow }),
3578
- /* @__PURE__ */ jsx(View, { style: styles18.listWrap, children: /* @__PURE__ */ jsx(
3650
+ /* @__PURE__ */ jsx(View, { style: [styles19.rootPreview, { backgroundColor: theme.colors.surface2 }], children: rootRow }),
3651
+ /* @__PURE__ */ jsx(View, { style: styles19.listWrap, children: /* @__PURE__ */ jsx(
3579
3652
  MessageList,
3580
3653
  {
3581
3654
  messages: replies,
@@ -3611,7 +3684,7 @@ function ThreadSheet({
3611
3684
  )
3612
3685
  ] });
3613
3686
  }
3614
- var styles18 = StyleSheet.create({
3687
+ var styles19 = StyleSheet.create({
3615
3688
  modalRoot: {
3616
3689
  flex: 1,
3617
3690
  justifyContent: "flex-end"
@@ -3683,7 +3756,7 @@ function TypingIndicator({ typing, labelFor }) {
3683
3756
  const ids = Array.from(typing);
3684
3757
  const isTyping = ids.length > 0;
3685
3758
  if (!isTyping) return /* @__PURE__ */ jsx(View, { style: { height: 0 } });
3686
- return /* @__PURE__ */ jsxs(View, { style: styles19.row, children: [
3759
+ return /* @__PURE__ */ jsxs(View, { style: styles20.row, children: [
3687
3760
  /* @__PURE__ */ jsx(TypingDots, {}),
3688
3761
  /* @__PURE__ */ jsx(TypingLabel, { ids, ...labelFor ? { labelFor } : {} })
3689
3762
  ] });
@@ -3728,7 +3801,7 @@ function TypingDots() {
3728
3801
  ],
3729
3802
  opacity: val.interpolate({ inputRange: [0, 1], outputRange: [0.5, 1] })
3730
3803
  });
3731
- return /* @__PURE__ */ jsxs(View, { style: styles19.dotsWrap, children: [
3804
+ return /* @__PURE__ */ jsxs(View, { style: styles20.dotsWrap, children: [
3732
3805
  /* @__PURE__ */ jsx(Animated.View, { style: dot(a) }),
3733
3806
  /* @__PURE__ */ jsx(Animated.View, { style: dot(b) }),
3734
3807
  /* @__PURE__ */ jsx(Animated.View, { style: dot(c) })
@@ -3744,9 +3817,9 @@ function TypingLabel({
3744
3817
  const name1 = useDisplayName(id1, labelFor);
3745
3818
  const name2 = useDisplayName(id2, labelFor);
3746
3819
  const text = ids.length === 1 ? `${name1} is typing` : ids.length === 2 ? `${name1} and ${name2} are typing` : `${ids.length} people are typing`;
3747
- return /* @__PURE__ */ jsx(Text, { style: [styles19.label, { color: theme.colors.ink2, fontFamily: theme.type.fontBody }], children: text });
3820
+ return /* @__PURE__ */ jsx(Text, { style: [styles20.label, { color: theme.colors.ink2, fontFamily: theme.type.fontBody }], children: text });
3748
3821
  }
3749
- var styles19 = StyleSheet.create({
3822
+ var styles20 = StyleSheet.create({
3750
3823
  row: {
3751
3824
  flexDirection: "row",
3752
3825
  alignItems: "center",
@@ -3984,12 +4057,12 @@ function ConversationView({
3984
4057
  return /* @__PURE__ */ jsx(UploadProvider, { children: /* @__PURE__ */ jsxs(
3985
4058
  KeyboardAvoidingView,
3986
4059
  {
3987
- style: [styles20.root, { backgroundColor: theme.colors.paper }],
4060
+ style: [styles21.root, { backgroundColor: theme.colors.paper }],
3988
4061
  behavior: Platform.OS === "ios" ? "padding" : "height",
3989
4062
  keyboardVerticalOffset: keyboardOffset,
3990
4063
  children: [
3991
4064
  headerNode,
3992
- /* @__PURE__ */ jsxs(View, { style: styles20.listWrap, children: [
4065
+ /* @__PURE__ */ jsxs(View, { style: styles21.listWrap, children: [
3993
4066
  /* @__PURE__ */ jsx(
3994
4067
  MessageList,
3995
4068
  {
@@ -4007,7 +4080,7 @@ function ConversationView({
4007
4080
  editingId ? /* @__PURE__ */ jsx(
4008
4081
  Pressable,
4009
4082
  {
4010
- style: styles20.editBackdrop,
4083
+ style: styles21.editBackdrop,
4011
4084
  onPress: () => setEditingId(null),
4012
4085
  accessibilityLabel: "Cancel editing"
4013
4086
  }
@@ -4042,7 +4115,7 @@ function readStateForMessage(msg, members, meId, sequenceByMessageId) {
4042
4115
  });
4043
4116
  return anyRead ? "read" : "sent";
4044
4117
  }
4045
- var styles20 = StyleSheet.create({
4118
+ var styles21 = StyleSheet.create({
4046
4119
  root: {
4047
4120
  flex: 1
4048
4121
  },
@@ -4124,13 +4197,13 @@ function UserPickerSheet({
4124
4197
  animationType: "slide",
4125
4198
  onRequestClose: handleClose,
4126
4199
  statusBarTranslucent: true,
4127
- children: /* @__PURE__ */ jsxs(View, { style: styles21.modalRoot, children: [
4128
- /* @__PURE__ */ jsx(Pressable, { style: styles21.backdrop, onPress: handleClose }),
4200
+ children: /* @__PURE__ */ jsxs(View, { style: styles22.modalRoot, children: [
4201
+ /* @__PURE__ */ jsx(Pressable, { style: styles22.backdrop, onPress: handleClose }),
4129
4202
  /* @__PURE__ */ jsxs(
4130
4203
  Animated.View,
4131
4204
  {
4132
4205
  style: [
4133
- styles21.sheet,
4206
+ styles22.sheet,
4134
4207
  {
4135
4208
  backgroundColor: theme.colors.paper,
4136
4209
  borderTopLeftRadius: theme.radii.xl,
@@ -4140,14 +4213,14 @@ function UserPickerSheet({
4140
4213
  theme.shadows.lg
4141
4214
  ],
4142
4215
  children: [
4143
- /* @__PURE__ */ jsx(View, { ...panHandlers, style: styles21.dragHandle, children: /* @__PURE__ */ jsx(View, { style: [styles21.dragPill, { backgroundColor: theme.colors.ink3 }] }) }),
4144
- /* @__PURE__ */ jsxs(View, { style: styles21.header, children: [
4216
+ /* @__PURE__ */ jsx(View, { ...panHandlers, style: styles22.dragHandle, children: /* @__PURE__ */ jsx(View, { style: [styles22.dragPill, { backgroundColor: theme.colors.ink3 }] }) }),
4217
+ /* @__PURE__ */ jsxs(View, { style: styles22.header, children: [
4145
4218
  /* @__PURE__ */ jsx(
4146
4219
  Pressable,
4147
4220
  {
4148
4221
  onPress: handleClose,
4149
4222
  hitSlop: 16,
4150
- style: [styles21.closeBtn, { backgroundColor: theme.colors.surface2 }],
4223
+ style: [styles22.closeBtn, { backgroundColor: theme.colors.surface2 }],
4151
4224
  accessibilityLabel: "Close picker",
4152
4225
  children: /* @__PURE__ */ jsx(PoolseIcon, { name: "close", size: 18, color: theme.colors.ink })
4153
4226
  }
@@ -4156,7 +4229,7 @@ function UserPickerSheet({
4156
4229
  Text,
4157
4230
  {
4158
4231
  style: [
4159
- styles21.title,
4232
+ styles22.title,
4160
4233
  { color: theme.colors.ink, fontFamily: theme.type.fontDisplay }
4161
4234
  ],
4162
4235
  numberOfLines: 1,
@@ -4170,7 +4243,7 @@ function UserPickerSheet({
4170
4243
  disabled: !canCreate,
4171
4244
  hitSlop: 6,
4172
4245
  style: [
4173
- styles21.createBtn,
4246
+ styles22.createBtn,
4174
4247
  {
4175
4248
  backgroundColor: canCreate ? theme.colors.brand : theme.colors.surface2,
4176
4249
  opacity: canCreate ? 1 : 0.6
@@ -4201,7 +4274,7 @@ function UserPickerSheet({
4201
4274
  value: groupName,
4202
4275
  onChangeText: setGroupName,
4203
4276
  style: [
4204
- styles21.groupNameInput,
4277
+ styles22.groupNameInput,
4205
4278
  {
4206
4279
  color: theme.colors.ink,
4207
4280
  backgroundColor: theme.colors.surface2,
@@ -4220,7 +4293,7 @@ function UserPickerSheet({
4220
4293
  value: query,
4221
4294
  onChangeText: setQuery,
4222
4295
  style: [
4223
- styles21.searchInput,
4296
+ styles22.searchInput,
4224
4297
  {
4225
4298
  color: theme.colors.ink,
4226
4299
  backgroundColor: theme.colors.surface2,
@@ -4236,7 +4309,7 @@ function UserPickerSheet({
4236
4309
  {
4237
4310
  data: filtered,
4238
4311
  keyExtractor: (u) => u.externalId,
4239
- ListEmptyComponent: /* @__PURE__ */ jsx(View, { style: styles21.empty, children: /* @__PURE__ */ jsx(Text, { style: [styles21.emptyText, { color: theme.colors.ink3 }], children: query ? "No matches." : "No users to show." }) }),
4312
+ ListEmptyComponent: /* @__PURE__ */ jsx(View, { style: styles22.empty, children: /* @__PURE__ */ jsx(Text, { style: [styles22.emptyText, { color: theme.colors.ink3 }], children: query ? "No matches." : "No users to show." }) }),
4240
4313
  renderItem: ({ item }) => /* @__PURE__ */ jsx(
4241
4314
  UserRow,
4242
4315
  {
@@ -4274,29 +4347,29 @@ function UserRow({
4274
4347
  {
4275
4348
  onPress,
4276
4349
  style: [
4277
- styles21.row,
4350
+ styles22.row,
4278
4351
  {
4279
4352
  backgroundColor: selected ? theme.colors.brandSoft : "transparent"
4280
4353
  }
4281
4354
  ],
4282
4355
  children: [
4283
- user.avatarUrl ? /* @__PURE__ */ jsx(Image, { source: { uri: user.avatarUrl }, style: styles21.avatarImg }) : /* @__PURE__ */ jsx(Avatar, { src: null, name: user.name, seed: user.externalId, size: "md" }),
4284
- /* @__PURE__ */ jsxs(View, { style: styles21.body, children: [
4356
+ user.avatarUrl ? /* @__PURE__ */ jsx(Image, { source: { uri: user.avatarUrl }, style: styles22.avatarImg }) : /* @__PURE__ */ jsx(Avatar, { src: null, name: user.name, seed: user.externalId, size: "md" }),
4357
+ /* @__PURE__ */ jsxs(View, { style: styles22.body, children: [
4285
4358
  /* @__PURE__ */ jsx(
4286
4359
  Text,
4287
4360
  {
4288
- style: [styles21.name, { color: theme.colors.ink, fontFamily: theme.type.fontBody }],
4361
+ style: [styles22.name, { color: theme.colors.ink, fontFamily: theme.type.fontBody }],
4289
4362
  numberOfLines: 1,
4290
4363
  children: user.name
4291
4364
  }
4292
4365
  ),
4293
- user.subtitle ? /* @__PURE__ */ jsx(Text, { style: [styles21.subtitle, { color: theme.colors.ink3 }], numberOfLines: 1, children: user.subtitle }) : null
4366
+ user.subtitle ? /* @__PURE__ */ jsx(Text, { style: [styles22.subtitle, { color: theme.colors.ink3 }], numberOfLines: 1, children: user.subtitle }) : null
4294
4367
  ] }),
4295
4368
  isGroup ? /* @__PURE__ */ jsx(
4296
4369
  View,
4297
4370
  {
4298
4371
  style: [
4299
- styles21.checkbox,
4372
+ styles22.checkbox,
4300
4373
  {
4301
4374
  borderColor: selected ? theme.colors.brand : theme.colors.border,
4302
4375
  backgroundColor: selected ? theme.colors.brand : "transparent"
@@ -4309,7 +4382,7 @@ function UserRow({
4309
4382
  }
4310
4383
  );
4311
4384
  }
4312
- var styles21 = StyleSheet.create({
4385
+ var styles22 = StyleSheet.create({
4313
4386
  modalRoot: {
4314
4387
  flex: 1,
4315
4388
  justifyContent: "flex-end"
@@ -4569,7 +4642,7 @@ var PoolseInbox = forwardRef(
4569
4642
  },
4570
4643
  [renderConversationRow, meExternalId, labelFor, avatarFor, unreadCounts]
4571
4644
  );
4572
- return /* @__PURE__ */ jsxs(View, { style: [styles22.root, { backgroundColor: theme.colors.paper }], children: [
4645
+ return /* @__PURE__ */ jsxs(View, { style: [styles23.root, { backgroundColor: theme.colors.paper }], children: [
4573
4646
  /* @__PURE__ */ jsxs(
4574
4647
  Animated.View,
4575
4648
  {
@@ -4580,7 +4653,7 @@ var PoolseInbox = forwardRef(
4580
4653
  View,
4581
4654
  {
4582
4655
  style: [
4583
- styles22.listHeader,
4656
+ styles23.listHeader,
4584
4657
  {
4585
4658
  backgroundColor: theme.colors.surface,
4586
4659
  borderBottomColor: theme.colors.border
@@ -4591,13 +4664,13 @@ var PoolseInbox = forwardRef(
4591
4664
  Text,
4592
4665
  {
4593
4666
  style: [
4594
- styles22.listTitle,
4667
+ styles23.listTitle,
4595
4668
  { color: theme.colors.ink, fontFamily: theme.type.fontDisplay }
4596
4669
  ],
4597
4670
  children: title
4598
4671
  }
4599
4672
  ),
4600
- /* @__PURE__ */ jsxs(View, { style: styles22.headerActions, children: [
4673
+ /* @__PURE__ */ jsxs(View, { style: styles23.headerActions, children: [
4601
4674
  users ? /* @__PURE__ */ jsxs(Fragment, { children: [
4602
4675
  /* @__PURE__ */ jsx(
4603
4676
  HeaderIconButton,
@@ -4710,7 +4783,7 @@ function HeaderIconButton({
4710
4783
  hitSlop: 10,
4711
4784
  accessibilityLabel: label,
4712
4785
  style: ({ pressed }) => [
4713
- styles22.iconBtn,
4786
+ styles23.iconBtn,
4714
4787
  {
4715
4788
  backgroundColor: pressed ? theme.colors.surface2 : "transparent"
4716
4789
  }
@@ -4740,31 +4813,31 @@ function DefaultConversationRow({
4740
4813
  {
4741
4814
  onPress,
4742
4815
  style: [
4743
- styles22.row,
4816
+ styles23.row,
4744
4817
  {
4745
4818
  backgroundColor: selected ? theme.colors.surface2 : "transparent",
4746
4819
  borderBottomColor: theme.colors.border
4747
4820
  }
4748
4821
  ],
4749
4822
  children: [
4750
- avatarUrl ? /* @__PURE__ */ jsx(Image, { source: { uri: avatarUrl }, style: styles22.rowAvatar }) : /* @__PURE__ */ jsx(Avatar, { src: null, name: title, seed: avatarSeed, size: "md" }),
4751
- /* @__PURE__ */ jsxs(View, { style: styles22.rowBody, children: [
4823
+ avatarUrl ? /* @__PURE__ */ jsx(Image, { source: { uri: avatarUrl }, style: styles23.rowAvatar }) : /* @__PURE__ */ jsx(Avatar, { src: null, name: title, seed: avatarSeed, size: "md" }),
4824
+ /* @__PURE__ */ jsxs(View, { style: styles23.rowBody, children: [
4752
4825
  /* @__PURE__ */ jsx(
4753
4826
  Text,
4754
4827
  {
4755
- style: [styles22.rowTitle, { color: theme.colors.ink, fontFamily: theme.type.fontBody }],
4828
+ style: [styles23.rowTitle, { color: theme.colors.ink, fontFamily: theme.type.fontBody }],
4756
4829
  numberOfLines: 1,
4757
4830
  children: title
4758
4831
  }
4759
4832
  ),
4760
- /* @__PURE__ */ jsx(Text, { style: [styles22.rowSubtitle, { color: theme.colors.ink3 }], numberOfLines: 1, children: conv.last_message_preview ?? (isDirect ? otherExtId ?? "" : `${(conv.member_external_ids ?? []).length} members`) })
4833
+ /* @__PURE__ */ jsx(Text, { style: [styles23.rowSubtitle, { color: theme.colors.ink3 }], numberOfLines: 1, children: conv.last_message_preview ?? (isDirect ? otherExtId ?? "" : `${(conv.member_external_ids ?? []).length} members`) })
4761
4834
  ] }),
4762
- unread > 0 ? /* @__PURE__ */ jsx(View, { style: [styles22.unreadPill, { backgroundColor: theme.colors.unreadPill }], children: /* @__PURE__ */ jsx(Text, { style: [styles22.unreadText, { color: theme.colors.unreadPillText }], children: unread > 99 ? "99+" : String(unread) }) }) : null
4835
+ unread > 0 ? /* @__PURE__ */ jsx(View, { style: [styles23.unreadPill, { backgroundColor: theme.colors.unreadPill }], children: /* @__PURE__ */ jsx(Text, { style: [styles23.unreadText, { color: theme.colors.unreadPillText }], children: unread > 99 ? "99+" : String(unread) }) }) : null
4763
4836
  ]
4764
4837
  }
4765
4838
  );
4766
4839
  }
4767
- var styles22 = StyleSheet.create({
4840
+ var styles23 = StyleSheet.create({
4768
4841
  root: {
4769
4842
  flex: 1,
4770
4843
  overflow: "hidden"
@@ -4968,10 +5041,10 @@ function VoiceRoomBar({
4968
5041
  View,
4969
5042
  {
4970
5043
  style: [
4971
- styles23.bar,
5044
+ styles24.bar,
4972
5045
  { backgroundColor: theme.colors.surface, borderBottomColor: theme.colors.border }
4973
5046
  ],
4974
- children: unavailableSlot ?? /* @__PURE__ */ jsx(Text, { style: [styles23.hint, { color: theme.colors.ink3 }], children: "Voice needs react-native-webrtc and a development build." })
5047
+ children: unavailableSlot ?? /* @__PURE__ */ jsx(Text, { style: [styles24.hint, { color: theme.colors.ink3 }], children: "Voice needs react-native-webrtc and a development build." })
4975
5048
  }
4976
5049
  );
4977
5050
  }
@@ -4979,22 +5052,22 @@ function VoiceRoomBar({
4979
5052
  View,
4980
5053
  {
4981
5054
  style: [
4982
- styles23.bar,
5055
+ styles24.bar,
4983
5056
  { backgroundColor: theme.colors.surface, borderBottomColor: theme.colors.border }
4984
5057
  ],
4985
5058
  children: [
4986
- /* @__PURE__ */ jsxs(View, { style: styles23.row, children: [
5059
+ /* @__PURE__ */ jsxs(View, { style: styles24.row, children: [
4987
5060
  /* @__PURE__ */ jsx(
4988
5061
  View,
4989
5062
  {
4990
5063
  style: [
4991
- styles23.dot,
5064
+ styles24.dot,
4992
5065
  { backgroundColor: connected ? theme.colors.brand : theme.colors.ink3 }
4993
5066
  ]
4994
5067
  }
4995
5068
  ),
4996
5069
  connected ? /* @__PURE__ */ jsxs(Fragment, { children: [
4997
- /* @__PURE__ */ jsx(View, { style: styles23.people, children: participants.length === 0 ? /* @__PURE__ */ jsx(Text, { style: [styles23.hint, { color: theme.colors.ink3 }], children: "Waiting for others\u2026" }) : participants.map((p) => /* @__PURE__ */ jsx(ParticipantChip, { participant: p, label: label(p.userId) }, p.userId)) }),
5070
+ /* @__PURE__ */ jsx(View, { style: styles24.people, children: participants.length === 0 ? /* @__PURE__ */ jsx(Text, { style: [styles24.hint, { color: theme.colors.ink3 }], children: "Waiting for others\u2026" }) : participants.map((p) => /* @__PURE__ */ jsx(ParticipantChip, { participant: p, label: label(p.userId) }, p.userId)) }),
4998
5071
  /* @__PURE__ */ jsx(
4999
5072
  Pressable,
5000
5073
  {
@@ -5002,7 +5075,7 @@ function VoiceRoomBar({
5002
5075
  accessibilityRole: "button",
5003
5076
  accessibilityState: { selected: muted },
5004
5077
  style: [
5005
- styles23.btn,
5078
+ styles24.btn,
5006
5079
  {
5007
5080
  borderColor: muted ? theme.colors.brand : theme.colors.border,
5008
5081
  backgroundColor: muted ? theme.colors.brandSoft : theme.colors.paper
@@ -5016,25 +5089,25 @@ function VoiceRoomBar({
5016
5089
  {
5017
5090
  onPress: leave,
5018
5091
  accessibilityRole: "button",
5019
- style: [styles23.btn, { borderColor: theme.colors.error }],
5092
+ style: [styles24.btn, { borderColor: theme.colors.error }],
5020
5093
  children: /* @__PURE__ */ jsx(Text, { style: { color: theme.colors.error }, children: "Leave" })
5021
5094
  }
5022
5095
  )
5023
5096
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
5024
- /* @__PURE__ */ jsx(Text, { style: [styles23.hint, { color: theme.colors.ink3 }], children: status === "connecting" ? "Connecting\u2026" : "Talk to everyone here" }),
5097
+ /* @__PURE__ */ jsx(Text, { style: [styles24.hint, { color: theme.colors.ink3 }], children: status === "connecting" ? "Connecting\u2026" : "Talk to everyone here" }),
5025
5098
  /* @__PURE__ */ jsx(
5026
5099
  Pressable,
5027
5100
  {
5028
5101
  onPress: () => void join(),
5029
5102
  disabled: status === "connecting",
5030
5103
  accessibilityRole: "button",
5031
- style: [styles23.btn, styles23.btnPrimary, { backgroundColor: theme.colors.brand }],
5104
+ style: [styles24.btn, styles24.btnPrimary, { backgroundColor: theme.colors.brand }],
5032
5105
  children: /* @__PURE__ */ jsx(Text, { style: { color: theme.colors.onBrand, fontWeight: "600" }, children: status === "connecting" ? "Joining\u2026" : "Join Voice" })
5033
5106
  }
5034
5107
  )
5035
5108
  ] })
5036
5109
  ] }),
5037
- error && /* @__PURE__ */ jsx(Text, { style: [styles23.error, { color: theme.colors.error }], children: error.message })
5110
+ error && /* @__PURE__ */ jsx(Text, { style: [styles24.error, { color: theme.colors.error }], children: error.message })
5038
5111
  ]
5039
5112
  }
5040
5113
  );
@@ -5045,7 +5118,7 @@ function ParticipantChip({ participant, label }) {
5045
5118
  View,
5046
5119
  {
5047
5120
  style: [
5048
- styles23.chip,
5121
+ styles24.chip,
5049
5122
  {
5050
5123
  backgroundColor: theme.colors.paper,
5051
5124
  // The speaking ring is a border colour swap rather than an
@@ -5064,7 +5137,7 @@ function ParticipantChip({ participant, label }) {
5064
5137
  }
5065
5138
  );
5066
5139
  }
5067
- var styles23 = StyleSheet.create({
5140
+ var styles24 = StyleSheet.create({
5068
5141
  bar: { paddingHorizontal: 14, paddingVertical: 8, borderBottomWidth: StyleSheet.hairlineWidth },
5069
5142
  row: { flexDirection: "row", alignItems: "center", gap: 8, flexWrap: "wrap" },
5070
5143
  dot: { width: 8, height: 8, borderRadius: 4 },
@@ -5086,42 +5159,77 @@ var styles23 = StyleSheet.create({
5086
5159
  function CallScreen({
5087
5160
  userId,
5088
5161
  labelFor,
5089
- calls: external,
5162
+ calls: callsProp,
5090
5163
  webrtc,
5164
+ livekit,
5165
+ livekitReactNative,
5091
5166
  onStatusChange,
5092
- nativeIncomingUi = false
5167
+ onVideoChange,
5168
+ nativeIncomingUi
5093
5169
  }) {
5094
5170
  const theme = usePoolseTheme();
5095
- const own = useCalls(external ? null : userId);
5096
- const calls = external ?? own;
5097
- const available = isNativeWebRtcAvailable(webrtc);
5171
+ const ownCalls = useCalls(callsProp ? null : userId);
5172
+ const calls = callsProp ?? ownCalls;
5173
+ const meshAvailable = isNativeWebRtcAvailable(webrtc);
5098
5174
  const opts = useMemo(
5099
- () => available && webrtc ? { webrtc: createNativeWebRtcAdapter(webrtc) } : {},
5100
- [available, webrtc]
5101
- );
5102
- const voice = useVoiceRoom(
5103
- calls.phase === "active" && available ? calls.activeConversationId : null,
5104
- opts
5175
+ () => meshAvailable && webrtc ? { webrtc: createNativeWebRtcAdapter(webrtc) } : {},
5176
+ [meshAvailable, webrtc]
5105
5177
  );
5178
+ const conversationId = calls.phase === "active" ? calls.activeConversationId : null;
5179
+ const sfu = useCallRoom(livekit ? conversationId : null, {
5180
+ livekit,
5181
+ video: calls.media === "video"
5182
+ });
5183
+ const mesh = useVoiceRoom(conversationId, opts);
5184
+ const usingSfu = sfu.sfuAvailable === true;
5185
+ const status = usingSfu ? toVoiceStatus(sfu.status) : mesh.status;
5106
5186
  useEffect(() => {
5107
- if (calls.phase === "active" && voice.status === "idle") void voice.join();
5108
- }, [calls.phase, voice]);
5187
+ if (calls.phase !== "active" || !conversationId) return;
5188
+ let cancelled = false;
5189
+ void (async () => {
5190
+ const connected2 = livekit ? await sfu.join() : false;
5191
+ if (cancelled || connected2) return;
5192
+ if (meshAvailable) await mesh.join();
5193
+ })();
5194
+ return () => {
5195
+ cancelled = true;
5196
+ };
5197
+ }, [calls.phase, conversationId, livekit, meshAvailable]);
5109
5198
  useEffect(() => {
5110
- onStatusChange?.(voice.status);
5111
- }, [voice.status, onStatusChange]);
5199
+ onStatusChange?.(status);
5200
+ }, [status, onStatusChange]);
5201
+ const videoOn = usingSfu && sfu.cameraEnabled;
5202
+ useEffect(() => {
5203
+ onVideoChange?.(videoOn);
5204
+ }, [videoOn, onVideoChange]);
5112
5205
  const label = labelFor ?? ((id) => `User ${id.slice(0, 6)}`);
5113
5206
  const ringingIn = calls.phase === "ringing-in";
5114
5207
  const visible = calls.phase !== "idle" && !(nativeIncomingUi && ringingIn);
5115
- const hangUp = () => {
5116
- voice.leave();
5208
+ const hangUp = useCallback(() => {
5209
+ sfu.leave();
5210
+ mesh.leave();
5117
5211
  void calls.hangUp();
5118
- };
5119
- return /* @__PURE__ */ jsx(Modal, { visible, animationType: "slide", transparent: false, onRequestClose: hangUp, children: /* @__PURE__ */ jsxs(View, { style: [styles24.screen, { backgroundColor: theme.colors.paper }], children: [
5120
- /* @__PURE__ */ jsxs(View, { style: styles24.identity, children: [
5121
- /* @__PURE__ */ jsx(Text, { style: [styles24.who, { color: theme.colors.ink }], children: calls.phase === "ringing-in" && calls.incoming ? label(calls.incoming.callerUserId) : calls.outgoing ? calls.outgoing.calleeUserIds.map(label).join(", ") : "" }),
5122
- /* @__PURE__ */ jsx(Text, { style: [styles24.state, { color: theme.colors.ink3 }], children: statusLine(calls, voice.status) })
5212
+ }, [sfu, mesh, calls]);
5213
+ const micOn = usingSfu ? sfu.micEnabled : !mesh.muted;
5214
+ const toggleMic = useCallback(() => {
5215
+ if (usingSfu) void sfu.toggleMic();
5216
+ else mesh.toggleMute();
5217
+ }, [usingSfu, sfu, mesh]);
5218
+ const error = calls.error ?? (usingSfu ? sfu.error : mesh.error);
5219
+ const connected = calls.phase === "active" && status === "connected";
5220
+ return /* @__PURE__ */ jsx(Modal, { visible, animationType: "slide", transparent: false, onRequestClose: hangUp, children: /* @__PURE__ */ jsxs(View, { style: [styles25.screen, { backgroundColor: theme.colors.paper }], children: [
5221
+ connected && usingSfu && sfu.participants.length > 0 ? /* @__PURE__ */ jsx(
5222
+ CallVideoGrid,
5223
+ {
5224
+ participants: sfu.participants,
5225
+ livekitReactNative,
5226
+ labelFor
5227
+ }
5228
+ ) : /* @__PURE__ */ jsxs(View, { style: styles25.identity, children: [
5229
+ /* @__PURE__ */ jsx(Text, { style: [styles25.who, { color: theme.colors.ink }], children: ringingIn && calls.incoming ? label(calls.incoming.callerUserId) : calls.outgoing ? calls.outgoing.calleeUserIds.map(label).join(", ") : "" }),
5230
+ /* @__PURE__ */ jsx(Text, { style: [styles25.state, { color: theme.colors.ink3 }], children: statusLine(calls, status) })
5123
5231
  ] }),
5124
- /* @__PURE__ */ jsx(View, { style: styles24.actions, children: calls.phase === "ringing-in" ? /* @__PURE__ */ jsxs(Fragment, { children: [
5232
+ /* @__PURE__ */ jsx(View, { style: styles25.actions, children: ringingIn ? /* @__PURE__ */ jsxs(Fragment, { children: [
5125
5233
  /* @__PURE__ */ jsx(
5126
5234
  CallButton,
5127
5235
  {
@@ -5149,21 +5257,41 @@ function CallScreen({
5149
5257
  /* @__PURE__ */ jsx(
5150
5258
  CallButton,
5151
5259
  {
5152
- label: voice.muted ? "Unmute" : "Mute",
5153
- color: theme.colors.ink2,
5154
- onPress: voice.toggleMute
5260
+ label: micOn ? "Mute" : "Unmute",
5261
+ color: micOn ? theme.colors.ink2 : theme.colors.brand,
5262
+ onPress: toggleMic
5263
+ }
5264
+ ),
5265
+ usingSfu && /* @__PURE__ */ jsx(
5266
+ CallButton,
5267
+ {
5268
+ label: videoOn ? "Camera off" : "Camera on",
5269
+ color: videoOn ? theme.colors.brand : theme.colors.ink2,
5270
+ onPress: () => void sfu.toggleCamera()
5155
5271
  }
5156
5272
  ),
5157
5273
  /* @__PURE__ */ jsx(CallButton, { label: "Hang up", color: theme.colors.error, onPress: hangUp })
5158
5274
  ] }) }),
5159
- !available && /* @__PURE__ */ jsx(Text, { style: [styles24.warn, { color: theme.colors.error }], children: "react-native-webrtc is not installed \u2014 this call has no audio." }),
5160
- (calls.error ?? voice.error) && /* @__PURE__ */ jsx(Text, { style: [styles24.warn, { color: theme.colors.error }], children: (calls.error ?? voice.error)?.message })
5275
+ !meshAvailable && !livekit && /* @__PURE__ */ jsx(Text, { style: [styles25.warn, { color: theme.colors.error }], children: "No WebRTC module supplied \u2014 this call has no audio." }),
5276
+ error && /* @__PURE__ */ jsx(Text, { style: [styles25.warn, { color: theme.colors.error }], children: error.message })
5161
5277
  ] }) });
5162
5278
  }
5163
- function statusLine(calls, voiceStatus) {
5279
+ function toVoiceStatus(status) {
5280
+ switch (status) {
5281
+ case "connecting":
5282
+ return "connecting";
5283
+ case "connected":
5284
+ return "connected";
5285
+ case "error":
5286
+ return "error";
5287
+ default:
5288
+ return "idle";
5289
+ }
5290
+ }
5291
+ function statusLine(calls, mediaStatus) {
5164
5292
  switch (calls.phase) {
5165
5293
  case "ringing-in":
5166
- return "Incoming call\u2026";
5294
+ return calls.media === "video" ? "Incoming video call\u2026" : "Incoming call\u2026";
5167
5295
  case "ringing-out":
5168
5296
  return "Ringing\u2026";
5169
5297
  case "declined":
@@ -5173,7 +5301,7 @@ function statusLine(calls, voiceStatus) {
5173
5301
  case "timed-out":
5174
5302
  return "No answer";
5175
5303
  case "active":
5176
- return voiceStatus === "connected" ? "Connected" : "Connecting\u2026";
5304
+ return mediaStatus === "connected" ? "Connected" : "Connecting\u2026";
5177
5305
  default:
5178
5306
  return "";
5179
5307
  }
@@ -5188,22 +5316,22 @@ function CallButton({
5188
5316
  {
5189
5317
  onPress,
5190
5318
  accessibilityRole: "button",
5191
- style: [styles24.callBtn, { backgroundColor: color }],
5192
- children: /* @__PURE__ */ jsx(Text, { style: styles24.callBtnText, children: label })
5319
+ style: [styles25.callBtn, { backgroundColor: color }],
5320
+ children: /* @__PURE__ */ jsx(Text, { style: styles25.callBtnText, children: label })
5193
5321
  }
5194
5322
  );
5195
5323
  }
5196
- var styles24 = StyleSheet.create({
5324
+ var styles25 = StyleSheet.create({
5197
5325
  screen: { flex: 1, justifyContent: "space-between", paddingVertical: 72, paddingHorizontal: 24 },
5198
5326
  identity: { alignItems: "center", gap: 8, marginTop: 48 },
5199
5327
  who: { fontSize: 28, fontWeight: "600", textAlign: "center" },
5200
5328
  state: { fontSize: 15 },
5201
- actions: { flexDirection: "row", justifyContent: "center", gap: 16 },
5329
+ actions: { flexDirection: "row", justifyContent: "center", gap: 12, flexWrap: "wrap" },
5202
5330
  callBtn: {
5203
- paddingHorizontal: 26,
5331
+ paddingHorizontal: 22,
5204
5332
  paddingVertical: 16,
5205
5333
  borderRadius: 999,
5206
- minWidth: 128,
5334
+ minWidth: 108,
5207
5335
  alignItems: "center"
5208
5336
  },
5209
5337
  callBtnText: { color: "#ffffff", fontSize: 16, fontWeight: "600" },
@@ -5255,7 +5383,7 @@ function useVoipCalls({
5255
5383
  call.callerUserId,
5256
5384
  call.callerName,
5257
5385
  "generic",
5258
- false
5386
+ call.media === "video"
5259
5387
  );
5260
5388
  } catch {
5261
5389
  }
@@ -5281,7 +5409,10 @@ function useVoipCalls({
5281
5409
  callId,
5282
5410
  conversationId,
5283
5411
  callerUserId: payload.caller_user_id ?? "",
5284
- callerName: payload.caller_name ?? "Incoming call"
5412
+ callerName: payload.caller_name ?? "Incoming call",
5413
+ // `has_video` is what older servers sent; `media` supersedes
5414
+ // it. Either says video, and the system UI offers video.
5415
+ media: payload.media === "video" || payload.has_video ? "video" : "audio"
5285
5416
  },
5286
5417
  payload.sent_at
5287
5418
  );
@@ -5330,7 +5461,8 @@ function useVoipCalls({
5330
5461
  void handlers.current.calls?.accept({
5331
5462
  callId: call.callId,
5332
5463
  conversationId: call.conversationId,
5333
- callerUserId: call.callerUserId
5464
+ callerUserId: call.callerUserId,
5465
+ media: call.media
5334
5466
  });
5335
5467
  handlers.current.onAnswer?.(call);
5336
5468
  }));
@@ -5346,7 +5478,8 @@ function useVoipCalls({
5346
5478
  void handlers.current.calls?.decline({
5347
5479
  callId: call.callId,
5348
5480
  conversationId: call.conversationId,
5349
- callerUserId: call.callerUserId
5481
+ callerUserId: call.callerUserId,
5482
+ media: call.media
5350
5483
  });
5351
5484
  handlers.current.onDecline?.(call);
5352
5485
  }));
@@ -5368,7 +5501,8 @@ function useVoipCalls({
5368
5501
  callId: incoming.callId,
5369
5502
  conversationId: incoming.conversationId,
5370
5503
  callerUserId: incoming.callerUserId,
5371
- callerName: incoming.callerUserId
5504
+ callerName: incoming.callerUserId,
5505
+ media: incoming.media
5372
5506
  });
5373
5507
  }
5374
5508
  }, [phase, incoming]);
@@ -5381,6 +5515,6 @@ function guessApnsEnvironment() {
5381
5515
  return __DEV__ ? "sandbox" : "production";
5382
5516
  }
5383
5517
 
5384
- export { AttachmentPicker, AttachmentPreview, Avatar, CallScreen, ChatHeader, ConversationList, ConversationView, DaySeparator, GroupDetailsSheet, ImageMosaic, MemberList, MentionInput, MessageActions, MessageBubble, MessageComposer, MessageList, MessageRow, PoolseIcon, PoolseInbox, PoolseLogo, PoolseTheme, primitives as Primitives, ReactionPicker, ReactionStrip, ThreadView, TypingIndicator, UploadQueueStrip, UserName, VoiceRoomBar, createNativeWebRtcAdapter, defaultDarkTheme, defaultLightTheme, isNativeWebRtcAvailable, isStalePush, useAppStateLifecycle, useDisplayName, usePoolseTheme, useVoipCalls };
5518
+ export { AttachmentPicker, AttachmentPreview, Avatar, CallScreen, CallVideoGrid, ChatHeader, ConversationList, ConversationView, DaySeparator, GroupDetailsSheet, ImageMosaic, MemberList, MentionInput, MessageActions, MessageBubble, MessageComposer, MessageList, MessageRow, PoolseIcon, PoolseInbox, PoolseLogo, PoolseTheme, primitives as Primitives, ReactionPicker, ReactionStrip, ThreadView, TypingIndicator, UploadQueueStrip, UserName, VoiceRoomBar, createNativeWebRtcAdapter, defaultDarkTheme, defaultLightTheme, isNativeWebRtcAvailable, isStalePush, useAppStateLifecycle, useDisplayName, usePoolseTheme, useVoipCalls };
5385
5519
  //# sourceMappingURL=index.js.map
5386
5520
  //# sourceMappingURL=index.js.map