@planningcenter/chat-react-native 3.37.0 → 3.37.1-qa-736.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 (59) hide show
  1. package/build/components/conversation/message_form.d.ts.map +1 -1
  2. package/build/components/conversation/message_form.js +19 -7
  3. package/build/components/conversation/message_form.js.map +1 -1
  4. package/build/components/conversation/message_list.d.ts +10 -0
  5. package/build/components/conversation/message_list.d.ts.map +1 -0
  6. package/build/components/conversation/message_list.js +13 -0
  7. package/build/components/conversation/message_list.js.map +1 -0
  8. package/build/components/conversations/conversations.d.ts.map +1 -1
  9. package/build/components/conversations/conversations.js +6 -16
  10. package/build/components/conversations/conversations.js.map +1 -1
  11. package/build/components/conversations/conversations_blank_state.d.ts +8 -0
  12. package/build/components/conversations/conversations_blank_state.d.ts.map +1 -0
  13. package/build/components/conversations/conversations_blank_state.js +25 -0
  14. package/build/components/conversations/conversations_blank_state.js.map +1 -0
  15. package/build/hooks/use_attachment_uploader.d.ts.map +1 -1
  16. package/build/hooks/use_attachment_uploader.js +9 -0
  17. package/build/hooks/use_attachment_uploader.js.map +1 -1
  18. package/build/hooks/use_features.d.ts +1 -0
  19. package/build/hooks/use_features.d.ts.map +1 -1
  20. package/build/hooks/use_features.js +1 -0
  21. package/build/hooks/use_features.js.map +1 -1
  22. package/build/hooks/use_upload_client.d.ts +4 -0
  23. package/build/hooks/use_upload_client.d.ts.map +1 -1
  24. package/build/hooks/use_upload_client.js +13 -1
  25. package/build/hooks/use_upload_client.js.map +1 -1
  26. package/build/jest.js +1 -1
  27. package/build/jest.js.map +1 -1
  28. package/build/screens/age_check/age_check_underage_screen.js +1 -1
  29. package/build/screens/age_check/age_check_underage_screen.js.map +1 -1
  30. package/build/screens/avatar_picker/emoji_tab.d.ts.map +1 -1
  31. package/build/screens/avatar_picker/emoji_tab.js +2 -6
  32. package/build/screens/avatar_picker/emoji_tab.js.map +1 -1
  33. package/build/screens/conversation_screen.d.ts.map +1 -1
  34. package/build/screens/conversation_screen.js +3 -7
  35. package/build/screens/conversation_screen.js.map +1 -1
  36. package/build/types/jolt_events/attachment_events.d.ts +14 -0
  37. package/build/types/jolt_events/attachment_events.d.ts.map +1 -0
  38. package/build/types/jolt_events/attachment_events.js +2 -0
  39. package/build/types/jolt_events/attachment_events.js.map +1 -0
  40. package/build/types/jolt_events/index.d.ts +3 -1
  41. package/build/types/jolt_events/index.d.ts.map +1 -1
  42. package/build/types/jolt_events/index.js.map +1 -1
  43. package/package.json +4 -4
  44. package/src/__tests__/hooks/use_attachment_uploader.test.tsx +36 -0
  45. package/src/__tests__/jest.ts +1 -1
  46. package/src/components/conversation/__tests__/message_list.test.tsx +14 -0
  47. package/src/components/conversation/message_form.tsx +21 -7
  48. package/src/components/conversation/message_list.tsx +42 -0
  49. package/src/components/conversations/conversations.tsx +9 -16
  50. package/src/components/conversations/conversations_blank_state.tsx +42 -0
  51. package/src/hooks/use_attachment_uploader.ts +14 -1
  52. package/src/hooks/use_features.ts +1 -0
  53. package/src/hooks/use_upload_client.ts +19 -1
  54. package/src/jest.ts +1 -1
  55. package/src/screens/age_check/age_check_underage_screen.tsx +1 -1
  56. package/src/screens/avatar_picker/emoji_tab.tsx +2 -6
  57. package/src/screens/conversation_screen.tsx +5 -14
  58. package/src/types/jolt_events/attachment_events.ts +14 -0
  59. package/src/types/jolt_events/index.ts +3 -0
@@ -1 +1 @@
1
- {"version":3,"file":"use_attachment_uploader.js","sourceRoot":"","sources":["../../src/hooks/use_attachment_uploader.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { ApiResource } from '../types'\nimport {\n FileAttachment,\n FileUploadState,\n NativeAttachmentFile,\n} from '../types/resources/denormalized_attachment_resource_for_create'\nimport { useApiClient } from './use_api_client'\nimport { useChatConfiguration } from './use_chat_configuration'\nimport { useUploadClient } from './use_upload_client'\n\nexport interface FileError {\n file_type?: string[]\n file_size?: boolean\n}\n\nexport function useAttachmentUploader({\n conversationId,\n draftAttachments,\n}: {\n conversationId: number\n draftAttachments?: FileAttachment[]\n}) {\n const apiClient = useApiClient()\n const uploadApi = useUploadClient()\n const { allowedFileExtensions, maxFileSizeInBytes, maxAttachmentsPerMessage } =\n useChatConfiguration()\n const maxFileSizeInMb = Number((maxFileSizeInBytes / (1024 * 1024)).toFixed(1))\n const [attachments, setAttachments] = useState<FileAttachment[]>(() => draftAttachments || [])\n const uploadState = useRef<FileUploadState>({})\n const [lastUploadId, setLastUploadId] = useState<string>()\n const numberOfAttachments = attachments.length\n const [errorMessage, setErrorMessage] = useState<string | null>(null)\n\n const handleFilesAttached = useCallback(\n (files: NativeAttachmentFile[]) => {\n const fileErrors = {} as FileError\n\n const validFiles = files.filter(file => {\n const extension = file.name.toLowerCase().split('.').pop() as string\n const isValidExtension = allowedFileExtensions.includes(`.${extension}`)\n const isValidFileSize = file.size <= maxFileSizeInBytes\n\n if (!isValidExtension) {\n fileErrors.file_type ||= []\n fileErrors.file_type.push(extension)\n }\n if (!isValidFileSize) {\n fileErrors.file_size = true\n }\n\n return isValidFileSize && isValidExtension\n })\n\n const errorMessages: string[] = []\n if (fileErrors.file_type) {\n errorMessages.push(\n `The following file types are not supported: ${fileErrors.file_type.join(', ')}`\n )\n }\n if (fileErrors.file_size) {\n errorMessages.push(`File size exceeds ${maxFileSizeInMb} MB`)\n }\n if (numberOfAttachments + validFiles.length > maxAttachmentsPerMessage) {\n errorMessages.push(`You can't attach more than ${maxAttachmentsPerMessage} files at once.`)\n }\n if (errorMessages.length > 0) {\n setErrorMessage(errorMessages.join('\\n'))\n return\n }\n\n const newAttachments: FileAttachment[] = validFiles.map(file => ({\n file,\n status: 'uploading',\n uploadedAt: Date.now(),\n }))\n\n if (newAttachments && newAttachments.length > 0) {\n setAttachments(prevAttachments => [...prevAttachments, ...newAttachments])\n\n newAttachments.forEach(attachment => {\n uploadApi\n .uploadFile(attachment.file)\n .then(({ id: uploadedFileId }) =>\n apiClient.chat.post<ApiResource<MessageAttachmentResource>>({\n url: `/me/conversations/${conversationId}/message_attachments`,\n data: {\n data: {\n type: 'MessageAttachment',\n attributes: { uploaded_file_id: uploadedFileId },\n },\n },\n })\n )\n .then(({ data: { id: messageAttachmentId } }) => {\n uploadState.current[attachment.file.name] = {\n status: 'success',\n id: messageAttachmentId,\n }\n setLastUploadId(messageAttachmentId)\n })\n .catch(async err => {\n const isFlagged = err?.code === 'image_flagged'\n uploadState.current[attachment.file.name] = {\n status: 'error',\n flagged: isFlagged,\n }\n if (!isFlagged) {\n // Dev builds surface the raw server detail to shorten the\n // feedback loop on backend errors (e.g. AWS SSO re-auth).\n // Production users always see the generic message.\n const serverDetail = __DEV__ ? await extractDevOnlyServerErrorDetail(err) : null\n setErrorMessage(serverDetail ?? 'This file could not be uploaded.')\n }\n setLastUploadId(attachment.file.name)\n })\n })\n }\n },\n [\n numberOfAttachments,\n uploadApi,\n apiClient.chat,\n conversationId,\n allowedFileExtensions,\n maxFileSizeInBytes,\n maxFileSizeInMb,\n maxAttachmentsPerMessage,\n ]\n )\n\n useEffect(() => {\n if (!lastUploadId) return\n\n setLastUploadId(undefined)\n setAttachments(\n attachments.map(attachment => {\n // Don't risk overwriting ids already set\n if (attachment.id) return attachment\n\n const state = uploadState.current[attachment.file.name]\n if (state) {\n return { ...attachment, id: state.id, status: state.status, flagged: state.flagged }\n }\n return attachment\n })\n )\n }, [attachments, lastUploadId])\n\n const removeAttachment = useCallback((attachment: FileAttachment) => {\n setAttachments(prevAttachments =>\n prevAttachments.filter(a => a.file.uri !== attachment.file.uri)\n )\n }, [])\n\n const removeFlaggedAttachments = useCallback(() => {\n setAttachments(prevAttachments => prevAttachments.filter(a => !a.flagged))\n }, [])\n\n const reset = useCallback(() => {\n setAttachments([])\n setErrorMessage(null)\n }, [])\n\n const pendingUploads = attachments.filter(a => a.status === 'uploading').length > 0\n const flaggedAttachmentCount = attachments.filter(a => a.flagged).length\n\n const attachmentIds = useMemo(\n () => attachments.filter(a => a.status === 'success' && a.id).map(a => a.id as string),\n [attachments]\n )\n\n return {\n attachments,\n attachmentIds,\n handleFilesAttached,\n removeAttachment,\n removeFlaggedAttachments,\n reset,\n pendingUploads,\n errorMessage,\n flaggedAttachmentCount,\n remainingAttachable: Math.max(0, maxAttachmentsPerMessage - numberOfAttachments),\n }\n}\n\nasync function extractDevOnlyServerErrorDetail(err: unknown): Promise<string | null> {\n const response = err as Response | null\n if (!response?.clone) return null\n try {\n const body = await response.clone().json()\n const detail = body?.errors?.[0]?.detail ?? body?.detail\n return typeof detail === 'string' ? detail : null\n } catch {\n return null\n }\n}\n\ninterface MessageAttachmentResource {\n type: 'MessageAttachment'\n id: string\n uploadedFileId: string\n filename: string\n messageSortKey: string\n metadata: Record<string, unknown>\n checksum: string\n contentType: string\n byteSize: number\n}\n"]}
1
+ {"version":3,"file":"use_attachment_uploader.js","sourceRoot":"","sources":["../../src/hooks/use_attachment_uploader.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { ApiResource, CurrentPersonResource } from '../types'\nimport { AttachmentFlaggedEvent } from '../types/jolt_events/attachment_events'\nimport {\n FileAttachment,\n FileUploadState,\n NativeAttachmentFile,\n} from '../types/resources/denormalized_attachment_resource_for_create'\nimport { useApiGet } from './use_api'\nimport { useApiClient } from './use_api_client'\nimport { useChatConfiguration } from './use_chat_configuration'\nimport { currentPersonRequestArgs } from './use_current_person'\nimport { useJoltChannel, useJoltEvent } from './use_jolt'\nimport { useUploadClient } from './use_upload_client'\n\nexport interface FileError {\n file_type?: string[]\n file_size?: boolean\n}\n\nexport function useAttachmentUploader({\n conversationId,\n draftAttachments,\n}: {\n conversationId: number\n draftAttachments?: FileAttachment[]\n}) {\n const apiClient = useApiClient()\n const uploadApi = useUploadClient()\n const { allowedFileExtensions, maxFileSizeInBytes, maxAttachmentsPerMessage } =\n useChatConfiguration()\n const maxFileSizeInMb = Number((maxFileSizeInBytes / (1024 * 1024)).toFixed(1))\n const [attachments, setAttachments] = useState<FileAttachment[]>(() => draftAttachments || [])\n const uploadState = useRef<FileUploadState>({})\n const [lastUploadId, setLastUploadId] = useState<string>()\n const numberOfAttachments = attachments.length\n const [errorMessage, setErrorMessage] = useState<string | null>(null)\n\n const { data: currentPerson } = useApiGet<CurrentPersonResource>(currentPersonRequestArgs)\n const joltChannel = useJoltChannel(`chat.people.${currentPerson?.id}`, Boolean(currentPerson?.id))\n useJoltEvent(joltChannel, 'attachment.flagged', (e: AttachmentFlaggedEvent) => {\n const flaggedId = e.data.data.attachment_id\n setAttachments(prev =>\n prev.map(a => (a.id === flaggedId ? { ...a, flagged: true, status: 'error' } : a))\n )\n })\n\n const handleFilesAttached = useCallback(\n (files: NativeAttachmentFile[]) => {\n const fileErrors = {} as FileError\n\n const validFiles = files.filter(file => {\n const extension = file.name.toLowerCase().split('.').pop() as string\n const isValidExtension = allowedFileExtensions.includes(`.${extension}`)\n const isValidFileSize = file.size <= maxFileSizeInBytes\n\n if (!isValidExtension) {\n fileErrors.file_type ||= []\n fileErrors.file_type.push(extension)\n }\n if (!isValidFileSize) {\n fileErrors.file_size = true\n }\n\n return isValidFileSize && isValidExtension\n })\n\n const errorMessages: string[] = []\n if (fileErrors.file_type) {\n errorMessages.push(\n `The following file types are not supported: ${fileErrors.file_type.join(', ')}`\n )\n }\n if (fileErrors.file_size) {\n errorMessages.push(`File size exceeds ${maxFileSizeInMb} MB`)\n }\n if (numberOfAttachments + validFiles.length > maxAttachmentsPerMessage) {\n errorMessages.push(`You can't attach more than ${maxAttachmentsPerMessage} files at once.`)\n }\n if (errorMessages.length > 0) {\n setErrorMessage(errorMessages.join('\\n'))\n return\n }\n\n const newAttachments: FileAttachment[] = validFiles.map(file => ({\n file,\n status: 'uploading',\n uploadedAt: Date.now(),\n }))\n\n if (newAttachments && newAttachments.length > 0) {\n setAttachments(prevAttachments => [...prevAttachments, ...newAttachments])\n\n newAttachments.forEach(attachment => {\n uploadApi\n .uploadFile(attachment.file)\n .then(({ id: uploadedFileId }) =>\n apiClient.chat.post<ApiResource<MessageAttachmentResource>>({\n url: `/me/conversations/${conversationId}/message_attachments`,\n data: {\n data: {\n type: 'MessageAttachment',\n attributes: { uploaded_file_id: uploadedFileId },\n },\n },\n })\n )\n .then(({ data: { id: messageAttachmentId } }) => {\n uploadState.current[attachment.file.name] = {\n status: 'success',\n id: messageAttachmentId,\n }\n setLastUploadId(messageAttachmentId)\n })\n .catch(async err => {\n const isFlagged = err?.code === 'image_flagged'\n uploadState.current[attachment.file.name] = {\n status: 'error',\n flagged: isFlagged,\n }\n if (!isFlagged) {\n // Dev builds surface the raw server detail to shorten the\n // feedback loop on backend errors (e.g. AWS SSO re-auth).\n // Production users always see the generic message.\n const serverDetail = __DEV__ ? await extractDevOnlyServerErrorDetail(err) : null\n setErrorMessage(serverDetail ?? 'This file could not be uploaded.')\n }\n setLastUploadId(attachment.file.name)\n })\n })\n }\n },\n [\n numberOfAttachments,\n uploadApi,\n apiClient.chat,\n conversationId,\n allowedFileExtensions,\n maxFileSizeInBytes,\n maxFileSizeInMb,\n maxAttachmentsPerMessage,\n ]\n )\n\n useEffect(() => {\n if (!lastUploadId) return\n\n setLastUploadId(undefined)\n setAttachments(\n attachments.map(attachment => {\n // Don't risk overwriting ids already set\n if (attachment.id) return attachment\n\n const state = uploadState.current[attachment.file.name]\n if (state) {\n return { ...attachment, id: state.id, status: state.status, flagged: state.flagged }\n }\n return attachment\n })\n )\n }, [attachments, lastUploadId])\n\n const removeAttachment = useCallback((attachment: FileAttachment) => {\n setAttachments(prevAttachments =>\n prevAttachments.filter(a => a.file.uri !== attachment.file.uri)\n )\n }, [])\n\n const removeFlaggedAttachments = useCallback(() => {\n setAttachments(prevAttachments => prevAttachments.filter(a => !a.flagged))\n }, [])\n\n const reset = useCallback(() => {\n setAttachments([])\n setErrorMessage(null)\n }, [])\n\n const pendingUploads = attachments.filter(a => a.status === 'uploading').length > 0\n const flaggedAttachmentCount = attachments.filter(a => a.flagged).length\n\n const attachmentIds = useMemo(\n () => attachments.filter(a => a.status === 'success' && a.id).map(a => a.id as string),\n [attachments]\n )\n\n return {\n attachments,\n attachmentIds,\n handleFilesAttached,\n removeAttachment,\n removeFlaggedAttachments,\n reset,\n pendingUploads,\n errorMessage,\n flaggedAttachmentCount,\n remainingAttachable: Math.max(0, maxAttachmentsPerMessage - numberOfAttachments),\n }\n}\n\nasync function extractDevOnlyServerErrorDetail(err: unknown): Promise<string | null> {\n const response = err as Response | null\n if (!response?.clone) return null\n try {\n const body = await response.clone().json()\n const detail = body?.errors?.[0]?.detail ?? body?.detail\n return typeof detail === 'string' ? detail : null\n } catch {\n return null\n }\n}\n\ninterface MessageAttachmentResource {\n type: 'MessageAttachment'\n id: string\n uploadedFileId: string\n filename: string\n messageSortKey: string\n metadata: Record<string, unknown>\n checksum: string\n contentType: string\n byteSize: number\n}\n"]}
@@ -11,6 +11,7 @@ export declare const availableFeatures: {
11
11
  readonly custom_conversation_avatars: "ROLLOUT_custom_conversation_avatars";
12
12
  readonly jump_to_unread: "ROLLOUT_jump_to_unread";
13
13
  readonly conversation_safety_lock: "ROLLOUT_conversation_safety_lock";
14
+ readonly video_moderation: "ROLLOUT_MOBILE_video_moderation";
14
15
  };
