@poolse/react-native 2.8.4 → 2.10.0

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