@adminide-stack/yantra-mobile 12.0.105-alpha.0 → 12.0.106-alpha.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.
Files changed (33) hide show
  1. package/lib/features/messaging/BlockedContactsScreen.js +127 -0
  2. package/lib/features/messaging/BlockedContactsScreen.js.map +1 -0
  3. package/lib/features/messaging/ChatAttachments.js +4 -2
  4. package/lib/features/messaging/ChatAttachments.js.map +1 -1
  5. package/lib/features/messaging/ChatComponents.js +194 -10
  6. package/lib/features/messaging/ChatComponents.js.map +1 -1
  7. package/lib/features/messaging/ChatInfoScreen.js +173 -17
  8. package/lib/features/messaging/ChatInfoScreen.js.map +1 -1
  9. package/lib/features/messaging/ConversationListScreen.js +17 -1
  10. package/lib/features/messaging/ConversationListScreen.js.map +1 -1
  11. package/lib/features/messaging/MediaGalleryScreen.js +264 -0
  12. package/lib/features/messaging/MediaGalleryScreen.js.map +1 -0
  13. package/lib/features/messaging/NativeChatExperience.js +137 -18
  14. package/lib/features/messaging/NativeChatExperience.js.map +1 -1
  15. package/lib/features/messaging/NewGroupScreen.js +191 -0
  16. package/lib/features/messaging/NewGroupScreen.js.map +1 -0
  17. package/lib/features/messaging/PollComposer.js +137 -0
  18. package/lib/features/messaging/PollComposer.js.map +1 -0
  19. package/lib/features/messaging/PollVotesScreen.js +122 -0
  20. package/lib/features/messaging/PollVotesScreen.js.map +1 -0
  21. package/lib/features/messaging/ThreadScreen.js +180 -13
  22. package/lib/features/messaging/ThreadScreen.js.map +1 -1
  23. package/lib/features/messaging/chatLinks.js +39 -2
  24. package/lib/features/messaging/chatLinks.js.map +1 -1
  25. package/lib/features/messaging/chatModel.js +186 -19
  26. package/lib/features/messaging/chatModel.js.map +1 -1
  27. package/lib/features/messaging/chatOperations.js +111 -2
  28. package/lib/features/messaging/chatOperations.js.map +1 -1
  29. package/lib/features/messaging/nativeChatChannelQuery.js +7 -2
  30. package/lib/features/messaging/nativeChatChannelQuery.js.map +1 -1
  31. package/lib/features/messaging/useChatData.js +248 -10
  32. package/lib/features/messaging/useChatData.js.map +1 -1
  33. package/package.json +3 -3