15
16
  export {};
16
17
  //# sourceMappingURL=use_features.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use_features.d.ts","sourceRoot":"","sources":["../../src/hooks/use_features.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAA;AAI1E,KAAK,WAAW,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAA;AAE7E,wBAAgB,WAAW;;kCAiBT,WAAW;EAS5B;AAED,eAAO,MAAM,iBAAiB;;;;;;;CAO0B,CAAA"}
1
+ {"version":3,"file":"use_features.d.ts","sourceRoot":"","sources":["../../src/hooks/use_features.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAA;AAI1E,KAAK,WAAW,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAA;AAE7E,wBAAgB,WAAW;;kCAiBT,WAAW;EAS5B;AAED,eAAO,MAAM,iBAAiB;;;;;;;;CAQ0B,CAAA"}
@@ -28,6 +28,7 @@ export const availableFeatures = {
28
28
  custom_conversation_avatars: 'ROLLOUT_custom_conversation_avatars',
29
29
  jump_to_unread: 'ROLLOUT_jump_to_unread',
30
30
  conversation_safety_lock: 'ROLLOUT_conversation_safety_lock',
31
+ video_moderation: 'ROLLOUT_MOBILE_video_moderation',
31
32
  };
32
33
  const stableEmptyFeatures = {
33
34
  data: [],
@@ -1 +1 @@
1
- {"version":3,"file":"use_features.js","sourceRoot":"","sources":["../../src/hooks/use_features.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAGnC,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAA;AAC3F,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAI/C,MAAM,UAAU,WAAW;IACzB,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;IAChC,MAAM,WAAW,GAAG,sBAAsB,EAAE,CAAA;IAE5C,MAAM,EAAE,IAAI,EAAE,GAAG,gBAAgB,CAAC;QAChC,QAAQ,EAAE,mBAAmB,EAAE;QAC/B,OAAO,EAAE,GAAG,EAAE;YACZ,OAAO,SAAS,CAAC,IAAI;iBAClB,GAAG,CAAiC,WAAW,CAAC;iBAChD,KAAK,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,CAAA;QACrC,CAAC;QACD,SAAS,EAAE,IAAI,GAAG,EAAE,GAAG,CAAC,EAAE,YAAY;KACvC,CAAC,CAAA;IAEF,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAA;IAE1B,MAAM,cAAc,GAAG,WAAW,CAChC,CAAC,WAAwB,EAAE,EAAE,CAC3B,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,EAC3E,CAAC,QAAQ,CAAC,CACX,CAAA;IAED,OAAO;QACL,QAAQ;QACR,cAAc;KACf,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,6BAA6B,EAAE,uCAAuC;IACtE,iBAAiB,EAAE,kCAAkC;IACrD,yBAAyB,EAAE,8CAA8C;IACzE,2BAA2B,EAAE,qCAAqC;IAClE,cAAc,EAAE,wBAAwB;IACxC,wBAAwB,EAAE,kCAAkC;CACN,CAAA;AAExD,MAAM,mBAAmB,GAAmC;IAC1D,IAAI,EAAE,EAAE;IACR,KAAK,EAAE,EAAE;IACT,IAAI,EAAE;QACJ,KAAK,EAAE,CAAC;QACR,UAAU,EAAE,CAAC;KACd;CACF,CAAA","sourcesContent":["import { useSuspenseQuery } from '@tanstack/react-query'\nimport { useCallback } from 'react'\nimport { ApiCollection } from '../types'\nimport type { FeatureResource } from '../types/resources/feature_resource'\nimport { getFeaturesRequestArgs, getFeaturesQueryKey } from '../utils/request/get_features'\nimport { useApiClient } from './use_api_client'\n\ntype FeatureName = (typeof availableFeatures)[keyof typeof availableFeatures]\n\nexport function useFeatures() {\n const apiClient = useApiClient()\n const requestArgs = getFeaturesRequestArgs()\n\n const { data } = useSuspenseQuery({\n queryKey: getFeaturesQueryKey(),\n queryFn: () => {\n return apiClient.chat\n .get<ApiCollection<FeatureResource>>(requestArgs)\n .catch(() => stableEmptyFeatures)\n },\n staleTime: 1000 * 60 * 5, // 5 minutes\n })\n\n const features = data.data\n\n const featureEnabled = useCallback(\n (featureName: FeatureName) =>\n features.some(feature => feature.name === featureName && feature.enabled),\n [features]\n )\n\n return {\n features,\n featureEnabled,\n }\n}\n\nexport const availableFeatures = {\n gender_specific_conversations: 'ROLLOUT_gender_specific_conversations',\n message_reporting: 'ROLLOUT_MOBILE_message_reporting',\n granular_notifications_ui: 'ROLLOUT_granular_notification_preferences_ui',\n custom_conversation_avatars: 'ROLLOUT_custom_conversation_avatars',\n jump_to_unread: 'ROLLOUT_jump_to_unread',\n conversation_safety_lock: 'ROLLOUT_conversation_safety_lock',\n} as const satisfies Record<string, `ROLLOUT_${string}`>\n\nconst stableEmptyFeatures: ApiCollection<FeatureResource> = {\n data: [],\n links: {},\n meta: {\n count: 0,\n totalCount: 0,\n },\n}\n"]}
1
+ {"version":3,"file":"use_features.js","sourceRoot":"","sources":["../../src/hooks/use_features.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAGnC,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAA;AAC3F,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAI/C,MAAM,UAAU,WAAW;IACzB,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;IAChC,MAAM,WAAW,GAAG,sBAAsB,EAAE,CAAA;IAE5C,MAAM,EAAE,IAAI,EAAE,GAAG,gBAAgB,CAAC;QAChC,QAAQ,EAAE,mBAAmB,EAAE;QAC/B,OAAO,EAAE,GAAG,EAAE;YACZ,OAAO,SAAS,CAAC,IAAI;iBAClB,GAAG,CAAiC,WAAW,CAAC;iBAChD,KAAK,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,CAAA;QACrC,CAAC;QACD,SAAS,EAAE,IAAI,GAAG,EAAE,GAAG,CAAC,EAAE,YAAY;KACvC,CAAC,CAAA;IAEF,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAA;IAE1B,MAAM,cAAc,GAAG,WAAW,CAChC,CAAC,WAAwB,EAAE,EAAE,CAC3B,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,EAC3E,CAAC,QAAQ,CAAC,CACX,CAAA;IAED,OAAO;QACL,QAAQ;QACR,cAAc;KACf,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,6BAA6B,EAAE,uCAAuC;IACtE,iBAAiB,EAAE,kCAAkC;IACrD,yBAAyB,EAAE,8CAA8C;IACzE,2BAA2B,EAAE,qCAAqC;IAClE,cAAc,EAAE,wBAAwB;IACxC,wBAAwB,EAAE,kCAAkC;IAC5D,gBAAgB,EAAE,iCAAiC;CACG,CAAA;AAExD,MAAM,mBAAmB,GAAmC;IAC1D,IAAI,EAAE,EAAE;IACR,KAAK,EAAE,EAAE;IACT,IAAI,EAAE;QACJ,KAAK,EAAE,CAAC;QACR,UAAU,EAAE,CAAC;KACd;CACF,CAAA","sourcesContent":["import { useSuspenseQuery } from '@tanstack/react-query'\nimport { useCallback } from 'react'\nimport { ApiCollection } from '../types'\nimport type { FeatureResource } from '../types/resources/feature_resource'\nimport { getFeaturesRequestArgs, getFeaturesQueryKey } from '../utils/request/get_features'\nimport { useApiClient } from './use_api_client'\n\ntype FeatureName = (typeof availableFeatures)[keyof typeof availableFeatures]\n\nexport function useFeatures() {\n const apiClient = useApiClient()\n const requestArgs = getFeaturesRequestArgs()\n\n const { data } = useSuspenseQuery({\n queryKey: getFeaturesQueryKey(),\n queryFn: () => {\n return apiClient.chat\n .get<ApiCollection<FeatureResource>>(requestArgs)\n .catch(() => stableEmptyFeatures)\n },\n staleTime: 1000 * 60 * 5, // 5 minutes\n })\n\n const features = data.data\n\n const featureEnabled = useCallback(\n (featureName: FeatureName) =>\n features.some(feature => feature.name === featureName && feature.enabled),\n [features]\n )\n\n return {\n features,\n featureEnabled,\n }\n}\n\nexport const availableFeatures = {\n gender_specific_conversations: 'ROLLOUT_gender_specific_conversations',\n message_reporting: 'ROLLOUT_MOBILE_message_reporting',\n granular_notifications_ui: 'ROLLOUT_granular_notification_preferences_ui',\n custom_conversation_avatars: 'ROLLOUT_custom_conversation_avatars',\n jump_to_unread: 'ROLLOUT_jump_to_unread',\n conversation_safety_lock: 'ROLLOUT_conversation_safety_lock',\n video_moderation: 'ROLLOUT_MOBILE_video_moderation',\n} as const satisfies Record<string, `ROLLOUT_${string}`>\n\nconst stableEmptyFeatures: ApiCollection<FeatureResource> = {\n data: [],\n links: {},\n meta: {\n count: 0,\n totalCount: 0,\n },\n}\n"]}
@@ -6,6 +6,10 @@ export interface FileForUploadClient {
6
6
  }
7
7
  export declare const useUploadClient: () => UploadClient;
8
8
  declare class UploadClient extends Client {
9
+ private videoModerationEnabled;
10
+ constructor({ videoModerationEnabled, ...rest }: ConstructorParameters<typeof Client>[0] & {
11
+ videoModerationEnabled: boolean;
12
+ });
9
13
  uploadFile(file: FileForUploadClient): Promise<UploadedResource>;
10
14
  }
11
15
  interface UploadedResource {
@@ -1 +1 @@
1
- {"version":3,"file":"use_upload_client.d.ts","sourceRoot":"","sources":["../../src/hooks/use_upload_client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAGjC,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,eAAO,MAAM,eAAe,oBAiB3B,CAAA;AAED,cAAM,YAAa,SAAQ,MAAM;IACzB,UAAU,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAiCvE;AAED,UAAU,gBAAgB;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE;QACV,eAAe,EAAE,MAAM,CAAA;QACvB,SAAS,EAAE,MAAM,CAAA;QACjB,GAAG,EAAE,MAAM,CAAA;QACX,UAAU,EAAE,MAAM,CAAA;QAClB,UAAU,EAAE,MAAM,CAAA;QAClB,SAAS,EAAE,MAAM,CAAA;QACjB,IAAI,EAAE,MAAM,CAAA;QACZ,YAAY,EAAE,MAAM,CAAA;QACpB,SAAS,EAAE,MAAM,CAAA;QACjB,QAAQ,EAAE,MAAM,CAAA;KACjB,CAAA;CACF"}
1
+ {"version":3,"file":"use_upload_client.d.ts","sourceRoot":"","sources":["../../src/hooks/use_upload_client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAIjC,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,eAAO,MAAM,eAAe,oBAoB3B,CAAA;AAED,cAAM,YAAa,SAAQ,MAAM;IAC/B,OAAO,CAAC,sBAAsB,CAAS;gBAE3B,EACV,sBAAsB,EACtB,GAAG,IAAI,EACR,EAAE,qBAAqB,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG;QAAE,sBAAsB,EAAE,OAAO,CAAA;KAAE;IAK1E,UAAU,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAqCvE;AAED,UAAU,gBAAgB;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE;QACV,eAAe,EAAE,MAAM,CAAA;QACvB,SAAS,EAAE,MAAM,CAAA;QACjB,GAAG,EAAE,MAAM,CAAA;QACX,UAAU,EAAE,MAAM,CAAA;QAClB,UAAU,EAAE,MAAM,CAAA;QAClB,SAAS,EAAE,MAAM,CAAA;QACjB,IAAI,EAAE,MAAM,CAAA;QACZ,YAAY,EAAE,MAAM,CAAA;QACpB,SAAS,EAAE,MAAM,CAAA;QACjB,QAAQ,EAAE,MAAM,CAAA;KACjB,CAAA;CACF"}
@@ -2,18 +2,27 @@ import { useContext, useMemo } from 'react';
2
2
  import { ChatContext } from '../contexts/chat_context';
3
3
  import { Client } from '../utils';
4
4
  import { UploadUri } from '../utils/upload_uri';
5
+ import { availableFeatures, useFeatures } from './use_features';
5
6
  export const useUploadClient = () => {
6
7
  const { session, onUnauthorizedResponse } = useContext(ChatContext);
8
+ const { featureEnabled } = useFeatures();
9
+ const videoModerationEnabled = featureEnabled(availableFeatures.video_moderation);
7
10
  const uri = useMemo(() => new UploadUri({ session }), [session]);
8
11
  const api = useMemo(() => new UploadClient({
9
12
  version: '2025-05-16', // not really needed, but required by the Client constructor
10
13
  root: uri.baseUrl,
11
14
  defaultHeaders: uri.headers,
12
15
  onUnauthorizedResponse,
13
- }), [uri, onUnauthorizedResponse]);
16
+ videoModerationEnabled,
17
+ }), [uri, onUnauthorizedResponse, videoModerationEnabled]);
14
18
  return api;
15
19
  };
16
20
  class UploadClient extends Client {
21
+ videoModerationEnabled;
22
+ constructor({ videoModerationEnabled, ...rest }) {
23
+ super(rest);
24
+ this.videoModerationEnabled = videoModerationEnabled;
25
+ }
17
26
  async uploadFile(file) {
18
27
  const formData = new FormData();
19
28
  formData.append('file', {
@@ -23,6 +32,9 @@ class UploadClient extends Client {
23
32
  });
24
33
  const headers = { ...this.headers };
25
34
  delete headers['Content-Type'];
35
+ if (this.videoModerationEnabled && file.type.startsWith('video/')) {
36
+ headers['X-PCO-Moderate-Video'] = 'true';
37
+ }
26
38
  const response = await fetch(`${this.root}/v2/files`, {
27
39
  method: 'POST',
28
40
  headers,
@@ -1 +1 @@
1
- {"version":3,"file":"use_upload_client.js","sourceRoot":"","sources":["../../src/hooks/use_upload_client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAQ/C,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,EAAE;IAClC,MAAM,EAAE,OAAO,EAAE,sBAAsB,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,CAAA;IAEnE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAA;IAEhE,MAAM,GAAG,GAAG,OAAO,CACjB,GAAG,EAAE,CACH,IAAI,YAAY,CAAC;QACf,OAAO,EAAE,YAAY,EAAE,4DAA4D;QACnF,IAAI,EAAE,GAAG,CAAC,OAAO;QACjB,cAAc,EAAE,GAAG,CAAC,OAAO;QAC3B,sBAAsB;KACvB,CAAC,EACJ,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAC9B,CAAA;IAED,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA;AAED,MAAM,YAAa,SAAQ,MAAM;IAC/B,KAAK,CAAC,UAAU,CAAC,IAAyB;QACxC,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAA;QAC/B,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE;YACtB,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC,CAAA;QAEF,MAAM,OAAO,GAA2B,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAA;QAC3D,OAAO,OAAO,CAAC,cAAc,CAAC,CAAA;QAE9B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,WAAW,EAAE;YACpD,MAAM,EAAE,MAAM;YACd,OAAO;YACP,IAAI,EAAE,QAAQ;SACf,CAAC,CAAA;QAEF,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;YACzD,IAAI,SAAS,EAAE,MAAM,KAAK,mBAAmB,EAAE,CAAC;gBAC9C,OAAO,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CAAA;YAClD,CAAC;YACD,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAA;QACnC,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAA;QACnC,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;QAE1C,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAC7B,CAAC;CACF","sourcesContent":["import { useContext, useMemo } from 'react'\nimport { ChatContext } from '../contexts/chat_context'\nimport { Client } from '../utils'\nimport { UploadUri } from '../utils/upload_uri'\n\nexport interface FileForUploadClient {\n uri: string\n name: string\n type: string // Should be a MIME type\n}\n\nexport const useUploadClient = () => {\n const { session, onUnauthorizedResponse } = useContext(ChatContext)\n\n const uri = useMemo(() => new UploadUri({ session }), [session])\n\n const api = useMemo(\n () =>\n new UploadClient({\n version: '2025-05-16', // not really needed, but required by the Client constructor\n root: uri.baseUrl,\n defaultHeaders: uri.headers,\n onUnauthorizedResponse,\n }),\n [uri, onUnauthorizedResponse]\n )\n\n return api\n}\n\nclass UploadClient extends Client {\n async uploadFile(file: FileForUploadClient): Promise<UploadedResource> {\n const formData = new FormData()\n formData.append('file', {\n uri: file.uri,\n name: file.name,\n type: file.type,\n })\n\n const headers: RequestInit['headers'] = { ...this.headers }\n delete headers['Content-Type']\n\n const response = await fetch(`${this.root}/v2/files`, {\n method: 'POST',\n headers,\n body: formData,\n })\n\n if (response.status === 403) {\n const errorBody = await response.json().catch(() => null)\n if (errorBody?.detail === 'Image was flagged') {\n return Promise.reject({ code: 'image_flagged' })\n }\n return this.handleNotOk(response)\n }\n\n if (!response.ok) {\n return this.handleNotOk(response)\n }\n\n const jsonResponse = await response.json()\n\n return jsonResponse.data[0]\n }\n}\n\ninterface UploadedResource {\n id: string\n type: string\n attributes: {\n organization_id: string\n person_id: string\n md5: string\n created_at: string\n expires_at: string\n source_ip: string\n name: string\n content_type: string\n file_size: number\n location: string\n }\n}\n"]}
1
+ {"version":3,"file":"use_upload_client.js","sourceRoot":"","sources":["../../src/hooks/use_upload_client.ts"],"names":[],"mappings":"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","sourcesContent":["import { useContext, useMemo } from 'react'\nimport { ChatContext } from '../contexts/chat_context'\nimport { Client } from '../utils'\nimport { UploadUri } from '../utils/upload_uri'\nimport { availableFeatures, useFeatures } from './use_features'\n\nexport interface FileForUploadClient {\n uri: string\n name: string\n type: string // Should be a MIME type\n}\n\nexport const useUploadClient = () => {\n const { session, onUnauthorizedResponse } = useContext(ChatContext)\n const { featureEnabled } = useFeatures()\n const videoModerationEnabled = featureEnabled(availableFeatures.video_moderation)\n\n const uri = useMemo(() => new UploadUri({ session }), [session])\n\n const api = useMemo(\n () =>\n new UploadClient({\n version: '2025-05-16', // not really needed, but required by the Client constructor\n root: uri.baseUrl,\n defaultHeaders: uri.headers,\n onUnauthorizedResponse,\n videoModerationEnabled,\n }),\n [uri, onUnauthorizedResponse, videoModerationEnabled]\n )\n\n return api\n}\n\nclass UploadClient extends Client {\n private videoModerationEnabled: boolean\n\n constructor({\n videoModerationEnabled,\n ...rest\n }: ConstructorParameters<typeof Client>[0] & { videoModerationEnabled: boolean }) {\n super(rest)\n this.videoModerationEnabled = videoModerationEnabled\n }\n\n async uploadFile(file: FileForUploadClient): Promise<UploadedResource> {\n const formData = new FormData()\n formData.append('file', {\n uri: file.uri,\n name: file.name,\n type: file.type,\n })\n\n const headers: RequestInit['headers'] = { ...this.headers }\n delete headers['Content-Type']\n\n if (this.videoModerationEnabled && file.type.startsWith('video/')) {\n headers['X-PCO-Moderate-Video'] = 'true'\n }\n\n const response = await fetch(`${this.root}/v2/files`, {\n method: 'POST',\n headers,\n body: formData,\n })\n\n if (response.status === 403) {\n const errorBody = await response.json().catch(() => null)\n if (errorBody?.detail === 'Image was flagged') {\n return Promise.reject({ code: 'image_flagged' })\n }\n return this.handleNotOk(response)\n }\n\n if (!response.ok) {\n return this.handleNotOk(response)\n }\n\n const jsonResponse = await response.json()\n\n return jsonResponse.data[0]\n }\n}\n\ninterface UploadedResource {\n id: string\n type: string\n attributes: {\n organization_id: string\n person_id: string\n md5: string\n created_at: string\n expires_at: string\n source_ip: string\n name: string\n content_type: string\n file_size: number\n location: string\n }\n}\n"]}
package/build/jest.js CHANGED
@@ -16,7 +16,7 @@
16
16
  */
17
17
  export const jestTransformPackages = [
18
18
  '@planningcenter/chat-react-native',
19
+ '@planningcenter/emoji-keyboard',
19
20
  '@fortawesome',
20
- 'rn-emoji-keyboard',
21
21
  ];
22
22
  //# sourceMappingURL=jest.js.map
package/build/jest.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"jest.js","sourceRoot":"","sources":["../src/jest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,mCAAmC;IACnC,cAAc;IACd,mBAAmB;CACpB,CAAA","sourcesContent":["/**\n * Jest configuration helpers for consuming apps.\n *\n * Usage in jest.config.js:\n *\n * const { jestTransformPackages } = require('@planningcenter/chat-react-native/jest')\n *\n * const ignorePatterns = [\n * ...yourPatterns,\n * ...jestTransformPackages,\n * ].join('|')\n *\n * module.exports = {\n * transformIgnorePatterns: [`node_modules/(?!${ignorePatterns})`],\n * }\n */\nexport const jestTransformPackages = [\n '@planningcenter/chat-react-native',\n '@fortawesome',\n 'rn-emoji-keyboard',\n]\n"]}
1
+ {"version":3,"file":"jest.js","sourceRoot":"","sources":["../src/jest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,mCAAmC;IACnC,gCAAgC;IAChC,cAAc;CACf,CAAA","sourcesContent":["/**\n * Jest configuration helpers for consuming apps.\n *\n * Usage in jest.config.js:\n *\n * const { jestTransformPackages } = require('@planningcenter/chat-react-native/jest')\n *\n * const ignorePatterns = [\n * ...yourPatterns,\n * ...jestTransformPackages,\n * ].join('|')\n *\n * module.exports = {\n * transformIgnorePatterns: [`node_modules/(?!${ignorePatterns})`],\n * }\n */\nexport const jestTransformPackages = [\n '@planningcenter/chat-react-native',\n '@planningcenter/emoji-keyboard',\n '@fortawesome',\n]\n"]}
@@ -21,7 +21,7 @@ export function AgeCheckUnderageScreen({ contactEmail } = {}) {
21
21
 
22
22
  <View style={styles.content}>
23
23
  <Heading variant="h3" style={styles.baseText}>
24
- Your age does not meet the minimum safety requirements to use chat.
24
+ Chat is only available for users 13 and older.
25
25
  </Heading>
26
26
  <Text variant="tertiary" style={styles.baseText}>
27
27
  If you submitted the wrong birthdate by accident,{` `}
@@ -1 +1 @@
1
- {"version":3,"file":"age_check_underage_screen.js","sourceRoot":"","sources":["../../../src/screens/age_check/age_check_underage_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useRoute, RouteProp } from '@react-navigation/native'\nimport React from 'react'\nimport { Linking, StyleSheet, View, ScrollView } from 'react-native'\nimport { Heading } from '../../components'\nimport { Icon, Text, TextInlineButton } from '../../components/display'\nimport { useTheme } from '../../hooks'\nimport type { AgeCheckParams } from './screen_props'\n\nexport interface AgeCheckUnderageScreenProps {\n contactEmail?: string\n}\n\nexport function AgeCheckUnderageScreen({ contactEmail }: AgeCheckUnderageScreenProps = {}) {\n const styles = useStyles()\n const route = useRoute<RouteProp<AgeCheckParams, 'UnderagePerson'>>()\n\n const email = contactEmail ?? route?.params?.contactEmail\n\n const openChurchAdminHelp = () => {\n if (!email) return\n Linking.openURL(`mailto:${email}`)\n }\n\n const openTerms = () => {\n Linking.openURL('https://www.planningcenter.com/terms')\n }\n\n return (\n <ScrollView style={styles.scrollView} contentContainerStyle={styles.container}>\n <Icon name=\"general.outlinedTextMessage\" size={32} style={styles.icon} />\n\n <View style={styles.content}>\n <Heading variant=\"h3\" style={styles.baseText}>\n Your age does not meet the minimum safety requirements to use chat.\n </Heading>\n <Text variant=\"tertiary\" style={styles.baseText}>\n If you submitted the wrong birthdate by accident,{` `}\n {email ? (\n <TextInlineButton\n onPress={openChurchAdminHelp}\n accessibilityRole=\"link\"\n accessibilityHint=\"Opens email client to contact your church administrator\"\n style={styles.linkText}\n >\n please contact your church administrator\n </TextInlineButton>\n ) : (\n <>please contact your church administrator</>\n )}\n {` `}\n to update your profile.\n </Text>\n <Text variant=\"tertiary\" style={styles.baseText}>\n For more information, view our{` `}\n <TextInlineButton\n onPress={openTerms}\n accessibilityRole=\"link\"\n accessibilityHint=\"Opens terms of service in browser\"\n style={styles.linkText}\n >\n terms of service\n </TextInlineButton>\n .\n </Text>\n </View>\n </ScrollView>\n )\n}\n\nconst useStyles = () => {\n const { colors } = useTheme()\n return StyleSheet.create({\n scrollView: {\n flex: 1,\n },\n container: {\n alignItems: 'center',\n justifyContent: 'center',\n gap: 16,\n padding: 16,\n minHeight: '100%',\n },\n icon: {\n color: colors.iconColorDefaultDisabled,\n },\n content: {\n alignItems: 'center',\n gap: 8,\n maxWidth: 250,\n },\n baseText: {\n textAlign: 'center',\n color: colors.textColorDefaultSecondary,\n },\n linkText: {\n fontSize: 14,\n },\n })\n}\n"]}
1
+ {"version":3,"file":"age_check_underage_screen.js","sourceRoot":"","sources":["../../../src/screens/age_check/age_check_underage_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useRoute, RouteProp } from '@react-navigation/native'\nimport React from 'react'\nimport { Linking, StyleSheet, View, ScrollView } from 'react-native'\nimport { Heading } from '../../components'\nimport { Icon, Text, TextInlineButton } from '../../components/display'\nimport { useTheme } from '../../hooks'\nimport type { AgeCheckParams } from './screen_props'\n\nexport interface AgeCheckUnderageScreenProps {\n contactEmail?: string\n}\n\nexport function AgeCheckUnderageScreen({ contactEmail }: AgeCheckUnderageScreenProps = {}) {\n const styles = useStyles()\n const route = useRoute<RouteProp<AgeCheckParams, 'UnderagePerson'>>()\n\n const email = contactEmail ?? route?.params?.contactEmail\n\n const openChurchAdminHelp = () => {\n if (!email) return\n Linking.openURL(`mailto:${email}`)\n }\n\n const openTerms = () => {\n Linking.openURL('https://www.planningcenter.com/terms')\n }\n\n return (\n <ScrollView style={styles.scrollView} contentContainerStyle={styles.container}>\n <Icon name=\"general.outlinedTextMessage\" size={32} style={styles.icon} />\n\n <View style={styles.content}>\n <Heading variant=\"h3\" style={styles.baseText}>\n Chat is only available for users 13 and older.\n </Heading>\n <Text variant=\"tertiary\" style={styles.baseText}>\n If you submitted the wrong birthdate by accident,{` `}\n {email ? (\n <TextInlineButton\n onPress={openChurchAdminHelp}\n accessibilityRole=\"link\"\n accessibilityHint=\"Opens email client to contact your church administrator\"\n style={styles.linkText}\n >\n please contact your church administrator\n </TextInlineButton>\n ) : (\n <>please contact your church administrator</>\n )}\n {` `}\n to update your profile.\n </Text>\n <Text variant=\"tertiary\" style={styles.baseText}>\n For more information, view our{` `}\n <TextInlineButton\n onPress={openTerms}\n accessibilityRole=\"link\"\n accessibilityHint=\"Opens terms of service in browser\"\n style={styles.linkText}\n >\n terms of service\n </TextInlineButton>\n .\n </Text>\n </View>\n </ScrollView>\n )\n}\n\nconst useStyles = () => {\n const { colors } = useTheme()\n return StyleSheet.create({\n scrollView: {\n flex: 1,\n },\n container: {\n alignItems: 'center',\n justifyContent: 'center',\n gap: 16,\n padding: 16,\n minHeight: '100%',\n },\n icon: {\n color: colors.iconColorDefaultDisabled,\n },\n content: {\n alignItems: 'center',\n gap: 8,\n maxWidth: 250,\n },\n baseText: {\n textAlign: 'center',\n color: colors.textColorDefaultSecondary,\n },\n linkText: {\n fontSize: 14,\n },\n })\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"emoji_tab.d.ts","sourceRoot":"","sources":["../../../src/screens/avatar_picker/emoji_tab.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsB,MAAM,OAAO,CAAA;AAgB1C,UAAU,aAAa;IACrB,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACvC;AAED,wBAAgB,QAAQ,CAAC,EAAE,aAAa,EAAE,EAAE,aAAa,qBAwDxD"}
1
+ {"version":3,"file":"emoji_tab.d.ts","sourceRoot":"","sources":["../../../src/screens/avatar_picker/emoji_tab.tsx"],"names":[],"mappings":"AACA,OAAO,KAAsB,MAAM,OAAO,CAAA;AAW1C,UAAU,aAAa;IACrB,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACvC;AAED,wBAAgB,QAAQ,CAAC,EAAE,aAAa,EAAE,EAAE,aAAa,qBAwDxD"}
@@ -1,13 +1,9 @@
1
+ import { EmojiKeyboard, emojisByCategory } from '@planningcenter/emoji-keyboard';
1
2
  import React, { useCallback } from 'react';
2
3
  import { StyleSheet, View } from 'react-native';
3
- import { EmojiKeyboard } from 'rn-emoji-keyboard';
4
- // rn-emoji-keyboard exposes no public exclusion API, so we reach into its
5
- // internal src/ tree for the emoji JSON. Version is pinned in package.json
6
- // — verify this path still resolves before bumping rn-emoji-keyboard.
7
- import emojiData from 'rn-emoji-keyboard/src/assets/emojis.json';
8
4
  import { useTheme } from '../../hooks';
9
5
  const BLOCKED_EMOJIS = new Set(['🖕']);
10
- const filteredEmojis = emojiData.map(category => ({
6
+ const filteredEmojis = emojisByCategory.map(category => ({
11
7
  ...category,
12
8
  data: category.data.filter(e => !BLOCKED_EMOJIS.has(e.emoji)),
13
9
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"emoji_tab.js","sourceRoot":"","sources":["../../../src/screens/avatar_picker/emoji_tab.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useCallback } from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { EmojiKeyboard, type EmojiType, type EmojisByCategory } from 'rn-emoji-keyboard'\n// rn-emoji-keyboard exposes no public exclusion API, so we reach into its\n// internal src/ tree for the emoji JSON. Version is pinned in package.json\n// — verify this path still resolves before bumping rn-emoji-keyboard.\nimport emojiData from 'rn-emoji-keyboard/src/assets/emojis.json'\nimport { useTheme } from '../../hooks'\n\nconst BLOCKED_EMOJIS = new Set(['🖕'])\n\nconst filteredEmojis = (emojiData as EmojisByCategory[]).map(category => ({\n ...category,\n data: category.data.filter(e => !BLOCKED_EMOJIS.has(e.emoji)),\n}))\n\ninterface EmojiTabProps {\n onEmojiSelect: (emoji: string) => void\n}\n\nexport function EmojiTab({ onEmojiSelect }: EmojiTabProps) {\n const styles = useStyles()\n const { colors } = useTheme()\n\n const handleEmojiSelected = useCallback(\n (emojiObject: EmojiType) => {\n onEmojiSelect(emojiObject.emoji)\n },\n [onEmojiSelect]\n )\n\n const emojiTheme = {\n container: colors.fillColorNeutral100Inverted,\n header: colors.textColorDefaultSecondary,\n knob: colors.fillColorNeutral040,\n skinTonesContainer: colors.fillColorNeutral060,\n category: {\n icon: colors.textColorDefaultSecondary,\n iconActive: colors.interaction,\n container: colors.fillColorNeutral100Inverted,\n containerActive: colors.fillColorNeutral080,\n },\n search: {\n background: colors.fillColorNeutral080,\n text: colors.textColorDefaultPrimary,\n placeholder: colors.textColorDefaultSecondary,\n icon: colors.textColorDefaultSecondary,\n },\n emoji: {\n selected: colors.fillColorNeutral080,\n },\n }\n\n return (\n <View style={styles.container}>\n <EmojiKeyboard\n categoryPosition=\"top\"\n emojisByCategory={filteredEmojis}\n onEmojiSelected={handleEmojiSelected}\n enableSearchBar\n enableRecentlyUsed\n theme={emojiTheme}\n styles={{\n container: { borderRadius: 0 },\n category: {\n container: {\n borderRadius: 0,\n marginTop: -6,\n borderBottomWidth: 1,\n borderBottomColor: colors.borderColorDefaultDim,\n },\n },\n }}\n />\n </View>\n )\n}\n\nconst useStyles = () => {\n const { colors } = useTheme()\n\n return StyleSheet.create({\n container: {\n flex: 1,\n backgroundColor: colors.fillColorNeutral100Inverted,\n },\n })\n}\n"]}
1
+ {"version":3,"file":"emoji_tab.js","sourceRoot":"","sources":["../../../src/screens/avatar_picker/emoji_tab.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAkB,MAAM,gCAAgC,CAAA;AAChG,OAAO,KAAK,EAAE,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAEtC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;AAEtC,MAAM,cAAc,GAAG,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACvD,GAAG,QAAQ;IACX,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;CAC9D,CAAC,CAAC,CAAA;AAMH,MAAM,UAAU,QAAQ,CAAC,EAAE,aAAa,EAAiB;IACvD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;IAE7B,MAAM,mBAAmB,GAAG,WAAW,CACrC,CAAC,WAAsB,EAAE,EAAE;QACzB,aAAa,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;IAClC,CAAC,EACD,CAAC,aAAa,CAAC,CAChB,CAAA;IAED,MAAM,UAAU,GAAG;QACjB,SAAS,EAAE,MAAM,CAAC,2BAA2B;QAC7C,MAAM,EAAE,MAAM,CAAC,yBAAyB;QACxC,IAAI,EAAE,MAAM,CAAC,mBAAmB;QAChC,kBAAkB,EAAE,MAAM,CAAC,mBAAmB;QAC9C,QAAQ,EAAE;YACR,IAAI,EAAE,MAAM,CAAC,yBAAyB;YACtC,UAAU,EAAE,MAAM,CAAC,WAAW;YAC9B,SAAS,EAAE,MAAM,CAAC,2BAA2B;YAC7C,eAAe,EAAE,MAAM,CAAC,mBAAmB;SAC5C;QACD,MAAM,EAAE;YACN,UAAU,EAAE,MAAM,CAAC,mBAAmB;YACtC,IAAI,EAAE,MAAM,CAAC,uBAAuB;YACpC,WAAW,EAAE,MAAM,CAAC,yBAAyB;YAC7C,IAAI,EAAE,MAAM,CAAC,yBAAyB;SACvC;QACD,KAAK,EAAE;YACL,QAAQ,EAAE,MAAM,CAAC,mBAAmB;SACrC;KACF,CAAA;IAED,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAC5B;MAAA,CAAC,aAAa,CACZ,gBAAgB,CAAC,KAAK,CACtB,gBAAgB,CAAC,CAAC,cAAc,CAAC,CACjC,eAAe,CAAC,CAAC,mBAAmB,CAAC,CACrC,eAAe,CACf,kBAAkB,CAClB,KAAK,CAAC,CAAC,UAAU,CAAC,CAClB,MAAM,CAAC,CAAC;YACN,SAAS,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE;YAC9B,QAAQ,EAAE;gBACR,SAAS,EAAE;oBACT,YAAY,EAAE,CAAC;oBACf,SAAS,EAAE,CAAC,CAAC;oBACb,iBAAiB,EAAE,CAAC;oBACpB,iBAAiB,EAAE,MAAM,CAAC,qBAAqB;iBAChD;aACF;SACF,CAAC,EAEN;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC;AAED,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;IAE7B,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,SAAS,EAAE;YACT,IAAI,EAAE,CAAC;YACP,eAAe,EAAE,MAAM,CAAC,2BAA2B;SACpD;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import { EmojiKeyboard, emojisByCategory, type EmojiType } from '@planningcenter/emoji-keyboard'\nimport React, { useCallback } from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { useTheme } from '../../hooks'\n\nconst BLOCKED_EMOJIS = new Set(['🖕'])\n\nconst filteredEmojis = emojisByCategory.map(category => ({\n ...category,\n data: category.data.filter(e => !BLOCKED_EMOJIS.has(e.emoji)),\n}))\n\ninterface EmojiTabProps {\n onEmojiSelect: (emoji: string) => void\n}\n\nexport function EmojiTab({ onEmojiSelect }: EmojiTabProps) {\n const styles = useStyles()\n const { colors } = useTheme()\n\n const handleEmojiSelected = useCallback(\n (emojiObject: EmojiType) => {\n onEmojiSelect(emojiObject.emoji)\n },\n [onEmojiSelect]\n )\n\n const emojiTheme = {\n container: colors.fillColorNeutral100Inverted,\n header: colors.textColorDefaultSecondary,\n knob: colors.fillColorNeutral040,\n skinTonesContainer: colors.fillColorNeutral060,\n category: {\n icon: colors.textColorDefaultSecondary,\n iconActive: colors.interaction,\n container: colors.fillColorNeutral100Inverted,\n containerActive: colors.fillColorNeutral080,\n },\n search: {\n background: colors.fillColorNeutral080,\n text: colors.textColorDefaultPrimary,\n placeholder: colors.textColorDefaultSecondary,\n icon: colors.textColorDefaultSecondary,\n },\n emoji: {\n selected: colors.fillColorNeutral080,\n },\n }\n\n return (\n <View style={styles.container}>\n <EmojiKeyboard\n categoryPosition=\"top\"\n emojisByCategory={filteredEmojis}\n onEmojiSelected={handleEmojiSelected}\n enableSearchBar\n enableRecentlyUsed\n theme={emojiTheme}\n styles={{\n container: { borderRadius: 0 },\n category: {\n container: {\n borderRadius: 0,\n marginTop: -6,\n borderBottomWidth: 1,\n borderBottomColor: colors.borderColorDefaultDim,\n },\n },\n }}\n />\n </View>\n )\n}\n\nconst useStyles = () => {\n const { colors } = useTheme()\n\n return StyleSheet.create({\n container: {\n flex: 1,\n backgroundColor: colors.fillColorNeutral100Inverted,\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;AACjC,OAAO,KAA4D,MAAM,OAAO,CAAA;AA2ChF,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAA;AAiBjF,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,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,CAAC,sBAAsB,CAAC,CAAA;AAK/E,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,EAAE,uBAAuB,qBA6BpE;AAuSD,UAAU,4BAA6B,SAAQ,gBAAgB;IAC7D,eAAe,EAAE,MAAM,CAAA;IACvB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,eAAO,MAAM,uBAAuB,GAAI,8DAOrC,4BAA4B,sBAoC9B,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;AACjC,OAAO,KAA4D,MAAM,OAAO,CAAA;AA6ChF,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAA;AAiBjF,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,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,CAAC,sBAAsB,CAAC,CAAA;AAE/E,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,EAAE,uBAAuB,qBA6BpE;AAkSD,UAAU,4BAA6B,SAAQ,gBAAgB;IAC7D,eAAe,EAAE,MAAM,CAAA;IACvB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,eAAO,MAAM,uBAAuB,GAAI,8DAOrC,4BAA4B,sBAoC9B,CAAA"}
@@ -2,7 +2,7 @@ import { date as formatDate } from '@planningcenter/datetime-fmt';
2
2
  import { HeaderTitle, PlatformPressable } from '@react-navigation/elements';
3
3
  import { CommonActions, useNavigation, useTheme as useNavigationTheme, useRoute, } from '@react-navigation/native';
4
4
  import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
5
- import { ActivityIndicator, FlatList, Platform, StyleSheet, View } from 'react-native';
5
+ import { ActivityIndicator, Platform, StyleSheet, View } from 'react-native';
6
6
  import Animated, { FadeIn, FadeOut } from 'react-native-reanimated';
7
7
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
8
8
  import { Badge, Icon, Text } from '../components';
@@ -10,6 +10,7 @@ import { EmptyConversationBlankState } from '../components/conversation/empty_co
10
10
  import { JumpToBottomButton } from '../components/conversation/jump_to_bottom_button';
11
11
  import { Message } from '../components/conversation/message';
12
12
  import { MessageForm } from '../components/conversation/message_form';
13
+ import { MessageList } from '../components/conversation/message_list';
13
14
  import { ConversationDisabledBanner, LeaderMessagesDisabledBanner, MemberMessagesDisabledBanner, } from '../components/conversation/messages_disabled_banners';
14
15
  import { ReplyShadowMessage } from '../components/conversation/reply_shadow_message';
15
16
  import { SystemMessage } from '../components/conversation/system_message';
@@ -37,8 +38,6 @@ import { groupMessages, UNREAD_DIVIDER_KEY, } from '../utils/group_messages';
37
38
  import { detectDividerExitTowardNewer, reportViewableMessages, } from '../utils/message_viewability';
38
39
  import { CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL } from '../utils/styles';
39
40
  import { isSystemMessage } from '../utils/system_messages';
40
- const extractItemKey = (item) => String(item.id);
41
- const maintainVisibleContentPosition = { minIndexForVisible: 0 };
42
41
  export function ConversationScreen({ route }) {
43
42
  const { conversation_id, message_id, reply_root_id } = route.params;
44
43
  const { data: conversation } = useConversation({ conversation_id });
@@ -164,7 +163,7 @@ function ConversationScreenContent({ route }) {
164
163
  }
165
164
  return (<View style={styles.container}>
166
165
  <KeyboardView>
167
- {noMessages ? (<EmptyConversationBlankState />) : (<FlatList inverted ref={listRef} contentContainerStyle={styles.listContainer} maintainVisibleContentPosition={maintainVisibleContentPosition} data={items} keyExtractor={extractItemKey} onScroll={onScroll} onScrollBeginDrag={onScrollBeginDrag} scrollEventThrottle={64} viewabilityConfigCallbackPairs={viewabilityConfigCallbackPairs} onContentSizeChange={onContentSizeChange} onScrollToIndexFailed={onScrollToIndexFailed} renderItem={renderItem} onEndReached={() => fetchOlderMessages()} ListHeaderComponent={listHeader}/>)}
166
+ {noMessages ? (<EmptyConversationBlankState />) : (<MessageList listRef={listRef} data={items} onScroll={onScroll} onScrollBeginDrag={onScrollBeginDrag} viewabilityConfigCallbackPairs={viewabilityConfigCallbackPairs} onContentSizeChange={onContentSizeChange} onScrollToIndexFailed={onScrollToIndexFailed} renderItem={renderItem} onEndReached={() => fetchOlderMessages()} ListHeaderComponent={listHeader}/>)}
168
167
  <JumpToBottomButton onPress={handleJumpToBottom} visible={showJumpToBottomButton} loading={isJumpingToBottom}/>
169
168
  {!noMessages && <TypingIndicator />}
170
169
  {showLeaderDisabledReplyBanner && <LeaderMessagesDisabledBanner />}
@@ -275,9 +274,6 @@ const useStyles = () => {
275
274
  backgroundColor: navigationTheme.colors.card,
276
275
  paddingBottom: bottom,
277
276
  },
278
- listContainer: {
279
- paddingVertical: 12,
280
- },
281
277
  listHeader: {
282
278
  // Just whitespace to provide space where the typing indicator can be
283
279
  height: 16,
@@ -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 React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { ActivityIndicator, FlatList, Platform, StyleSheet, View } from 'react-native'\nimport Animated, { FadeIn, FadeOut } from 'react-native-reanimated'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\nimport { Badge, Icon, Text } from '../components'\nimport { EmptyConversationBlankState } from '../components/conversation/empty_conversation_blank_state'\nimport { JumpToBottomButton } from '../components/conversation/jump_to_bottom_button'\nimport { Message } from '../components/conversation/message'\nimport { MessageForm } from '../components/conversation/message_form'\nimport {\n ConversationDisabledBanner,\n LeaderMessagesDisabledBanner,\n MemberMessagesDisabledBanner,\n} from '../components/conversation/messages_disabled_banners'\nimport { ReplyShadowMessage } from '../components/conversation/reply_shadow_message'\nimport { SystemMessage } from '../components/conversation/system_message'\nimport { TypingIndicator } from '../components/conversation/typing_indicator'\nimport { UnreadDivider } from '../components/conversation/unread_divider'\nimport { KeyboardView } from '../components/display/keyboard_view'\nimport BlankState from '../components/primitive/blank_state_primitive'\nimport {\n ConversationContextProvider,\n useConversationContext,\n} from '../contexts/conversation_context'\nimport { useTheme } from '../hooks'\nimport { useConversation } from '../hooks/use_conversation'\nimport { useConversationJoltEvents } from '../hooks/use_conversation_jolt_events'\nimport { useConversationMessages } from '../hooks/use_conversation_messages'\nimport { useConversationMessagesJoltEvents } from '../hooks/use_conversation_messages_jolt_events'\nimport { availableFeatures, useFeatures } from '../hooks/use_features'\nimport { useFlatListViewability } from '../hooks/use_flat_list_viewability'\nimport { useJumpToBottomAction } from '../hooks/use_jump_to_bottom_action'\nimport { useJumpToUnreadAnchor } from '../hooks/use_jump_to_unread_anchor'\nimport { useJumpToUnreadGates } from '../hooks/use_jump_to_unread_gates'\nimport { useMarkLatestMessageRead } from '../hooks/use_mark_latest_message_read'\nimport {\n analyticsEvents,\n normalizeAnalyticsMetadata,\n usePublishProductAnalyticsEvent,\n} from '../hooks/use_product_analytics'\nimport { useScrollTracking } from '../hooks/use_scroll_tracking'\nimport { useTrackHighestSeenMessage } from '../hooks/use_track_highest_seen_message'\nimport { ConversationResource } from '../types/resources/conversation'\nimport { ConversationBadgeResource } from '../types/resources/conversation_badge'\nimport { MessageResource } from '../types/resources/message'\nimport { getRelativeDateStatus } from '../utils/date'\nimport {\n groupMessages,\n UNREAD_DIVIDER_KEY,\n type DateSeparator,\n type EnrichedMessage,\n} from '../utils/group_messages'\nimport {\n detectDividerExitTowardNewer,\n reportViewableMessages,\n type ViewabilityObserver,\n} from '../utils/message_viewability'\nimport { CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL } from '../utils/styles'\nimport { isSystemMessage } from '../utils/system_messages'\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 message_id?: string\n title?: string\n subtitle?: string\n badge?: ConversationBadgeResource\n deleted?: boolean\n muted?: boolean\n}\n\nexport type ConversationScreenProps = StaticScreenProps<ConversationRouteProps>\n\nconst extractItemKey = (item: EnrichedMessage) => String(item.id)\nconst maintainVisibleContentPosition = { minIndexForVisible: 0 }\n\nexport function ConversationScreen({ route }: ConversationScreenProps) {\n const { conversation_id, message_id, reply_root_id } = route.params\n\n const { data: conversation } = useConversation({ conversation_id })\n const { featureEnabled } = useFeatures()\n\n usePublishProductAnalyticsEvent(analyticsEvents.conversation_show_opened, {\n reply_root_id,\n ...normalizeAnalyticsMetadata(conversation),\n })\n\n const lastReadMessageSortKey = conversation.conversationMembership?.lastReadMessageSortKey ?? null\n const jumpToUnreadAnchor =\n featureEnabled(availableFeatures.jump_to_unread) && !reply_root_id\n ? lastReadMessageSortKey\n : null\n const initialMessageId = message_id ?? jumpToUnreadAnchor\n const initialMessageIdIsAnchor = !!initialMessageId && !message_id\n\n return (\n <ConversationContextProvider\n conversationId={conversation_id}\n currentPageReplyRootId={reply_root_id ?? null}\n initialMessageId={initialMessageId}\n initialMessageIdIsAnchor={initialMessageIdIsAnchor}\n >\n <ConversationScreenContent route={route} />\n </ConversationContextProvider>\n )\n}\n\nfunction ConversationScreenContent({ route }: ConversationScreenProps) {\n const styles = useStyles()\n const navigation = useNavigation()\n const {\n conversation_id: conversationId,\n editing_message_id: editingMessageId,\n reply_root_id: replyRootId,\n reply_root_author_name: replyRootAuthorName,\n } = route.params\n const { data: conversation } = useConversation(route.params)\n const {\n messages,\n fetchOlderMessages,\n fetchNewerMessages,\n hasMoreNewerMessages,\n isFetchingNewerMessages,\n cancelFetchNewerMessages,\n } = useConversationMessages({ conversation_id: conversationId, reply_root_id: replyRootId })\n\n const { jumpToUnreadActive } = useJumpToUnreadGates()\n const { initialMessageId } = useConversationContext()\n\n useConversationJoltEvents({ conversationId })\n useConversationMessagesJoltEvents({ conversationId })\n useEnsureConversationsRouteExists()\n useMarkLatestMessageRead({ conversation, messages })\n const { onMessageSeen } = useTrackHighestSeenMessage()\n\n const items = useMemo(\n () =>\n groupMessages({\n ms: messages,\n inReplyScreen: !!replyRootId,\n jumpToUnreadActive,\n initialMessageId,\n }),\n [messages, replyRootId, jumpToUnreadActive, initialMessageId]\n )\n const noMessages = items.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(editingMessageId))\n const replyRootAuthorFirstName = replyRootAuthorName?.split(' ')[0]\n const replyHeaderTitle = replyRootAuthorFirstName\n ? `Reply to ${replyRootAuthorFirstName}`\n : 'Reply'\n // Prefer the membership for optimistic updates.\n const muted = conversation.conversationMembership?.muted ?? conversation.muted\n\n const listRef = useRef<FlatList>(null)\n const [dividerScrolledPast, setDividerScrolledPast] = useState(false)\n\n const observers = useMemo<ViewabilityObserver<EnrichedMessage>[]>(\n () => [\n reportViewableMessages(onMessageSeen),\n detectDividerExitTowardNewer({\n dividerKey: UNREAD_DIVIDER_KEY,\n initialMessageId,\n onExited: () => setDividerScrolledPast(true),\n }),\n ],\n [onMessageSeen, initialMessageId]\n )\n\n const { viewabilityConfigCallbackPairs, onScrollBeginDrag: viewabilityOnScrollBeginDrag } =\n useFlatListViewability({ observers })\n const {\n onContentSizeChange,\n onScrollToIndexFailed,\n onScrollBeginDrag: anchorOnScrollBeginDrag,\n } = useJumpToUnreadAnchor({ listRef, items })\n const onScrollBeginDrag = useCallback(() => {\n viewabilityOnScrollBeginDrag()\n anchorOnScrollBeginDrag()\n }, [viewabilityOnScrollBeginDrag, anchorOnScrollBeginDrag])\n const { onScroll, showJumpToBottomButton } = useScrollTracking({\n hasMoreNewerMessages,\n isFetchingNewerMessages,\n fetchNewerMessages,\n cancelFetchNewerMessages,\n })\n const { handleJumpToBottom, isJumpingToBottom } = useJumpToBottomAction({ listRef })\n\n const listHeader = useMemo(\n () => (\n <View>\n {isFetchingNewerMessages && (\n <Animated.View\n entering={FadeIn.duration(750)}\n exiting={FadeOut.duration(750)}\n style={styles.loadingFooter}\n accessibilityRole=\"progressbar\"\n accessibilityLabel=\"Loading more messages\"\n >\n <ActivityIndicator />\n </Animated.View>\n )}\n <View style={styles.listHeader} />\n </View>\n ),\n [isFetchingNewerMessages, styles.loadingFooter, styles.listHeader]\n )\n\n const renderItem = useCallback(\n ({ item }: { item: EnrichedMessage }) => {\n if (item.type === 'DateSeparator') return <InlineDateSeparator {...item} />\n if (item.type === 'UnreadDivider') return <UnreadDivider scrolledPast={dividerScrolledPast} />\n if (item.type === 'ReplyShadowMessage') {\n return (\n <ReplyShadowMessage\n {...item}\n conversation_id={conversationId}\n inReplyScreen={!!replyRootId}\n />\n )\n }\n if (isSystemMessage(item)) {\n return <SystemMessage message={item} conversationId={conversationId} />\n }\n return (\n <Message\n {...item}\n canDeleteNonAuthoredMessages={canDeleteNonAuthoredMessages}\n conversation_id={conversationId}\n latestReadMessageSortKey={conversation?.latestReadMessageSortKey}\n inReplyScreen={!!replyRootId}\n />\n )\n },\n [\n dividerScrolledPast,\n conversationId,\n replyRootId,\n canDeleteNonAuthoredMessages,\n conversation?.latestReadMessageSortKey,\n ]\n )\n\n useEffect(() => {\n if (replyRootId) {\n navigation.setParams({\n title: replyHeaderTitle,\n })\n } else {\n navigation.setParams({\n title: title,\n badge: badges?.[0],\n deleted: conversation?.deleted,\n muted,\n })\n }\n }, [navigation, title, badges, conversation?.deleted, replyRootId, replyHeaderTitle, muted])\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 maintainVisibleContentPosition={maintainVisibleContentPosition}\n data={items}\n keyExtractor={extractItemKey}\n onScroll={onScroll}\n onScrollBeginDrag={onScrollBeginDrag}\n scrollEventThrottle={64}\n viewabilityConfigCallbackPairs={viewabilityConfigCallbackPairs}\n onContentSizeChange={onContentSizeChange}\n onScrollToIndexFailed={onScrollToIndexFailed}\n renderItem={renderItem}\n onEndReached={() => fetchOlderMessages()}\n ListHeaderComponent={listHeader}\n />\n )}\n <JumpToBottomButton\n onPress={handleJumpToBottom}\n visible={showJumpToBottomButton}\n loading={isJumpingToBottom}\n />\n {!noMessages && <TypingIndicator />}\n {showLeaderDisabledReplyBanner && <LeaderMessagesDisabledBanner />}\n <ConversationBottomBar\n conversation={conversation}\n canReply={canReply}\n replyRootAuthorFirstName={replyRootAuthorFirstName}\n replyRootId={replyRootId}\n currentlyEditingMessage={currentlyEditingMessage}\n />\n </KeyboardView>\n </View>\n )\n}\n\ninterface ConversationBottomBarProps {\n conversation: ConversationResource\n canReply: boolean | undefined\n replyRootAuthorFirstName: string | undefined\n replyRootId: string | null | undefined\n currentlyEditingMessage: MessageResource | undefined\n}\n\nfunction ConversationBottomBar({\n conversation,\n canReply,\n replyRootAuthorFirstName,\n replyRootId,\n currentlyEditingMessage,\n}: ConversationBottomBarProps) {\n if (conversation.disabled) return <ConversationDisabledBanner />\n if (!canReply) return <MemberMessagesDisabledBanner />\n return (\n <MessageForm.Root\n replyRootAuthorFirstName={replyRootAuthorFirstName}\n conversation={conversation}\n replyRootId={replyRootId}\n currentlyEditingMessage={currentlyEditingMessage}\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}\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\ninterface ConversationScreenTitleProps extends HeaderTitleProps {\n conversation_id: number\n badge?: ConversationBadgeResource\n deleted?: boolean\n muted?: boolean\n}\n\nexport const ConversationScreenTitle = ({\n conversation_id,\n badge,\n children,\n style,\n deleted,\n muted,\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 <View style={styles.titleTextContainer}>\n <HeaderTitle maxFontSizeMultiplier={1} style={style}>\n {children}\n </HeaderTitle>\n </View>\n {muted && <Icon name=\"general.bellMuted\" size={12} />}\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 flex: 1,\n },\n titleWrapper: {\n alignItems: 'center',\n columnGap: 4,\n flexDirection: 'row',\n flexShrink: 1,\n },\n titleTextContainer: {\n flexShrink: 1,\n minWidth: 0,\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 loadingFooter: {\n paddingVertical: 12,\n alignItems: 'center',\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":"AAAA,OAAO,EAAE,IAAI,IAAI,UAAU,EAAE,MAAM,8BAA8B,CAAA;AACjE,OAAO,EAAE,WAAW,EAAoB,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAC7F,OAAO,EACL,aAAa,EAGb,aAAa,EACb,QAAQ,IAAI,kBAAkB,EAC9B,QAAQ,GACT,MAAM,0BAA0B,CAAA;AACjC,OAAO,KAAK,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChF,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAE5E,OAAO,QAAQ,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAClE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,2BAA2B,EAAE,MAAM,2DAA2D,CAAA;AACvG,OAAO,EAAE,kBAAkB,EAAE,MAAM,kDAAkD,CAAA;AACrF,OAAO,EAAE,OAAO,EAAE,MAAM,oCAAoC,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAA;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAA;AACrE,OAAO,EACL,0BAA0B,EAC1B,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,sDAAsD,CAAA;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAA;AACpF,OAAO,EAAE,aAAa,EAAE,MAAM,2CAA2C,CAAA;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAA;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,2CAA2C,CAAA;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAA;AAClE,OAAO,UAAU,MAAM,+CAA+C,CAAA;AACtE,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,GACvB,MAAM,kCAAkC,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAA;AACjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAA;AAC5E,OAAO,EAAE,iCAAiC,EAAE,MAAM,gDAAgD,CAAA;AAClG,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAA;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAA;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAA;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAA;AACxE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAA;AAChF,OAAO,EACL,eAAe,EACf,0BAA0B,EAC1B,+BAA+B,GAChC,MAAM,gCAAgC,CAAA;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AAChE,OAAO,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAA;AAIpF,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,EACL,aAAa,EACb,kBAAkB,GAGnB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,GAEvB,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAAE,4CAA4C,EAAE,MAAM,iBAAiB,CAAA;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAmB1D,MAAM,UAAU,kBAAkB,CAAC,EAAE,KAAK,EAA2B;IACnE,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG,KAAK,CAAC,MAAM,CAAA;IAEnE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,eAAe,CAAC,EAAE,eAAe,EAAE,CAAC,CAAA;IACnE,MAAM,EAAE,cAAc,EAAE,GAAG,WAAW,EAAE,CAAA;IAExC,+BAA+B,CAAC,eAAe,CAAC,wBAAwB,EAAE;QACxE,aAAa;QACb,GAAG,0BAA0B,CAAC,YAAY,CAAC;KAC5C,CAAC,CAAA;IAEF,MAAM,sBAAsB,GAAG,YAAY,CAAC,sBAAsB,EAAE,sBAAsB,IAAI,IAAI,CAAA;IAClG,MAAM,kBAAkB,GACtB,cAAc,CAAC,iBAAiB,CAAC,cAAc,CAAC,IAAI,CAAC,aAAa;QAChE,CAAC,CAAC,sBAAsB;QACxB,CAAC,CAAC,IAAI,CAAA;IACV,MAAM,gBAAgB,GAAG,UAAU,IAAI,kBAAkB,CAAA;IACzD,MAAM,wBAAwB,GAAG,CAAC,CAAC,gBAAgB,IAAI,CAAC,UAAU,CAAA;IAElE,OAAO,CACL,CAAC,2BAA2B,CAC1B,cAAc,CAAC,CAAC,eAAe,CAAC,CAChC,sBAAsB,CAAC,CAAC,aAAa,IAAI,IAAI,CAAC,CAC9C,gBAAgB,CAAC,CAAC,gBAAgB,CAAC,CACnC,wBAAwB,CAAC,CAAC,wBAAwB,CAAC,CAEnD;MAAA,CAAC,yBAAyB,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,EAC1C;IAAA,EAAE,2BAA2B,CAAC,CAC/B,CAAA;AACH,CAAC;AAED,SAAS,yBAAyB,CAAC,EAAE,KAAK,EAA2B;IACnE,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,MAAM,UAAU,GAAG,aAAa,EAAE,CAAA;IAClC,MAAM,EACJ,eAAe,EAAE,cAAc,EAC/B,kBAAkB,EAAE,gBAAgB,EACpC,aAAa,EAAE,WAAW,EAC1B,sBAAsB,EAAE,mBAAmB,GAC5C,GAAG,KAAK,CAAC,MAAM,CAAA;IAChB,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IAC5D,MAAM,EACJ,QAAQ,EACR,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,uBAAuB,EACvB,wBAAwB,GACzB,GAAG,uBAAuB,CAAC,EAAE,eAAe,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC,CAAA;IAE5F,MAAM,EAAE,kBAAkB,EAAE,GAAG,oBAAoB,EAAE,CAAA;IACrD,MAAM,EAAE,gBAAgB,EAAE,GAAG,sBAAsB,EAAE,CAAA;IAErD,yBAAyB,CAAC,EAAE,cAAc,EAAE,CAAC,CAAA;IAC7C,iCAAiC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAA;IACrD,iCAAiC,EAAE,CAAA;IACnC,wBAAwB,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,CAAA;IACpD,MAAM,EAAE,aAAa,EAAE,GAAG,0BAA0B,EAAE,CAAA;IAEtD,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CACH,aAAa,CAAC;QACZ,EAAE,EAAE,QAAQ;QACZ,aAAa,EAAE,CAAC,CAAC,WAAW;QAC5B,kBAAkB;QAClB,gBAAgB;KACjB,CAAC,EACJ,CAAC,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE,gBAAgB,CAAC,CAC9D,CAAA;IACD,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,KAAK,CAAC,CAAA;IAErC,MAAM,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,YAAY,CAAA;IACtE,MAAM,QAAQ,GAAG,aAAa,EAAE,QAAQ,CAAA;IACxC,MAAM,6BAA6B,GAAG,QAAQ,IAAI,eAAe,CAAA;IACjE,MAAM,4BAA4B,GAAG,aAAa,EAAE,4BAA4B,IAAI,KAAK,CAAA;IACzF,MAAM,uBAAuB,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAA;IAC7F,MAAM,wBAAwB,GAAG,mBAAmB,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;IACnE,MAAM,gBAAgB,GAAG,wBAAwB;QAC/C,CAAC,CAAC,YAAY,wBAAwB,EAAE;QACxC,CAAC,CAAC,OAAO,CAAA;IACX,gDAAgD;IAChD,MAAM,KAAK,GAAG,YAAY,CAAC,sBAAsB,EAAE,KAAK,IAAI,YAAY,CAAC,KAAK,CAAA;IAE9E,MAAM,OAAO,GAAG,MAAM,CAAW,IAAI,CAAC,CAAA;IACtC,MAAM,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAErE,MAAM,SAAS,GAAG,OAAO,CACvB,GAAG,EAAE,CAAC;QACJ,sBAAsB,CAAC,aAAa,CAAC;QACrC,4BAA4B,CAAC;YAC3B,UAAU,EAAE,kBAAkB;YAC9B,gBAAgB;YAChB,QAAQ,EAAE,GAAG,EAAE,CAAC,sBAAsB,CAAC,IAAI,CAAC;SAC7C,CAAC;KACH,EACD,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAClC,CAAA;IAED,MAAM,EAAE,8BAA8B,EAAE,iBAAiB,EAAE,4BAA4B,EAAE,GACvF,sBAAsB,CAAC,EAAE,SAAS,EAAE,CAAC,CAAA;IACvC,MAAM,EACJ,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,EAAE,uBAAuB,GAC3C,GAAG,qBAAqB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAA;IAC7C,MAAM,iBAAiB,GAAG,WAAW,CAAC,GAAG,EAAE;QACzC,4BAA4B,EAAE,CAAA;QAC9B,uBAAuB,EAAE,CAAA;IAC3B,CAAC,EAAE,CAAC,4BAA4B,EAAE,uBAAuB,CAAC,CAAC,CAAA;IAC3D,MAAM,EAAE,QAAQ,EAAE,sBAAsB,EAAE,GAAG,iBAAiB,CAAC;QAC7D,oBAAoB;QACpB,uBAAuB;QACvB,kBAAkB;QAClB,wBAAwB;KACzB,CAAC,CAAA;IACF,MAAM,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,GAAG,qBAAqB,CAAC,EAAE,OAAO,EAAE,CAAC,CAAA;IAEpF,MAAM,UAAU,GAAG,OAAO,CACxB,GAAG,EAAE,CAAC,CACJ,CAAC,IAAI,CACH;QAAA,CAAC,uBAAuB,IAAI,CAC1B,CAAC,QAAQ,CAAC,IAAI,CACZ,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAC/B,OAAO,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAC/B,KAAK,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAC5B,iBAAiB,CAAC,aAAa,CAC/B,kBAAkB,CAAC,uBAAuB,CAE1C;YAAA,CAAC,iBAAiB,CAAC,AAAD,EACpB;UAAA,EAAE,QAAQ,CAAC,IAAI,CAAC,CACjB,CACD;QAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,EACjC;MAAA,EAAE,IAAI,CAAC,CACR,EACD,CAAC,uBAAuB,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,UAAU,CAAC,CACnE,CAAA;IAED,MAAM,UAAU,GAAG,WAAW,CAC5B,CAAC,EAAE,IAAI,EAA6B,EAAE,EAAE;QACtC,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe;YAAE,OAAO,CAAC,mBAAmB,CAAC,IAAI,IAAI,CAAC,EAAG,CAAA;QAC3E,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe;YAAE,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,mBAAmB,CAAC,EAAG,CAAA;QAC9F,IAAI,IAAI,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;YACvC,OAAO,CACL,CAAC,kBAAkB,CACjB,IAAI,IAAI,CAAC,CACT,eAAe,CAAC,CAAC,cAAc,CAAC,CAChC,aAAa,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,EAC7B,CACH,CAAA;QACH,CAAC;QACD,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,cAAc,CAAC,CAAC,cAAc,CAAC,EAAG,CAAA;QACzE,CAAC;QACD,OAAO,CACL,CAAC,OAAO,CACN,IAAI,IAAI,CAAC,CACT,4BAA4B,CAAC,CAAC,4BAA4B,CAAC,CAC3D,eAAe,CAAC,CAAC,cAAc,CAAC,CAChC,wBAAwB,CAAC,CAAC,YAAY,EAAE,wBAAwB,CAAC,CACjE,aAAa,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,EAC7B,CACH,CAAA;IACH,CAAC,EACD;QACE,mBAAmB;QACnB,cAAc;QACd,WAAW;QACX,4BAA4B;QAC5B,YAAY,EAAE,wBAAwB;KACvC,CACF,CAAA;IAED,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,WAAW,EAAE,CAAC;YAChB,UAAU,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,gBAAgB;aACxB,CAAC,CAAA;QACJ,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,KAAK;gBACZ,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;gBAClB,OAAO,EAAE,YAAY,EAAE,OAAO;gBAC9B,KAAK;aACN,CAAC,CAAA;QACJ,CAAC;IACH,CAAC,EAAE,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,CAAC,CAAC,CAAA;IAE5F,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;QAC1C,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAC5B;QAAA,CAAC,UAAU,CAAC,IAAI,CACd;UAAA,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,6BAA6B,EACtD;UAAA,CAAC,UAAU,CAAC,OAAO,CACjB;YAAA,CAAC,UAAU,CAAC,OAAO,CAAC,kCAAkC,EAAE,UAAU,CAAC,OAAO,CAC5E;UAAA,EAAE,UAAU,CAAC,OAAO,CACpB;UAAA,CAAC,UAAU,CAAC,MAAM,CAChB,OAAO,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAC3B,KAAK,CAAC,uBAAuB,CAC7B,iBAAiB,CAAC,0CAA0C,CAC5D,iBAAiB,CAAC,MAAM,EAE5B;QAAA,EAAE,UAAU,CAAC,IAAI,CACnB;MAAA,EAAE,IAAI,CAAC,CACR,CAAA;IACH,CAAC;IAED,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAC5B;MAAA,CAAC,YAAY,CACX;QAAA,CAAC,UAAU,CAAC,CAAC,CAAC,CACZ,CAAC,2BAA2B,CAAC,AAAD,EAAG,CAChC,CAAC,CAAC,CAAC,CACF,CAAC,WAAW,CACV,OAAO,CAAC,CAAC,OAAO,CAAC,CACjB,IAAI,CAAC,CAAC,KAAK,CAAC,CACZ,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,iBAAiB,CAAC,CAAC,iBAAiB,CAAC,CACrC,8BAA8B,CAAC,CAAC,8BAA8B,CAAC,CAC/D,mBAAmB,CAAC,CAAC,mBAAmB,CAAC,CACzC,qBAAqB,CAAC,CAAC,qBAAqB,CAAC,CAC7C,UAAU,CAAC,CAAC,UAAU,CAAC,CACvB,YAAY,CAAC,CAAC,GAAG,EAAE,CAAC,kBAAkB,EAAE,CAAC,CACzC,mBAAmB,CAAC,CAAC,UAAU,CAAC,EAChC,CACH,CACD;QAAA,CAAC,kBAAkB,CACjB,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAC5B,OAAO,CAAC,CAAC,sBAAsB,CAAC,CAChC,OAAO,CAAC,CAAC,iBAAiB,CAAC,EAE7B;QAAA,CAAC,CAAC,UAAU,IAAI,CAAC,eAAe,CAAC,AAAD,EAAG,CACnC;QAAA,CAAC,6BAA6B,IAAI,CAAC,4BAA4B,CAAC,AAAD,EAAG,CAClE;QAAA,CAAC,qBAAqB,CACpB,YAAY,CAAC,CAAC,YAAY,CAAC,CAC3B,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,wBAAwB,CAAC,CAAC,wBAAwB,CAAC,CACnD,WAAW,CAAC,CAAC,WAAW,CAAC,CACzB,uBAAuB,CAAC,CAAC,uBAAuB,CAAC,EAErD;MAAA,EAAE,YAAY,CAChB;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC;AAUD,SAAS,qBAAqB,CAAC,EAC7B,YAAY,EACZ,QAAQ,EACR,wBAAwB,EACxB,WAAW,EACX,uBAAuB,GACI;IAC3B,IAAI,YAAY,CAAC,QAAQ;QAAE,OAAO,CAAC,0BAA0B,CAAC,AAAD,EAAG,CAAA;IAChE,IAAI,CAAC,QAAQ;QAAE,OAAO,CAAC,4BAA4B,CAAC,AAAD,EAAG,CAAA;IACtD,OAAO,CACL,CAAC,WAAW,CAAC,IAAI,CACf,wBAAwB,CAAC,CAAC,wBAAwB,CAAC,CACnD,YAAY,CAAC,CAAC,YAAY,CAAC,CAC3B,WAAW,CAAC,CAAC,WAAW,CAAC,CACzB,uBAAuB,CAAC,CAAC,uBAAuB,CAAC,CACjD,GAAG,CAAC,CACF,uBAAuB;YACrB,CAAC,CAAC,qBAAqB,uBAAuB,CAAC,EAAE,EAAE;YACnD,CAAC,CAAC,kBACN,CAAC,CAED;MAAA,CAAC,WAAW,CAAC,gBAAgB,CAAC,AAAD,EAC7B;MAAA,CAAC,WAAW,CAAC,QAAQ,CAAC,AAAD,EACrB;MAAA,CAAC,WAAW,CAAC,SAAS,CAAC,AAAD,EACtB;MAAA,CAAC,WAAW,CAAC,YAAY,CAAC,AAAD,EAC3B;IAAA,EAAE,WAAW,CAAC,IAAI,CAAC,CACpB,CAAA;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,EAAE,IAAI,EAAiB;IAClD,MAAM,MAAM,GAAG,sBAAsB,EAAE,CAAA;IACvC,MAAM,EAAE,UAAU,EAAE,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAA;IAClD,MAAM,QAAQ,GAAG,CAAC,UAAU,CAAA;IAC5B,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;IAErE,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAC5B;MAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,EAC9B;MAAA,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAC9C;QAAA,CAAC,SAAS,CACZ;MAAA,EAAE,IAAI,CACN;MAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,EAChC;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC;AAED,MAAM,sBAAsB,GAAG,GAAG,EAAE;IAClC,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAA;IACxB,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,SAAS,EAAE;YACT,UAAU,EAAE,QAAQ;YACpB,aAAa,EAAE,KAAK;YACpB,iBAAiB,EAAE,4CAA4C;YAC/D,eAAe,EAAE,EAAE;SACpB;QACD,SAAS,EAAE;YACT,IAAI,EAAE,CAAC;YACP,MAAM,EAAE,CAAC;YACT,cAAc,EAAE,CAAC;YACjB,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,sBAAsB;SACpD;QACD,QAAQ,EAAE;YACR,iBAAiB,EAAE,CAAC;SACrB;KACF,CAAC,CAAA;AACJ,CAAC,CAAA;AASD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,EACtC,eAAe,EACf,KAAK,EACL,QAAQ,EACR,KAAK,EACL,OAAO,EACP,KAAK,GACwB,EAAE,EAAE;IACjC,MAAM,MAAM,GAAG,uBAAuB,EAAE,CAAA;IACxC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAA;IAClC,MAAM,YAAY,GAAG,KAAK,EAAE,eAAe,IAAI,EAAE,CAAA;IACjD,MAAM,WAAW,GAAG,KAAK,EAAE,OAAO,CAAA;IAClC,MAAM,IAAI,GAAG,KAAK,EAAE,IAAI,IAAI,SAAS,CAAA;IAErC,OAAO,CACL,CAAC,iBAAiB,CAChB,iBAAiB,CAAC,0CAA0C,CAC5D,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CACxB,OAAO,CAAC,CAAC,GAAG,EAAE;YACZ,IAAI,OAAO;gBAAE,OAAM;YAEnB,UAAU,CAAC,QAAQ,CAAC,qBAAqB,EAAE,EAAE,eAAe,EAAE,CAAC,CAAA;QACjE,CAAC,CAAC,CAEF;MAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAC/B;QAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,CACrC;UAAA,CAAC,WAAW,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAClD;YAAA,CAAC,QAAQ,CACX;UAAA,EAAE,WAAW,CACf;QAAA,EAAE,IAAI,CACN;QAAA,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAG,CACrD;QAAA,CAAC,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAG,CAC5D;MAAA,EAAE,IAAI,CACN;MAAA,CAAC,KAAK,CACJ,OAAO,CAAC,YAAY,CACpB,eAAe,CAAC,CAAC,WAAW,CAAC,CAC7B,KAAK,CAAC,CAAC,YAAY,CAAC,CACpB,SAAS,CAAC,CAAC,IAAI,CAAC,CAChB,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CACpB,qBAAqB,CAAC,CAAC,CAAC,CAAC,EAE7B;IAAA,EAAE,iBAAiB,CAAC,CACrB,CAAA;AACH,CAAC,CAAA;AAED,MAAM,uBAAuB,GAAG,GAAG,EAAE;IACnC,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,SAAS,EAAE;YACT,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;YACzE,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;YACtD,IAAI,EAAE,CAAC;SACR;QACD,YAAY,EAAE;YACZ,UAAU,EAAE,QAAQ;YACpB,SAAS,EAAE,CAAC;YACZ,aAAa,EAAE,KAAK;YACpB,UAAU,EAAE,CAAC;SACd;QACD,kBAAkB,EAAE;YAClB,UAAU,EAAE,CAAC;YACb,QAAQ,EAAE,CAAC;SACZ;QACD,KAAK,EAAE;YACL,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;YACxE,SAAS,EAAE,CAAC;SACb;KACF,CAAC,CAAA;AACJ,CAAC,CAAA;AAED,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,MAAM,eAAe,GAAG,kBAAkB,EAAE,CAAA;IAC5C,MAAM,EAAE,MAAM,EAAE,GAAG,iBAAiB,EAAE,CAAA;IAEtC,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,SAAS,EAAE;YACT,IAAI,EAAE,CAAC;YACP,cAAc,EAAE,QAAQ;YACxB,eAAe,EAAE,eAAe,CAAC,MAAM,CAAC,IAAI;YAC5C,aAAa,EAAE,MAAM;SACtB;QACD,UAAU,EAAE;YACV,qEAAqE;YACrE,MAAM,EAAE,EAAE;SACX;QACD,aAAa,EAAE;YACb,eAAe,EAAE,EAAE;YACnB,UAAU,EAAE,QAAQ;SACrB;KACF,CAAC,CAAA;AACJ,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,iCAAiC,GAAG,GAAG,EAAE;IAC7C,MAAM,UAAU,GAAG,aAAa,EAAE,CAAA;IAClC,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAA+C,CAAA;IAE1E,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,eAAe,GAAG,UAAU,CAAC,QAAQ,EAAE,CAAA;QAC7C,MAAM,MAAM,GAAG,eAAe,EAAE,MAAM,IAAI,EAAE,CAAA;QAC5C,MAAM,kBAAkB,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CAAC,CAAA;QAEvE,IAAI,kBAAkB;YAAE,OAAM;QAE9B,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;YAC1B,OAAO,aAAa,CAAC,KAAK,CAAC;gBACzB,GAAG,KAAK;gBACR,MAAM,EAAE;oBACN,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,EAAE,mBAAmB,EAAE,MAAM,EAAE,mBAAmB,EAAE,EAAE;oBACvF,GAAG,MAAM;iBACV;gBACD,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,CAAC;aACvB,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAA;AAC/C,CAAC,CAAA","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 React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { ActivityIndicator, Platform, StyleSheet, View } from 'react-native'\nimport type { FlatList } from 'react-native-gesture-handler'\nimport Animated, { FadeIn, FadeOut } from 'react-native-reanimated'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\nimport { Badge, Icon, Text } from '../components'\nimport { EmptyConversationBlankState } from '../components/conversation/empty_conversation_blank_state'\nimport { JumpToBottomButton } from '../components/conversation/jump_to_bottom_button'\nimport { Message } from '../components/conversation/message'\nimport { MessageForm } from '../components/conversation/message_form'\nimport { MessageList } from '../components/conversation/message_list'\nimport {\n ConversationDisabledBanner,\n LeaderMessagesDisabledBanner,\n MemberMessagesDisabledBanner,\n} from '../components/conversation/messages_disabled_banners'\nimport { ReplyShadowMessage } from '../components/conversation/reply_shadow_message'\nimport { SystemMessage } from '../components/conversation/system_message'\nimport { TypingIndicator } from '../components/conversation/typing_indicator'\nimport { UnreadDivider } from '../components/conversation/unread_divider'\nimport { KeyboardView } from '../components/display/keyboard_view'\nimport BlankState from '../components/primitive/blank_state_primitive'\nimport {\n ConversationContextProvider,\n useConversationContext,\n} from '../contexts/conversation_context'\nimport { useTheme } from '../hooks'\nimport { useConversation } from '../hooks/use_conversation'\nimport { useConversationJoltEvents } from '../hooks/use_conversation_jolt_events'\nimport { useConversationMessages } from '../hooks/use_conversation_messages'\nimport { useConversationMessagesJoltEvents } from '../hooks/use_conversation_messages_jolt_events'\nimport { availableFeatures, useFeatures } from '../hooks/use_features'\nimport { useFlatListViewability } from '../hooks/use_flat_list_viewability'\nimport { useJumpToBottomAction } from '../hooks/use_jump_to_bottom_action'\nimport { useJumpToUnreadAnchor } from '../hooks/use_jump_to_unread_anchor'\nimport { useJumpToUnreadGates } from '../hooks/use_jump_to_unread_gates'\nimport { useMarkLatestMessageRead } from '../hooks/use_mark_latest_message_read'\nimport {\n analyticsEvents,\n normalizeAnalyticsMetadata,\n usePublishProductAnalyticsEvent,\n} from '../hooks/use_product_analytics'\nimport { useScrollTracking } from '../hooks/use_scroll_tracking'\nimport { useTrackHighestSeenMessage } from '../hooks/use_track_highest_seen_message'\nimport { ConversationResource } from '../types/resources/conversation'\nimport { ConversationBadgeResource } from '../types/resources/conversation_badge'\nimport { MessageResource } from '../types/resources/message'\nimport { getRelativeDateStatus } from '../utils/date'\nimport {\n groupMessages,\n UNREAD_DIVIDER_KEY,\n type DateSeparator,\n type EnrichedMessage,\n} from '../utils/group_messages'\nimport {\n detectDividerExitTowardNewer,\n reportViewableMessages,\n type ViewabilityObserver,\n} from '../utils/message_viewability'\nimport { CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL } from '../utils/styles'\nimport { isSystemMessage } from '../utils/system_messages'\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 message_id?: string\n title?: string\n subtitle?: string\n badge?: ConversationBadgeResource\n deleted?: boolean\n muted?: boolean\n}\n\nexport type ConversationScreenProps = StaticScreenProps<ConversationRouteProps>\n\nexport function ConversationScreen({ route }: ConversationScreenProps) {\n const { conversation_id, message_id, reply_root_id } = route.params\n\n const { data: conversation } = useConversation({ conversation_id })\n const { featureEnabled } = useFeatures()\n\n usePublishProductAnalyticsEvent(analyticsEvents.conversation_show_opened, {\n reply_root_id,\n ...normalizeAnalyticsMetadata(conversation),\n })\n\n const lastReadMessageSortKey = conversation.conversationMembership?.lastReadMessageSortKey ?? null\n const jumpToUnreadAnchor =\n featureEnabled(availableFeatures.jump_to_unread) && !reply_root_id\n ? lastReadMessageSortKey\n : null\n const initialMessageId = message_id ?? jumpToUnreadAnchor\n const initialMessageIdIsAnchor = !!initialMessageId && !message_id\n\n return (\n <ConversationContextProvider\n conversationId={conversation_id}\n currentPageReplyRootId={reply_root_id ?? null}\n initialMessageId={initialMessageId}\n initialMessageIdIsAnchor={initialMessageIdIsAnchor}\n >\n <ConversationScreenContent route={route} />\n </ConversationContextProvider>\n )\n}\n\nfunction ConversationScreenContent({ route }: ConversationScreenProps) {\n const styles = useStyles()\n const navigation = useNavigation()\n const {\n conversation_id: conversationId,\n editing_message_id: editingMessageId,\n reply_root_id: replyRootId,\n reply_root_author_name: replyRootAuthorName,\n } = route.params\n const { data: conversation } = useConversation(route.params)\n const {\n messages,\n fetchOlderMessages,\n fetchNewerMessages,\n hasMoreNewerMessages,\n isFetchingNewerMessages,\n cancelFetchNewerMessages,\n } = useConversationMessages({ conversation_id: conversationId, reply_root_id: replyRootId })\n\n const { jumpToUnreadActive } = useJumpToUnreadGates()\n const { initialMessageId } = useConversationContext()\n\n useConversationJoltEvents({ conversationId })\n useConversationMessagesJoltEvents({ conversationId })\n useEnsureConversationsRouteExists()\n useMarkLatestMessageRead({ conversation, messages })\n const { onMessageSeen } = useTrackHighestSeenMessage()\n\n const items = useMemo(\n () =>\n groupMessages({\n ms: messages,\n inReplyScreen: !!replyRootId,\n jumpToUnreadActive,\n initialMessageId,\n }),\n [messages, replyRootId, jumpToUnreadActive, initialMessageId]\n )\n const noMessages = items.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(editingMessageId))\n const replyRootAuthorFirstName = replyRootAuthorName?.split(' ')[0]\n const replyHeaderTitle = replyRootAuthorFirstName\n ? `Reply to ${replyRootAuthorFirstName}`\n : 'Reply'\n // Prefer the membership for optimistic updates.\n const muted = conversation.conversationMembership?.muted ?? conversation.muted\n\n const listRef = useRef<FlatList>(null)\n const [dividerScrolledPast, setDividerScrolledPast] = useState(false)\n\n const observers = useMemo<ViewabilityObserver<EnrichedMessage>[]>(\n () => [\n reportViewableMessages(onMessageSeen),\n detectDividerExitTowardNewer({\n dividerKey: UNREAD_DIVIDER_KEY,\n initialMessageId,\n onExited: () => setDividerScrolledPast(true),\n }),\n ],\n [onMessageSeen, initialMessageId]\n )\n\n const { viewabilityConfigCallbackPairs, onScrollBeginDrag: viewabilityOnScrollBeginDrag } =\n useFlatListViewability({ observers })\n const {\n onContentSizeChange,\n onScrollToIndexFailed,\n onScrollBeginDrag: anchorOnScrollBeginDrag,\n } = useJumpToUnreadAnchor({ listRef, items })\n const onScrollBeginDrag = useCallback(() => {\n viewabilityOnScrollBeginDrag()\n anchorOnScrollBeginDrag()\n }, [viewabilityOnScrollBeginDrag, anchorOnScrollBeginDrag])\n const { onScroll, showJumpToBottomButton } = useScrollTracking({\n hasMoreNewerMessages,\n isFetchingNewerMessages,\n fetchNewerMessages,\n cancelFetchNewerMessages,\n })\n const { handleJumpToBottom, isJumpingToBottom } = useJumpToBottomAction({ listRef })\n\n const listHeader = useMemo(\n () => (\n <View>\n {isFetchingNewerMessages && (\n <Animated.View\n entering={FadeIn.duration(750)}\n exiting={FadeOut.duration(750)}\n style={styles.loadingFooter}\n accessibilityRole=\"progressbar\"\n accessibilityLabel=\"Loading more messages\"\n >\n <ActivityIndicator />\n </Animated.View>\n )}\n <View style={styles.listHeader} />\n </View>\n ),\n [isFetchingNewerMessages, styles.loadingFooter, styles.listHeader]\n )\n\n const renderItem = useCallback(\n ({ item }: { item: EnrichedMessage }) => {\n if (item.type === 'DateSeparator') return <InlineDateSeparator {...item} />\n if (item.type === 'UnreadDivider') return <UnreadDivider scrolledPast={dividerScrolledPast} />\n if (item.type === 'ReplyShadowMessage') {\n return (\n <ReplyShadowMessage\n {...item}\n conversation_id={conversationId}\n inReplyScreen={!!replyRootId}\n />\n )\n }\n if (isSystemMessage(item)) {\n return <SystemMessage message={item} conversationId={conversationId} />\n }\n return (\n <Message\n {...item}\n canDeleteNonAuthoredMessages={canDeleteNonAuthoredMessages}\n conversation_id={conversationId}\n latestReadMessageSortKey={conversation?.latestReadMessageSortKey}\n inReplyScreen={!!replyRootId}\n />\n )\n },\n [\n dividerScrolledPast,\n conversationId,\n replyRootId,\n canDeleteNonAuthoredMessages,\n conversation?.latestReadMessageSortKey,\n ]\n )\n\n useEffect(() => {\n if (replyRootId) {\n navigation.setParams({\n title: replyHeaderTitle,\n })\n } else {\n navigation.setParams({\n title: title,\n badge: badges?.[0],\n deleted: conversation?.deleted,\n muted,\n })\n }\n }, [navigation, title, badges, conversation?.deleted, replyRootId, replyHeaderTitle, muted])\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 <MessageList\n listRef={listRef}\n data={items}\n onScroll={onScroll}\n onScrollBeginDrag={onScrollBeginDrag}\n viewabilityConfigCallbackPairs={viewabilityConfigCallbackPairs}\n onContentSizeChange={onContentSizeChange}\n onScrollToIndexFailed={onScrollToIndexFailed}\n renderItem={renderItem}\n onEndReached={() => fetchOlderMessages()}\n ListHeaderComponent={listHeader}\n />\n )}\n <JumpToBottomButton\n onPress={handleJumpToBottom}\n visible={showJumpToBottomButton}\n loading={isJumpingToBottom}\n />\n {!noMessages && <TypingIndicator />}\n {showLeaderDisabledReplyBanner && <LeaderMessagesDisabledBanner />}\n <ConversationBottomBar\n conversation={conversation}\n canReply={canReply}\n replyRootAuthorFirstName={replyRootAuthorFirstName}\n replyRootId={replyRootId}\n currentlyEditingMessage={currentlyEditingMessage}\n />\n </KeyboardView>\n </View>\n )\n}\n\ninterface ConversationBottomBarProps {\n conversation: ConversationResource\n canReply: boolean | undefined\n replyRootAuthorFirstName: string | undefined\n replyRootId: string | null | undefined\n currentlyEditingMessage: MessageResource | undefined\n}\n\nfunction ConversationBottomBar({\n conversation,\n canReply,\n replyRootAuthorFirstName,\n replyRootId,\n currentlyEditingMessage,\n}: ConversationBottomBarProps) {\n if (conversation.disabled) return <ConversationDisabledBanner />\n if (!canReply) return <MemberMessagesDisabledBanner />\n return (\n <MessageForm.Root\n replyRootAuthorFirstName={replyRootAuthorFirstName}\n conversation={conversation}\n replyRootId={replyRootId}\n currentlyEditingMessage={currentlyEditingMessage}\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}\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\ninterface ConversationScreenTitleProps extends HeaderTitleProps {\n conversation_id: number\n badge?: ConversationBadgeResource\n deleted?: boolean\n muted?: boolean\n}\n\nexport const ConversationScreenTitle = ({\n conversation_id,\n badge,\n children,\n style,\n deleted,\n muted,\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 <View style={styles.titleTextContainer}>\n <HeaderTitle maxFontSizeMultiplier={1} style={style}>\n {children}\n </HeaderTitle>\n </View>\n {muted && <Icon name=\"general.bellMuted\" size={12} />}\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 flex: 1,\n },\n titleWrapper: {\n alignItems: 'center',\n columnGap: 4,\n flexDirection: 'row',\n flexShrink: 1,\n },\n titleTextContainer: {\n flexShrink: 1,\n minWidth: 0,\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 listHeader: {\n // Just whitespace to provide space where the typing indicator can be\n height: 16,\n },\n loadingFooter: {\n paddingVertical: 12,\n alignItems: 'center',\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"]}
@@ -0,0 +1,14 @@
1
+ import type { CustomMessage } from '@planningcenter/jolt-client/dist/types/JoltConnection';
2
+ interface AttachmentFlaggedEventData extends Record<string, unknown> {
3
+ data: {
4
+ attachment_id: string;
5
+ conversation_id: number;
6
+ content_type: string;
7
+ };
8
+ }
9
+ export interface AttachmentFlaggedEvent extends CustomMessage {
10
+ event: 'attachment.flagged';
11
+ data: AttachmentFlaggedEventData;
12
+ }
13
+ export {};
14
+ //# sourceMappingURL=attachment_events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment_events.d.ts","sourceRoot":"","sources":["../../../src/types/jolt_events/attachment_events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uDAAuD,CAAA;AAE1F,UAAU,0BAA2B,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAClE,IAAI,EAAE;QACJ,aAAa,EAAE,MAAM,CAAA;QACrB,eAAe,EAAE,MAAM,CAAA;QACvB,YAAY,EAAE,MAAM,CAAA;KACrB,CAAA;CACF;AAED,MAAM,WAAW,sBAAuB,SAAQ,aAAa;IAC3D,KAAK,EAAE,oBAAoB,CAAA;IAC3B,IAAI,EAAE,0BAA0B,CAAA;CACjC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=attachment_events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment_events.js","sourceRoot":"","sources":["../../../src/types/jolt_events/attachment_events.ts"],"names":[],"mappings":"","sourcesContent":["import type { CustomMessage } from '@planningcenter/jolt-client/dist/types/JoltConnection'\n\ninterface AttachmentFlaggedEventData extends Record<string, unknown> {\n data: {\n attachment_id: string\n conversation_id: number\n content_type: string\n }\n}\n\nexport interface AttachmentFlaggedEvent extends CustomMessage {\n event: 'attachment.flagged'\n data: AttachmentFlaggedEventData\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import type { AttachmentFlaggedEvent } from './attachment_events';
1
2
  import type { ConversationCreatedEvent, ConversationDeletedEvent, ConversationUpdatedEvent, ConversationReadEvent } from './conversation_events';
2
3
  import type { MessageCreatedEvent, MessageDeletedEvent, MessageUpdatedEvent } from './message_events';
3
4
  import type { ReactionCreatedEvent, ReactionDeletedEvent } from './reaction_events';
@@ -6,7 +7,8 @@ export type JoltConversationEvent = ConversationCreatedEvent | ConversationUpdat
6
7
  export type JoltMessageEvent = MessageCreatedEvent | MessageUpdatedEvent | MessageDeletedEvent;
7
8
  export type JoltReactionEvent = ReactionCreatedEvent | ReactionDeletedEvent;
8
9
  export type JoltTypingEvent = TypingBroadcastEvent;
9
- export type CustomJoltEvent = JoltConversationEvent | JoltMessageEvent | JoltReactionEvent | JoltTypingEvent;
10
+ export type JoltAttachmentEvent = AttachmentFlaggedEvent;
11
+ export type CustomJoltEvent = JoltConversationEvent | JoltMessageEvent | JoltReactionEvent | JoltTypingEvent | JoltAttachmentEvent;
10
12
  export type JoltEventName = CustomJoltEvent['event'] | 'STREAM_USER_UPDATED';
11
13
  export type JoltSubscriptionPattern = JoltEventName | 'reaction.*';
12
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/jolt_events/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EACxB,wBAAwB,EACxB,wBAAwB,EACxB,qBAAqB,EACtB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AACnF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAE3D,MAAM,MAAM,qBAAqB,GAC7B,wBAAwB,GACxB,wBAAwB,GACxB,wBAAwB,GACxB,qBAAqB,CAAA;AACzB,MAAM,MAAM,gBAAgB,GAAG,mBAAmB,GAAG,mBAAmB,GAAG,mBAAmB,CAAA;AAC9F,MAAM,MAAM,iBAAiB,GAAG,oBAAoB,GAAG,oBAAoB,CAAA;AAC3E,MAAM,MAAM,eAAe,GAAG,oBAAoB,CAAA;AAElD,MAAM,MAAM,eAAe,GACvB,qBAAqB,GACrB,gBAAgB,GAChB,iBAAiB,GACjB,eAAe,CAAA;AAEnB,MAAM,MAAM,aAAa,GAAG,eAAe,CAAC,OAAO,CAAC,GAAG,qBAAqB,CAAA;AAC5E,MAAM,MAAM,uBAAuB,GAAG,aAAa,GAAG,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/jolt_events/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AACjE,OAAO,KAAK,EACV,wBAAwB,EACxB,wBAAwB,EACxB,wBAAwB,EACxB,qBAAqB,EACtB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AACnF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAE3D,MAAM,MAAM,qBAAqB,GAC7B,wBAAwB,GACxB,wBAAwB,GACxB,wBAAwB,GACxB,qBAAqB,CAAA;AACzB,MAAM,MAAM,gBAAgB,GAAG,mBAAmB,GAAG,mBAAmB,GAAG,mBAAmB,CAAA;AAC9F,MAAM,MAAM,iBAAiB,GAAG,oBAAoB,GAAG,oBAAoB,CAAA;AAC3E,MAAM,MAAM,eAAe,GAAG,oBAAoB,CAAA;AAClD,MAAM,MAAM,mBAAmB,GAAG,sBAAsB,CAAA;AAExD,MAAM,MAAM,eAAe,GACvB,qBAAqB,GACrB,gBAAgB,GAChB,iBAAiB,GACjB,eAAe,GACf,mBAAmB,CAAA;AAEvB,MAAM,MAAM,aAAa,GAAG,eAAe,CAAC,OAAO,CAAC,GAAG,qBAAqB,CAAA;AAC5E,MAAM,MAAM,uBAAuB,GAAG,aAAa,GAAG,YAAY,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/jolt_events/index.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n ConversationCreatedEvent,\n ConversationDeletedEvent,\n ConversationUpdatedEvent,\n ConversationReadEvent,\n} from './conversation_events'\nimport type {\n MessageCreatedEvent,\n MessageDeletedEvent,\n MessageUpdatedEvent,\n} from './message_events'\nimport type { ReactionCreatedEvent, ReactionDeletedEvent } from './reaction_events'\nimport type { TypingBroadcastEvent } from './typing_events'\n\nexport type JoltConversationEvent =\n | ConversationCreatedEvent\n | ConversationUpdatedEvent\n | ConversationDeletedEvent\n | ConversationReadEvent\nexport type JoltMessageEvent = MessageCreatedEvent | MessageUpdatedEvent | MessageDeletedEvent\nexport type JoltReactionEvent = ReactionCreatedEvent | ReactionDeletedEvent\nexport type JoltTypingEvent = TypingBroadcastEvent\n\nexport type CustomJoltEvent =\n | JoltConversationEvent\n | JoltMessageEvent\n | JoltReactionEvent\n | JoltTypingEvent\n\nexport type JoltEventName = CustomJoltEvent['event'] | 'STREAM_USER_UPDATED'\nexport type JoltSubscriptionPattern = JoltEventName | 'reaction.*'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/jolt_events/index.ts"],"names":[],"mappings":"","sourcesContent":["import type { AttachmentFlaggedEvent } from './attachment_events'\nimport type {\n ConversationCreatedEvent,\n ConversationDeletedEvent,\n ConversationUpdatedEvent,\n ConversationReadEvent,\n} from './conversation_events'\nimport type {\n MessageCreatedEvent,\n MessageDeletedEvent,\n MessageUpdatedEvent,\n} from './message_events'\nimport type { ReactionCreatedEvent, ReactionDeletedEvent } from './reaction_events'\nimport type { TypingBroadcastEvent } from './typing_events'\n\nexport type JoltConversationEvent =\n | ConversationCreatedEvent\n | ConversationUpdatedEvent\n | ConversationDeletedEvent\n | ConversationReadEvent\nexport type JoltMessageEvent = MessageCreatedEvent | MessageUpdatedEvent | MessageDeletedEvent\nexport type JoltReactionEvent = ReactionCreatedEvent | ReactionDeletedEvent\nexport type JoltTypingEvent = TypingBroadcastEvent\nexport type JoltAttachmentEvent = AttachmentFlaggedEvent\n\nexport type CustomJoltEvent =\n | JoltConversationEvent\n | JoltMessageEvent\n | JoltReactionEvent\n | JoltTypingEvent\n | JoltAttachmentEvent\n\nexport type JoltEventName = CustomJoltEvent['event'] | 'STREAM_USER_UPDATED'\nexport type JoltSubscriptionPattern = JoltEventName | 'reaction.*'\n"]}