@planningcenter/chat-react-native 3.18.0-rc.9 → 3.19.0-rc.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 (31) hide show
  1. package/build/components/conversation/message.d.ts.map +1 -1
  2. package/build/components/conversation/message.js +28 -12
  3. package/build/components/conversation/message.js.map +1 -1
  4. package/build/components/conversation/message_form.js +1 -1
  5. package/build/components/conversation/message_form.js.map +1 -1
  6. package/build/components/conversation/reply_shadow_message.d.ts.map +1 -1
  7. package/build/components/conversation/reply_shadow_message.js +8 -3
  8. package/build/components/conversation/reply_shadow_message.js.map +1 -1
  9. package/build/hooks/use_conversation_messages.d.ts.map +1 -1
  10. package/build/hooks/use_conversation_messages.js +2 -1
  11. package/build/hooks/use_conversation_messages.js.map +1 -1
  12. package/build/hooks/use_message_draft.d.ts +1 -1
  13. package/build/hooks/use_message_draft.d.ts.map +1 -1
  14. package/build/hooks/use_message_draft.js +6 -2
  15. package/build/hooks/use_message_draft.js.map +1 -1
  16. package/build/screens/age_check/age_check_required_screen.js +1 -1
  17. package/build/screens/age_check/age_check_required_screen.js.map +1 -1
  18. package/build/screens/age_check/components/age_check_select_birthdate_modal.js +2 -2
  19. package/build/screens/age_check/components/age_check_select_birthdate_modal.js.map +1 -1
  20. package/build/screens/conversation_screen.d.ts.map +1 -1
  21. package/build/screens/conversation_screen.js +18 -8
  22. package/build/screens/conversation_screen.js.map +1 -1
  23. package/package.json +2 -2
  24. package/src/components/conversation/message.tsx +40 -11
  25. package/src/components/conversation/message_form.tsx +1 -1
  26. package/src/components/conversation/reply_shadow_message.tsx +9 -2
  27. package/src/hooks/use_conversation_messages.ts +3 -1
  28. package/src/hooks/use_message_draft.ts +6 -2
  29. package/src/screens/age_check/age_check_required_screen.tsx +1 -1
  30. package/src/screens/age_check/components/age_check_select_birthdate_modal.tsx +2 -0
  31. package/src/screens/conversation_screen.tsx +21 -8