@@ -1,4 +1,4 @@
1
- import {jsx,jsxs}from'react/jsx-runtime';import*as React from'react';import {StyleSheet,AppState,Platform,BackHandler,View,ActivityIndicator}from'react-native';import {chatThemes,EmptyState}from'./ChatComponents.js';import {useAppTheme}from'../../theme/AppThemeProvider.js';import {ConversationListScreen}from'./ConversationListScreen.js';import {ContactsScreen}from'./ContactsScreen.js';import {ThreadScreen}from'./ThreadScreen.js';import {ChatInfoScreen}from'./ChatInfoScreen.js';import {NotificationSettingsScreen}from'./NotificationSettingsScreen.js';import {ForwardScreen}from'./ForwardScreen.js';import {StarredMessagesScreen}from'./StarredMessagesScreen.js';import {MessageInfoScreen}from'./MessageInfoScreen.js';import {useConversations,useThread,useTyping,useMarkRead,useReadWatermark,forwardMessage}from'./useChatData.js';import {SET_DRAFT_MUTATION,VIEW_CHANNEL_MUTATION,SEARCH_MESSAGES_QUERY,SET_CHANNEL_MUTE_MUTATION,YANTRA_CHAT_INVITER_QUERY}from'./chatOperations.js';import {messageStatus,toChatMessage,muteUntilFor,toEpoch,isMuted,muteLabel}from'./chatModel.js';import {buildChatInviteUrl,chatInviteMessage,whatsAppInviteUrl}from'./chatInviteLink.js';import {InviteSheet}from'./InviteSheet.js';import {createLinkPreviewLoader,openChatLink}from'./linkPreview.js';import {useContactMatches}from'./useContactMatches.js';const DEFAULT_INVITE_WEB_BASE = "https://yantra.app";
1
+ import {jsx,jsxs}from'react/jsx-runtime';import*as React from'react';import {StyleSheet,AppState,Platform,BackHandler,View,ActivityIndicator}from'react-native';import {chatThemes,EmptyState}from'./ChatComponents.js';import {useAppTheme}from'../../theme/AppThemeProvider.js';import {ConversationListScreen}from'./ConversationListScreen.js';import {ContactsScreen}from'./ContactsScreen.js';import {ThreadScreen}from'./ThreadScreen.js';import {ChatInfoScreen}from'./ChatInfoScreen.js';import {NotificationSettingsScreen}from'./NotificationSettingsScreen.js';import {ForwardScreen}from'./ForwardScreen.js';import {NewGroupScreen}from'./NewGroupScreen.js';import {ActionSheet}from'./ActionSheet.js';import {StarredMessagesScreen}from'./StarredMessagesScreen.js';import {MessageInfoScreen}from'./MessageInfoScreen.js';import {MediaGalleryScreen}from'./MediaGalleryScreen.js';import {BlockedContactsScreen}from'./BlockedContactsScreen.js';import {PollVotesScreen}from'./PollVotesScreen.js';import {useConversations,useThread,useTyping,useMarkRead,useReadWatermark,forwardMessage}from'./useChatData.js';import {SET_DRAFT_MUTATION,VIEW_CHANNEL_MUTATION,SEARCH_MESSAGES_QUERY,SET_CHANNEL_MUTE_MUTATION,YANTRA_CHAT_INVITER_QUERY}from'./chatOperations.js';import {messageStatus,toChatMessage,muteUntilFor,toEpoch,isMuted,muteLabel,displayNameOf}from'./chatModel.js';import {ImageViewer}from'./ChatAttachments.js';import {buildChatInviteUrl,chatInviteMessage,whatsAppInviteUrl}from'./chatInviteLink.js';import {InviteSheet}from'./InviteSheet.js';import {createLinkPreviewLoader,openChatLink}from'./linkPreview.js';import {useContactMatches}from'./useContactMatches.js';const DEFAULT_INVITE_WEB_BASE = "https://yantra.app";
2
2
  const DRAFT_SAVE_DELAY_MS = 800;
3
3
  const LIVE_READ_THROTTLE_MS = 2e3;
