@planningcenter/chat-react-native 3.14.0-rc.0 → 3.14.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/components/conversation/message.d.ts.map +1 -1
- package/build/components/conversation/message.js +4 -0
- package/build/components/conversation/message.js.map +1 -1
- package/build/components/conversation/message_form.d.ts.map +1 -1
- package/build/components/conversation/message_form.js +23 -3
- package/build/components/conversation/message_form.js.map +1 -1
- package/build/components/conversations/conversations.d.ts.map +1 -1
- package/build/components/conversations/conversations.js +2 -0
- package/build/components/conversations/conversations.js.map +1 -1
- package/build/components/display/toggle_button.d.ts +5 -1
- package/build/components/display/toggle_button.d.ts.map +1 -1
- package/build/components/display/toggle_button.js +8 -2
- package/build/components/display/toggle_button.js.map +1 -1
- package/build/hooks/use_attachment_uploader.d.ts +2 -1
- package/build/hooks/use_attachment_uploader.d.ts.map +1 -1
- package/build/hooks/use_attachment_uploader.js +6 -2
- package/build/hooks/use_attachment_uploader.js.map +1 -1
- package/build/hooks/use_conversations_jolt_events.d.ts.map +1 -1
- package/build/hooks/use_conversations_jolt_events.js +10 -5
- package/build/hooks/use_conversations_jolt_events.js.map +1 -1
- package/build/hooks/use_jolt.d.ts +1 -1
- package/build/hooks/use_jolt.d.ts.map +1 -1
- package/build/hooks/use_jolt.js +3 -2
- package/build/hooks/use_jolt.js.map +1 -1
- package/build/hooks/use_message_draft.d.ts +13 -0
- package/build/hooks/use_message_draft.d.ts.map +1 -0
- package/build/hooks/use_message_draft.js +83 -0
- package/build/hooks/use_message_draft.js.map +1 -0
- package/build/screens/conversation_new/components/services_form.d.ts.map +1 -1
- package/build/screens/conversation_new/components/services_form.js +12 -8
- package/build/screens/conversation_new/components/services_form.js.map +1 -1
- package/build/screens/conversation_screen.d.ts.map +1 -1
- package/build/screens/conversation_screen.js +6 -1
- package/build/screens/conversation_screen.js.map +1 -1
- package/build/screens/conversation_select_recipients/conversation_select_recipients_screen.d.ts.map +1 -1
- package/build/screens/conversation_select_recipients/conversation_select_recipients_screen.js +10 -6
- package/build/screens/conversation_select_recipients/conversation_select_recipients_screen.js.map +1 -1
- package/build/screens/conversations/conversations_screen.d.ts.map +1 -1
- package/build/screens/conversations/conversations_screen.js +0 -2
- package/build/screens/conversations/conversations_screen.js.map +1 -1
- package/build/screens/message_actions_screen.d.ts.map +1 -1
- package/build/screens/message_actions_screen.js +2 -1
- package/build/screens/message_actions_screen.js.map +1 -1
- package/build/types/resources/denormalized_attachment_resource_for_create.d.ts +1 -0
- package/build/types/resources/denormalized_attachment_resource_for_create.d.ts.map +1 -1
- package/build/types/resources/denormalized_attachment_resource_for_create.js.map +1 -1
- package/package.json +2 -2
- package/src/components/conversation/message.tsx +4 -0
- package/src/components/conversation/message_form.tsx +25 -3
- package/src/components/conversations/conversations.tsx +3 -1
- package/src/components/display/toggle_button.tsx +15 -1
- package/src/hooks/use_attachment_uploader.ts +12 -2
- package/src/hooks/use_conversations_jolt_events.ts +13 -6
- package/src/hooks/use_jolt.ts +6 -2
- package/src/hooks/use_message_draft.ts +108 -0
- package/src/screens/conversation_new/components/services_form.tsx +4 -2
- package/src/screens/conversation_screen.tsx +7 -0
- package/src/screens/conversation_select_recipients/conversation_select_recipients_screen.tsx +4 -2
- package/src/screens/conversations/conversations_screen.tsx +0 -2
- package/src/screens/message_actions_screen.tsx +2 -1
- package/src/types/resources/denormalized_attachment_resource_for_create.ts +1 -0
- package/build/screens/conversations/components/conversations_jolt_events.d.ts +0 -7
- package/build/screens/conversations/components/conversations_jolt_events.d.ts.map +0 -1
- package/build/screens/conversations/components/conversations_jolt_events.js +0 -14
- package/build/screens/conversations/components/conversations_jolt_events.js.map +0 -1
- package/src/screens/conversations/components/conversations_jolt_events.tsx +0 -23
|
@@ -5,10 +5,10 @@ import { useApiClient } from './use_api_client';
|
|
|
5
5
|
const MAX_FILE_SIZE_IN_MB = 50;
|
|
6
6
|
const MAX_FILE_SIZE_IN_BYTES = MAX_FILE_SIZE_IN_MB * 1024 * 1024;
|
|
7
7
|
const MAX_NUMBER_OF_ATTACHMENTS = 10;
|
|
8
|
-
export function useAttachmentUploader({ conversationId }) {
|
|
8
|
+
export function useAttachmentUploader({ conversationId, draftAttachments, }) {
|
|
9
9
|
const apiClient = useApiClient();
|
|
10
10
|
const uploadApi = useUploadClient();
|
|
11
|
-
const [attachments, setAttachments] = useState([]);
|
|
11
|
+
const [attachments, setAttachments] = useState(() => draftAttachments || []);
|
|
12
12
|
const uploadState = useRef({});
|
|
13
13
|
const [lastUploadId, setLastUploadId] = useState();
|
|
14
14
|
const numberOfAttachments = attachments.length;
|
|
@@ -45,6 +45,7 @@ export function useAttachmentUploader({ conversationId }) {
|
|
|
45
45
|
const newAttachments = validFiles.map(file => ({
|
|
46
46
|
file,
|
|
47
47
|
status: 'uploading',
|
|
48
|
+
uploadedAt: Date.now(),
|
|
48
49
|
}));
|
|
49
50
|
if (newAttachments && newAttachments.length > 0) {
|
|
50
51
|
setAttachments(prevAttachments => [...prevAttachments, ...newAttachments]);
|
|
@@ -81,6 +82,9 @@ export function useAttachmentUploader({ conversationId }) {
|
|
|
81
82
|
return;
|
|
82
83
|
setLastUploadId(undefined);
|
|
83
84
|
setAttachments(attachments.map(attachment => {
|
|
85
|
+
// Don't risk overwriting ids already set
|
|
86
|
+
if (attachment.id)
|
|
87
|
+
return attachment;
|
|
84
88
|
const state = uploadState.current[attachment.file.name];
|
|
85
89
|
if (state) {
|
|
86
90
|
return { ...attachment, id: state.id, status: state.status };
|
|
@@ -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 { SUPPORTED_EXTENSIONS } from './attachments/supported_extensions'\nimport { useUploadClient } from './use_upload_client'\nimport { useApiClient } from './use_api_client'\nimport { ApiResource } from '../types'\nimport {\n FileAttachment,\n FileUploadState,\n NativeAttachmentFile,\n} from '../types/resources/denormalized_attachment_resource_for_create'\n\nexport interface FileError {\n file_type?: string[]\n file_size?: boolean\n}\n\nconst MAX_FILE_SIZE_IN_MB = 50\nconst MAX_FILE_SIZE_IN_BYTES = MAX_FILE_SIZE_IN_MB * 1024 * 1024\nconst MAX_NUMBER_OF_ATTACHMENTS = 10\n\nexport function useAttachmentUploader({ conversationId }: { conversationId: number }) {\n const apiClient = useApiClient()\n const uploadApi = useUploadClient()\n const [attachments, setAttachments] = useState<FileAttachment[]>([])\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.split('.').pop() as string\n const isValidExtension = SUPPORTED_EXTENSIONS.includes(`.${extension}`)\n const isValidFileSize = file.size <= MAX_FILE_SIZE_IN_BYTES\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 ${MAX_FILE_SIZE_IN_MB} MB`)\n }\n if (numberOfAttachments + validFiles.length > MAX_NUMBER_OF_ATTACHMENTS) {\n errorMessages.push(`You can't attach more than ${MAX_NUMBER_OF_ATTACHMENTS} 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 }))\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(() => {\n uploadState.current[attachment.file.name] = {\n status: 'error',\n }\n setLastUploadId(attachment.file.name)\n })\n })\n }\n },\n [numberOfAttachments, uploadApi, apiClient.chat, conversationId]\n )\n\n useEffect(() => {\n if (!lastUploadId) return\n\n setLastUploadId(undefined)\n setAttachments(\n attachments.map(attachment => {\n const state = uploadState.current[attachment.file.name]\n if (state) {\n return { ...attachment, id: state.id, status: state.status }\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 reset = useCallback(() => {\n setAttachments([])\n setErrorMessage(null)\n }, [])\n\n const pendingUploads = attachments.filter(a => a.status === 'uploading').length > 0\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 reset,\n pendingUploads,\n errorMessage,\n remainingAttachable: MAX_NUMBER_OF_ATTACHMENTS - numberOfAttachments,\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 { SUPPORTED_EXTENSIONS } from './attachments/supported_extensions'\nimport { useUploadClient } from './use_upload_client'\nimport { useApiClient } from './use_api_client'\nimport { ApiResource } from '../types'\nimport {\n FileAttachment,\n FileUploadState,\n NativeAttachmentFile,\n} from '../types/resources/denormalized_attachment_resource_for_create'\n\nexport interface FileError {\n file_type?: string[]\n file_size?: boolean\n}\n\nconst MAX_FILE_SIZE_IN_MB = 50\nconst MAX_FILE_SIZE_IN_BYTES = MAX_FILE_SIZE_IN_MB * 1024 * 1024\nconst MAX_NUMBER_OF_ATTACHMENTS = 10\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 [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.split('.').pop() as string\n const isValidExtension = SUPPORTED_EXTENSIONS.includes(`.${extension}`)\n const isValidFileSize = file.size <= MAX_FILE_SIZE_IN_BYTES\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 ${MAX_FILE_SIZE_IN_MB} MB`)\n }\n if (numberOfAttachments + validFiles.length > MAX_NUMBER_OF_ATTACHMENTS) {\n errorMessages.push(`You can't attach more than ${MAX_NUMBER_OF_ATTACHMENTS} 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(() => {\n uploadState.current[attachment.file.name] = {\n status: 'error',\n }\n setLastUploadId(attachment.file.name)\n })\n })\n }\n },\n [numberOfAttachments, uploadApi, apiClient.chat, conversationId]\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 }\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 reset = useCallback(() => {\n setAttachments([])\n setErrorMessage(null)\n }, [])\n\n const pendingUploads = attachments.filter(a => a.status === 'uploading').length > 0\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 reset,\n pendingUploads,\n errorMessage,\n remainingAttachable: MAX_NUMBER_OF_ATTACHMENTS - numberOfAttachments,\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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_conversations_jolt_events.d.ts","sourceRoot":"","sources":["../../src/hooks/use_conversations_jolt_events.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAA;
|
|
1
|
+
{"version":3,"file":"use_conversations_jolt_events.d.ts","sourceRoot":"","sources":["../../src/hooks/use_conversations_jolt_events.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAA;AAavE,wBAAgB,0BAA0B,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,QA6BjF"}
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import { useConversationsCache } from './use_conversations_cache';
|
|
2
|
-
import {
|
|
2
|
+
import { currentPersonRequestArgs, useCurrentPersonCache } from './use_current_person';
|
|
3
3
|
import { useJoltChannel, useJoltEvent } from './use_jolt';
|
|
4
|
-
import {
|
|
4
|
+
import { useApiGet } from './use_api';
|
|
5
5
|
import { useApiClient } from './use_api_client';
|
|
6
|
+
import { completeMessageCreationConversationTracking } from '../utils/performance_tracking';
|
|
7
|
+
const useCurrentPerson = () => {
|
|
8
|
+
return useApiGet(currentPersonRequestArgs);
|
|
9
|
+
};
|
|
6
10
|
export function useConversationsJoltEvents(args) {
|
|
7
|
-
const currentPerson = useCurrentPerson();
|
|
8
|
-
const joltChannel = useJoltChannel(`chat.people.${currentPerson.id}`);
|
|
11
|
+
const { data: currentPerson } = useCurrentPerson();
|
|
9
12
|
const cache = useConversationsCache(args);
|
|
10
13
|
const currentPersonCache = useCurrentPersonCache();
|
|
11
14
|
const apiClient = useApiClient();
|
|
15
|
+
const enabled = currentPerson?.id ? true : false;
|
|
16
|
+
const joltChannel = useJoltChannel(`chat.people.${currentPerson?.id}`, enabled);
|
|
12
17
|
useJoltEvent(joltChannel, 'conversation.updated', (e) => {
|
|
13
18
|
if (e.data.data.last_message_idempotent_key &&
|
|
14
|
-
e.data.data.last_message_author_id === currentPerson
|
|
19
|
+
e.data.data.last_message_author_id === currentPerson?.id) {
|
|
15
20
|
completeMessageCreationConversationTracking({
|
|
16
21
|
apiClient,
|
|
17
22
|
idempotentKey: e.data.data.last_message_idempotent_key,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_conversations_jolt_events.js","sourceRoot":"","sources":["../../src/hooks/use_conversations_jolt_events.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAA;AACjE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"use_conversations_jolt_events.js","sourceRoot":"","sources":["../../src/hooks/use_conversations_jolt_events.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAA;AACjE,OAAO,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AACtF,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAE/C,OAAO,EAAE,2CAA2C,EAAE,MAAM,+BAA+B,CAAA;AAE3F,MAAM,gBAAgB,GAAG,GAAG,EAAE;IAC5B,OAAO,SAAS,CAAwB,wBAAwB,CAAC,CAAA;AACnE,CAAC,CAAA;AAED,MAAM,UAAU,0BAA0B,CAAC,IAAuC;IAChF,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,gBAAgB,EAAE,CAAA;IAClD,MAAM,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAA;IACzC,MAAM,kBAAkB,GAAG,qBAAqB,EAAE,CAAA;IAClD,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;IAChC,MAAM,OAAO,GAAG,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAA;IAChD,MAAM,WAAW,GAAG,cAAc,CAAC,eAAe,aAAa,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,CAAA;IAE/E,YAAY,CAAC,WAAW,EAAE,sBAAsB,EAAE,CAAC,CAAwB,EAAE,EAAE;QAC7E,IACE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,2BAA2B;YACvC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAsB,KAAK,aAAa,EAAE,EAAE,EACxD,CAAC;YACD,2CAA2C,CAAC;gBAC1C,SAAS;gBACT,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,2BAA2B;aACvD,CAAC,CAAA;QACJ,CAAC;QACD,KAAK,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAA;IAC3C,CAAC,CAAC,CAAA;IACF,YAAY,CAAC,WAAW,EAAE,sBAAsB,EAAE,CAAC,CAAwB,EAAE,EAAE,CAC7E,KAAK,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAC1C,CAAA;IACD,YAAY,CAAC,WAAW,EAAE,wBAAwB,EAAE,CAAC,CAAwB,EAAE,EAAE,CAC/E,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CACtC,CAAA;IAED,YAAY,CAAC,WAAW,EAAE,qBAAqB,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAA,CAAC,gDAAgD;IAChI,YAAY,CAAC,WAAW,EAAE,mBAAmB,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAA;AAC/E,CAAC","sourcesContent":["import { CurrentPersonResource } from '../types'\nimport { ConversationRequestArgs } from '../utils/request/conversation'\nimport { useConversationsCache } from './use_conversations_cache'\nimport { currentPersonRequestArgs, useCurrentPersonCache } from './use_current_person'\nimport { useJoltChannel, useJoltEvent } from './use_jolt'\nimport { useApiGet } from './use_api'\nimport { useApiClient } from './use_api_client'\nimport { JoltConversationEvent } from '../types/jolt_events'\nimport { completeMessageCreationConversationTracking } from '../utils/performance_tracking'\n\nconst useCurrentPerson = () => {\n return useApiGet<CurrentPersonResource>(currentPersonRequestArgs)\n}\n\nexport function useConversationsJoltEvents(args?: Partial<ConversationRequestArgs>) {\n const { data: currentPerson } = useCurrentPerson()\n const cache = useConversationsCache(args)\n const currentPersonCache = useCurrentPersonCache()\n const apiClient = useApiClient()\n const enabled = currentPerson?.id ? true : false\n const joltChannel = useJoltChannel(`chat.people.${currentPerson?.id}`, enabled)\n\n useJoltEvent(joltChannel, 'conversation.updated', (e: JoltConversationEvent) => {\n if (\n e.data.data.last_message_idempotent_key &&\n e.data.data.last_message_author_id === currentPerson?.id\n ) {\n completeMessageCreationConversationTracking({\n apiClient,\n idempotentKey: e.data.data.last_message_idempotent_key,\n })\n }\n cache.fetchUpdate({ id: e.data.data.id })\n })\n useJoltEvent(joltChannel, 'conversation.created', (e: JoltConversationEvent) =>\n cache.fetchCreate({ id: e.data.data.id })\n )\n useJoltEvent(joltChannel, 'conversation.destroyed', (e: JoltConversationEvent) =>\n cache.destroy({ id: e.data.data.id })\n )\n\n useJoltEvent(joltChannel, 'STREAM_USER_UPDATED', currentPersonCache.invalidate) // Would be nice to have a non-stream chat event\n useJoltEvent(joltChannel, 'conversation.read', currentPersonCache.invalidate)\n}\n"]}
|
|
@@ -2,7 +2,7 @@ import JoltClient from '@planningcenter/jolt-client';
|
|
|
2
2
|
import { CustomMessage } from '@planningcenter/jolt-client/dist/types/JoltConnection';
|
|
3
3
|
import { JoltSubscription } from '@planningcenter/jolt-client/dist/types/JoltSubscription';
|
|
4
4
|
export declare const useJoltClient: () => JoltClient | undefined;
|
|
5
|
-
export declare function useJoltChannel(channelName: string): JoltSubscription | undefined | null;
|
|
5
|
+
export declare function useJoltChannel(channelName: string, enabled?: boolean): JoltSubscription | undefined | null;
|
|
6
6
|
type UserCallbackFn<T> = (_event: T) => void;
|
|
7
7
|
export declare function useJoltEvent<T extends CustomMessage>(channel: JoltSubscription | undefined | null, eventName: string, callback: UserCallbackFn<T>): void;
|
|
8
8
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_jolt.d.ts","sourceRoot":"","sources":["../../src/hooks/use_jolt.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,6BAA6B,CAAA;AACpD,OAAO,EACL,aAAa,EAEd,MAAM,uDAAuD,CAAA;AAC9D,OAAO,EAEL,gBAAgB,EACjB,MAAM,yDAAyD,CAAA;AAchE,eAAO,MAAM,aAAa,QAAO,UAAU,GAAG,SAiG7C,CAAA;AAED,wBAAgB,cAAc,
|
|
1
|
+
{"version":3,"file":"use_jolt.d.ts","sourceRoot":"","sources":["../../src/hooks/use_jolt.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,6BAA6B,CAAA;AACpD,OAAO,EACL,aAAa,EAEd,MAAM,uDAAuD,CAAA;AAC9D,OAAO,EAEL,gBAAgB,EACjB,MAAM,yDAAyD,CAAA;AAchE,eAAO,MAAM,aAAa,QAAO,UAAU,GAAG,SAiG7C,CAAA;AAED,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,OAAc,GACtB,gBAAgB,GAAG,SAAS,GAAG,IAAI,CAwCrC;AAED,KAAK,cAAc,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,CAAA;AAE5C,wBAAgB,YAAY,CAAC,CAAC,SAAS,aAAa,EAClD,OAAO,EAAE,gBAAgB,GAAG,SAAS,GAAG,IAAI,EAC5C,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,QAO5B"}
|
package/build/hooks/use_jolt.js
CHANGED
|
@@ -83,10 +83,11 @@ export const useJoltClient = () => {
|
|
|
83
83
|
});
|
|
84
84
|
return joltClient;
|
|
85
85
|
};
|
|
86
|
-
export function useJoltChannel(channelName) {
|
|
86
|
+
export function useJoltChannel(channelName, enabled = true) {
|
|
87
87
|
const jolt = useJoltClient();
|
|
88
88
|
const appState = useAppState();
|
|
89
89
|
const queryClient = useQueryClient();
|
|
90
|
+
const ready = Boolean(jolt) && appState !== 'background' && enabled;
|
|
90
91
|
const handleSubscribe = useCallback(async () => {
|
|
91
92
|
if (!jolt)
|
|
92
93
|
return null;
|
|
@@ -99,7 +100,7 @@ export function useJoltChannel(channelName) {
|
|
|
99
100
|
const { data: subscription } = useQuery({
|
|
100
101
|
queryKey: ['jolt-subscription', channelName],
|
|
101
102
|
queryFn: handleSubscribe,
|
|
102
|
-
enabled:
|
|
103
|
+
enabled: ready,
|
|
103
104
|
});
|
|
104
105
|
const handleUnsubscribe = useCallback(() => {
|
|
105
106
|
queryClient.removeQueries({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_jolt.js","sourceRoot":"","sources":["../../src/hooks/use_jolt.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"use_jolt.js","sourceRoot":"","sources":["../../src/hooks/use_jolt.ts"],"names":[],"mappings":"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","sourcesContent":["import JoltClient from '@planningcenter/jolt-client'\nimport {\n CustomMessage,\n FetchAuthToken,\n} from '@planningcenter/jolt-client/dist/types/JoltConnection'\nimport {\n FetchSubscribeToken,\n JoltSubscription,\n} from '@planningcenter/jolt-client/dist/types/JoltSubscription'\nimport { useQuery, useQueryClient, useSuspenseQuery } from '@tanstack/react-query'\nimport { useCallback, useEffect, useMemo } from 'react'\nimport { useChatContext } from '../contexts/chat_context'\nimport { ApiResource } from '../types'\nimport { Client, Uri } from '../utils'\nimport { useAppState } from './use_app_state'\n\ninterface JoltResponse {\n type: 'JoltToken'\n id: string\n wssUrl: string\n}\n\nexport const useJoltClient = (): JoltClient | undefined => {\n const { session } = useChatContext()\n const sessionAccessToken = session.token?.access_token\n const queryClient = useQueryClient()\n const uri = useMemo(() => new Uri({ session }), [session])\n const apiClient = useMemo(\n () =>\n new Client({\n root: uri.api(`/chat/v2`),\n defaultHeaders: uri.headers,\n version: '2018-11-01',\n }),\n [uri]\n )\n\n const fetchJoltToken = async () => {\n return queryClient.fetchQuery({\n queryKey: ['jolt-token'],\n queryFn: () => {\n return apiClient.post<ApiResource<JoltResponse>>({\n url: '/me/jolt_authorize',\n data: {\n data: {\n type: 'JoltToken',\n attributes: {},\n },\n },\n })\n },\n staleTime: 5000, // 5 seconds\n })\n }\n\n /** The wssUrl is static and doesn't change so we can cache it to infinity and beyond */\n const { data: wssUrl } = useSuspenseQuery<string>({\n queryKey: ['wss-url'],\n queryFn: () => fetchJoltToken().then(res => res.data.wssUrl),\n staleTime: Infinity,\n gcTime: Infinity,\n })\n\n const fetchAuthTokenFn: FetchAuthToken = () => {\n return queryClient.fetchQuery({\n queryKey: ['jolt-auth-token'],\n queryFn: () => fetchJoltToken().then(res => res.data.id),\n })\n }\n\n const fetchSubscribeToken: FetchSubscribeToken = (channel: string, connectionId: string) => {\n return apiClient\n .post<ApiResource<JoltResponse>>({\n url: '/me/jolt_subscribe',\n data: {\n data: {\n type: 'JoltSubscribeToken',\n attributes: { channel, cid: connectionId },\n },\n },\n })\n .then(res => res.data.id)\n .catch((res: unknown) => {\n console.error('failed to subscribe to Jolt channel', res)\n return ''\n })\n }\n\n const fetchSubscribeTokenFn: FetchSubscribeToken = (\n channel: string,\n connectionId: string,\n options\n ) => {\n return queryClient.fetchQuery({\n queryKey: ['jolt-subscribe-token', channel, connectionId],\n queryFn: () => fetchSubscribeToken(channel, connectionId, options),\n })\n }\n\n const { data: joltClient } = useQuery({\n enabled: Boolean(wssUrl),\n queryKey: ['jolt-client', wssUrl, sessionAccessToken],\n queryFn: async () => {\n if (!wssUrl) return undefined\n\n return new JoltClient(\n wssUrl,\n {\n fetchAuthTokenFn,\n fetchSubscribeTokenFn,\n },\n { logToConsole: false }\n )\n },\n staleTime: Infinity,\n gcTime: Infinity,\n })\n\n return joltClient\n}\n\nexport function useJoltChannel(\n channelName: string,\n enabled: boolean = true\n): JoltSubscription | undefined | null {\n const jolt = useJoltClient()\n const appState = useAppState()\n const queryClient = useQueryClient()\n const ready = Boolean(jolt) && appState !== 'background' && enabled\n\n const handleSubscribe = useCallback(async () => {\n if (!jolt) return null\n\n // If the subscription already exists, we don't need to subscribe again\n const alreadySubscribed = jolt.subscriptions.find(c => c.channel === channelName)\n if (alreadySubscribed) return alreadySubscribed\n\n return jolt.subscribe(channelName)\n }, [channelName, jolt])\n\n const { data: subscription } = useQuery<JoltSubscription | null>({\n queryKey: ['jolt-subscription', channelName],\n queryFn: handleSubscribe,\n enabled: ready,\n })\n\n const handleUnsubscribe = useCallback(() => {\n queryClient.removeQueries({\n queryKey: ['jolt-subscription', channelName],\n exact: true,\n })\n\n jolt?.unsubscribe(channelName)\n }, [queryClient, channelName, jolt])\n\n useEffect(() => {\n if (appState !== 'background') return handleUnsubscribe\n\n handleUnsubscribe()\n\n return () => null\n }, [appState, handleUnsubscribe])\n\n return subscription\n}\n\ntype UserCallbackFn<T> = (_event: T) => void\n\nexport function useJoltEvent<T extends CustomMessage>(\n channel: JoltSubscription | undefined | null,\n eventName: string,\n callback: UserCallbackFn<T>\n) {\n useEffect(() => {\n if (!channel) return () => {}\n\n return channel.bind(eventName, e => callback(e as T))\n }, [channel, eventName, callback])\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FileAttachment } from '../types/resources/denormalized_attachment_resource_for_create';
|
|
2
|
+
interface MessageDraft {
|
|
3
|
+
text: string;
|
|
4
|
+
attachments: FileAttachment[];
|
|
5
|
+
lastUpdated: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function useMessageDraft(conversationId: number): {
|
|
8
|
+
draft: MessageDraft | null;
|
|
9
|
+
saveDraft: (text: string, attachments: FileAttachment[]) => void;
|
|
10
|
+
clearDraft: () => void;
|
|
11
|
+
};
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=use_message_draft.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use_message_draft.d.ts","sourceRoot":"","sources":["../../src/hooks/use_message_draft.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gEAAgE,CAAA;AAEpG,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,cAAc,EAAE,CAAA;IAC7B,WAAW,EAAE,MAAM,CAAA;CACpB;AAQD,wBAAgB,eAAe,CAAC,cAAc,EAAE,MAAM;;sBAyC3C,MAAM,eAAe,cAAc,EAAE;;EAkD/C"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
2
|
+
import { useAsyncStorage } from './use_async_storage';
|
|
3
|
+
const DRAFT_STORAGE_KEY = 'chat_message_drafts';
|
|
4
|
+
const DRAFT_EXPIRY_HOURS = 720; // 30 days
|
|
5
|
+
const DRAFT_EXPIRY_MS = DRAFT_EXPIRY_HOURS * 60 * 60 * 1000;
|
|
6
|
+
const ATTACHMENT_EXPIRY_HOURS = 48; // 2 days
|
|
7
|
+
const ATTACHMENT_EXPIRY_MS = ATTACHMENT_EXPIRY_HOURS * 60 * 60 * 1000;
|
|
8
|
+
export function useMessageDraft(conversationId) {
|
|
9
|
+
const conversationKey = conversationId.toString();
|
|
10
|
+
const [allDrafts, setAllDrafts] = useAsyncStorage(DRAFT_STORAGE_KEY, {});
|
|
11
|
+
const [draft, setDraft] = useState(() => {
|
|
12
|
+
const storedDraft = allDrafts[conversationKey] || null;
|
|
13
|
+
// Filter expired attachments
|
|
14
|
+
if (storedDraft?.attachments) {
|
|
15
|
+
const now = Date.now();
|
|
16
|
+
storedDraft.attachments = storedDraft.attachments.filter(attachment => {
|
|
17
|
+
if (!attachment.uploadedAt)
|
|
18
|
+
return false;
|
|
19
|
+
return now - attachment.uploadedAt < ATTACHMENT_EXPIRY_MS;
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return storedDraft;
|
|
23
|
+
});
|
|
24
|
+
// Clean up expired drafts on mount
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const now = Date.now();
|
|
27
|
+
const validDrafts = {};
|
|
28
|
+
Object.entries(allDrafts).forEach(([id, draftData]) => {
|
|
29
|
+
if (draftData?.lastUpdated && now - draftData.lastUpdated < DRAFT_EXPIRY_MS) {
|
|
30
|
+
validDrafts[id] = draftData;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
// If we filtered out any drafts, update storage
|
|
34
|
+
if (Object.keys(validDrafts).length !== Object.keys(allDrafts).length) {
|
|
35
|
+
setAllDrafts(validDrafts);
|
|
36
|
+
}
|
|
37
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
38
|
+
}, []); // I only want this to run on mount
|
|
39
|
+
const saveDraft = useCallback((text, attachments) => {
|
|
40
|
+
const hasContent = text.trim().length > 0 || attachments.length > 0;
|
|
41
|
+
const updatedDrafts = { ...allDrafts };
|
|
42
|
+
if (hasContent) {
|
|
43
|
+
// Convert attachments to serializable format (similar to web implementation)
|
|
44
|
+
const normalizedAttachments = attachments
|
|
45
|
+
.filter(att => att.id && att.status === 'success')
|
|
46
|
+
.map(att => ({
|
|
47
|
+
...att,
|
|
48
|
+
file: {
|
|
49
|
+
uri: att.file.uri,
|
|
50
|
+
name: att.file.name,
|
|
51
|
+
type: att.file.type,
|
|
52
|
+
size: att.file.size,
|
|
53
|
+
width: att.file.width,
|
|
54
|
+
height: att.file.height,
|
|
55
|
+
},
|
|
56
|
+
}));
|
|
57
|
+
const newDraft = {
|
|
58
|
+
text,
|
|
59
|
+
attachments: normalizedAttachments,
|
|
60
|
+
lastUpdated: Date.now(),
|
|
61
|
+
};
|
|
62
|
+
updatedDrafts[conversationKey] = newDraft;
|
|
63
|
+
setDraft(newDraft);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
delete updatedDrafts[conversationKey];
|
|
67
|
+
setDraft(null);
|
|
68
|
+
}
|
|
69
|
+
setAllDrafts(updatedDrafts);
|
|
70
|
+
}, [conversationKey, allDrafts, setAllDrafts]);
|
|
71
|
+
const clearDraft = useCallback(() => {
|
|
72
|
+
const updatedDrafts = { ...allDrafts };
|
|
73
|
+
delete updatedDrafts[conversationKey];
|
|
74
|
+
setAllDrafts(updatedDrafts);
|
|
75
|
+
setDraft(null);
|
|
76
|
+
}, [conversationKey, allDrafts, setAllDrafts]);
|
|
77
|
+
return {
|
|
78
|
+
draft,
|
|
79
|
+
saveDraft,
|
|
80
|
+
clearDraft,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=use_message_draft.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use_message_draft.js","sourceRoot":"","sources":["../../src/hooks/use_message_draft.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useState } from 'react'\nimport { useAsyncStorage } from './use_async_storage'\nimport type { FileAttachment } from '../types/resources/denormalized_attachment_resource_for_create'\n\ninterface MessageDraft {\n text: string\n attachments: FileAttachment[]\n lastUpdated: number\n}\n\nconst DRAFT_STORAGE_KEY = 'chat_message_drafts'\nconst DRAFT_EXPIRY_HOURS = 720 // 30 days\nconst DRAFT_EXPIRY_MS = DRAFT_EXPIRY_HOURS * 60 * 60 * 1000\nconst ATTACHMENT_EXPIRY_HOURS = 48 // 2 days\nconst ATTACHMENT_EXPIRY_MS = ATTACHMENT_EXPIRY_HOURS * 60 * 60 * 1000\n\nexport function useMessageDraft(conversationId: number) {\n const conversationKey = conversationId.toString()\n const [allDrafts, setAllDrafts] = useAsyncStorage<Record<string, MessageDraft>>(\n DRAFT_STORAGE_KEY,\n {}\n )\n\n const [draft, setDraft] = useState<MessageDraft | null>(() => {\n const storedDraft = allDrafts[conversationKey] || null\n\n // Filter expired attachments\n if (storedDraft?.attachments) {\n const now = Date.now()\n storedDraft.attachments = storedDraft.attachments.filter(attachment => {\n if (!attachment.uploadedAt) return false\n return now - attachment.uploadedAt < ATTACHMENT_EXPIRY_MS\n })\n }\n\n return storedDraft\n })\n\n // Clean up expired drafts on mount\n useEffect(() => {\n const now = Date.now()\n const validDrafts: Record<string, MessageDraft> = {}\n\n Object.entries(allDrafts).forEach(([id, draftData]) => {\n if (draftData?.lastUpdated && now - draftData.lastUpdated < DRAFT_EXPIRY_MS) {\n validDrafts[id] = draftData\n }\n })\n\n // If we filtered out any drafts, update storage\n if (Object.keys(validDrafts).length !== Object.keys(allDrafts).length) {\n setAllDrafts(validDrafts)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []) // I only want this to run on mount\n\n const saveDraft = useCallback(\n (text: string, attachments: FileAttachment[]) => {\n const hasContent = text.trim().length > 0 || attachments.length > 0\n const updatedDrafts = { ...allDrafts }\n\n if (hasContent) {\n // Convert attachments to serializable format (similar to web implementation)\n const normalizedAttachments = attachments\n .filter(att => att.id && att.status === 'success')\n .map(att => ({\n ...att,\n file: {\n uri: att.file.uri,\n name: att.file.name,\n type: att.file.type,\n size: att.file.size,\n width: att.file.width,\n height: att.file.height,\n },\n }))\n\n const newDraft: MessageDraft = {\n text,\n attachments: normalizedAttachments,\n lastUpdated: Date.now(),\n }\n\n updatedDrafts[conversationKey] = newDraft\n setDraft(newDraft)\n } else {\n delete updatedDrafts[conversationKey]\n setDraft(null)\n }\n\n setAllDrafts(updatedDrafts)\n },\n [conversationKey, allDrafts, setAllDrafts]\n )\n\n const clearDraft = useCallback(() => {\n const updatedDrafts = { ...allDrafts }\n delete updatedDrafts[conversationKey]\n setAllDrafts(updatedDrafts)\n setDraft(null)\n }, [conversationKey, allDrafts, setAllDrafts])\n\n return {\n draft,\n saveDraft,\n clearDraft,\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services_form.d.ts","sourceRoot":"","sources":["../../../../src/screens/conversation_new/components/services_form.tsx"],"names":[],"mappings":"AACA,OAAO,KAAoD,MAAM,OAAO,CAAA;AAYxE,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAA;
|
|
1
|
+
{"version":3,"file":"services_form.d.ts","sourceRoot":"","sources":["../../../../src/screens/conversation_new/components/services_form.tsx"],"names":[],"mappings":"AACA,OAAO,KAAoD,MAAM,OAAO,CAAA;AAYxE,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAA;AAI5E,KAAK,iBAAiB,GAAG;IACvB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,cAAc,CAAC,EAAE,eAAe,CAAA;CACjC,CAAA;AAED,eAAO,MAAM,YAAY,uDAItB,iBAAiB,sBA2EnB,CAAA"}
|
|
@@ -11,6 +11,7 @@ import { useTeamMembersForNewConversation } from '../../../hooks/services/use_te
|
|
|
11
11
|
import { useFindOrCreateServicesConversation } from '../../../hooks/services/use_find_or_create_services_conversation';
|
|
12
12
|
import { tokens } from '../../../vendor/tapestry/tokens';
|
|
13
13
|
import { useServicesTeams } from '../../../hooks/services/use_services_team';
|
|
14
|
+
import { Haptic } from '../../../utils/native_adapters';
|
|
14
15
|
export const ServicesForm = ({ initialTeamIds, initialPlanId, teamFilterType, }) => {
|
|
15
16
|
const styles = useStyles();
|
|
16
17
|
const [selectedPlanId, setSelectedPlanId] = useState(initialPlanId);
|
|
@@ -69,14 +70,17 @@ function FormContent({ selectedTeamIds, removeSelection, selectedPlanId, setSele
|
|
|
69
70
|
<View style={styles.toSection}>
|
|
70
71
|
<View style={styles.toSectionRow}>
|
|
71
72
|
<Heading variant="h3">To:</Heading>
|
|
72
|
-
<TextButton accessibilityLabel="Select teams" textStyle={styles.teamCountHeader} onPress={() =>
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
73
|
+
<TextButton accessibilityLabel="Select teams" textStyle={styles.teamCountHeader} onPress={() => {
|
|
74
|
+
Haptic.impactLight();
|
|
75
|
+
navigation.navigate('New', {
|
|
76
|
+
screen: 'ConversationFilterRecipients',
|
|
77
|
+
params: {
|
|
78
|
+
source_app_name: 'Services',
|
|
79
|
+
team_ids: selectedTeamIds,
|
|
80
|
+
team_filter_type: teamFilterType,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
}}>
|
|
80
84
|
{teamCountHeader}
|
|
81
85
|
</TextButton>
|
|
82
86
|
</View>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services_form.js","sourceRoot":"","sources":["../../../../src/screens/conversation_new/components/services_form.tsx"],"names":[],"mappings":"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","sourcesContent":["import { StackActions, useNavigation } from '@react-navigation/native'\nimport React, { useCallback, useEffect, useMemo, useState } from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { Badge, Banner, ChildNotice, Heading, Switch, TextButton } from '../../../components'\nimport { ActionButton } from '../../../components/display/action_button'\nimport { Divider, FormList } from './form_list'\nimport { pluralize } from '../../../utils'\nimport { uniq } from 'lodash'\nimport { FilterByPlan } from './filter_by_plan'\nimport { useTeamMembersForNewConversation } from '../../../hooks/services/use_team_members_for_new_conversation'\nimport { useFindOrCreateServicesConversation } from '../../../hooks/services/use_find_or_create_services_conversation'\nimport { ConversationResource, MemberResource } from '../../../types'\nimport { tokens } from '../../../vendor/tapestry/tokens'\nimport { TeamFilterTypes } from '../../conversation_filter_recipients/types'\nimport { useServicesTeams } from '../../../hooks/services/use_services_team'\n\ntype ServicesFormProps = {\n initialTeamIds?: number[]\n initialPlanId?: number\n teamFilterType?: TeamFilterTypes\n}\n\nexport const ServicesForm = ({\n initialTeamIds,\n initialPlanId,\n teamFilterType,\n}: ServicesFormProps) => {\n const styles = useStyles()\n const [selectedPlanId, setSelectedPlanId] = useState<number | undefined>(initialPlanId)\n const initialState = useMemo(() => uniq(initialTeamIds) || [], [initialTeamIds]) // Uniq here because services can send duplicates in the teams_i_lead response.\n const [selectedTeamIds, setSelectedTeamIds] = useState<number[]>(initialState)\n\n // Sync with fresh props when they change (from navigation)\n useEffect(() => {\n setSelectedTeamIds(initialState)\n setSelectedPlanId(initialPlanId)\n }, [initialState, initialPlanId])\n\n const removeSelection = useCallback(\n (teamId: number) => {\n setSelectedTeamIds(selectedTeamIds.filter(id => id !== teamId))\n },\n [selectedTeamIds]\n )\n\n const [filerByPlan, setFilterByPlan] = useState(false)\n\n const { members, isError: isMemberError } = useTeamMembersForNewConversation({\n teamIds: selectedTeamIds,\n planId: selectedPlanId,\n })\n const adultMembers = useMemo(() => members.filter(member => !member.child), [members])\n\n const navigation = useNavigation()\n const {\n mutate: createConversation,\n isPending,\n selectionHasConversation,\n isLoadingConversationCheck,\n } = useFindOrCreateServicesConversation({\n teamIds: selectedTeamIds,\n planId: filerByPlan ? selectedPlanId : undefined,\n onSuccess: (conversation: ConversationResource) => {\n // exit from the create stack\n navigation.getParent()?.goBack()\n // navigate to the conversation screen\n navigation.dispatch(\n StackActions.push('Conversation', {\n conversation_id: conversation.id,\n })\n )\n },\n })\n\n return (\n <View style={styles.formContainer}>\n <FormList\n memberData={adultMembers}\n FormContent={\n <FormContent\n selectedTeamIds={selectedTeamIds}\n removeSelection={removeSelection}\n selectedPlanId={selectedPlanId}\n setSelectedPlanId={setSelectedPlanId}\n filterByPlan={filerByPlan}\n setFilterByPlan={setFilterByPlan}\n members={members}\n isMemberError={isMemberError}\n teamFilterType={teamFilterType}\n />\n }\n />\n <ActionButton\n disabled={!selectedTeamIds.length || isPending || isLoadingConversationCheck}\n title={selectionHasConversation ? 'Open conversation' : 'Start conversation'}\n onPress={createConversation}\n infoText=\"Conversation will be automatically updated if any members are added or removed from included teams.\"\n loading={isLoadingConversationCheck}\n />\n </View>\n )\n}\n\ninterface FormContentProps {\n selectedTeamIds: number[]\n removeSelection: (teamId: number) => void\n selectedPlanId?: number\n setSelectedPlanId: (planId: number | undefined) => void\n filterByPlan: boolean\n setFilterByPlan: (value: boolean) => void\n members: MemberResource[]\n isMemberError: boolean\n teamFilterType?: TeamFilterTypes\n}\n\nfunction FormContent({\n selectedTeamIds,\n removeSelection,\n selectedPlanId,\n setSelectedPlanId,\n filterByPlan,\n setFilterByPlan,\n members,\n isMemberError,\n teamFilterType,\n}: FormContentProps) {\n const navigation = useNavigation()\n const servicesTeams = useServicesTeams()\n const selectedTeams = useMemo(() => {\n return servicesTeams.filter(team => selectedTeamIds.includes(team.value.teamId))\n }, [selectedTeamIds, servicesTeams])\n\n const styles = useStyles()\n const teamCountHeader = pluralize(selectedTeamIds.length, 'team')\n const memberCount = members.length\n const childMembers = useMemo(() => members.filter(member => member.child), [members])\n const hasChildren = childMembers.length > 0\n const multipleServiceTypes =\n uniq(selectedTeams.flatMap(team => team.value.serviceTypeIds)).length > 1\n const firstTeamId = selectedTeamIds[0]\n const serviceTypeName =\n !multipleServiceTypes && selectedTeams.length > 0\n ? selectedTeams[0].serviceTypeNames[0]\n : undefined\n\n filterByPlan = filterByPlan && !!firstTeamId && !multipleServiceTypes\n\n return (\n <View style={styles.formContent}>\n <View style={styles.toSection}>\n <View style={styles.toSectionRow}>\n <Heading variant=\"h3\">To:</Heading>\n <TextButton\n accessibilityLabel=\"Select teams\"\n textStyle={styles.teamCountHeader}\n onPress={() =>\n navigation.navigate('New', {\n screen: 'ConversationFilterRecipients',\n params: {\n source_app_name: 'Services',\n team_ids: selectedTeamIds,\n team_filter_type: teamFilterType,\n },\n })\n }\n >\n {teamCountHeader}\n </TextButton>\n </View>\n <View style={styles.toSectionRow}>\n {selectedTeams.map(team => {\n const serviceTypeAcronyms = team.serviceTypeAcronyms.join(', ')\n const label = `${team.teamName} | ${serviceTypeAcronyms}`\n\n return (\n <View key={team.value.teamId} style={styles.badgeRow}>\n <Badge\n iconNameRight=\"general.x\"\n label={label}\n onPress={() => removeSelection(team.value.teamId)}\n />\n </View>\n )\n })}\n </View>\n </View>\n <Divider />\n <View style={styles.filterByPlanSection}>\n <View style={styles.filterByPlanSectionLead}>\n <Heading variant=\"h3\">Filter by plan</Heading>\n <Switch\n value={filterByPlan}\n onValueChange={value => {\n setFilterByPlan(value)\n if (!value) {\n setSelectedPlanId(undefined)\n }\n }}\n disabled={multipleServiceTypes}\n />\n </View>\n {multipleServiceTypes ? (\n <Banner\n appearance=\"neutral\"\n description=\"Plan filtering is not possible using teams from multiple service types. Try choosing teams above with only one service type.\"\n />\n ) : filterByPlan ? (\n <FilterByPlan\n teamIds={selectedTeamIds}\n selectedPlanId={selectedPlanId}\n serviceTypeName={serviceTypeName}\n onPlanSelect={setSelectedPlanId}\n />\n ) : null}\n </View>\n <Divider />\n <View style={styles.memberSection}>\n <Heading variant=\"h3\">{pluralize(memberCount, 'member')} selected</Heading>\n {hasChildren && (\n <ChildNotice childMembers={childMembers} showMembers={true} style={styles.banner} />\n )}\n {isMemberError && (\n <Banner\n appearance=\"error\"\n description=\"There was an issue loading team members, please refresh and try again.\"\n style={styles.banner}\n />\n )}\n </View>\n </View>\n )\n}\n\nconst useStyles = () => {\n const sectionPadding = 16\n\n return StyleSheet.create({\n formContainer: {\n flex: 1,\n },\n formContent: {\n paddingBottom: sectionPadding,\n flex: 1,\n },\n toSection: {\n padding: sectionPadding,\n gap: 8,\n },\n toSectionRow: {\n flexDirection: 'row',\n gap: 8,\n alignItems: 'baseline',\n flexWrap: 'wrap',\n },\n badgeRow: {\n flexDirection: 'row',\n },\n groupName: {\n fontSize: 18,\n },\n filterByPlanSection: {\n padding: sectionPadding,\n gap: 12,\n },\n filterByPlanSectionLead: {\n flexDirection: 'row',\n gap: 8,\n justifyContent: 'space-between',\n alignItems: 'center',\n },\n filterByPlanSectionRow: {\n flexDirection: 'row',\n gap: 8,\n },\n titleInput: {\n fontSize: 18,\n },\n memberSection: {\n padding: sectionPadding,\n paddingBottom: 0,\n },\n banner: {\n marginTop: 16,\n },\n teamCountHeader: {\n fontSize: tokens.fontSizeLg,\n },\n })\n}\n"]}
|
|
1
|
+
{"version":3,"file":"services_form.js","sourceRoot":"","sources":["../../../../src/screens/conversation_new/components/services_form.tsx"],"names":[],"mappings":"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","sourcesContent":["import { StackActions, useNavigation } from '@react-navigation/native'\nimport React, { useCallback, useEffect, useMemo, useState } from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { Badge, Banner, ChildNotice, Heading, Switch, TextButton } from '../../../components'\nimport { ActionButton } from '../../../components/display/action_button'\nimport { Divider, FormList } from './form_list'\nimport { pluralize } from '../../../utils'\nimport { uniq } from 'lodash'\nimport { FilterByPlan } from './filter_by_plan'\nimport { useTeamMembersForNewConversation } from '../../../hooks/services/use_team_members_for_new_conversation'\nimport { useFindOrCreateServicesConversation } from '../../../hooks/services/use_find_or_create_services_conversation'\nimport { ConversationResource, MemberResource } from '../../../types'\nimport { tokens } from '../../../vendor/tapestry/tokens'\nimport { TeamFilterTypes } from '../../conversation_filter_recipients/types'\nimport { useServicesTeams } from '../../../hooks/services/use_services_team'\nimport { Haptic } from '../../../utils/native_adapters'\n\ntype ServicesFormProps = {\n initialTeamIds?: number[]\n initialPlanId?: number\n teamFilterType?: TeamFilterTypes\n}\n\nexport const ServicesForm = ({\n initialTeamIds,\n initialPlanId,\n teamFilterType,\n}: ServicesFormProps) => {\n const styles = useStyles()\n const [selectedPlanId, setSelectedPlanId] = useState<number | undefined>(initialPlanId)\n const initialState = useMemo(() => uniq(initialTeamIds) || [], [initialTeamIds]) // Uniq here because services can send duplicates in the teams_i_lead response.\n const [selectedTeamIds, setSelectedTeamIds] = useState<number[]>(initialState)\n\n // Sync with fresh props when they change (from navigation)\n useEffect(() => {\n setSelectedTeamIds(initialState)\n setSelectedPlanId(initialPlanId)\n }, [initialState, initialPlanId])\n\n const removeSelection = useCallback(\n (teamId: number) => {\n setSelectedTeamIds(selectedTeamIds.filter(id => id !== teamId))\n },\n [selectedTeamIds]\n )\n\n const [filerByPlan, setFilterByPlan] = useState(false)\n\n const { members, isError: isMemberError } = useTeamMembersForNewConversation({\n teamIds: selectedTeamIds,\n planId: selectedPlanId,\n })\n const adultMembers = useMemo(() => members.filter(member => !member.child), [members])\n\n const navigation = useNavigation()\n const {\n mutate: createConversation,\n isPending,\n selectionHasConversation,\n isLoadingConversationCheck,\n } = useFindOrCreateServicesConversation({\n teamIds: selectedTeamIds,\n planId: filerByPlan ? selectedPlanId : undefined,\n onSuccess: (conversation: ConversationResource) => {\n // exit from the create stack\n navigation.getParent()?.goBack()\n // navigate to the conversation screen\n navigation.dispatch(\n StackActions.push('Conversation', {\n conversation_id: conversation.id,\n })\n )\n },\n })\n\n return (\n <View style={styles.formContainer}>\n <FormList\n memberData={adultMembers}\n FormContent={\n <FormContent\n selectedTeamIds={selectedTeamIds}\n removeSelection={removeSelection}\n selectedPlanId={selectedPlanId}\n setSelectedPlanId={setSelectedPlanId}\n filterByPlan={filerByPlan}\n setFilterByPlan={setFilterByPlan}\n members={members}\n isMemberError={isMemberError}\n teamFilterType={teamFilterType}\n />\n }\n />\n <ActionButton\n disabled={!selectedTeamIds.length || isPending || isLoadingConversationCheck}\n title={selectionHasConversation ? 'Open conversation' : 'Start conversation'}\n onPress={createConversation}\n infoText=\"Conversation will be automatically updated if any members are added or removed from included teams.\"\n loading={isLoadingConversationCheck}\n />\n </View>\n )\n}\n\ninterface FormContentProps {\n selectedTeamIds: number[]\n removeSelection: (teamId: number) => void\n selectedPlanId?: number\n setSelectedPlanId: (planId: number | undefined) => void\n filterByPlan: boolean\n setFilterByPlan: (value: boolean) => void\n members: MemberResource[]\n isMemberError: boolean\n teamFilterType?: TeamFilterTypes\n}\n\nfunction FormContent({\n selectedTeamIds,\n removeSelection,\n selectedPlanId,\n setSelectedPlanId,\n filterByPlan,\n setFilterByPlan,\n members,\n isMemberError,\n teamFilterType,\n}: FormContentProps) {\n const navigation = useNavigation()\n const servicesTeams = useServicesTeams()\n const selectedTeams = useMemo(() => {\n return servicesTeams.filter(team => selectedTeamIds.includes(team.value.teamId))\n }, [selectedTeamIds, servicesTeams])\n\n const styles = useStyles()\n const teamCountHeader = pluralize(selectedTeamIds.length, 'team')\n const memberCount = members.length\n const childMembers = useMemo(() => members.filter(member => member.child), [members])\n const hasChildren = childMembers.length > 0\n const multipleServiceTypes =\n uniq(selectedTeams.flatMap(team => team.value.serviceTypeIds)).length > 1\n const firstTeamId = selectedTeamIds[0]\n const serviceTypeName =\n !multipleServiceTypes && selectedTeams.length > 0\n ? selectedTeams[0].serviceTypeNames[0]\n : undefined\n\n filterByPlan = filterByPlan && !!firstTeamId && !multipleServiceTypes\n\n return (\n <View style={styles.formContent}>\n <View style={styles.toSection}>\n <View style={styles.toSectionRow}>\n <Heading variant=\"h3\">To:</Heading>\n <TextButton\n accessibilityLabel=\"Select teams\"\n textStyle={styles.teamCountHeader}\n onPress={() => {\n Haptic.impactLight()\n navigation.navigate('New', {\n screen: 'ConversationFilterRecipients',\n params: {\n source_app_name: 'Services',\n team_ids: selectedTeamIds,\n team_filter_type: teamFilterType,\n },\n })\n }}\n >\n {teamCountHeader}\n </TextButton>\n </View>\n <View style={styles.toSectionRow}>\n {selectedTeams.map(team => {\n const serviceTypeAcronyms = team.serviceTypeAcronyms.join(', ')\n const label = `${team.teamName} | ${serviceTypeAcronyms}`\n\n return (\n <View key={team.value.teamId} style={styles.badgeRow}>\n <Badge\n iconNameRight=\"general.x\"\n label={label}\n onPress={() => removeSelection(team.value.teamId)}\n />\n </View>\n )\n })}\n </View>\n </View>\n <Divider />\n <View style={styles.filterByPlanSection}>\n <View style={styles.filterByPlanSectionLead}>\n <Heading variant=\"h3\">Filter by plan</Heading>\n <Switch\n value={filterByPlan}\n onValueChange={value => {\n setFilterByPlan(value)\n if (!value) {\n setSelectedPlanId(undefined)\n }\n }}\n disabled={multipleServiceTypes}\n />\n </View>\n {multipleServiceTypes ? (\n <Banner\n appearance=\"neutral\"\n description=\"Plan filtering is not possible using teams from multiple service types. Try choosing teams above with only one service type.\"\n />\n ) : filterByPlan ? (\n <FilterByPlan\n teamIds={selectedTeamIds}\n selectedPlanId={selectedPlanId}\n serviceTypeName={serviceTypeName}\n onPlanSelect={setSelectedPlanId}\n />\n ) : null}\n </View>\n <Divider />\n <View style={styles.memberSection}>\n <Heading variant=\"h3\">{pluralize(memberCount, 'member')} selected</Heading>\n {hasChildren && (\n <ChildNotice childMembers={childMembers} showMembers={true} style={styles.banner} />\n )}\n {isMemberError && (\n <Banner\n appearance=\"error\"\n description=\"There was an issue loading team members, please refresh and try again.\"\n style={styles.banner}\n />\n )}\n </View>\n </View>\n )\n}\n\nconst useStyles = () => {\n const sectionPadding = 16\n\n return StyleSheet.create({\n formContainer: {\n flex: 1,\n },\n formContent: {\n paddingBottom: sectionPadding,\n flex: 1,\n },\n toSection: {\n padding: sectionPadding,\n gap: 8,\n },\n toSectionRow: {\n flexDirection: 'row',\n gap: 8,\n alignItems: 'baseline',\n flexWrap: 'wrap',\n },\n badgeRow: {\n flexDirection: 'row',\n },\n groupName: {\n fontSize: 18,\n },\n filterByPlanSection: {\n padding: sectionPadding,\n gap: 12,\n },\n filterByPlanSectionLead: {\n flexDirection: 'row',\n gap: 8,\n justifyContent: 'space-between',\n alignItems: 'center',\n },\n filterByPlanSectionRow: {\n flexDirection: 'row',\n gap: 8,\n },\n titleInput: {\n fontSize: 18,\n },\n memberSection: {\n padding: sectionPadding,\n paddingBottom: 0,\n },\n banner: {\n marginTop: 16,\n },\n teamCountHeader: {\n fontSize: tokens.fontSizeLg,\n },\n })\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation_screen.d.ts","sourceRoot":"","sources":["../../src/screens/conversation_screen.tsx"],"names":[],"mappings":"AACA,OAAO,EAAe,gBAAgB,EAAqB,MAAM,4BAA4B,CAAA;AAC7F,OAAO,EAGL,iBAAiB,EAIlB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,KAAmD,MAAM,OAAO,CAAA;AAkBvE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAA;AAOjF,MAAM,MAAM,sBAAsB,GAAG;IACnC,eAAe,EAAE,MAAM,CAAA;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,CAAC,sBAAsB,CAAC,CAAA;AAE/E,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"conversation_screen.d.ts","sourceRoot":"","sources":["../../src/screens/conversation_screen.tsx"],"names":[],"mappings":"AACA,OAAO,EAAe,gBAAgB,EAAqB,MAAM,4BAA4B,CAAA;AAC7F,OAAO,EAGL,iBAAiB,EAIlB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,KAAmD,MAAM,OAAO,CAAA;AAkBvE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAA;AAOjF,MAAM,MAAM,sBAAsB,GAAG;IACnC,eAAe,EAAE,MAAM,CAAA;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,CAAC,sBAAsB,CAAC,CAAA;AAE/E,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,EAAE,uBAAuB,qBAwHpE;AAED,MAAM,MAAM,aAAa,GAAG;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAwC/E,eAAO,MAAM,aAAa,OAAQ,eAAe,EAAE,wCAkClD,CAAA;AACD,UAAU,4BAA6B,SAAQ,gBAAgB;IAC7D,eAAe,EAAE,MAAM,CAAA;IACvB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,eAAO,MAAM,uBAAuB,0DAMjC,4BAA4B,sBAiC9B,CAAA"}
|
|
@@ -80,7 +80,12 @@ export function ConversationScreen({ route }) {
|
|
|
80
80
|
<JumpToBottomButton onPress={handleReturnToBottom} visible={showJumpToBottomButton}/>
|
|
81
81
|
{!noMessages && <TypingIndicator conversationId={conversation_id}/>}
|
|
82
82
|
{showLeaderDisabledReplyBanner && <LeaderDisabledRepliesBanner />}
|
|
83
|
-
{canReply ? (<MessageForm.Root conversation={conversation} currentlyEditingMessage={currentlyEditingMessage}
|
|
83
|
+
{canReply ? (<MessageForm.Root conversation={conversation} currentlyEditingMessage={currentlyEditingMessage}
|
|
84
|
+
// We use a separate key so that it remounts component when switching between new
|
|
85
|
+
// and edit message. This simplifies internal state handling.
|
|
86
|
+
key={currentlyEditingMessage
|
|
87
|
+
? `edit-message-form-${currentlyEditingMessage.id}`
|
|
88
|
+
: 'new-message-form'}>
|
|
84
89
|
<MessageForm.AttachmentPicker />
|
|
85
90
|
<MessageForm.Commands />
|
|
86
91
|
<MessageForm.TextInput />
|