@@ -1 +1 @@
1
- {"version":3,"file":"use_conversation_messages.d.ts","sourceRoot":"","sources":["../../src/hooks/use_conversation_messages.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,wBAAwB,EAAwB,MAAM,oBAAoB,CAAA;AAGnF,eAAO,MAAM,uBAAuB,uCACE;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,SACvF,wBAAwB;;;;;;CAkBhC,CAAA"}
1
+ {"version":3,"file":"use_conversation_messages.d.ts","sourceRoot":"","sources":["../../src/hooks/use_conversation_messages.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,wBAAwB,EAAwB,MAAM,oBAAoB,CAAA;AAGnF,eAAO,MAAM,uBAAuB,uCACE;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,SACvF,wBAAwB;;;;;;CAoBhC,CAAA"}
@@ -5,7 +5,8 @@ export const useConversationMessages = ({ conversation_id, reply_root_id }, opts
5
5
  const { data, refetch, isRefetching, fetchNextPage } = useSuspensePaginator(getMessagesRequestArgs({ conversation_id, reply_root_id }), opts);
6
6
  const queryKey = getMessagesQueryKey({ conversation_id, reply_root_id });
7
7
  const messages = useMemo(() => data
8
- .filter(message => !message.deletedAt && (message.attachments?.length || message.text?.length))
8
+ .filter(message => (!message.deletedAt || message.replyRootId) &&
9
+ (message.attachments?.length || message.text?.length))
9
10
  .sort((a, b) => -a.id.localeCompare(b.id)), [data]);
10
11
  return { messages, refetch, isRefetching, fetchNextPage, queryKey };
11
12
  };
@@ -1 +1 @@
1
- {"version":3,"file":"use_conversation_messages.js","sourceRoot":"","sources":["../../src/hooks/use_conversation_messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAE/B,OAAO,EAA4B,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AACnF,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AAE3F,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,EAAE,eAAe,EAAE,aAAa,EAA8D,EAC9F,IAA+B,EAC/B,EAAE;IACF,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,oBAAoB,CACzE,sBAAsB,CAAC,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC,EAC1D,IAAI,CACL,CAAA;IACD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC,CAAA;IACxE,MAAM,QAAQ,GAAG,OAAO,CACtB,GAAG,EAAE,CACH,IAAI;SACD,MAAM,CACL,OAAO,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,IAAI,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CACvF;SACA,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAC9C,CAAC,IAAI,CAAC,CACP,CAAA;IAED,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAA;AACrE,CAAC,CAAA","sourcesContent":["import { useMemo } from 'react'\nimport { MessageResource } from '../types'\nimport { SuspensePaginatorOptions, useSuspensePaginator } from './use_suspense_api'\nimport { getMessagesQueryKey, getMessagesRequestArgs } from '../utils/request/get_messages'\n\nexport const useConversationMessages = (\n { conversation_id, reply_root_id }: { conversation_id: number; reply_root_id?: string | null },\n opts?: SuspensePaginatorOptions\n) => {\n const { data, refetch, isRefetching, fetchNextPage } = useSuspensePaginator<MessageResource>(\n getMessagesRequestArgs({ conversation_id, reply_root_id }),\n opts\n )\n const queryKey = getMessagesQueryKey({ conversation_id, reply_root_id })\n const messages = useMemo(\n () =>\n data\n .filter(\n message => !message.deletedAt && (message.attachments?.length || message.text?.length)\n )\n .sort((a, b) => -a.id.localeCompare(b.id)),\n [data]\n )\n\n return { messages, refetch, isRefetching, fetchNextPage, queryKey }\n}\n"]}
1
+ {"version":3,"file":"use_conversation_messages.js","sourceRoot":"","sources":["../../src/hooks/use_conversation_messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAE/B,OAAO,EAA4B,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AACnF,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AAE3F,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,EAAE,eAAe,EAAE,aAAa,EAA8D,EAC9F,IAA+B,EAC/B,EAAE;IACF,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,oBAAoB,CACzE,sBAAsB,CAAC,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC,EAC1D,IAAI,CACL,CAAA;IACD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC,CAAA;IACxE,MAAM,QAAQ,GAAG,OAAO,CACtB,GAAG,EAAE,CACH,IAAI;SACD,MAAM,CACL,OAAO,CAAC,EAAE,CACR,CAAC,CAAC,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,WAAW,CAAC;QAC3C,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,IAAI,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CACxD;SACA,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAC9C,CAAC,IAAI,CAAC,CACP,CAAA;IAED,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAA;AACrE,CAAC,CAAA","sourcesContent":["import { useMemo } from 'react'\nimport { MessageResource } from '../types'\nimport { SuspensePaginatorOptions, useSuspensePaginator } from './use_suspense_api'\nimport { getMessagesQueryKey, getMessagesRequestArgs } from '../utils/request/get_messages'\n\nexport const useConversationMessages = (\n { conversation_id, reply_root_id }: { conversation_id: number; reply_root_id?: string | null },\n opts?: SuspensePaginatorOptions\n) => {\n const { data, refetch, isRefetching, fetchNextPage } = useSuspensePaginator<MessageResource>(\n getMessagesRequestArgs({ conversation_id, reply_root_id }),\n opts\n )\n const queryKey = getMessagesQueryKey({ conversation_id, reply_root_id })\n const messages = useMemo(\n () =>\n data\n .filter(\n message =>\n (!message.deletedAt || message.replyRootId) &&\n (message.attachments?.length || message.text?.length)\n )\n .sort((a, b) => -a.id.localeCompare(b.id)),\n [data]\n )\n\n return { messages, refetch, isRefetching, fetchNextPage, queryKey }\n}\n"]}
@@ -4,7 +4,7 @@ interface MessageDraft {
4
4
  attachments: FileAttachment[];
5
5
  lastUpdated: number;
6
6
  }
7
- export declare function useMessageDraft(conversationId: number): {
7
+ export declare function useMessageDraft(): {
8
8
  draft: MessageDraft | null;
9
9
  saveDraft: (text: string, attachments: FileAttachment[]) => void;
10
10
  clearDraft: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"use_message_draft.d.ts","sourceRoot":"","sources":["../../src/hooks/use_message_draft.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gEAAgE,CAAA;AAEpG,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,cAAc,EAAE,CAAA;IAC7B,WAAW,EAAE,MAAM,CAAA;CACpB;AAQD,wBAAgB,eAAe,CAAC,cAAc,EAAE,MAAM;;sBAmD3C,MAAM,eAAe,cAAc,EAAE;;EAkD/C"}
1
+ {"version":3,"file":"use_message_draft.d.ts","sourceRoot":"","sources":["../../src/hooks/use_message_draft.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gEAAgE,CAAA;AAGpG,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,cAAc,EAAE,CAAA;IAC7B,WAAW,EAAE,MAAM,CAAA;CACpB;AAQD,wBAAgB,eAAe;;sBAsDpB,MAAM,eAAe,cAAc,EAAE;;EAkD/C"}
@@ -1,12 +1,16 @@
1
1
  import { useCallback, useEffect, useRef, useState } from 'react';
2
2
  import { useAsyncStorage } from './use_async_storage';
3
+ import { useConversationContext } from '../contexts/conversation_context';
3
4
  const DRAFT_STORAGE_KEY = 'chat_message_drafts';
4
5
  const DRAFT_EXPIRY_HOURS = 720; // 30 days
5
6
  const DRAFT_EXPIRY_MS = DRAFT_EXPIRY_HOURS * 60 * 60 * 1000;
6
7
  const ATTACHMENT_EXPIRY_HOURS = 48; // 2 days
7
8
  const ATTACHMENT_EXPIRY_MS = ATTACHMENT_EXPIRY_HOURS * 60 * 60 * 1000;
8
- export function useMessageDraft(conversationId) {
9
- const conversationKey = conversationId.toString();
9
+ export function useMessageDraft() {
10
+ const { conversationId, currentPageReplyRootId } = useConversationContext();
11
+ const conversationKey = currentPageReplyRootId
12
+ ? `${conversationId}/threads/${currentPageReplyRootId}`
13
+ : String(conversationId);
10
14
  const [allDrafts, setAllDrafts] = useAsyncStorage(DRAFT_STORAGE_KEY, {});
11
15
  const [draft, setDraft] = useState(() => {
12
16
  const storedDraft = allDrafts[conversationKey] || null;
@@ -1 +1 @@
1
- {"version":3,"file":"use_message_draft.js","sourceRoot":"","sources":["../../src/hooks/use_message_draft.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AASrD,MAAM,iBAAiB,GAAG,qBAAqB,CAAA;AAC/C,MAAM,kBAAkB,GAAG,GAAG,CAAA,CAAC,UAAU;AACzC,MAAM,eAAe,GAAG,kBAAkB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AAC3D,MAAM,uBAAuB,GAAG,EAAE,CAAA,CAAC,SAAS;AAC5C,MAAM,oBAAoB,GAAG,uBAAuB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AAErE,MAAM,UAAU,eAAe,CAAC,cAAsB;IACpD,MAAM,eAAe,GAAG,cAAc,CAAC,QAAQ,EAAE,CAAA;IACjD,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,eAAe,CAC/C,iBAAiB,EACjB,EAAE,CACH,CAAA;IAED,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAsB,GAAG,EAAE;QAC3D,MAAM,WAAW,GAAG,SAAS,CAAC,eAAe,CAAC,IAAI,IAAI,CAAA;QAEtD,6BAA6B;QAC7B,IAAI,WAAW,EAAE,WAAW,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;YACtB,MAAM,gBAAgB,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE;gBACnE,IAAI,CAAC,UAAU,CAAC,UAAU;oBAAE,OAAO,KAAK,CAAA;gBACxC,OAAO,GAAG,GAAG,UAAU,CAAC,UAAU,GAAG,oBAAoB,CAAA;YAC3D,CAAC,CAAC,CAAA;YAEF,OAAO;gBACL,GAAG,WAAW;gBACd,WAAW,EAAE,gBAAgB;aAC9B,CAAA;QACH,CAAC;QAED,OAAO,WAAW,CAAA;IACpB,CAAC,CAAC,CAAA;IAEF,4EAA4E;IAC5E,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAElC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,YAAY,CAAC,OAAO;YAAE,OAAM;QAEhC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACtB,MAAM,WAAW,GAAiC,EAAE,CAAA;QAEpD,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,CAAC,EAAE,EAAE;YACpD,IAAI,SAAS,EAAE,WAAW,IAAI,GAAG,GAAG,SAAS,CAAC,WAAW,GAAG,eAAe,EAAE,CAAC;gBAC5E,WAAW,CAAC,EAAE,CAAC,GAAG,SAAS,CAAA;YAC7B,CAAC;QACH,CAAC,CAAC,CAAA;QAEF,gDAAgD;QAChD,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,CAAC;YACtE,YAAY,CAAC,WAAW,CAAC,CAAA;QAC3B,CAAC;QAED,YAAY,CAAC,OAAO,GAAG,IAAI,CAAA;IAC7B,CAAC,EAAE,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAA;IAE7B,MAAM,SAAS,GAAG,WAAW,CAC3B,CAAC,IAAY,EAAE,WAA6B,EAAE,EAAE;QAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,CAAA;QACnE,MAAM,aAAa,GAAG,EAAE,GAAG,SAAS,EAAE,CAAA;QAEtC,IAAI,UAAU,EAAE,CAAC;YACf,6EAA6E;YAC7E,MAAM,qBAAqB,GAAG,WAAW;iBACtC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC;iBACjD,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACX,GAAG,GAAG;gBACN,IAAI,EAAE;oBACJ,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG;oBACjB,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI;oBACnB,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI;oBACnB,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI;oBACnB,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK;oBACrB,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM;iBACxB;aACF,CAAC,CAAC,CAAA;YAEL,MAAM,QAAQ,GAAiB;gBAC7B,IAAI;gBACJ,WAAW,EAAE,qBAAqB;gBAClC,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;aACxB,CAAA;YAED,aAAa,CAAC,eAAe,CAAC,GAAG,QAAQ,CAAA;YACzC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QACpB,CAAC;aAAM,CAAC;YACN,OAAO,aAAa,CAAC,eAAe,CAAC,CAAA;YACrC,QAAQ,CAAC,IAAI,CAAC,CAAA;QAChB,CAAC;QAED,YAAY,CAAC,aAAa,CAAC,CAAA;IAC7B,CAAC,EACD,CAAC,eAAe,EAAE,SAAS,EAAE,YAAY,CAAC,CAC3C,CAAA;IAED,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE;QAClC,MAAM,aAAa,GAAG,EAAE,GAAG,SAAS,EAAE,CAAA;QACtC,OAAO,aAAa,CAAC,eAAe,CAAC,CAAA;QACrC,YAAY,CAAC,aAAa,CAAC,CAAA;QAC3B,QAAQ,CAAC,IAAI,CAAC,CAAA;IAChB,CAAC,EAAE,CAAC,eAAe,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC,CAAA;IAE9C,OAAO;QACL,KAAK;QACL,SAAS;QACT,UAAU;KACX,CAAA;AACH,CAAC","sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react'\nimport { useAsyncStorage } from './use_async_storage'\nimport type { FileAttachment } from '../types/resources/denormalized_attachment_resource_for_create'\n\ninterface MessageDraft {\n text: string\n attachments: FileAttachment[]\n lastUpdated: number\n}\n\nconst DRAFT_STORAGE_KEY = 'chat_message_drafts'\nconst DRAFT_EXPIRY_HOURS = 720 // 30 days\nconst DRAFT_EXPIRY_MS = DRAFT_EXPIRY_HOURS * 60 * 60 * 1000\nconst ATTACHMENT_EXPIRY_HOURS = 48 // 2 days\nconst ATTACHMENT_EXPIRY_MS = ATTACHMENT_EXPIRY_HOURS * 60 * 60 * 1000\n\nexport function useMessageDraft(conversationId: number) {\n const conversationKey = conversationId.toString()\n const [allDrafts, setAllDrafts] = useAsyncStorage<Record<string, MessageDraft>>(\n DRAFT_STORAGE_KEY,\n {}\n )\n\n const [draft, setDraft] = useState<MessageDraft | null>(() => {\n const storedDraft = allDrafts[conversationKey] || null\n\n // Filter expired attachments\n if (storedDraft?.attachments) {\n const now = Date.now()\n const validAttachments = storedDraft.attachments.filter(attachment => {\n if (!attachment.uploadedAt) return false\n return now - attachment.uploadedAt < ATTACHMENT_EXPIRY_MS\n })\n\n return {\n ...storedDraft,\n attachments: validAttachments,\n }\n }\n\n return storedDraft\n })\n\n // Clean up expired drafts only once on mount - React 18 recommended pattern\n const hasCleanedUp = useRef(false)\n\n useEffect(() => {\n if (hasCleanedUp.current) return\n\n const now = Date.now()\n const validDrafts: Record<string, MessageDraft> = {}\n\n Object.entries(allDrafts).forEach(([id, draftData]) => {\n if (draftData?.lastUpdated && now - draftData.lastUpdated < DRAFT_EXPIRY_MS) {\n validDrafts[id] = draftData\n }\n })\n\n // If we filtered out any drafts, update storage\n if (Object.keys(validDrafts).length !== Object.keys(allDrafts).length) {\n setAllDrafts(validDrafts)\n }\n\n hasCleanedUp.current = true\n }, [allDrafts, setAllDrafts])\n\n const saveDraft = useCallback(\n (text: string, attachments: FileAttachment[]) => {\n const hasContent = text.trim().length > 0 || attachments.length > 0\n const updatedDrafts = { ...allDrafts }\n\n if (hasContent) {\n // Convert attachments to serializable format (similar to web implementation)\n const normalizedAttachments = attachments\n .filter(att => att.id && att.status === 'success')\n .map(att => ({\n ...att,\n file: {\n uri: att.file.uri,\n name: att.file.name,\n type: att.file.type,\n size: att.file.size,\n width: att.file.width,\n height: att.file.height,\n },\n }))\n\n const newDraft: MessageDraft = {\n text,\n attachments: normalizedAttachments,\n lastUpdated: Date.now(),\n }\n\n updatedDrafts[conversationKey] = newDraft\n setDraft(newDraft)\n } else {\n delete updatedDrafts[conversationKey]\n setDraft(null)\n }\n\n setAllDrafts(updatedDrafts)\n },\n [conversationKey, allDrafts, setAllDrafts]\n )\n\n const clearDraft = useCallback(() => {\n const updatedDrafts = { ...allDrafts }\n delete updatedDrafts[conversationKey]\n setAllDrafts(updatedDrafts)\n setDraft(null)\n }, [conversationKey, allDrafts, setAllDrafts])\n\n return {\n draft,\n saveDraft,\n clearDraft,\n }\n}\n"]}
1
+ {"version":3,"file":"use_message_draft.js","sourceRoot":"","sources":["../../src/hooks/use_message_draft.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react'\nimport { useAsyncStorage } from './use_async_storage'\nimport type { FileAttachment } from '../types/resources/denormalized_attachment_resource_for_create'\nimport { useConversationContext } from '../contexts/conversation_context'\n\ninterface MessageDraft {\n text: string\n attachments: FileAttachment[]\n lastUpdated: number\n}\n\nconst DRAFT_STORAGE_KEY = 'chat_message_drafts'\nconst DRAFT_EXPIRY_HOURS = 720 // 30 days\nconst DRAFT_EXPIRY_MS = DRAFT_EXPIRY_HOURS * 60 * 60 * 1000\nconst ATTACHMENT_EXPIRY_HOURS = 48 // 2 days\nconst ATTACHMENT_EXPIRY_MS = ATTACHMENT_EXPIRY_HOURS * 60 * 60 * 1000\n\nexport function useMessageDraft() {\n const { conversationId, currentPageReplyRootId } = useConversationContext()\n const conversationKey = currentPageReplyRootId\n ? `${conversationId}/threads/${currentPageReplyRootId}`\n : String(conversationId)\n const [allDrafts, setAllDrafts] = useAsyncStorage<Record<string, MessageDraft>>(\n DRAFT_STORAGE_KEY,\n {}\n )\n\n const [draft, setDraft] = useState<MessageDraft | null>(() => {\n const storedDraft = allDrafts[conversationKey] || null\n\n // Filter expired attachments\n if (storedDraft?.attachments) {\n const now = Date.now()\n const validAttachments = storedDraft.attachments.filter(attachment => {\n if (!attachment.uploadedAt) return false\n return now - attachment.uploadedAt < ATTACHMENT_EXPIRY_MS\n })\n\n return {\n ...storedDraft,\n attachments: validAttachments,\n }\n }\n\n return storedDraft\n })\n\n // Clean up expired drafts only once on mount - React 18 recommended pattern\n const hasCleanedUp = useRef(false)\n\n useEffect(() => {\n if (hasCleanedUp.current) return\n\n const now = Date.now()\n const validDrafts: Record<string, MessageDraft> = {}\n\n Object.entries(allDrafts).forEach(([id, draftData]) => {\n if (draftData?.lastUpdated && now - draftData.lastUpdated < DRAFT_EXPIRY_MS) {\n validDrafts[id] = draftData\n }\n })\n\n // If we filtered out any drafts, update storage\n if (Object.keys(validDrafts).length !== Object.keys(allDrafts).length) {\n setAllDrafts(validDrafts)\n }\n\n hasCleanedUp.current = true\n }, [allDrafts, setAllDrafts])\n\n const saveDraft = useCallback(\n (text: string, attachments: FileAttachment[]) => {\n const hasContent = text.trim().length > 0 || attachments.length > 0\n const updatedDrafts = { ...allDrafts }\n\n if (hasContent) {\n // Convert attachments to serializable format (similar to web implementation)\n const normalizedAttachments = attachments\n .filter(att => att.id && att.status === 'success')\n .map(att => ({\n ...att,\n file: {\n uri: att.file.uri,\n name: att.file.name,\n type: att.file.type,\n size: att.file.size,\n width: att.file.width,\n height: att.file.height,\n },\n }))\n\n const newDraft: MessageDraft = {\n text,\n attachments: normalizedAttachments,\n lastUpdated: Date.now(),\n }\n\n updatedDrafts[conversationKey] = newDraft\n setDraft(newDraft)\n } else {\n delete updatedDrafts[conversationKey]\n setDraft(null)\n }\n\n setAllDrafts(updatedDrafts)\n },\n [conversationKey, allDrafts, setAllDrafts]\n )\n\n const clearDraft = useCallback(() => {\n const updatedDrafts = { ...allDrafts }\n delete updatedDrafts[conversationKey]\n setAllDrafts(updatedDrafts)\n setDraft(null)\n }, [conversationKey, allDrafts, setAllDrafts])\n\n return {\n draft,\n saveDraft,\n clearDraft,\n }\n}\n"]}
@@ -25,7 +25,7 @@ export function AgeCheckRequiredScreen() {
25
25
  const { submitAgeCheck, isPending, isSuccess } = useSubmitAgeCheck();
26
26
  const styles = useStyles();
27
27
  const birthdateStamp = birthdate
28
- ? formatDate(birthdate, { style: 'standard', year: true })
28
+ ? formatDate(birthdate, { style: 'standard', year: true, timeZone: 'UTC' })
29
29
  : 'Missing';
30
30
  const age = birthdate ? calculateAge(birthdate) : null;
31
31
  const confirmationText = birthdate !== null
@@ -1 +1 @@
1
- {"version":3,"file":"age_check_required_screen.js","sourceRoot":"","sources":["../../../src/screens/age_check/age_check_required_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState } from 'react'\nimport { date as formatDate } from '@planningcenter/datetime-fmt'\nimport { StyleSheet, View } from 'react-native'\nimport { Button } from '../../components/display/button'\nimport { Text } from '../../components/display/text'\nimport { Icon } from '../../components/display/icon'\nimport { Avatar } from '../../components/display/avatar'\nimport { Banner } from '../../components/display/banner'\nimport { useCurrentPerson, useTheme, useSubmitAgeCheck } from '../../hooks'\nimport { Heading } from '../../components'\nimport { platformFontWeightBold } from '../../utils/styles'\nimport { AgeCheckSelectBirthdateModal } from './components/age_check_select_birthdate_modal'\n\nfunction calculateAge(birthdate: Date) {\n const today = new Date()\n const age = today.getFullYear() - birthdate.getFullYear()\n const hasHadBirthdayThisYear =\n today.getMonth() > birthdate.getMonth() ||\n (today.getMonth() === birthdate.getMonth() && today.getDate() >= birthdate.getDate())\n return hasHadBirthdayThisYear ? age : age - 1\n}\n\nexport function AgeCheckRequiredScreen() {\n const person = useCurrentPerson()\n\n const [birthdate, setBirthdate] = useState<Date | null>(null)\n const [draftBirthdate, setDraftBirthdate] = useState<Date | null>(null)\n const [isBirthdateModalOpen, setBirthdateModalOpen] = useState(false)\n const { submitAgeCheck, isPending, isSuccess } = useSubmitAgeCheck()\n const styles = useStyles()\n\n const birthdateStamp = birthdate\n ? formatDate(birthdate, { style: 'standard', year: true })\n : 'Missing'\n\n const age = birthdate ? calculateAge(birthdate) : null\n\n const confirmationText =\n birthdate !== null\n ? `Your birthdate is ${birthdateStamp} and you are ${age} years old. Is that correct?`\n : ''\n\n const openBirthdateModal = () => {\n setDraftBirthdate(birthdate || new Date())\n setBirthdateModalOpen(true)\n }\n\n const closeBirthdateModal = () => {\n setBirthdateModalOpen(false)\n }\n\n const handleSubmitAgeConfirmation = () => {\n if (!birthdate) return\n submitAgeCheck(birthdate)\n }\n\n return (\n <View style={styles.container}>\n <View style={styles.header}>\n <View style={styles.heading}>\n <Icon name=\"general.exclamationTriangle\" size={20} style={styles.warningIcon} />\n <Heading variant=\"h2\">Your age is required to use chat</Heading>\n </View>\n <Text>To help protect those who may be underage, we need to verify your birthdate.</Text>\n </View>\n <View style={styles.cards}>\n <View style={styles.card}>\n <Heading variant=\"h3\">My profile</Heading>\n <View style={styles.profileContent}>\n <Avatar sourceUri={person.avatar || ''} size=\"lg\" showFallback={!person.avatar} />\n <View style={styles.personInfo}>\n <Text style={styles.name} numberOfLines={1}>\n {person.name}\n </Text>\n <View style={styles.birthdateInfo}>\n <Text variant=\"tertiary\" style={styles.birthdateLabel}>\n Birthdate:\n </Text>\n <Text variant=\"tertiary\">{birthdateStamp}</Text>\n </View>\n </View>\n {birthdate && (\n <Button\n title=\"Edit\"\n accessibilityHint=\"Choose a new birthdate for your profile\"\n size=\"sm\"\n variant=\"outline\"\n style={styles.editButton}\n onPress={openBirthdateModal}\n />\n )}\n </View>\n {!birthdate && (\n <Button\n title=\"Add birthdate\"\n accessibilityHint=\"Choose a birthdate for your profile\"\n size=\"lg\"\n style={styles.primaryButton}\n onPress={openBirthdateModal}\n />\n )}\n </View>\n {birthdate && (\n <View style={styles.card}>\n <Heading variant=\"h3\">Age confirmation</Heading>\n {age !== null && age < 13 ? (\n <Banner appearance=\"warning\" description={confirmationText} />\n ) : (\n <Text>{confirmationText}</Text>\n )}\n <Button\n title=\"Yes, update my profile\"\n size=\"lg\"\n style={styles.primaryButton}\n onPress={handleSubmitAgeConfirmation}\n disabled={isPending || isSuccess}\n />\n </View>\n )}\n </View>\n <Text variant=\"tertiary\">\n Your birthdate will be added to your profile, but it is only visible to church\n administrators. It will not be shared with other church members, unless you give permission.\n </Text>\n\n <AgeCheckSelectBirthdateModal\n onChange={setDraftBirthdate}\n onDismiss={closeBirthdateModal}\n onRequestClose={closeBirthdateModal}\n onSubmit={setBirthdate}\n value={draftBirthdate || new Date()}\n visible={isBirthdateModalOpen}\n />\n </View>\n )\n}\n\nconst useStyles = () => {\n const { colors } = useTheme()\n return StyleSheet.create({\n container: {\n flex: 1,\n backgroundColor: colors.surfaceColor080,\n padding: 16,\n gap: 16,\n },\n header: {\n gap: 8,\n },\n heading: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 8,\n },\n warningIcon: {\n color: colors.statusErrorIcon,\n },\n card: {\n backgroundColor: colors.surfaceColor100,\n borderRadius: 8,\n padding: 16,\n gap: 8,\n },\n cards: {\n gap: 8,\n },\n profileContent: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 8,\n },\n personInfo: {\n flex: 1,\n },\n primaryButton: {\n alignSelf: 'center',\n marginTop: 8,\n },\n name: {\n fontWeight: platformFontWeightBold,\n },\n birthdateLabel: {\n fontWeight: platformFontWeightBold,\n },\n birthdateInfo: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 4,\n },\n editButton: {\n alignSelf: 'flex-end',\n },\n formSheetContent: {\n flex: 1,\n },\n })\n}\n"]}
1
+ {"version":3,"file":"age_check_required_screen.js","sourceRoot":"","sources":["../../../src/screens/age_check/age_check_required_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState } from 'react'\nimport { date as formatDate } from '@planningcenter/datetime-fmt'\nimport { StyleSheet, View } from 'react-native'\nimport { Button } from '../../components/display/button'\nimport { Text } from '../../components/display/text'\nimport { Icon } from '../../components/display/icon'\nimport { Avatar } from '../../components/display/avatar'\nimport { Banner } from '../../components/display/banner'\nimport { useCurrentPerson, useTheme, useSubmitAgeCheck } from '../../hooks'\nimport { Heading } from '../../components'\nimport { platformFontWeightBold } from '../../utils/styles'\nimport { AgeCheckSelectBirthdateModal } from './components/age_check_select_birthdate_modal'\n\nfunction calculateAge(birthdate: Date) {\n const today = new Date()\n const age = today.getFullYear() - birthdate.getFullYear()\n const hasHadBirthdayThisYear =\n today.getMonth() > birthdate.getMonth() ||\n (today.getMonth() === birthdate.getMonth() && today.getDate() >= birthdate.getDate())\n return hasHadBirthdayThisYear ? age : age - 1\n}\n\nexport function AgeCheckRequiredScreen() {\n const person = useCurrentPerson()\n\n const [birthdate, setBirthdate] = useState<Date | null>(null)\n const [draftBirthdate, setDraftBirthdate] = useState<Date | null>(null)\n const [isBirthdateModalOpen, setBirthdateModalOpen] = useState(false)\n const { submitAgeCheck, isPending, isSuccess } = useSubmitAgeCheck()\n const styles = useStyles()\n\n const birthdateStamp = birthdate\n ? formatDate(birthdate, { style: 'standard', year: true, timeZone: 'UTC' })\n : 'Missing'\n\n const age = birthdate ? calculateAge(birthdate) : null\n\n const confirmationText =\n birthdate !== null\n ? `Your birthdate is ${birthdateStamp} and you are ${age} years old. Is that correct?`\n : ''\n\n const openBirthdateModal = () => {\n setDraftBirthdate(birthdate || new Date())\n setBirthdateModalOpen(true)\n }\n\n const closeBirthdateModal = () => {\n setBirthdateModalOpen(false)\n }\n\n const handleSubmitAgeConfirmation = () => {\n if (!birthdate) return\n submitAgeCheck(birthdate)\n }\n\n return (\n <View style={styles.container}>\n <View style={styles.header}>\n <View style={styles.heading}>\n <Icon name=\"general.exclamationTriangle\" size={20} style={styles.warningIcon} />\n <Heading variant=\"h2\">Your age is required to use chat</Heading>\n </View>\n <Text>To help protect those who may be underage, we need to verify your birthdate.</Text>\n </View>\n <View style={styles.cards}>\n <View style={styles.card}>\n <Heading variant=\"h3\">My profile</Heading>\n <View style={styles.profileContent}>\n <Avatar sourceUri={person.avatar || ''} size=\"lg\" showFallback={!person.avatar} />\n <View style={styles.personInfo}>\n <Text style={styles.name} numberOfLines={1}>\n {person.name}\n </Text>\n <View style={styles.birthdateInfo}>\n <Text variant=\"tertiary\" style={styles.birthdateLabel}>\n Birthdate:\n </Text>\n <Text variant=\"tertiary\">{birthdateStamp}</Text>\n </View>\n </View>\n {birthdate && (\n <Button\n title=\"Edit\"\n accessibilityHint=\"Choose a new birthdate for your profile\"\n size=\"sm\"\n variant=\"outline\"\n style={styles.editButton}\n onPress={openBirthdateModal}\n />\n )}\n </View>\n {!birthdate && (\n <Button\n title=\"Add birthdate\"\n accessibilityHint=\"Choose a birthdate for your profile\"\n size=\"lg\"\n style={styles.primaryButton}\n onPress={openBirthdateModal}\n />\n )}\n </View>\n {birthdate && (\n <View style={styles.card}>\n <Heading variant=\"h3\">Age confirmation</Heading>\n {age !== null && age < 13 ? (\n <Banner appearance=\"warning\" description={confirmationText} />\n ) : (\n <Text>{confirmationText}</Text>\n )}\n <Button\n title=\"Yes, update my profile\"\n size=\"lg\"\n style={styles.primaryButton}\n onPress={handleSubmitAgeConfirmation}\n disabled={isPending || isSuccess}\n />\n </View>\n )}\n </View>\n <Text variant=\"tertiary\">\n Your birthdate will be added to your profile, but it is only visible to church\n administrators. It will not be shared with other church members, unless you give permission.\n </Text>\n\n <AgeCheckSelectBirthdateModal\n onChange={setDraftBirthdate}\n onDismiss={closeBirthdateModal}\n onRequestClose={closeBirthdateModal}\n onSubmit={setBirthdate}\n value={draftBirthdate || new Date()}\n visible={isBirthdateModalOpen}\n />\n </View>\n )\n}\n\nconst useStyles = () => {\n const { colors } = useTheme()\n return StyleSheet.create({\n container: {\n flex: 1,\n backgroundColor: colors.surfaceColor080,\n padding: 16,\n gap: 16,\n },\n header: {\n gap: 8,\n },\n heading: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 8,\n },\n warningIcon: {\n color: colors.statusErrorIcon,\n },\n card: {\n backgroundColor: colors.surfaceColor100,\n borderRadius: 8,\n padding: 16,\n gap: 8,\n },\n cards: {\n gap: 8,\n },\n profileContent: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 8,\n },\n personInfo: {\n flex: 1,\n },\n primaryButton: {\n alignSelf: 'center',\n marginTop: 8,\n },\n name: {\n fontWeight: platformFontWeightBold,\n },\n birthdateLabel: {\n fontWeight: platformFontWeightBold,\n },\n birthdateInfo: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 4,\n },\n editButton: {\n alignSelf: 'flex-end',\n },\n formSheetContent: {\n flex: 1,\n },\n })\n}\n"]}
@@ -38,7 +38,7 @@ function IOSBirthdateModal({ onChange, onDismiss, onRequestClose, onSubmit, valu
38
38
  Birthdate
39
39
  </Text>
40
40
  <View style={styles.pickerContainer}>
41
- <DateTimePicker accessibilityLabelledBy="birthdateLabel" testID="age-check-date-picker" mode="date" display="spinner" value={selected} maximumDate={today} onChange={handleChange}/>
41
+ <DateTimePicker timeZoneName="UTC" accessibilityLabelledBy="birthdateLabel" testID="age-check-date-picker" mode="date" display="spinner" value={selected} maximumDate={today} onChange={handleChange}/>
42
42
  </View>
43
43
  </View>
44
44
  </View>
@@ -56,7 +56,7 @@ function AndroidBirthdatePicker({ onRequestClose, onSubmit, value, visible, }) {
56
56
  }
57
57
  onRequestClose();
58
58
  };
59
- return (<DateTimePicker testID="age-check-date-picker-android" mode="date" display="spinner" value={selected} maximumDate={today} onChange={handleAndroidDateChange}/>);
59
+ return (<DateTimePicker timeZoneName="UTC" testID="age-check-date-picker-android" mode="date" display="spinner" value={selected} maximumDate={today} onChange={handleAndroidDateChange}/>);
60
60
  }
61
61
  const useStyles = () => {
62
62
  const { colors } = useTheme();
@@ -1 +1 @@
1
- {"version":3,"file":"age_check_select_birthdate_modal.js","sourceRoot":"","sources":["../../../../src/screens/age_check/components/age_check_select_birthdate_modal.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react'\nimport { Modal, Platform, StyleSheet, View } from 'react-native'\nimport DateTimePicker, { DateTimePickerEvent } from '@react-native-community/datetimepicker'\nimport FormSheet from '../../../components/primitive/form_sheet'\nimport { Text } from '../../../components/display/text'\nimport { useTheme } from '../../../hooks'\n\nexport type AgeCheckSelectBirthdateProps = {\n onChange: (date: Date) => void\n onDismiss?: () => void\n onRequestClose: () => void\n onSubmit: (date: Date) => void\n value?: Date | null\n visible?: boolean\n}\n\nexport function AgeCheckSelectBirthdateModal(props: AgeCheckSelectBirthdateProps) {\n if (Platform.OS === 'ios') return <IOSBirthdateModal {...props} />\n if (Platform.OS === 'android') return <AndroidBirthdatePicker {...props} />\n\n return <Text>Birthdate selection is not supported on this platform.</Text>\n}\n\nfunction IOSBirthdateModal({\n onChange,\n onDismiss,\n onRequestClose,\n onSubmit,\n value,\n visible,\n}: AgeCheckSelectBirthdateProps) {\n const styles = useStyles()\n const today = React.useMemo(() => new Date(), [])\n const selected = value || today\n\n const handleChange = (_event: DateTimePickerEvent, date?: Date) => {\n if (date) onChange(date)\n }\n\n const handleSave = () => {\n onSubmit(selected)\n onRequestClose()\n }\n\n return (\n <Modal\n visible={visible}\n animationType=\"slide\"\n presentationStyle=\"pageSheet\"\n onRequestClose={onRequestClose}\n onDismiss={onDismiss}\n >\n <FormSheet.Root style={styles.formSheet} contentStyle={styles.formSheetContent}>\n <FormSheet.Header>\n <FormSheet.HeaderTitle>Your birthdate</FormSheet.HeaderTitle>\n <FormSheet.HeaderActions>\n <FormSheet.HeaderTextButton onPress={onRequestClose}>Cancel</FormSheet.HeaderTextButton>\n <FormSheet.HeaderButton title=\"Save\" onPress={handleSave} />\n </FormSheet.HeaderActions>\n </FormSheet.Header>\n <View style={styles.content}>\n <View style={styles.card}>\n <Text nativeID=\"birthdateLabel\" variant=\"tertiary\" style={styles.label}>\n Birthdate\n </Text>\n <View style={styles.pickerContainer}>\n <DateTimePicker\n accessibilityLabelledBy=\"birthdateLabel\"\n testID=\"age-check-date-picker\"\n mode=\"date\"\n display=\"spinner\"\n value={selected}\n maximumDate={today}\n onChange={handleChange}\n />\n </View>\n </View>\n </View>\n </FormSheet.Root>\n </Modal>\n )\n}\n\nfunction AndroidBirthdatePicker({\n onRequestClose,\n onSubmit,\n value,\n visible,\n}: AgeCheckSelectBirthdateProps) {\n if (!visible) return null\n\n const today = new Date()\n const selected = value || today\n\n const handleAndroidDateChange = (event: DateTimePickerEvent, selectedDate?: Date) => {\n if (event.type === 'set' && selectedDate) {\n onSubmit(selectedDate)\n }\n onRequestClose()\n }\n\n return (\n <DateTimePicker\n testID=\"age-check-date-picker-android\"\n mode=\"date\"\n display=\"spinner\"\n value={selected}\n maximumDate={today}\n onChange={handleAndroidDateChange}\n />\n )\n}\n\nconst useStyles = () => {\n const { colors } = useTheme()\n return StyleSheet.create({\n formSheet: {\n backgroundColor: colors.surfaceColor080,\n },\n formSheetContent: {\n flex: 1,\n },\n content: {\n flex: 1,\n backgroundColor: colors.surfaceColor080,\n padding: 16,\n justifyContent: 'flex-start',\n },\n card: {\n backgroundColor: colors.surfaceColor100,\n borderRadius: 8,\n padding: 16,\n },\n label: {\n marginBottom: 8,\n textTransform: 'uppercase',\n },\n pickerContainer: {\n backgroundColor: colors.surfaceColor100,\n borderRadius: 8,\n },\n })\n}\n"]}
1
+ {"version":3,"file":"age_check_select_birthdate_modal.js","sourceRoot":"","sources":["../../../../src/screens/age_check/components/age_check_select_birthdate_modal.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react'\nimport { Modal, Platform, StyleSheet, View } from 'react-native'\nimport DateTimePicker, { DateTimePickerEvent } from '@react-native-community/datetimepicker'\nimport FormSheet from '../../../components/primitive/form_sheet'\nimport { Text } from '../../../components/display/text'\nimport { useTheme } from '../../../hooks'\n\nexport type AgeCheckSelectBirthdateProps = {\n onChange: (date: Date) => void\n onDismiss?: () => void\n onRequestClose: () => void\n onSubmit: (date: Date) => void\n value?: Date | null\n visible?: boolean\n}\n\nexport function AgeCheckSelectBirthdateModal(props: AgeCheckSelectBirthdateProps) {\n if (Platform.OS === 'ios') return <IOSBirthdateModal {...props} />\n if (Platform.OS === 'android') return <AndroidBirthdatePicker {...props} />\n\n return <Text>Birthdate selection is not supported on this platform.</Text>\n}\n\nfunction IOSBirthdateModal({\n onChange,\n onDismiss,\n onRequestClose,\n onSubmit,\n value,\n visible,\n}: AgeCheckSelectBirthdateProps) {\n const styles = useStyles()\n const today = React.useMemo(() => new Date(), [])\n const selected = value || today\n\n const handleChange = (_event: DateTimePickerEvent, date?: Date) => {\n if (date) onChange(date)\n }\n\n const handleSave = () => {\n onSubmit(selected)\n onRequestClose()\n }\n\n return (\n <Modal\n visible={visible}\n animationType=\"slide\"\n presentationStyle=\"pageSheet\"\n onRequestClose={onRequestClose}\n onDismiss={onDismiss}\n >\n <FormSheet.Root style={styles.formSheet} contentStyle={styles.formSheetContent}>\n <FormSheet.Header>\n <FormSheet.HeaderTitle>Your birthdate</FormSheet.HeaderTitle>\n <FormSheet.HeaderActions>\n <FormSheet.HeaderTextButton onPress={onRequestClose}>Cancel</FormSheet.HeaderTextButton>\n <FormSheet.HeaderButton title=\"Save\" onPress={handleSave} />\n </FormSheet.HeaderActions>\n </FormSheet.Header>\n <View style={styles.content}>\n <View style={styles.card}>\n <Text nativeID=\"birthdateLabel\" variant=\"tertiary\" style={styles.label}>\n Birthdate\n </Text>\n <View style={styles.pickerContainer}>\n <DateTimePicker\n timeZoneName=\"UTC\"\n accessibilityLabelledBy=\"birthdateLabel\"\n testID=\"age-check-date-picker\"\n mode=\"date\"\n display=\"spinner\"\n value={selected}\n maximumDate={today}\n onChange={handleChange}\n />\n </View>\n </View>\n </View>\n </FormSheet.Root>\n </Modal>\n )\n}\n\nfunction AndroidBirthdatePicker({\n onRequestClose,\n onSubmit,\n value,\n visible,\n}: AgeCheckSelectBirthdateProps) {\n if (!visible) return null\n\n const today = new Date()\n const selected = value || today\n\n const handleAndroidDateChange = (event: DateTimePickerEvent, selectedDate?: Date) => {\n if (event.type === 'set' && selectedDate) {\n onSubmit(selectedDate)\n }\n onRequestClose()\n }\n\n return (\n <DateTimePicker\n timeZoneName=\"UTC\"\n testID=\"age-check-date-picker-android\"\n mode=\"date\"\n display=\"spinner\"\n value={selected}\n maximumDate={today}\n onChange={handleAndroidDateChange}\n />\n )\n}\n\nconst useStyles = () => {\n const { colors } = useTheme()\n return StyleSheet.create({\n formSheet: {\n backgroundColor: colors.surfaceColor080,\n },\n formSheetContent: {\n flex: 1,\n },\n content: {\n flex: 1,\n backgroundColor: colors.surfaceColor080,\n padding: 16,\n justifyContent: 'flex-start',\n },\n card: {\n backgroundColor: colors.surfaceColor100,\n borderRadius: 8,\n padding: 16,\n },\n label: {\n marginBottom: 8,\n textTransform: 'uppercase',\n },\n pickerContainer: {\n backgroundColor: colors.surfaceColor100,\n borderRadius: 8,\n },\n })\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"conversation_screen.d.ts","sourceRoot":"","sources":["../../src/screens/conversation_screen.tsx"],"names":[],"mappings":"AACA,OAAO,EAAe,gBAAgB,EAAqB,MAAM,4BAA4B,CAAA;AAC7F,OAAO,EAGL,iBAAiB,EAIlB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,KAAmD,MAAM,OAAO,CAAA;AAkBvE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAA;AAMjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAA;AAIpF,MAAM,MAAM,sBAAsB,GAAG;IACnC,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,CAAC,sBAAsB,CAAC,CAAA;AAE/E,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,EAAE,uBAAuB,qBAWpE;AA8JD,MAAM,MAAM,aAAa,GAAG;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAwC/E,KAAK,kBAAkB,GAAG;IACxB,IAAI,EAAE,oBAAoB,CAAA;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,oBAAoB,EAAE,OAAO,CAAA;IAC7B,iBAAiB,EAAE,OAAO,CAAA;CAC3B,CAAA;AAED,UAAU,kBAAkB;IAC1B,EAAE,EAAE,eAAe,EAAE,CAAA;IACrB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,eAAO,MAAM,aAAa,2CAIvB,kBAAkB,6DAiFpB,CAAA;AACD,UAAU,4BAA6B,SAAQ,gBAAgB;IAC7D,eAAe,EAAE,MAAM,CAAA;IACvB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,eAAO,MAAM,uBAAuB,0DAMjC,4BAA4B,sBAiC9B,CAAA"}
1
+ {"version":3,"file":"conversation_screen.d.ts","sourceRoot":"","sources":["../../src/screens/conversation_screen.tsx"],"names":[],"mappings":"AACA,OAAO,EAAe,gBAAgB,EAAqB,MAAM,4BAA4B,CAAA;AAC7F,OAAO,EAGL,iBAAiB,EAIlB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,KAAmD,MAAM,OAAO,CAAA;AAkBvE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAA;AAMjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAA;AAIpF,MAAM,MAAM,sBAAsB,GAAG;IACnC,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,CAAC,sBAAsB,CAAC,CAAA;AAE/E,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,EAAE,uBAAuB,qBAWpE;AA8JD,MAAM,MAAM,aAAa,GAAG;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAwC/E,KAAK,kBAAkB,GAAG;IACxB,IAAI,EAAE,oBAAoB,CAAA;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,oBAAoB,EAAE,OAAO,CAAA;IAC7B,iBAAiB,EAAE,OAAO,CAAA;CAC3B,CAAA;AAED,UAAU,kBAAkB;IAC1B,EAAE,EAAE,eAAe,EAAE,CAAA;IACrB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,eAAO,MAAM,aAAa,2CAIvB,kBAAkB,6DA8FpB,CAAA;AACD,UAAU,4BAA6B,SAAQ,gBAAgB;IAC7D,eAAe,EAAE,MAAM,CAAA;IACvB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,eAAO,MAAM,uBAAuB,0DAMjC,4BAA4B,sBAiC9B,CAAA"}
@@ -182,6 +182,21 @@ export const groupMessages = ({ ms, inReplyScreen, repliesEnabled = false, }) =>
182
182
  const insertReplyShadowMessage = message.replyRootId &&
183
183
  !threadRoot &&
184
184
  (prevMessageDifferentThread || prevMessageIsDateSeparator);
185
+ const lastInGroup = !nextMessage ||
186
+ nextMessageDifferentAuthor ||
187
+ nextMessageMoreThan5Minutes ||
188
+ nextMessageDifferentThread ||
189
+ nextMessageIsDateSeparator;
190
+ const renderAuthor = !message.mine &&
191
+ (!prevMessage ||
192
+ prevMessageDifferentAuthor ||
193
+ prevMessageMoreThan5Minutes ||
194
+ prevMessageDifferentThread ||
195
+ prevMessageIsDateSeparator);
196
+ const nextIsReplyShadowMessage = repliesEnabled &&
197
+ nextMessageInThread &&
198
+ !nextMessageThreadRoot &&
199
+ (nextMessageDifferentThread || nextMessageIsDateSeparator);
185
200
  if (message.mine && !encounteredOneOfMyMessages) {
186
201
  encounteredOneOfMyMessages = true;
187
202
  message.myLatestInConversation = true;
@@ -189,17 +204,12 @@ export const groupMessages = ({ ms, inReplyScreen, repliesEnabled = false, }) =>
189
204
  else {
190
205
  message.myLatestInConversation = false;
191
206
  }
192
- message.lastInGroup = !nextMessage || nextMessageDifferentAuthor || nextMessageMoreThan5Minutes;
193
- message.renderAuthor =
194
- !message.mine && (!prevMessage || prevMessageDifferentAuthor || prevMessageMoreThan5Minutes);
207
+ message.lastInGroup = lastInGroup;
208
+ message.renderAuthor = renderAuthor;
195
209
  message.threadPosition = null;
196
210
  message.nextRendersAuthor = nextMessage?.renderAuthor;
197
211
  message.isReplyShadowMessage = false;
198
- message.nextIsReplyShadowMessage =
199
- repliesEnabled &&
200
- nextMessageInThread &&
201
- !nextMessageThreadRoot &&
202
- (nextMessageDifferentThread || nextMessageIsDateSeparator);
212
+ message.nextIsReplyShadowMessage = nextIsReplyShadowMessage;
203
213
  if (!inReplyScreen && inThread) {
204
214
  message.prevIsMyReply = prevMessage?.mine;
205
215
  message.nextIsMyReply = nextMessage?.mine;
@@ -1 +1 @@
1
- {"version":3,"file":"conversation_screen.js","sourceRoot":"","sources":["../../src/screens/conversation_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import { date as formatDate } from '@planningcenter/datetime-fmt'\nimport { HeaderTitle, HeaderTitleProps, PlatformPressable } from '@react-navigation/elements'\nimport {\n CommonActions,\n RouteProp,\n StaticScreenProps,\n useNavigation,\n useTheme as useNavigationTheme,\n useRoute,\n} from '@react-navigation/native'\nimport moment from 'moment'\nimport React, { useCallback, useEffect, useRef, useState } from 'react'\nimport { FlatList, Platform, StyleSheet, View } from 'react-native'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\nimport { Badge, Icon, Text } from '../components'\nimport {\n LeaderMessagesDisabledBanner,\n MemberMessagesDisabledBanner,\n} from '../components/conversation/messages_disabled_banners'\nimport { EmptyConversationBlankState } from '../components/conversation/empty_conversation_blank_state'\nimport BlankState from '../components/primitive/blank_state_primitive'\nimport { Message } from '../components/conversation/message'\nimport { MessageForm } from '../components/conversation/message_form'\nimport { TypingIndicator } from '../components/conversation/typing_indicator'\nimport { KeyboardView } from '../components/display/keyboard_view'\nimport { useTheme } from '../hooks'\nimport { useConversation } from '../hooks/use_conversation'\nimport { useConversationMessages } from '../hooks/use_conversation_messages'\nimport { useConversationMessagesJoltEvents } from '../hooks/use_conversation_messages_jolt_events'\nimport { MessageResource } from '../types'\nimport { ConversationBadgeResource } from '../types/resources/conversation_badge'\nimport { getRelativeDateStatus } from '../utils/date'\nimport { useMarkLatestMessageRead } from '../hooks/use_mark_latest_message_read'\nimport { CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL } from '../utils/styles'\nimport { useConversationJoltEvents } from '../hooks/use_conversation_jolt_events'\nimport { JumpToBottomButton } from '../components/conversation/jump_to_bottom_button'\nimport { ReplyShadowMessage } from '../components/conversation/reply_shadow_message'\nimport { availableFeatures, useFeatures } from '../hooks/use_features'\nimport { ConversationContextProvider } from '../contexts/conversation_context'\n\nexport type ConversationRouteProps = {\n conversation_id: number\n reply_root_id?: string | null\n reply_root_author_name?: string\n chat_group_graph_id?: string\n clear_input?: boolean\n editing_message_id?: number | null\n title?: string\n subtitle?: string\n badge?: ConversationBadgeResource\n deleted?: boolean\n}\n\nexport type ConversationScreenProps = StaticScreenProps<ConversationRouteProps>\n\nexport function ConversationScreen({ route }: ConversationScreenProps) {\n const { conversation_id, reply_root_id } = route.params\n\n return (\n <ConversationContextProvider\n conversationId={conversation_id}\n currentPageReplyRootId={reply_root_id ?? null}\n >\n <ConversationScreenContent route={route} />\n </ConversationContextProvider>\n )\n}\n\nfunction ConversationScreenContent({ route }: ConversationScreenProps) {\n const styles = useStyles()\n const navigation = useNavigation()\n const { conversation_id, editing_message_id, reply_root_id, reply_root_author_name } =\n route.params\n const { data: conversation } = useConversation(route.params)\n const { messages, refetch, isRefetching, fetchNextPage } = useConversationMessages({\n conversation_id,\n reply_root_id,\n })\n useConversationJoltEvents({ conversationId: conversation_id })\n useConversationMessagesJoltEvents({ conversationId: conversation_id })\n useEnsureConversationsRouteExists()\n useMarkLatestMessageRead({ conversation, messages })\n const { featureEnabled } = useFeatures()\n const repliesEnabled = featureEnabled(availableFeatures.threaded_replies)\n const messagesWithSeparators = groupMessages({\n ms: messages,\n inReplyScreen: !!reply_root_id,\n repliesEnabled,\n })\n const noMessages = messagesWithSeparators.length === 0\n\n const { repliesDisabled, memberAbility, badges, title } = conversation\n const canReply = memberAbility?.canReply\n const showLeaderDisabledReplyBanner = canReply && repliesDisabled\n const canDeleteNonAuthoredMessages = memberAbility?.canDeleteNonAuthoredMessages ?? false\n const currentlyEditingMessage = messages.find(m => String(m.id) === String(editing_message_id))\n const replyRootAuthorFirstName = reply_root_author_name?.split(' ')[0]\n const replyHeaderTitle = replyRootAuthorFirstName\n ? `Reply to ${replyRootAuthorFirstName}`\n : 'Reply'\n\n const listRef = useRef<FlatList>(null)\n const [showJumpToBottomButton, setShowJumpToBottomButton] = useState(false)\n\n const trackScroll = (event: any) => {\n const offsetY = event.nativeEvent.contentOffset.y\n setShowJumpToBottomButton(offsetY > 200)\n }\n\n const handleReturnToBottom = useCallback(() => {\n listRef.current?.scrollToOffset({\n offset: 0,\n })\n }, [])\n\n useEffect(() => {\n if (reply_root_id) {\n navigation.setParams({\n title: replyHeaderTitle,\n })\n } else {\n navigation.setParams({\n title: title,\n badge: badges?.[0],\n deleted: conversation?.deleted,\n })\n }\n }, [navigation, title, badges, conversation?.deleted, reply_root_id, replyHeaderTitle])\n\n if (!conversation || conversation.deleted) {\n return (\n <View style={styles.container}>\n <BlankState.Root>\n <BlankState.Imagery name=\"general.outlinedTextMessage\" />\n <BlankState.Content>\n <BlankState.Heading>This conversation has been deleted</BlankState.Heading>\n </BlankState.Content>\n <BlankState.Button\n onPress={navigation.goBack}\n title=\"Back to conversations\"\n accessibilityHint=\"Navigates back to the conversations list\"\n accessibilityRole=\"link\"\n />\n </BlankState.Root>\n </View>\n )\n }\n\n return (\n <View style={styles.container}>\n <KeyboardView>\n {noMessages ? (\n <EmptyConversationBlankState />\n ) : (\n <FlatList\n inverted\n ref={listRef}\n contentContainerStyle={styles.listContainer}\n refreshing={isRefetching}\n onRefresh={refetch}\n data={messagesWithSeparators}\n keyExtractor={item => item.id}\n onScroll={trackScroll}\n scrollEventThrottle={10}\n renderItem={({ item }) => {\n if (item.type === 'DateSeparator') {\n return <InlineDateSeparator {...item} />\n }\n\n if (item.type === 'ReplyShadowMessage') {\n return (\n <ReplyShadowMessage\n {...item}\n conversation_id={conversation_id}\n inReplyScreen={!!reply_root_id}\n />\n )\n }\n\n return (\n <Message\n {...item}\n canDeleteNonAuthoredMessages={canDeleteNonAuthoredMessages}\n conversation_id={conversation_id}\n latestReadMessageSortKey={conversation?.latestReadMessageSortKey}\n inReplyScreen={!!reply_root_id}\n repliesEnabled={repliesEnabled}\n />\n )\n }}\n onEndReached={() => fetchNextPage()}\n ListHeaderComponent={<View style={styles.listHeader} />}\n />\n )}\n <JumpToBottomButton onPress={handleReturnToBottom} visible={showJumpToBottomButton} />\n {!noMessages && <TypingIndicator />}\n {showLeaderDisabledReplyBanner && <LeaderMessagesDisabledBanner />}\n {canReply ? (\n <MessageForm.Root\n replyRootAuthorFirstName={replyRootAuthorFirstName}\n conversation={conversation}\n replyRootId={reply_root_id}\n currentlyEditingMessage={currentlyEditingMessage}\n // We use a separate key so that it remounts component when switching between new\n // and edit message. This simplifies internal state handling.\n key={\n currentlyEditingMessage\n ? `edit-message-form-${currentlyEditingMessage.id}`\n : 'new-message-form'\n }\n >\n <MessageForm.AttachmentPicker />\n <MessageForm.Commands />\n <MessageForm.TextInput />\n <MessageForm.SubmitButton />\n </MessageForm.Root>\n ) : (\n <MemberMessagesDisabledBanner />\n )}\n </KeyboardView>\n </View>\n )\n}\n\nexport type DateSeparator = { type: 'DateSeparator'; id: string; date: string }\n\nfunction InlineDateSeparator({ date }: DateSeparator) {\n const styles = useDateSeparatorStyles()\n const { isThisYear } = getRelativeDateStatus(date)\n const showYear = !isThisYear\n const dateStamp = formatDate(date, { style: 'long', year: showYear })\n\n return (\n <View style={styles.container}>\n <View style={styles.separator} />\n <Text variant=\"footnote\" style={styles.dateText}>\n {dateStamp}\n </Text>\n <View style={styles.separator} />\n </View>\n )\n}\n\nconst useDateSeparatorStyles = () => {\n const theme = useTheme()\n return StyleSheet.create({\n container: {\n alignItems: 'center',\n flexDirection: 'row',\n paddingHorizontal: CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL,\n paddingVertical: 16,\n },\n separator: {\n flex: 1,\n height: 1,\n borderTopWidth: 1,\n borderTopColor: theme.colors.borderColorDefaultBase,\n },\n dateText: {\n paddingHorizontal: 8,\n },\n })\n}\n\ntype ReplyShadowMessage = {\n type: 'ReplyShadowMessage'\n id: string\n messageId: string\n isReplyShadowMessage: boolean\n nextRendersAuthor: boolean\n}\n\ninterface GroupMessagesProps {\n ms: MessageResource[]\n inReplyScreen?: boolean\n repliesEnabled?: boolean\n}\n\nexport const groupMessages = ({\n ms,\n inReplyScreen,\n repliesEnabled = false,\n}: GroupMessagesProps) => {\n let enrichedMessages: (MessageResource | DateSeparator | ReplyShadowMessage)[] = []\n let encounteredOneOfMyMessages = false\n\n ms.forEach((message, i) => {\n const prevMessage = ms[i + 1]\n const nextMessage = ms[i - 1]\n const date = moment(message.createdAt).format('YYYY-MM-DD')\n const inThread = message.replyRootId !== null\n const nextMessageInThread = nextMessage?.replyRootId !== null\n const threadRoot = message.replyRootId === message.id\n const nextMessageThreadRoot = nextMessage?.replyRootId === nextMessage?.id\n const prevMessageDifferentThread = message.replyRootId !== prevMessage?.replyRootId\n const nextMessageDifferentThread = message.replyRootId !== nextMessage?.replyRootId\n const prevMessageDifferentAuthor = message.author?.id !== prevMessage?.author?.id\n const nextMessageDifferentAuthor = message.author?.id !== nextMessage?.author?.id\n const prevMessageMoreThan5Minutes =\n prevMessage &&\n new Date(message.createdAt).getTime() - new Date(prevMessage.createdAt).getTime() > 60000 * 5\n const nextMessageMoreThan5Minutes =\n nextMessage &&\n new Date(nextMessage.createdAt).getTime() - new Date(message.createdAt).getTime() > 60000 * 5\n const prevMessageIsDateSeparator =\n prevMessage && date !== moment(prevMessage.createdAt).format('YYYY-MM-DD')\n const nextMessageIsDateSeparator =\n nextMessage && date !== moment(nextMessage.createdAt).format('YYYY-MM-DD')\n const insertReplyShadowMessage =\n message.replyRootId &&\n !threadRoot &&\n (prevMessageDifferentThread || prevMessageIsDateSeparator)\n\n if (message.mine && !encounteredOneOfMyMessages) {\n encounteredOneOfMyMessages = true\n message.myLatestInConversation = true\n } else {\n message.myLatestInConversation = false\n }\n message.lastInGroup = !nextMessage || nextMessageDifferentAuthor || nextMessageMoreThan5Minutes\n message.renderAuthor =\n !message.mine && (!prevMessage || prevMessageDifferentAuthor || prevMessageMoreThan5Minutes)\n message.threadPosition = null\n message.nextRendersAuthor = nextMessage?.renderAuthor\n message.isReplyShadowMessage = false\n message.nextIsReplyShadowMessage =\n repliesEnabled &&\n nextMessageInThread &&\n !nextMessageThreadRoot &&\n (nextMessageDifferentThread || nextMessageIsDateSeparator)\n\n if (!inReplyScreen && inThread) {\n message.prevIsMyReply = prevMessage?.mine\n message.nextIsMyReply = nextMessage?.mine\n\n const firstInThread = threadRoot\n const lastInThread = nextMessageDifferentThread || nextMessageIsDateSeparator\n\n if (firstInThread && lastInThread)\n message.threadPosition = null // ensures we don't render a connector for root replies that aren't immediately followed up a reply\n else if (firstInThread) message.threadPosition = 'first'\n else if (lastInThread) message.threadPosition = 'last'\n else message.threadPosition = 'center'\n }\n\n enrichedMessages.push(message)\n\n if (insertReplyShadowMessage && repliesEnabled) {\n enrichedMessages.push({\n type: 'ReplyShadowMessage',\n id: `${message.id}-${message.replyRootId}`,\n messageId: message.replyRootId!,\n isReplyShadowMessage: true,\n nextRendersAuthor: message?.renderAuthor,\n })\n }\n\n if (!prevMessage || date !== moment(prevMessage.createdAt).format('YYYY-MM-DD')) {\n enrichedMessages.push({ type: 'DateSeparator', id: `day-divider-${message.id}`, date })\n }\n })\n\n return enrichedMessages\n}\ninterface ConversationScreenTitleProps extends HeaderTitleProps {\n conversation_id: number\n badge?: ConversationBadgeResource\n deleted?: boolean\n}\n\nexport const ConversationScreenTitle = ({\n conversation_id,\n badge,\n children,\n style,\n deleted,\n}: ConversationScreenTitleProps) => {\n const styles = usePressableHeaderStyle()\n const navigation = useNavigation()\n const resourceType = badge?.pcoResourceType || ''\n const productName = badge?.appName\n const name = badge?.text || undefined\n\n return (\n <PlatformPressable\n accessibilityHint=\"Opens details about members and settings\"\n style={styles.container}\n onPress={() => {\n if (deleted) return\n\n navigation.navigate('ConversationDetails', { conversation_id })\n }}\n >\n <View style={styles.titleWrapper}>\n <HeaderTitle maxFontSizeMultiplier={1} style={style}>\n {children}\n </HeaderTitle>\n {!deleted && <Icon name=\"general.downChevron\" size={12} />}\n </View>\n <Badge\n variant=\"metaSubtle\"\n productLogoName={productName}\n label={resourceType}\n metaLabel={name}\n style={styles.badge}\n maxFontSizeMultiplier={1}\n />\n </PlatformPressable>\n )\n}\n\nconst usePressableHeaderStyle = () => {\n return StyleSheet.create({\n container: {\n alignItems: Platform.select({ android: 'flex-start', default: 'center' }),\n marginRight: Platform.select({ ios: 20, default: 16 }),\n },\n titleWrapper: {\n alignItems: 'center',\n columnGap: 4,\n flexDirection: 'row',\n flexShrink: 1,\n },\n badge: {\n alignSelf: Platform.select({ android: 'flex-start', default: 'center' }),\n marginTop: 2,\n },\n })\n}\n\nconst useStyles = () => {\n const navigationTheme = useNavigationTheme()\n const { bottom } = useSafeAreaInsets()\n\n return StyleSheet.create({\n container: {\n flex: 1,\n justifyContent: 'center',\n backgroundColor: navigationTheme.colors.card,\n paddingBottom: bottom,\n },\n listContainer: {\n paddingVertical: 12,\n },\n listHeader: {\n // Just whitespace to provide space where the typing indicator can be\n height: 16,\n },\n })\n}\n\n/**\n * useEnsureConversationsRouteExists\n */\nconst useEnsureConversationsRouteExists = () => {\n const navigation = useNavigation()\n const { params } = useRoute<RouteProp<ConversationScreenProps['route']>>()\n\n useEffect(() => {\n const navigationState = navigation.getState()\n const routes = navigationState?.routes || []\n const conversationsRoute = routes.find(r => r.name === 'Conversations')\n\n if (conversationsRoute) return\n\n navigation.dispatch(state => {\n return CommonActions.reset({\n ...state,\n routes: [\n { name: 'Conversations', params: { chat_group_graph_id: params?.chat_group_graph_id } },\n ...routes,\n ],\n index: state.index + 1,\n })\n })\n }, [navigation, params?.chat_group_graph_id])\n}\n"]}
1
+ {"version":3,"file":"conversation_screen.js","sourceRoot":"","sources":["../../src/screens/conversation_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import { date as formatDate } from '@planningcenter/datetime-fmt'\nimport { HeaderTitle, HeaderTitleProps, PlatformPressable } from '@react-navigation/elements'\nimport {\n CommonActions,\n RouteProp,\n StaticScreenProps,\n useNavigation,\n useTheme as useNavigationTheme,\n useRoute,\n} from '@react-navigation/native'\nimport moment from 'moment'\nimport React, { useCallback, useEffect, useRef, useState } from 'react'\nimport { FlatList, Platform, StyleSheet, View } from 'react-native'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\nimport { Badge, Icon, Text } from '../components'\nimport {\n LeaderMessagesDisabledBanner,\n MemberMessagesDisabledBanner,\n} from '../components/conversation/messages_disabled_banners'\nimport { EmptyConversationBlankState } from '../components/conversation/empty_conversation_blank_state'\nimport BlankState from '../components/primitive/blank_state_primitive'\nimport { Message } from '../components/conversation/message'\nimport { MessageForm } from '../components/conversation/message_form'\nimport { TypingIndicator } from '../components/conversation/typing_indicator'\nimport { KeyboardView } from '../components/display/keyboard_view'\nimport { useTheme } from '../hooks'\nimport { useConversation } from '../hooks/use_conversation'\nimport { useConversationMessages } from '../hooks/use_conversation_messages'\nimport { useConversationMessagesJoltEvents } from '../hooks/use_conversation_messages_jolt_events'\nimport { MessageResource } from '../types'\nimport { ConversationBadgeResource } from '../types/resources/conversation_badge'\nimport { getRelativeDateStatus } from '../utils/date'\nimport { useMarkLatestMessageRead } from '../hooks/use_mark_latest_message_read'\nimport { CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL } from '../utils/styles'\nimport { useConversationJoltEvents } from '../hooks/use_conversation_jolt_events'\nimport { JumpToBottomButton } from '../components/conversation/jump_to_bottom_button'\nimport { ReplyShadowMessage } from '../components/conversation/reply_shadow_message'\nimport { availableFeatures, useFeatures } from '../hooks/use_features'\nimport { ConversationContextProvider } from '../contexts/conversation_context'\n\nexport type ConversationRouteProps = {\n conversation_id: number\n reply_root_id?: string | null\n reply_root_author_name?: string\n chat_group_graph_id?: string\n clear_input?: boolean\n editing_message_id?: number | null\n title?: string\n subtitle?: string\n badge?: ConversationBadgeResource\n deleted?: boolean\n}\n\nexport type ConversationScreenProps = StaticScreenProps<ConversationRouteProps>\n\nexport function ConversationScreen({ route }: ConversationScreenProps) {\n const { conversation_id, reply_root_id } = route.params\n\n return (\n <ConversationContextProvider\n conversationId={conversation_id}\n currentPageReplyRootId={reply_root_id ?? null}\n >\n <ConversationScreenContent route={route} />\n </ConversationContextProvider>\n )\n}\n\nfunction ConversationScreenContent({ route }: ConversationScreenProps) {\n const styles = useStyles()\n const navigation = useNavigation()\n const { conversation_id, editing_message_id, reply_root_id, reply_root_author_name } =\n route.params\n const { data: conversation } = useConversation(route.params)\n const { messages, refetch, isRefetching, fetchNextPage } = useConversationMessages({\n conversation_id,\n reply_root_id,\n })\n useConversationJoltEvents({ conversationId: conversation_id })\n useConversationMessagesJoltEvents({ conversationId: conversation_id })\n useEnsureConversationsRouteExists()\n useMarkLatestMessageRead({ conversation, messages })\n const { featureEnabled } = useFeatures()\n const repliesEnabled = featureEnabled(availableFeatures.threaded_replies)\n const messagesWithSeparators = groupMessages({\n ms: messages,\n inReplyScreen: !!reply_root_id,\n repliesEnabled,\n })\n const noMessages = messagesWithSeparators.length === 0\n\n const { repliesDisabled, memberAbility, badges, title } = conversation\n const canReply = memberAbility?.canReply\n const showLeaderDisabledReplyBanner = canReply && repliesDisabled\n const canDeleteNonAuthoredMessages = memberAbility?.canDeleteNonAuthoredMessages ?? false\n const currentlyEditingMessage = messages.find(m => String(m.id) === String(editing_message_id))\n const replyRootAuthorFirstName = reply_root_author_name?.split(' ')[0]\n const replyHeaderTitle = replyRootAuthorFirstName\n ? `Reply to ${replyRootAuthorFirstName}`\n : 'Reply'\n\n const listRef = useRef<FlatList>(null)\n const [showJumpToBottomButton, setShowJumpToBottomButton] = useState(false)\n\n const trackScroll = (event: any) => {\n const offsetY = event.nativeEvent.contentOffset.y\n setShowJumpToBottomButton(offsetY > 200)\n }\n\n const handleReturnToBottom = useCallback(() => {\n listRef.current?.scrollToOffset({\n offset: 0,\n })\n }, [])\n\n useEffect(() => {\n if (reply_root_id) {\n navigation.setParams({\n title: replyHeaderTitle,\n })\n } else {\n navigation.setParams({\n title: title,\n badge: badges?.[0],\n deleted: conversation?.deleted,\n })\n }\n }, [navigation, title, badges, conversation?.deleted, reply_root_id, replyHeaderTitle])\n\n if (!conversation || conversation.deleted) {\n return (\n <View style={styles.container}>\n <BlankState.Root>\n <BlankState.Imagery name=\"general.outlinedTextMessage\" />\n <BlankState.Content>\n <BlankState.Heading>This conversation has been deleted</BlankState.Heading>\n </BlankState.Content>\n <BlankState.Button\n onPress={navigation.goBack}\n title=\"Back to conversations\"\n accessibilityHint=\"Navigates back to the conversations list\"\n accessibilityRole=\"link\"\n />\n </BlankState.Root>\n </View>\n )\n }\n\n return (\n <View style={styles.container}>\n <KeyboardView>\n {noMessages ? (\n <EmptyConversationBlankState />\n ) : (\n <FlatList\n inverted\n ref={listRef}\n contentContainerStyle={styles.listContainer}\n refreshing={isRefetching}\n onRefresh={refetch}\n data={messagesWithSeparators}\n keyExtractor={item => item.id}\n onScroll={trackScroll}\n scrollEventThrottle={10}\n renderItem={({ item }) => {\n if (item.type === 'DateSeparator') {\n return <InlineDateSeparator {...item} />\n }\n\n if (item.type === 'ReplyShadowMessage') {\n return (\n <ReplyShadowMessage\n {...item}\n conversation_id={conversation_id}\n inReplyScreen={!!reply_root_id}\n />\n )\n }\n\n return (\n <Message\n {...item}\n canDeleteNonAuthoredMessages={canDeleteNonAuthoredMessages}\n conversation_id={conversation_id}\n latestReadMessageSortKey={conversation?.latestReadMessageSortKey}\n inReplyScreen={!!reply_root_id}\n repliesEnabled={repliesEnabled}\n />\n )\n }}\n onEndReached={() => fetchNextPage()}\n ListHeaderComponent={<View style={styles.listHeader} />}\n />\n )}\n <JumpToBottomButton onPress={handleReturnToBottom} visible={showJumpToBottomButton} />\n {!noMessages && <TypingIndicator />}\n {showLeaderDisabledReplyBanner && <LeaderMessagesDisabledBanner />}\n {canReply ? (\n <MessageForm.Root\n replyRootAuthorFirstName={replyRootAuthorFirstName}\n conversation={conversation}\n replyRootId={reply_root_id}\n currentlyEditingMessage={currentlyEditingMessage}\n // We use a separate key so that it remounts component when switching between new\n // and edit message. This simplifies internal state handling.\n key={\n currentlyEditingMessage\n ? `edit-message-form-${currentlyEditingMessage.id}`\n : 'new-message-form'\n }\n >\n <MessageForm.AttachmentPicker />\n <MessageForm.Commands />\n <MessageForm.TextInput />\n <MessageForm.SubmitButton />\n </MessageForm.Root>\n ) : (\n <MemberMessagesDisabledBanner />\n )}\n </KeyboardView>\n </View>\n )\n}\n\nexport type DateSeparator = { type: 'DateSeparator'; id: string; date: string }\n\nfunction InlineDateSeparator({ date }: DateSeparator) {\n const styles = useDateSeparatorStyles()\n const { isThisYear } = getRelativeDateStatus(date)\n const showYear = !isThisYear\n const dateStamp = formatDate(date, { style: 'long', year: showYear })\n\n return (\n <View style={styles.container}>\n <View style={styles.separator} />\n <Text variant=\"footnote\" style={styles.dateText}>\n {dateStamp}\n </Text>\n <View style={styles.separator} />\n </View>\n )\n}\n\nconst useDateSeparatorStyles = () => {\n const theme = useTheme()\n return StyleSheet.create({\n container: {\n alignItems: 'center',\n flexDirection: 'row',\n paddingHorizontal: CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL,\n paddingVertical: 16,\n },\n separator: {\n flex: 1,\n height: 1,\n borderTopWidth: 1,\n borderTopColor: theme.colors.borderColorDefaultBase,\n },\n dateText: {\n paddingHorizontal: 8,\n },\n })\n}\n\ntype ReplyShadowMessage = {\n type: 'ReplyShadowMessage'\n id: string\n messageId: string\n isReplyShadowMessage: boolean\n nextRendersAuthor: boolean\n}\n\ninterface GroupMessagesProps {\n ms: MessageResource[]\n inReplyScreen?: boolean\n repliesEnabled?: boolean\n}\n\nexport const groupMessages = ({\n ms,\n inReplyScreen,\n repliesEnabled = false,\n}: GroupMessagesProps) => {\n let enrichedMessages: (MessageResource | DateSeparator | ReplyShadowMessage)[] = []\n let encounteredOneOfMyMessages = false\n\n ms.forEach((message, i) => {\n const prevMessage = ms[i + 1]\n const nextMessage = ms[i - 1]\n const date = moment(message.createdAt).format('YYYY-MM-DD')\n const inThread = message.replyRootId !== null\n const nextMessageInThread = nextMessage?.replyRootId !== null\n const threadRoot = message.replyRootId === message.id\n const nextMessageThreadRoot = nextMessage?.replyRootId === nextMessage?.id\n const prevMessageDifferentThread = message.replyRootId !== prevMessage?.replyRootId\n const nextMessageDifferentThread = message.replyRootId !== nextMessage?.replyRootId\n const prevMessageDifferentAuthor = message.author?.id !== prevMessage?.author?.id\n const nextMessageDifferentAuthor = message.author?.id !== nextMessage?.author?.id\n const prevMessageMoreThan5Minutes =\n prevMessage &&\n new Date(message.createdAt).getTime() - new Date(prevMessage.createdAt).getTime() > 60000 * 5\n const nextMessageMoreThan5Minutes =\n nextMessage &&\n new Date(nextMessage.createdAt).getTime() - new Date(message.createdAt).getTime() > 60000 * 5\n const prevMessageIsDateSeparator =\n prevMessage && date !== moment(prevMessage.createdAt).format('YYYY-MM-DD')\n const nextMessageIsDateSeparator =\n nextMessage && date !== moment(nextMessage.createdAt).format('YYYY-MM-DD')\n const insertReplyShadowMessage =\n message.replyRootId &&\n !threadRoot &&\n (prevMessageDifferentThread || prevMessageIsDateSeparator)\n const lastInGroup =\n !nextMessage ||\n nextMessageDifferentAuthor ||\n nextMessageMoreThan5Minutes ||\n nextMessageDifferentThread ||\n nextMessageIsDateSeparator\n const renderAuthor =\n !message.mine &&\n (!prevMessage ||\n prevMessageDifferentAuthor ||\n prevMessageMoreThan5Minutes ||\n prevMessageDifferentThread ||\n prevMessageIsDateSeparator)\n const nextIsReplyShadowMessage =\n repliesEnabled &&\n nextMessageInThread &&\n !nextMessageThreadRoot &&\n (nextMessageDifferentThread || nextMessageIsDateSeparator)\n\n if (message.mine && !encounteredOneOfMyMessages) {\n encounteredOneOfMyMessages = true\n message.myLatestInConversation = true\n } else {\n message.myLatestInConversation = false\n }\n message.lastInGroup = lastInGroup\n message.renderAuthor = renderAuthor\n message.threadPosition = null\n message.nextRendersAuthor = nextMessage?.renderAuthor\n message.isReplyShadowMessage = false\n message.nextIsReplyShadowMessage = nextIsReplyShadowMessage\n\n if (!inReplyScreen && inThread) {\n message.prevIsMyReply = prevMessage?.mine\n message.nextIsMyReply = nextMessage?.mine\n\n const firstInThread = threadRoot\n const lastInThread = nextMessageDifferentThread || nextMessageIsDateSeparator\n\n if (firstInThread && lastInThread)\n message.threadPosition = null // ensures we don't render a connector for root replies that aren't immediately followed up a reply\n else if (firstInThread) message.threadPosition = 'first'\n else if (lastInThread) message.threadPosition = 'last'\n else message.threadPosition = 'center'\n }\n\n enrichedMessages.push(message)\n\n if (insertReplyShadowMessage && repliesEnabled) {\n enrichedMessages.push({\n type: 'ReplyShadowMessage',\n id: `${message.id}-${message.replyRootId}`,\n messageId: message.replyRootId!,\n isReplyShadowMessage: true,\n nextRendersAuthor: message?.renderAuthor,\n })\n }\n\n if (!prevMessage || date !== moment(prevMessage.createdAt).format('YYYY-MM-DD')) {\n enrichedMessages.push({ type: 'DateSeparator', id: `day-divider-${message.id}`, date })\n }\n })\n\n return enrichedMessages\n}\ninterface ConversationScreenTitleProps extends HeaderTitleProps {\n conversation_id: number\n badge?: ConversationBadgeResource\n deleted?: boolean\n}\n\nexport const ConversationScreenTitle = ({\n conversation_id,\n badge,\n children,\n style,\n deleted,\n}: ConversationScreenTitleProps) => {\n const styles = usePressableHeaderStyle()\n const navigation = useNavigation()\n const resourceType = badge?.pcoResourceType || ''\n const productName = badge?.appName\n const name = badge?.text || undefined\n\n return (\n <PlatformPressable\n accessibilityHint=\"Opens details about members and settings\"\n style={styles.container}\n onPress={() => {\n if (deleted) return\n\n navigation.navigate('ConversationDetails', { conversation_id })\n }}\n >\n <View style={styles.titleWrapper}>\n <HeaderTitle maxFontSizeMultiplier={1} style={style}>\n {children}\n </HeaderTitle>\n {!deleted && <Icon name=\"general.downChevron\" size={12} />}\n </View>\n <Badge\n variant=\"metaSubtle\"\n productLogoName={productName}\n label={resourceType}\n metaLabel={name}\n style={styles.badge}\n maxFontSizeMultiplier={1}\n />\n </PlatformPressable>\n )\n}\n\nconst usePressableHeaderStyle = () => {\n return StyleSheet.create({\n container: {\n alignItems: Platform.select({ android: 'flex-start', default: 'center' }),\n marginRight: Platform.select({ ios: 20, default: 16 }),\n },\n titleWrapper: {\n alignItems: 'center',\n columnGap: 4,\n flexDirection: 'row',\n flexShrink: 1,\n },\n badge: {\n alignSelf: Platform.select({ android: 'flex-start', default: 'center' }),\n marginTop: 2,\n },\n })\n}\n\nconst useStyles = () => {\n const navigationTheme = useNavigationTheme()\n const { bottom } = useSafeAreaInsets()\n\n return StyleSheet.create({\n container: {\n flex: 1,\n justifyContent: 'center',\n backgroundColor: navigationTheme.colors.card,\n paddingBottom: bottom,\n },\n listContainer: {\n paddingVertical: 12,\n },\n listHeader: {\n // Just whitespace to provide space where the typing indicator can be\n height: 16,\n },\n })\n}\n\n/**\n * useEnsureConversationsRouteExists\n */\nconst useEnsureConversationsRouteExists = () => {\n const navigation = useNavigation()\n const { params } = useRoute<RouteProp<ConversationScreenProps['route']>>()\n\n useEffect(() => {\n const navigationState = navigation.getState()\n const routes = navigationState?.routes || []\n const conversationsRoute = routes.find(r => r.name === 'Conversations')\n\n if (conversationsRoute) return\n\n navigation.dispatch(state => {\n return CommonActions.reset({\n ...state,\n routes: [\n { name: 'Conversations', params: { chat_group_graph_id: params?.chat_group_graph_id } },\n ...routes,\n ],\n index: state.index + 1,\n })\n })\n }, [navigation, params?.chat_group_graph_id])\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planningcenter/chat-react-native",
3
- "version": "3.18.0-rc.9",
3
+ "version": "3.19.0-rc.0",
4
4
  "description": "",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -58,5 +58,5 @@
58
58
  "react-native-url-polyfill": "^2.0.0",
59
59
  "typescript": "<5.6.0"
60
60
  },
61
- "gitHead": "1c8ef808381f80f84eba2890e1bbfc706574c69d"
61
+ "gitHead": "10d9ed3969a9eb030da07befcc84ec698e425b73"
62
62
  }
@@ -1,6 +1,12 @@
1
1
  import { useNavigation } from '@react-navigation/native'
2
2
  import React, { useEffect } from 'react'
3
- import { Pressable, StyleSheet, useWindowDimensions, View } from 'react-native'
3
+ import {
4
+ AccessibilityActionEvent,
5
+ Pressable,
6
+ StyleSheet,
7
+ useWindowDimensions,
8
+ View,
9
+ } from 'react-native'
4
10
  import { MessageReaction } from '../../components/conversation/message_reaction'
5
11
  import { Avatar, Icon, Spinner, Text, TextButton, TextInlineButton } from '../../components/display'
6
12
  import {
@@ -27,6 +33,7 @@ import { Haptic } from '../../utils/native_adapters'
27
33
  import { TheirReplyConnector, MyReplyConnector, AVATAR_CONNECTOR_SPACING } from './reply_connectors'
28
34
  import { pluralize } from '../../utils'
29
35
  import { useConversationMessage } from '../../hooks/use_conversation_message'
36
+ import { some } from 'lodash'
30
37
  import { isNewMessage } from '../../utils/cache/messages_cache'
31
38
 
32
39
  /** Message
@@ -48,7 +55,7 @@ export function Message({
48
55
  repliesEnabled,
49
56
  ...message
50
57
  }: MessageProps) {
51
- const { text, reactionCounts, pending, error } = message
58
+ const { text, reactionCounts, pending, error, attachments, author } = message
52
59
  const styles = useMessageStyles(message)
53
60
  const navigation = useNavigation()
54
61
  const { colors } = useTheme()
@@ -70,7 +77,7 @@ export function Message({
70
77
  })
71
78
 
72
79
  const metaProps = {
73
- authorName: message.author.name,
80
+ authorName: author.name,
74
81
  createdAt: message.createdAt,
75
82
  }
76
83
 
@@ -79,12 +86,12 @@ export function Message({
79
86
  !inReplyScreen && message.replyRootId === message.id && repliesEnabled
80
87
  const isReplyRootMessage = message.replyRootId === message.id
81
88
  const isDeletedReplyRootMessage = isReplyRootMessage && !!message.deletedAt
89
+ const replyToReplyRootMessage = repliesEnabled && !isReplyRootMessage && !!message.replyRootId
82
90
 
83
91
  const replyCountText = pluralize(message.replyCount, 'reply')
84
92
  const messagePendingLabel = isPersisted ? 'Saving' : 'Sending'
85
- const replyRootAuthorName = message.replyRootId
86
- ? replyRootMessage?.author.name
87
- : message.author.name
93
+ const replyRootAuthorName = message.replyRootId ? replyRootMessage?.author.name : author.name
94
+ const messageText = isDeletedReplyRootMessage ? 'Message deleted' : text
88
95
 
89
96
  const messageBottomMargin =
90
97
  message.lastInGroup || message.nextIsReplyShadowMessage
@@ -93,6 +100,11 @@ export function Message({
93
100
  ? 8
94
101
  : 4
95
102
 
103
+ const messageIsReplyLabel = replyToReplyRootMessage ? 'Reply' : ''
104
+ const attachmentLabel = some(attachments) ? pluralize(attachments.length, 'attachment') : ''
105
+ const replyCountLabel = isReplyRootMessage ? replyCountText : ''
106
+ const accessibilityLabel = `${author?.name || ''} ${messageIsReplyLabel} ${attachmentLabel} ${messageText || ''} ${timestamp} ${replyCountLabel}`
107
+
96
108
  useEffect(() => {
97
109
  if (pending) {
98
110
  const timer = setTimeout(() => {
@@ -159,10 +171,23 @@ export function Message({
159
171
  navigation.navigate('ConversationReply', {
160
172
  conversation_id,
161
173
  reply_root_id: message.id,
162
- reply_root_author_name: message.author.name,
174
+ reply_root_author_name: author.name,
163
175
  })
164
176
  }
165
177
 
178
+ const accessibilityActions = [
179
+ {
180
+ name: 'navigateToReplies',
181
+ label: 'Navigate to replies',
182
+ },
183
+ ]
184
+
185
+ const handleAccessibilityAction = (event: AccessibilityActionEvent) => {
186
+ if (event.nativeEvent.actionName === 'navigateToReplies') {
187
+ handleNavigateToReplyPress()
188
+ }
189
+ }
190
+
166
191
  return (
167
192
  <Pressable
168
193
  onLongPress={handleMessageLongPress}
@@ -170,7 +195,11 @@ export function Message({
170
195
  onPressIn={handleMessagePressIn}
171
196
  onPressOut={handleMessagePressOut}
172
197
  android_ripple={{ color: colors.androidRippleNeutral, borderless: false, foreground: true }}
198
+ accessibilityRole="button"
199
+ accessibilityLabel={accessibilityLabel}
173
200
  accessibilityHint="Long press to view message actions like reacting and copying."
201
+ accessibilityActions={isReplyRootMessage ? accessibilityActions : undefined}
202
+ onAccessibilityAction={isReplyRootMessage ? handleAccessibilityAction : undefined}
174
203
  disabled={isDeletedReplyRootMessage}
175
204
  >
176
205
  <Animated.View style={[styles.message, animatedBackgroundColor]}>
@@ -179,7 +208,7 @@ export function Message({
179
208
  {renderAuthor ? (
180
209
  <Avatar
181
210
  size={'md'}
182
- sourceUri={message.author.avatar}
211
+ sourceUri={author.avatar}
183
212
  style={styles.avatar}
184
213
  maxFontSizeMultiplier={1}
185
214
  minFontSizeMultiplier={1}
@@ -197,7 +226,7 @@ export function Message({
197
226
  <View style={[styles.messageContent, { marginBottom: messageBottomMargin }]}>
198
227
  {renderAuthor && !isDeletedReplyRootMessage && (
199
228
  <Text variant="footnote" style={styles.authorName}>
200
- {message.author.name}
229
+ {author.name}
201
230
  </Text>
202
231
  )}
203
232
  <View
@@ -206,13 +235,13 @@ export function Message({
206
235
  >
207
236
  {isDeletedReplyRootMessage ? (
208
237
  <View style={styles.messageText}>
209
- <Text style={styles.replyRootDeletedText}>Message deleted</Text>
238
+ <Text style={styles.replyRootDeletedText}>{messageText}</Text>
210
239
  </View>
211
240
  ) : (
212
241
  <>
213
242
  <ErrorBoundary>
214
243
  <MessageAttachments
215
- attachments={message.attachments}
244
+ attachments={attachments}
216
245
  metaProps={metaProps}
217
246
  onMessageAttachmentLongPress={handleMessageAttachmentLongPress}
218
247
  onMessageLongPress={handleMessageLongPress}
@@ -98,7 +98,7 @@ function MessageFormRoot({
98
98
  const { giphyApiKey } = useContext(ChatContext)
99
99
  const canGiphy = !!giphyApiKey && !currentlyEditingMessage
100
100
  const styles = useMessageFormStyles()
101
- const { draft, saveDraft, clearDraft } = useMessageDraft(conversation.id)
101
+ const { draft, saveDraft, clearDraft } = useMessageDraft()
102
102
  const [text, setText] = React.useState(() => {
103
103
  // Initialize from draft only when not editing a message
104
104
  return currentlyEditingMessage ? '' : draft?.text || ''