4
4
  function Shell({
@@ -21,7 +21,7 @@ function NativeChatExperience({
21
21
  onInternalRouteChange,
22
22
  testID
23
23
  }) {
24
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
24
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
25
25
  const {
26
26
  isDark
27
27
  } = useAppTheme();
@@ -35,6 +35,9 @@ function NativeChatExperience({
35
35
  const [infoError, setInfoError] = React.useState(null);
36
36
  const [forwarding, setForwarding] = React.useState(null);
37
37
  const [infoMessage, setInfoMessage] = React.useState(null);
38
+ const [pollVotesMessage, setPollVotesMessage] = React.useState(null);
39
+ const [galleryBack, setGalleryBack] = React.useState("info");
40
+ const [galleryImageUrl, setGalleryImageUrl] = React.useState(null);
38
41
  const [jumpTo, setJumpTo] = React.useState(null);
39
42
  const [listRoute, setListRoute] = React.useState("list");
40
43
  const threadChannelId = route === "thread" || route === "info" || route === "forward" || route === "messageInfo" ? activeChannelId : null;
@@ -144,7 +147,7 @@ function NativeChatExperience({
144
147
  refreshContactsRef.current = contactMatches.refresh;
145
148
  const contactsGranted = contactMatches.permission === "granted";
146
149
  React.useEffect(() => {
147
- if (route !== "contacts" || !contactsGranted) return void 0;
150
+ if (route !== "contacts" && route !== "newGroup" || !contactsGranted) return void 0;
148
151
  void refreshContactsRef.current();
149
152
  const sub = AppState.addEventListener("change", (state) => {
150
153
  if (state === "active") void refreshContactsRef.current();
@@ -232,18 +235,44 @@ function NativeChatExperience({
232
235
  setInfoError(option ? "Couldn\u2019t mute this chat. Please try again." : "Couldn\u2019t unmute this chat. Please try again.");
233
236
  }
234
237
  }, [activeChannelId, muteBusy, conversations, services.gql]);
238
+ const runGroupAction = React.useCallback(async (fn) => {
239
+ if (muteBusy) return;
240
+ setMuteBusy(true);
241
+ setInfoError(null);
242
+ try {
243
+ const ok = await fn();
244
+ if (!ok) setInfoError("Something went wrong. Please try again.");
245
+ } finally {
246
+ setMuteBusy(false);
247
+ }
248
+ }, [muteBusy]);
249
+ const [exitConfirmId, setExitConfirmId] = React.useState(null);
250
+ const confirmExitGroup = React.useCallback((channelId) => setExitConfirmId(channelId), []);
251
+ const doExitGroup = React.useCallback(async (channelId) => {
252
+ setExitConfirmId(null);
253
+ const ok = await conversations.leaveGroup(channelId);
254
+ if (ok) {
255
+ setListRoute("list");
256
+ setRoute("list");
257
+ } else {
258
+ setInfoError("Couldn\u2019t leave this group. Please try again.");
259
+ }
260
+ }, [conversations]);
235
261
  React.useEffect(() => {
236
262
  if (Platform.OS !== "android") return void 0;
237
263
  const sub = BackHandler.addEventListener("hardwareBackPress", () => {
238
264
  if (route === "list") return false;
239
265
  if (route === "info" || route === "forward" || route === "messageInfo") setRoute("thread");
266
+ else if (route === "addParticipants") setRoute("info");
240
267
  else if (route === "notifications") setRoute(notificationsBack === "info" ? "info" : "list");
268
+ else if (route === "media" || route === "blocked") setRoute(galleryBack);
269
+ else if (route === "pollVotes") setRoute("thread");
241
270
  else if (route === "thread") setRoute(listRoute);
242
271
  else setRoute("list");
243
272
  return true;
244
273
  });
245
274
  return () => sub.remove();
246
- }, [route, notificationsBack, listRoute]);
275
+ }, [route, notificationsBack, listRoute, galleryBack]);
247
276
  const conversationsRef = React.useRef(conversations.conversations);
248
277
  conversationsRef.current = conversations.conversations;
249
278
  const openThread = React.useCallback((id, messageId) => {
@@ -349,6 +378,29 @@ function NativeChatExperience({
349
378
  openThread(channelId, messageId);
350
379
  } }) });
351
380
  }
381
+ if (route === "media") {
382
+ return /* @__PURE__ */ jsxs(Shell, { theme, testID, children: [
383
+ /* @__PURE__ */ jsx(MediaGalleryScreen, { gql: services.gql, channelId: activeChannelId, viewerId: viewer.userId, theme, fileBaseUrl: (_f = services.media) == null ? void 0 : _f.fileBaseUrl, linkPreviews, onOpenLink, onOpenImage: setGalleryImageUrl, onBack: () => setRoute(galleryBack) }),
384
+ /* @__PURE__ */ jsx(ImageViewer, { url: galleryImageUrl, onClose: () => setGalleryImageUrl(null) })
385
+ ] });
386
+ }
387
+ if (route === "blocked") {
388
+ return /* @__PURE__ */ jsx(Shell, { theme, testID, children: /* @__PURE__ */ jsx(BlockedContactsScreen, { gql: services.gql, theme, onBack: () => setRoute(galleryBack), onUnblock: conversations.unblockContact }) });
389
+ }
390
+ if (route === "pollVotes" && pollVotesMessage) {
391
+ const members = (_g = activeConversation == null ? void 0 : activeConversation.members) != null ? _g : [];
392
+ const peer = (_h = activeConversation == null ? void 0 : activeConversation.peer) != null ? _h : null;
393
+ const nameOf = (id) => {
394
+ const m = members.find((mm) => mm.id === id);
395
+ if (m) return m.name;
396
+ if (peer && String(peer.id) === id) return displayNameOf(peer);
397
+ return "Someone";
398
+ };
399
+ return /* @__PURE__ */ jsx(Shell, { theme, testID, children: /* @__PURE__ */ jsx(PollVotesScreen, { poll: (_i = pollVotesMessage.poll) != null ? _i : null, theme, viewerId: viewer.userId, nameOf, onBack: () => {
400
+ setPollVotesMessage(null);
401
+ setRoute("thread");
402
+ } }) });
403
+ }
352
404
  if (route === "messageInfo" && infoMessage && activeChannelId) {
353
405
  return /* @__PURE__ */ jsx(Shell, { theme, testID, children: /* @__PURE__ */ jsx(MessageInfoScreen, { gql: services.gql, channelId: activeChannelId, viewerId: viewer.userId, message: infoMessage, isGroup: activeConversation ? !activeConversation.isDirect : false, theme, onBack: () => {
354
406
  setInfoMessage(null);
@@ -365,10 +417,30 @@ function NativeChatExperience({
365
417
  return /* @__PURE__ */ jsx(Shell, { theme, testID, children: /* @__PURE__ */ jsx(NotificationSettingsScreen, { theme, settings: services.notificationSettings, push: services.push, onBack: () => setRoute(notificationsBack === "info" && activeChannelId ? "info" : "list") }) });
366
418
  }
367
419
  if (route === "info" && activeChannelId) {
368
- return /* @__PURE__ */ jsx(Shell, { theme, testID, children: /* @__PURE__ */ jsx(ChatInfoScreen, { title: activeTitle, avatarUrl: activeConversation == null ? void 0 : activeConversation.avatarUrl, isGroup: activeConversation ? !activeConversation.isDirect : false, memberNames: (_f = activeConversation == null ? void 0 : activeConversation.memberNames) != null ? _f : [], mutedUntil: (_g = activeConversation == null ? void 0 : activeConversation.mutedUntil) != null ? _g : 0, theme, busy: muteBusy, error: infoError, onBack: () => setRoute("thread"), onMute: setMute, onUnmute: () => setMute(null), onOpenNotifications: () => {
369
- setNotificationsBack("info");
370
- setRoute("notifications");
371
- }, onDismissError: () => setInfoError(null) }) });
420
+ const infoIsGroup = activeConversation ? !activeConversation.isDirect : false;
421
+ const infoPeerId = !infoIsGroup && ((_j = activeConversation == null ? void 0 : activeConversation.peer) == null ? void 0 : _j.id) ? String(activeConversation.peer.id) : null;
422
+ const infoPeerBlocked = Boolean(infoPeerId && conversations.isPeerBlocked(infoPeerId));
423
+ const canSetDisappearing = activeConversation ? activeConversation.isDirect || activeConversation.viewerIsAdmin : false;
424
+ return /* @__PURE__ */ jsxs(Shell, { theme, testID, children: [
425
+ /* @__PURE__ */ jsx(ChatInfoScreen, { title: activeTitle, avatarUrl: activeConversation == null ? void 0 : activeConversation.avatarUrl, isGroup: infoIsGroup, members: (_k = activeConversation == null ? void 0 : activeConversation.members) != null ? _k : [], description: activeConversation == null ? void 0 : activeConversation.description, viewerIsAdmin: Boolean(activeConversation == null ? void 0 : activeConversation.viewerIsAdmin), onlyAdminsSend: Boolean(activeConversation == null ? void 0 : activeConversation.onlyAdminsSend), onAddMembers: activeChannelId ? () => setRoute("addParticipants") : void 0, onRemoveMember: activeChannelId ? (memberId) => void runGroupAction(() => conversations.removeGroupMember(activeChannelId, memberId)) : void 0, onSetAdmin: activeChannelId ? (memberId, admin) => void runGroupAction(() => conversations.setGroupAdmin(activeChannelId, memberId, admin)) : void 0, onSetSendPolicy: activeChannelId ? (onlyAdmins) => void runGroupAction(() => conversations.setGroupSendPolicy(activeChannelId, onlyAdmins)) : void 0, onExitGroup: activeChannelId ? () => confirmExitGroup(activeChannelId) : void 0, mutedUntil: (_l = activeConversation == null ? void 0 : activeConversation.mutedUntil) != null ? _l : 0, theme, busy: muteBusy, error: infoError, onBack: () => setRoute("thread"), onMute: setMute, onUnmute: () => setMute(null), onOpenNotifications: () => {
426
+ setNotificationsBack("info");
427
+ setRoute("notifications");
428
+ }, onDismissError: () => setInfoError(null), disappearingSeconds: (_m = activeConversation == null ? void 0 : activeConversation.disappearingSeconds) != null ? _m : 0, onSetDisappearing: canSetDisappearing ? (seconds) => void runGroupAction(() => conversations.setDisappearing(activeChannelId, seconds)) : void 0, onOpenMedia: () => {
429
+ setGalleryBack("info");
430
+ setRoute("media");
431
+ }, isBlocked: infoPeerBlocked, peerName: activeConversation == null ? void 0 : activeConversation.title, onBlock: infoPeerId ? () => void conversations.blockContact(infoPeerId) : void 0, onUnblock: infoPeerId ? () => void conversations.unblockContact(infoPeerId) : void 0, onReport: infoPeerId ? (alsoBlock) => void conversations.reportTarget("CONTACT", infoPeerId, {
432
+ alsoBlock
433
+ }) : void 0 }),
434
+ /* @__PURE__ */ jsx(ActionSheet, { visible: Boolean(exitConfirmId), title: "Exit group?", detail: "You will no longer receive messages from this group. Admins will be notified.", actions: [{
435
+ key: "exit",
436
+ label: "Exit group",
437
+ icon: "exit-to-app",
438
+ destructive: true,
439
+ onPress: () => {
440
+ if (exitConfirmId) void doExitGroup(exitConfirmId);
441
+ }
442
+ }], theme, onClose: () => setExitConfirmId(null), testID: "chat-exit-group-sheet" })
443
+ ] });
372
444
  }
373
445
  if (route === "thread" && activeChannelId) {
374
446
  const threadError = thread.error === dismissedError ? null : thread.error;
@@ -376,8 +448,20 @@ function NativeChatExperience({
376
448
  const now = Date.now();
377
449
  const muted = activeConversation ? isMuted(activeConversation, now) : false;
378
450
  let subtitle = "tap here for contact info";
379
- if (isGroup) subtitle = [...(_h = activeConversation == null ? void 0 : activeConversation.memberNames) != null ? _h : [], "You"].join(", ");
380
- else if (muted) subtitle = muteLabel((_i = activeConversation == null ? void 0 : activeConversation.mutedUntil) != null ? _i : 0, now);
451
+ if (isGroup) subtitle = [...(_n = activeConversation == null ? void 0 : activeConversation.memberNames) != null ? _n : [], "You"].join(", ");
452
+ else if (muted) subtitle = muteLabel((_o = activeConversation == null ? void 0 : activeConversation.mutedUntil) != null ? _o : 0, now);
453
+ const groupMembers = isGroup ? (_p = activeConversation == null ? void 0 : activeConversation.members) != null ? _p : [] : [];
454
+ const viewerInGroup = !isGroup || groupMembers.length === 0 || groupMembers.some((m) => m.isYou);
455
+ const composerLock = !isGroup ? null : !viewerInGroup ? "notParticipant" : (activeConversation == null ? void 0 : activeConversation.onlyAdminsSend) && !(activeConversation == null ? void 0 : activeConversation.viewerIsAdmin) ? "adminsOnly" : null;
456
+ const memberNameOf = (id) => {
457
+ var _a2, _b2;
458
+ if (!id) return "Someone";
459
+ if (String(id) === viewer.userId) return (_a2 = viewer.displayName) != null ? _a2 : "You";
460
+ return ((_b2 = groupMembers.find((m) => m.id === String(id))) == null ? void 0 : _b2.name) || "Someone";
461
+ };
462
+ const peerId = !isGroup ? ((_q = activeConversation == null ? void 0 : activeConversation.peer) == null ? void 0 : _q.id) ? String(activeConversation.peer.id) : null : null;
463
+ const peerBlocked = Boolean(peerId && conversations.isPeerBlocked(peerId));
464
+ const disappearingOn = ((_r = activeConversation == null ? void 0 : activeConversation.disappearingSeconds) != null ? _r : 0) > 0;
381
465
  return /* @__PURE__ */ jsx(Shell, { theme, testID, children: /* @__PURE__ */ jsx(ThreadScreen, { title: activeTitle, subtitle, avatarUrl: activeConversation == null ? void 0 : activeConversation.avatarUrl, isGroup, muted, viewerId: viewer.userId, readWatermark, deliveredWatermark, initialUnreadCount: openedUnread, initialJumpTo: jumpTo, typingText, infoLabel: isGroup ? "Group info" : "Contact info", onDraftChange: (text) => {
382
466
  typing.onDraftChange(text);
383
467
  saveDraft(activeChannelId, text);
@@ -390,10 +474,10 @@ function NativeChatExperience({
390
474
  }, onSearch: searchChat, onLoadUntil: thread.loadUntil, onOpenInfo: () => {
391
475
  setInfoError(null);
392
476
  setRoute("info");
393
- }, messages: thread.messages, loading: thread.loading, loadingMore: thread.loadingMore, error: threadError, theme, connectionState: services.gql.connectionState, haptics: services.haptics, onBack: () => setRoute(listRoute), onSend: (body, replyTo) => {
477
+ }, messages: thread.messages, loading: thread.loading, loadingMore: thread.loadingMore, error: threadError, theme, connectionState: services.gql.connectionState, haptics: services.haptics, onBack: () => setRoute(listRoute), onSend: (body, replyTo, mentions) => {
394
478
  typing.onSent();
395
- return thread.send(body, replyTo);
396
- }, onLoadMore: thread.loadMore, onRetry: thread.retry, onReact: (messageId, emoji) => {
479
+ return thread.send(body, replyTo, mentions);
480
+ }, memberNameOf, mentionCandidates: isGroup ? groupMembers : [], composerLock, onLoadMore: thread.loadMore, onRetry: thread.retry, onReact: (messageId, emoji) => {
397
481
  var _a2, _b2;
398
482
  const current = (_b2 = (_a2 = thread.messages.find((m) => m.id === messageId)) == null ? void 0 : _a2.reactions.find((r) => r.mine)) == null ? void 0 : _b2.reaction;
399
483
  thread.react(messageId, current === emoji ? null : emoji);
@@ -403,7 +487,10 @@ function NativeChatExperience({
403
487
  } : void 0, onShareText: services.link ? (text) => {
404
488
  var _a2;
405
489
  return void ((_a2 = services.link) == null ? void 0 : _a2.share(text));
406
- } : void 0, media: services.media, audio: services.audio, linkPreviews, onOpenLink, onSendAttachments: thread.sendAttachments ? (files, caption, kind, replyTo) => {
490
+ } : void 0, onVote: thread.vote, onViewVotes: (message) => {
491
+ setPollVotesMessage(message);
492
+ setRoute("pollVotes");
493
+ }, onCreatePoll: thread.createPoll, onReportMessage: (message) => void conversations.reportTarget("MESSAGE", message.id), onKeep: disappearingOn ? thread.keep : void 0, peerBlocked, onUnblockPeer: peerId ? () => void conversations.unblockContact(peerId) : void 0, media: services.media, audio: services.audio, linkPreviews, onOpenLink, onSendAttachments: thread.sendAttachments ? (files, caption, kind, replyTo) => {
407
494
  var _a2;
408
495
  return (_a2 = thread.sendAttachments) == null ? void 0 : _a2.call(thread, files, caption, kind, replyTo);
409
496
  } : void 0, onDismissError: () => setDismissedError(thread.error) }) });
@@ -417,26 +504,58 @@ function NativeChatExperience({
417
504
  if (startChatError) setStartChatError(null);
418
505
  else void contactMatches.refresh();
419
506
  } }),
420
- /* @__PURE__ */ jsx(InviteSheet, { visible: inviteSheetOpen, name: inviteTarget ? ((_j = inviteTarget.match) == null ? void 0 : _j.displayName) || inviteTarget.displayName : "", number: (_m = (_l = (_k = inviteTarget == null ? void 0 : inviteTarget.rawNumbers) == null ? void 0 : _k[0]) != null ? _l : inviteTarget == null ? void 0 : inviteTarget.e164[0]) != null ? _m : null, imageUri: (_n = inviteTarget == null ? void 0 : inviteTarget.imageUri) != null ? _n : null, canWhatsApp: Boolean(inviteTarget && whatsAppInviteUrl(inviteTarget.e164[0], "x")), theme, onClose: () => setInviteSheetOpen(false), onChoose: (channel) => void sendInvite(channel), onCopy: () => {
507
+ /* @__PURE__ */ jsx(InviteSheet, { visible: inviteSheetOpen, name: inviteTarget ? ((_s = inviteTarget.match) == null ? void 0 : _s.displayName) || inviteTarget.displayName : "", number: (_v = (_u = (_t = inviteTarget == null ? void 0 : inviteTarget.rawNumbers) == null ? void 0 : _t[0]) != null ? _u : inviteTarget == null ? void 0 : inviteTarget.e164[0]) != null ? _v : null, imageUri: (_w = inviteTarget == null ? void 0 : inviteTarget.imageUri) != null ? _w : null, canWhatsApp: Boolean(inviteTarget && whatsAppInviteUrl(inviteTarget.e164[0], "x")), theme, onClose: () => setInviteSheetOpen(false), onChoose: (channel) => void sendInvite(channel), onCopy: () => {
421
508
  var _a2;
422
509
  if (inviteMessage) void ((_a2 = services.link) == null ? void 0 : _a2.copy(inviteMessage));
423
510
  } })
424
511
  ] });
425
512
  }
513
+ if (route === "newGroup" || route === "addParticipants") {
514
+ const adding = route === "addParticipants";
515
+ const existing = new Set((adding ? (_x = activeConversation == null ? void 0 : activeConversation.members) != null ? _x : [] : []).map((m) => m.id));
516
+ const candidates = contactMatches.onYantra.filter((c) => {
517
+ var _a2;
518
+ return ((_a2 = c.match) == null ? void 0 : _a2.userId) && !existing.has(String(c.match.userId));
519
+ }).map((c) => {
520
+ var _a2, _b2, _c2;
521
+ return {
522
+ userId: String(c.match.userId),
523
+ displayName: c.match.displayName || c.displayName,
524
+ imageUri: (_c2 = (_b2 = c.imageUri) != null ? _b2 : (_a2 = c.match) == null ? void 0 : _a2.picture) != null ? _c2 : null
525
+ };
526
+ });
527
+ return /* @__PURE__ */ jsx(Shell, { theme, testID, children: /* @__PURE__ */ jsx(NewGroupScreen, { candidates, theme, mode: adding ? "add" : "create", onCancel: () => setRoute(adding ? "info" : "list"), onCreate: async (name, memberIds) => {
528
+ if (adding) {
529
+ if (!activeChannelId) return null;
530
+ const id2 = await conversations.addGroupMembers(activeChannelId, memberIds);
531
+ if (id2) setRoute("info");
532
+ return id2;
533
+ }
534
+ const id = await conversations.createGroup(name, memberIds);
535
+ if (id) openThread(id);
536
+ return id;
537
+ } }) });
538
+ }
426
539
  const listError = conversations.error === dismissedError ? null : conversations.error;
427
540
  return /* @__PURE__ */ jsx(Shell, { theme, testID, children: /* @__PURE__ */ jsx(ConversationListScreen, { conversations: conversations.conversations, loading: conversations.loading, refreshing: conversations.refreshing, error: listError, theme, connectionState: services.gql.connectionState, canInvite: true, onRefresh: () => {
428
541
  conversations.refresh();
429
542
  void contactMatches.refresh();
430
- }, onRetry: conversations.refresh, loadingMore: conversations.loadingMore, onLoadMore: conversations.loadMore, onOpen: openThread, onNewChat: () => setRoute("contacts"), onOpenNotifications: () => {
543
+ }, onRetry: conversations.refresh, loadingMore: conversations.loadingMore, onLoadMore: conversations.loadMore, onOpen: openThread, onNewChat: () => setRoute("contacts"), onNewGroup: () => {
544
+ void contactMatches.refresh();
545
+ setRoute("newGroup");
546
+ }, onOpenNotifications: () => {
431
547
  setNotificationsBack("list");
432
548
  setRoute("notifications");
433
- }, pushStatus: (_o = services.push) == null ? void 0 : _o.status, onEnablePush: services.push ? () => {
549
+ }, pushStatus: (_y = services.push) == null ? void 0 : _y.status, onEnablePush: services.push ? () => {
434
550
  var _a2;
435
551
  return (_a2 = services.push) == null ? void 0 : _a2.enable();
436
552
  } : void 0, onDismissError: () => setDismissedError(conversations.error), notice: inviteNotice, onDismissNotice: () => setInviteNotice(null), mode: route === "archived" ? "archived" : "chats", archivedCount: conversations.conversations.filter((c) => c.archivedAt > 0).length, onOpenArchived: () => {
437
553
  setListRoute("archived");
438
554
  setRoute("archived");
439
- }, onOpenStarred: () => setRoute("starred"), onBack: () => {
555
+ }, onOpenStarred: () => setRoute("starred"), onOpenBlocked: () => {
556
+ setGalleryBack("list");
557
+ setRoute("blocked");
558
+ }, onBack: () => {
440
559
  setListRoute("list");
441
560
  setRoute("list");
442
561
  }, onSetListState: conversations.setListState }) });