@planningcenter/chat-react-native 3.20.1-rc.1 → 3.20.1-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.
@@ -1 +1 @@
1
- {"version":3,"file":"use_message_create_or_update.d.ts","sourceRoot":"","sources":["../../src/hooks/use_message_create_or_update.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,WAAW,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAQtE,OAAO,EAAE,uCAAuC,EAAE,MAAM,gEAAgE,CAAA;AAOxH,UAAU,KAAK;IACb,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED,wBAAgB,wBAAwB,CAAC,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,KAAK;UAqD5E,MAAM;kBACE,uCAAuC,EAAE;;;GA+E5D"}
1
+ {"version":3,"file":"use_message_create_or_update.d.ts","sourceRoot":"","sources":["../../src/hooks/use_message_create_or_update.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,WAAW,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAQtE,OAAO,EAAE,uCAAuC,EAAE,MAAM,gEAAgE,CAAA;AAOxH,UAAU,KAAK;IACb,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED,wBAAgB,wBAAwB,CAAC,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,KAAK;UAqD5E,MAAM;kBACE,uCAAuC,EAAE;;;GAgF5D"}
@@ -20,7 +20,7 @@ export function useMessageCreateOrUpdate({ conversationId, message, replyRootId
20
20
  let attributes = {
21
21
  text,
22
22
  ...(attachments ? { attachments } : {}),
23
- ...(replyRootId ? { reply_root: { id: replyRootId } } : {}),
23
+ ...(!isEditing && replyRootId ? { reply_root: { id: replyRootId } } : {}),
24
24
  };
25
25
  if (!isEditing) {
26
26
  const idempotentKey = insecureUUID();
@@ -54,6 +54,7 @@ export function useMessageCreateOrUpdate({ conversationId, message, replyRootId
54
54
  conversationId,
55
55
  message,
56
56
  text,
57
+ replyRootId,
57
58
  });
58
59
  return { message: optimisticMessage };
59
60
  }
@@ -1 +1 @@
1
- {"version":3,"file":"use_message_create_or_update.js","sourceRoot":"","sources":["../../src/hooks/use_message_create_or_update.ts"],"names":[],"mappings":"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","sourcesContent":["import { InfiniteData, useMutation } from '@tanstack/react-query'\nimport { getMessagesQueryKey, getMessagesRequestArgs } from '../utils/request/get_messages'\nimport { useApiClient } from './use_api_client'\nimport { ApiCollection, ApiResource, MessageResource } from '../types'\nimport { chatQueryClient } from '../contexts/api_provider'\nimport {\n deleteRecordInPagesData,\n Haptic,\n updateOrCreateRecordInPagesData,\n updateRecordInPagesData,\n} from '../utils'\nimport { DenormalizedAttachmentResourceForCreate } from '../types/resources/denormalized_attachment_resource_for_create'\nimport { useCurrentPerson } from './use_current_person'\nimport { optimisticallyUpdateMessage } from '../utils/cache/optimistically_update_message'\nimport { optimisticallyCreateMessage } from '../utils/cache/optimistically_create_message'\nimport { startMessageCreationTracking } from '../utils/performance_tracking'\nimport { isNewMessage, mergeMessageUpdate } from '../utils/cache/messages_cache'\n\ninterface Props {\n conversationId: number\n message?: MessageResource\n replyRootId?: string | null\n}\n\nexport function useMessageCreateOrUpdate({ conversationId, message, replyRootId }: Props) {\n const messageId = message?.id || null\n const isEditing = !isNewMessage(message)\n const apiClient = useApiClient()\n const currentPerson = useCurrentPerson()\n\n const mutation = useMutation({\n mutationFn: ({\n text,\n attachments,\n }: {\n text: string\n attachments?: DenormalizedAttachmentResourceForCreate[]\n }) => {\n const requestParams = getMessagesRequestArgs({ conversation_id: conversationId })\n const fieldsWithValueJoined = Object.fromEntries(\n Object.entries(requestParams.data.fields).map(([k, v]) => [k, v.join(',')])\n )\n let attributes: any = {\n text,\n ...(attachments ? { attachments } : {}),\n ...(replyRootId ? { reply_root: { id: replyRootId } } : {}),\n }\n if (!isEditing) {\n const idempotentKey = insecureUUID()\n attributes.idempotent_key = idempotentKey\n startMessageCreationTracking(idempotentKey)\n }\n const data = {\n ...requestParams.data,\n data: {\n type: 'Message',\n attributes,\n },\n fields: fieldsWithValueJoined,\n }\n\n if (isEditing) {\n return apiClient.chat.patch<ApiResource<MessageResource>>({\n url: `/me/conversations/${conversationId}/messages/${messageId}`,\n data,\n })\n } else {\n return apiClient.chat.post<ApiResource<MessageResource>>({\n url: `/me/conversations/${conversationId}/messages`,\n data,\n })\n }\n },\n onMutate: async ({\n text,\n attachments,\n }: {\n text: string\n attachments?: DenormalizedAttachmentResourceForCreate[]\n }) => {\n if (message && isEditing) {\n const optimisticMessage = optimisticallyUpdateMessage({\n conversationId,\n message,\n text,\n })\n\n return { message: optimisticMessage }\n }\n\n const optimisticMessage = optimisticallyCreateMessage({\n conversationId,\n message,\n text,\n attachments,\n currentPerson,\n replyRootId,\n })\n\n return { message: optimisticMessage }\n },\n onError: (error, variables, context) => {\n const { message: optimisticMessage } = context || {}\n Haptic.notificationError()\n\n // Add error to the optimistic message from the cache on error\n if (optimisticMessage) {\n const queryKey = getMessagesQueryKey({\n conversation_id: conversationId,\n reply_root_id: replyRootId,\n })\n chatQueryClient.setQueryData(\n queryKey,\n (data: InfiniteData<ApiCollection<MessageResource>> | undefined) =>\n updateRecordInPagesData({\n data,\n record: optimisticMessage,\n processRecord: (_next, prev) => ({\n ...prev,\n error: error.message || 'Failed to send message',\n pending: false, // Mark as no longer pending\n }),\n })\n )\n }\n },\n onSuccess: (result: ApiResource<MessageResource>, variables, context) => {\n const { message: optimisticMessage } = context || {}\n const updatedMessage = result.data\n type QueryData = InfiniteData<ApiCollection<MessageResource>>\n const queryKey = getMessagesQueryKey({\n conversation_id: conversationId,\n reply_root_id: replyRootId,\n })\n\n // First remove the optimistic message if it exists\n if (optimisticMessage) {\n chatQueryClient.setQueryData<QueryData>(queryKey, data =>\n deleteRecordInPagesData({\n data,\n record: optimisticMessage,\n })\n )\n }\n\n // Then add the real message\n chatQueryClient.setQueryData<QueryData>(queryKey, data =>\n updateOrCreateRecordInPagesData({\n data,\n record: updatedMessage,\n processRecord: (record, current) => mergeMessageUpdate(record, current),\n })\n )\n },\n })\n\n return mutation\n}\n\n/**\n * Generate a random UUID (v4) for idempotent keys.\n * Uses Math.random, which is not cryptographically secure.\n * An actual crypto library requires native dependencies.\n * This is OK for now since idempotent keys are not security-sensitive\n * or need to be guaranteed unique.\n * They are short lived and we use it in combination with the message's creator_id so\n * their impact is scoped only the current user.\n */\nfunction insecureUUID(): string {\n return 'xxxxxxxx-xxxx-4xxx-Nxxx-xxxxxxxxxxxx'\n .replace(/x/g, () => Math.floor(Math.random() * 16).toString(16))\n .replace(/N/g, () => (Math.floor(Math.random() * 4) + 8).toString(16))\n}\n"]}
1
+ {"version":3,"file":"use_message_create_or_update.js","sourceRoot":"","sources":["../../src/hooks/use_message_create_or_update.ts"],"names":[],"mappings":"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","sourcesContent":["import { InfiniteData, useMutation } from '@tanstack/react-query'\nimport { getMessagesQueryKey, getMessagesRequestArgs } from '../utils/request/get_messages'\nimport { useApiClient } from './use_api_client'\nimport { ApiCollection, ApiResource, MessageResource } from '../types'\nimport { chatQueryClient } from '../contexts/api_provider'\nimport {\n deleteRecordInPagesData,\n Haptic,\n updateOrCreateRecordInPagesData,\n updateRecordInPagesData,\n} from '../utils'\nimport { DenormalizedAttachmentResourceForCreate } from '../types/resources/denormalized_attachment_resource_for_create'\nimport { useCurrentPerson } from './use_current_person'\nimport { optimisticallyUpdateMessage } from '../utils/cache/optimistically_update_message'\nimport { optimisticallyCreateMessage } from '../utils/cache/optimistically_create_message'\nimport { startMessageCreationTracking } from '../utils/performance_tracking'\nimport { isNewMessage, mergeMessageUpdate } from '../utils/cache/messages_cache'\n\ninterface Props {\n conversationId: number\n message?: MessageResource\n replyRootId?: string | null\n}\n\nexport function useMessageCreateOrUpdate({ conversationId, message, replyRootId }: Props) {\n const messageId = message?.id || null\n const isEditing = !isNewMessage(message)\n const apiClient = useApiClient()\n const currentPerson = useCurrentPerson()\n\n const mutation = useMutation({\n mutationFn: ({\n text,\n attachments,\n }: {\n text: string\n attachments?: DenormalizedAttachmentResourceForCreate[]\n }) => {\n const requestParams = getMessagesRequestArgs({ conversation_id: conversationId })\n const fieldsWithValueJoined = Object.fromEntries(\n Object.entries(requestParams.data.fields).map(([k, v]) => [k, v.join(',')])\n )\n let attributes: any = {\n text,\n ...(attachments ? { attachments } : {}),\n ...(!isEditing && replyRootId ? { reply_root: { id: replyRootId } } : {}),\n }\n if (!isEditing) {\n const idempotentKey = insecureUUID()\n attributes.idempotent_key = idempotentKey\n startMessageCreationTracking(idempotentKey)\n }\n const data = {\n ...requestParams.data,\n data: {\n type: 'Message',\n attributes,\n },\n fields: fieldsWithValueJoined,\n }\n\n if (isEditing) {\n return apiClient.chat.patch<ApiResource<MessageResource>>({\n url: `/me/conversations/${conversationId}/messages/${messageId}`,\n data,\n })\n } else {\n return apiClient.chat.post<ApiResource<MessageResource>>({\n url: `/me/conversations/${conversationId}/messages`,\n data,\n })\n }\n },\n onMutate: async ({\n text,\n attachments,\n }: {\n text: string\n attachments?: DenormalizedAttachmentResourceForCreate[]\n }) => {\n if (message && isEditing) {\n const optimisticMessage = optimisticallyUpdateMessage({\n conversationId,\n message,\n text,\n replyRootId,\n })\n\n return { message: optimisticMessage }\n }\n\n const optimisticMessage = optimisticallyCreateMessage({\n conversationId,\n message,\n text,\n attachments,\n currentPerson,\n replyRootId,\n })\n\n return { message: optimisticMessage }\n },\n onError: (error, variables, context) => {\n const { message: optimisticMessage } = context || {}\n Haptic.notificationError()\n\n // Add error to the optimistic message from the cache on error\n if (optimisticMessage) {\n const queryKey = getMessagesQueryKey({\n conversation_id: conversationId,\n reply_root_id: replyRootId,\n })\n chatQueryClient.setQueryData(\n queryKey,\n (data: InfiniteData<ApiCollection<MessageResource>> | undefined) =>\n updateRecordInPagesData({\n data,\n record: optimisticMessage,\n processRecord: (_next, prev) => ({\n ...prev,\n error: error.message || 'Failed to send message',\n pending: false, // Mark as no longer pending\n }),\n })\n )\n }\n },\n onSuccess: (result: ApiResource<MessageResource>, variables, context) => {\n const { message: optimisticMessage } = context || {}\n const updatedMessage = result.data\n type QueryData = InfiniteData<ApiCollection<MessageResource>>\n const queryKey = getMessagesQueryKey({\n conversation_id: conversationId,\n reply_root_id: replyRootId,\n })\n\n // First remove the optimistic message if it exists\n if (optimisticMessage) {\n chatQueryClient.setQueryData<QueryData>(queryKey, data =>\n deleteRecordInPagesData({\n data,\n record: optimisticMessage,\n })\n )\n }\n\n // Then add the real message\n chatQueryClient.setQueryData<QueryData>(queryKey, data =>\n updateOrCreateRecordInPagesData({\n data,\n record: updatedMessage,\n processRecord: (record, current) => mergeMessageUpdate(record, current),\n })\n )\n },\n })\n\n return mutation\n}\n\n/**\n * Generate a random UUID (v4) for idempotent keys.\n * Uses Math.random, which is not cryptographically secure.\n * An actual crypto library requires native dependencies.\n * This is OK for now since idempotent keys are not security-sensitive\n * or need to be guaranteed unique.\n * They are short lived and we use it in combination with the message's creator_id so\n * their impact is scoped only the current user.\n */\nfunction insecureUUID(): string {\n return 'xxxxxxxx-xxxx-4xxx-Nxxx-xxxxxxxxxxxx'\n .replace(/x/g, () => Math.floor(Math.random() * 16).toString(16))\n .replace(/N/g, () => (Math.floor(Math.random() * 4) + 8).toString(16))\n}\n"]}
@@ -5,7 +5,7 @@ import { App } from './use_api_client';
5
5
  import { ApiError } from '../types/api_primitives';
6
6
  interface SuspenseGetOptions extends GetRequest {
7
7
  app?: App;
8
- reply_root_id?: string;
8
+ reply_root_id?: string | null;
9
9
  }
10
10
  export type SuspenseGetQueryOptions<T extends ResourceObject | ResourceObject[]> = Omit<UseSuspenseQueryOptions<ApiResource<T>, ApiError>, 'queryKey' | 'queryFn'>;
11
11
  export declare const useSuspenseGet: <T extends ResourceObject | ResourceObject[]>(args: SuspenseGetOptions, options?: SuspenseGetQueryOptions<T>) => {
@@ -1 +1 @@
1
- {"version":3,"file":"use_suspense_api.d.ts","sourceRoot":"","sources":["../../src/hooks/use_suspense_api.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kCAAkC,EAClC,YAAY,EAGZ,uBAAuB,EACxB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AACrE,OAAO,EAAE,UAAU,EAAe,MAAM,iBAAiB,CAAA;AACzD,OAAO,EAAE,GAAG,EAAgB,MAAM,kBAAkB,CAAA;AAEpD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAGlD,UAAU,kBAAmB,SAAQ,UAAU;IAC7C,GAAG,CAAC,EAAE,GAAG,CAAA;IACT,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,MAAM,uBAAuB,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,EAAE,IAAI,IAAI,CACrF,uBAAuB,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,EACjD,UAAU,GAAG,SAAS,CACvB,CAAA;AAED,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,cAAc,GAAG,cAAc,EAAE,QAClE,kBAAkB,YACd,uBAAuB,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;CAiBrC,CAAA;AAOD,MAAM,MAAM,wBAAwB,GAAG,IAAI,CACzC,kCAAkC,EAClC,kBAAkB,GAAG,kBAAkB,GAAG,SAAS,GAAG,UAAU,CACjE,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAI,CAAC,SAAS,cAAc,QACrD,kBAAkB,SACjB,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6ChC,CAAA;AAUD,MAAM,MAAM,eAAe,GAAG;IAC5B,kBAAkB,CAAC,KAAK,CAAC;IACzB,kBAAkB,CAAC,MAAM,CAAC;IAC1B,kBAAkB,CAAC,SAAS,CAAC;IAC7B,kBAAkB,CAAC,KAAK,CAAC;IACzB,kBAAkB,CAAC,eAAe,CAAC;CACpC,CAAA;AACD,eAAO,MAAM,kBAAkB,SAAU,kBAAkB,KAAG,eAM7D,CAAA"}
1
+ {"version":3,"file":"use_suspense_api.d.ts","sourceRoot":"","sources":["../../src/hooks/use_suspense_api.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kCAAkC,EAClC,YAAY,EAGZ,uBAAuB,EACxB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AACrE,OAAO,EAAE,UAAU,EAAe,MAAM,iBAAiB,CAAA;AACzD,OAAO,EAAE,GAAG,EAAgB,MAAM,kBAAkB,CAAA;AAEpD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAGlD,UAAU,kBAAmB,SAAQ,UAAU;IAC7C,GAAG,CAAC,EAAE,GAAG,CAAA;IACT,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED,MAAM,MAAM,uBAAuB,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,EAAE,IAAI,IAAI,CACrF,uBAAuB,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,EACjD,UAAU,GAAG,SAAS,CACvB,CAAA;AAED,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,cAAc,GAAG,cAAc,EAAE,QAClE,kBAAkB,YACd,uBAAuB,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;CAiBrC,CAAA;AAOD,MAAM,MAAM,wBAAwB,GAAG,IAAI,CACzC,kCAAkC,EAClC,kBAAkB,GAAG,kBAAkB,GAAG,SAAS,GAAG,UAAU,CACjE,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAI,CAAC,SAAS,cAAc,QACrD,kBAAkB,SACjB,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6ChC,CAAA;AAUD,MAAM,MAAM,eAAe,GAAG;IAC5B,kBAAkB,CAAC,KAAK,CAAC;IACzB,kBAAkB,CAAC,MAAM,CAAC;IAC1B,kBAAkB,CAAC,SAAS,CAAC;IAC7B,kBAAkB,CAAC,KAAK,CAAC;IACzB,kBAAkB,CAAC,eAAe,CAAC;CACpC,CAAA;AACD,eAAO,MAAM,kBAAkB,SAAU,kBAAkB,KAAG,eAM7D,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"use_suspense_api.js","sourceRoot":"","sources":["../../src/hooks/use_suspense_api.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n AnyUseSuspenseInfiniteQueryOptions,\n InfiniteData,\n useSuspenseInfiniteQuery,\n useSuspenseQuery,\n UseSuspenseQueryOptions,\n} from '@tanstack/react-query'\nimport { ApiCollection, ApiResource, ResourceObject } from '../types'\nimport { GetRequest, RequestData } from '../utils/client'\nimport { App, useApiClient } from './use_api_client'\nimport { Log } from '../utils'\nimport { ApiError } from '../types/api_primitives'\nimport { ResponseError } from '../utils/response_error'\n\ninterface SuspenseGetOptions extends GetRequest {\n app?: App\n reply_root_id?: string\n}\n\nexport type SuspenseGetQueryOptions<T extends ResourceObject | ResourceObject[]> = Omit<\n UseSuspenseQueryOptions<ApiResource<T>, ApiError>,\n 'queryKey' | 'queryFn'\n>\n\nexport const useSuspenseGet = <T extends ResourceObject | ResourceObject[]>(\n args: SuspenseGetOptions,\n options?: SuspenseGetQueryOptions<T>\n) => {\n type Resource = ApiResource<T>\n const apiClient = useApiClient()\n\n const { data, ...query } = useSuspenseQuery<Resource, ApiError>({\n queryKey: getRequestQueryKey(args),\n queryFn: ({ queryKey }) => {\n const [url, d, headers, app = 'chat'] = queryKey as RequestQueryKey\n return apiClient[app]\n .get({ url, data: d, headers })\n .catch(throwResponseError) as Promise<Resource>\n },\n ...options,\n })\n\n return { ...data, ...query }\n}\n\ntype NextMeta = Partial<{\n offset: string\n idLt: string\n}>\n\nexport type SuspensePaginatorOptions = Omit<\n AnyUseSuspenseInfiniteQueryOptions,\n 'getNextPageParam' | 'initialPageParam' | 'queryFn' | 'queryKey'\n>\n\nexport const useSuspensePaginator = <T extends ResourceObject>(\n args: SuspenseGetOptions,\n opts?: SuspensePaginatorOptions\n) => {\n const apiClient = useApiClient()\n const query = useSuspenseInfiniteQuery<\n ApiCollection<T>,\n Response,\n InfiniteData<ApiCollection<T>>,\n any,\n Partial<RequestData> | undefined\n >({\n queryKey: getRequestQueryKey(args),\n queryFn: ({ pageParam }) => {\n Log.info('useSuspenseGet', { pageParam })\n\n const pageParmWhere = pageParam?.where || {}\n const argsWhere = args.data.where || {}\n const where = { ...argsWhere, ...pageParmWhere }\n const app = args.app || 'chat'\n const offset = pageParam?.offset || args.data.offset\n const data = { ...args.data, where, offset }\n\n return apiClient[app]\n .get<ApiCollection<T>>({\n url: args.url,\n data,\n })\n .catch(throwResponseError)\n },\n initialPageParam: {} as Partial<RequestData>,\n getNextPageParam: lastPage => {\n const next: NextMeta = lastPage.meta?.next || {}\n const { offset, idLt } = next\n\n if (idLt) return { where: { id_lt: idLt } }\n if (offset) return { offset: Number(offset) }\n\n return undefined\n },\n ...(opts || {}),\n })\n\n const data: T[] = query.data?.pages.flatMap(page => page.data) || []\n const totalCount = query.data?.pages[0]?.meta?.totalCount || data.length\n\n return { ...query, data, totalCount }\n}\n\nconst throwResponseError = (error: unknown) => {\n if (error instanceof Response) {\n throw new ResponseError(error as ApiError)\n }\n\n return Promise.reject(error)\n}\n\nexport type RequestQueryKey = [\n SuspenseGetOptions['url'],\n SuspenseGetOptions['data'],\n SuspenseGetOptions['headers'],\n SuspenseGetOptions['app'],\n SuspenseGetOptions['reply_root_id'],\n]\nexport const getRequestQueryKey = (args: SuspenseGetOptions): RequestQueryKey => [\n args.url,\n args.data,\n args.headers,\n args.app || 'chat',\n args.reply_root_id,\n]\n"]}
1
+ {"version":3,"file":"use_suspense_api.js","sourceRoot":"","sources":["../../src/hooks/use_suspense_api.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n AnyUseSuspenseInfiniteQueryOptions,\n InfiniteData,\n useSuspenseInfiniteQuery,\n useSuspenseQuery,\n UseSuspenseQueryOptions,\n} from '@tanstack/react-query'\nimport { ApiCollection, ApiResource, ResourceObject } from '../types'\nimport { GetRequest, RequestData } from '../utils/client'\nimport { App, useApiClient } from './use_api_client'\nimport { Log } from '../utils'\nimport { ApiError } from '../types/api_primitives'\nimport { ResponseError } from '../utils/response_error'\n\ninterface SuspenseGetOptions extends GetRequest {\n app?: App\n reply_root_id?: string | null\n}\n\nexport type SuspenseGetQueryOptions<T extends ResourceObject | ResourceObject[]> = Omit<\n UseSuspenseQueryOptions<ApiResource<T>, ApiError>,\n 'queryKey' | 'queryFn'\n>\n\nexport const useSuspenseGet = <T extends ResourceObject | ResourceObject[]>(\n args: SuspenseGetOptions,\n options?: SuspenseGetQueryOptions<T>\n) => {\n type Resource = ApiResource<T>\n const apiClient = useApiClient()\n\n const { data, ...query } = useSuspenseQuery<Resource, ApiError>({\n queryKey: getRequestQueryKey(args),\n queryFn: ({ queryKey }) => {\n const [url, d, headers, app = 'chat'] = queryKey as RequestQueryKey\n return apiClient[app]\n .get({ url, data: d, headers })\n .catch(throwResponseError) as Promise<Resource>\n },\n ...options,\n })\n\n return { ...data, ...query }\n}\n\ntype NextMeta = Partial<{\n offset: string\n idLt: string\n}>\n\nexport type SuspensePaginatorOptions = Omit<\n AnyUseSuspenseInfiniteQueryOptions,\n 'getNextPageParam' | 'initialPageParam' | 'queryFn' | 'queryKey'\n>\n\nexport const useSuspensePaginator = <T extends ResourceObject>(\n args: SuspenseGetOptions,\n opts?: SuspensePaginatorOptions\n) => {\n const apiClient = useApiClient()\n const query = useSuspenseInfiniteQuery<\n ApiCollection<T>,\n Response,\n InfiniteData<ApiCollection<T>>,\n any,\n Partial<RequestData> | undefined\n >({\n queryKey: getRequestQueryKey(args),\n queryFn: ({ pageParam }) => {\n Log.info('useSuspenseGet', { pageParam })\n\n const pageParmWhere = pageParam?.where || {}\n const argsWhere = args.data.where || {}\n const where = { ...argsWhere, ...pageParmWhere }\n const app = args.app || 'chat'\n const offset = pageParam?.offset || args.data.offset\n const data = { ...args.data, where, offset }\n\n return apiClient[app]\n .get<ApiCollection<T>>({\n url: args.url,\n data,\n })\n .catch(throwResponseError)\n },\n initialPageParam: {} as Partial<RequestData>,\n getNextPageParam: lastPage => {\n const next: NextMeta = lastPage.meta?.next || {}\n const { offset, idLt } = next\n\n if (idLt) return { where: { id_lt: idLt } }\n if (offset) return { offset: Number(offset) }\n\n return undefined\n },\n ...(opts || {}),\n })\n\n const data: T[] = query.data?.pages.flatMap(page => page.data) || []\n const totalCount = query.data?.pages[0]?.meta?.totalCount || data.length\n\n return { ...query, data, totalCount }\n}\n\nconst throwResponseError = (error: unknown) => {\n if (error instanceof Response) {\n throw new ResponseError(error as ApiError)\n }\n\n return Promise.reject(error)\n}\n\nexport type RequestQueryKey = [\n SuspenseGetOptions['url'],\n SuspenseGetOptions['data'],\n SuspenseGetOptions['headers'],\n SuspenseGetOptions['app'],\n SuspenseGetOptions['reply_root_id'],\n]\nexport const getRequestQueryKey = (args: SuspenseGetOptions): RequestQueryKey => [\n args.url,\n args.data,\n args.headers,\n args.app || 'chat',\n args.reply_root_id,\n]\n"]}
@@ -92,14 +92,15 @@ function MessageActionsScreenContent({ message, conversation_id, canDeleteNonAut
92
92
  }, [handleDeleteMessage]);
93
93
  const handleEditPress = useCallback(() => {
94
94
  const state = navigation.getState?.();
95
- const targetRoute = state?.routes?.find(r => r.name === 'Conversation');
95
+ const targetRouteName = inReplyScreen ? 'ConversationReply' : 'Conversation';
96
+ const targetRoute = state?.routes?.find(r => r.name === targetRouteName);
96
97
  const params = omitBy({
97
98
  ...(targetRoute?.params || {}),
98
99
  conversation_id,
99
100
  editing_message_id: message.id,
100
101
  }, isNil);
101
- navigation.dispatch(StackActions.popTo('Conversation', params));
102
- }, [navigation, conversation_id, message.id]);
102
+ navigation.dispatch(StackActions.popTo(targetRouteName, params));
103
+ }, [navigation, conversation_id, message.id, inReplyScreen]);
103
104
  const handleViewReadReceiptsPress = useCallback(() => {
104
105
  Haptic.impactLight();
105
106
  const params = omitBy({
@@ -1 +1 @@
1
- {"version":3,"file":"message_actions_screen.js","sourceRoot":"","sources":["../../src/screens/message_actions_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import { PlatformPressable } from '@react-navigation/elements'\nimport { StackActions, StaticScreenProps, useNavigation } from '@react-navigation/native'\nimport { useMutation } from '@tanstack/react-query'\nimport { isNil, omitBy } from 'lodash'\nimport React, { useCallback } from 'react'\nimport { Alert, Platform, StyleSheet, View } from 'react-native'\nimport { Text } from '../components'\nimport { REACTION_EMOJIS, useReactionStyles } from '../components/conversation/message_reaction'\nimport FormSheet, { getFormSheetScreenOptions } from '../components/primitive/form_sheet'\nimport { useCreateAndroidRippleColor, useFontScale, useTheme } from '../hooks'\nimport { useApiClient } from '../hooks/use_api_client'\nimport { useConversationMessages } from '../hooks/use_conversation_messages'\nimport { useMessageReactionToggle } from '../hooks/use_message_reaction_toggle'\nimport { ReactionCountResource } from '../types/resources/reaction'\nimport { Clipboard, Haptic } from '../utils/native_adapters'\nimport { MessageResource } from '../types'\nimport { availableFeatures, useFeatures } from '../hooks/use_features'\n\nexport const MessageActionsScreenOptions = getFormSheetScreenOptions({\n sheetAllowedDetents: [0.5],\n headerTitle: 'Message actions',\n})\n\nexport type MessageActionsScreenProps = StaticScreenProps<{\n message_id: string\n reply_root_author_name?: string\n conversation_id: number\n canDeleteNonAuthoredMessages?: boolean\n inReplyScreen?: boolean\n}>\n\nexport function MessageActionsScreen({ route }: MessageActionsScreenProps) {\n const {\n conversation_id,\n message_id,\n canDeleteNonAuthoredMessages,\n inReplyScreen,\n reply_root_author_name,\n } = route.params\n\n const { messages, refetch } = useConversationMessages(\n { conversation_id },\n { refetchOnMount: false }\n )\n const message = messages.find(m => m.id === message_id)\n\n if (!message) return null\n\n return (\n <MessageActionsScreenContent\n message={message}\n conversation_id={conversation_id}\n canDeleteNonAuthoredMessages={canDeleteNonAuthoredMessages || false}\n refetchMessages={refetch}\n inReplyScreen={inReplyScreen}\n replyRootAuthorName={reply_root_author_name}\n />\n )\n}\n\nfunction MessageActionsScreenContent({\n message,\n conversation_id,\n canDeleteNonAuthoredMessages,\n refetchMessages,\n inReplyScreen,\n replyRootAuthorName,\n}: {\n message: MessageResource\n conversation_id: number\n canDeleteNonAuthoredMessages: boolean\n refetchMessages: () => void\n inReplyScreen?: boolean\n replyRootAuthorName?: string\n}) {\n const navigation = useNavigation()\n const apiClient = useApiClient()\n const styles = useStyles()\n const { featureEnabled } = useFeatures()\n const repliesEnabled = featureEnabled(availableFeatures.threaded_replies)\n const expandedLink = message.attachments.find(attachment => attachment.type === 'ExpandedLink')\n const hasExpandedLink = !!expandedLink\n\n const myReactions = message?.reactionCounts\n .filter(reaction => reaction.mine)\n .map(reaction => reaction.value)\n\n const availableReactions = Object.entries(REACTION_EMOJIS).map(([value, emoji]) => {\n return {\n value: value as ReactionCountResource['value'],\n emoji,\n mine: myReactions?.includes(value as ReactionCountResource['value']),\n }\n })\n\n const attachmentForCopy = (): string => {\n const giphyTitleLink = message?.attachments.find(\n attachment => attachment.type === 'giphy'\n )?.titleLink\n\n if (giphyTitleLink) return giphyTitleLink\n return ''\n }\n\n const handleReplyPress = useCallback(() => {\n navigation.goBack()\n // Waits for the modal to be dismissed before pushing the reply screen\n requestAnimationFrame(() => {\n navigation.navigate('ConversationReply', {\n conversation_id,\n reply_root_id: message.replyRootId || message.id,\n reply_root_author_name: replyRootAuthorName,\n })\n })\n }, [navigation, conversation_id, message.id, message.replyRootId, replyRootAuthorName])\n\n const handleCopyPress = () => {\n Clipboard.setStringAsync(message?.text || attachmentForCopy() || '')\n navigation.goBack()\n }\n\n const { handleReactionToggle, isPending } = useMessageReactionToggle({\n conversation_id,\n message,\n onSuccess: () => navigation.goBack(),\n })\n\n const deleteMessage = useCallback(() => {\n const url = `/me/conversations/${conversation_id}/messages/${message.id}/`\n\n return apiClient.chat.delete({ url })\n }, [apiClient, conversation_id, message.id])\n\n const { mutate: handleDeleteMessage } = useMutation({\n mutationFn: deleteMessage,\n onSuccess: () => {\n refetchMessages()\n Haptic.notificationSuccess()\n navigation.goBack()\n },\n onError: () => {\n Alert.alert('Oops', 'We were unable to delete this message. Please try again.')\n },\n })\n\n const handleDeleteConfirm = useCallback(() => {\n Alert.alert('Delete message', 'Are you sure you want to permanently delete this message?', [\n { text: 'Cancel', style: 'cancel' },\n { text: 'Delete', style: 'destructive', onPress: () => handleDeleteMessage() },\n ])\n }, [handleDeleteMessage])\n\n const handleEditPress = useCallback(() => {\n const state = navigation.getState?.()\n const targetRoute = state?.routes?.find(r => r.name === 'Conversation')\n const params = omitBy(\n {\n ...(targetRoute?.params || {}),\n conversation_id,\n editing_message_id: message.id,\n },\n isNil\n )\n navigation.dispatch(StackActions.popTo('Conversation', params))\n }, [navigation, conversation_id, message.id])\n\n const handleViewReadReceiptsPress = useCallback(() => {\n Haptic.impactLight()\n const params = omitBy(\n {\n conversation_id,\n message_id: message.id,\n },\n isNil\n )\n navigation.dispatch(StackActions.popTo('MessageReadReceipts', params))\n }, [navigation, conversation_id, message.id])\n\n const removeLinkPreview = useCallback(() => {\n const url = `/me/conversations/${conversation_id}/messages/${message.id}/remove_expanded_link`\n const data = {\n data: { type: 'ExpandedLink', attributes: { expanded_link_id: expandedLink?.id } },\n }\n\n return apiClient.chat.post({ url, data })\n }, [apiClient, conversation_id, message.id, expandedLink])\n\n const { mutate: handleRemoveLinkPreview } = useMutation({\n mutationFn: removeLinkPreview,\n onSuccess: () => {\n refetchMessages()\n Haptic.notificationSuccess()\n navigation.goBack()\n },\n onError: () => {\n Alert.alert('Oops', 'We were unable to remove the preview. Please try again.')\n },\n })\n\n const handleRemoveLinkPreviewConfirm = useCallback(() => {\n Alert.alert('Remove link preview?', 'This will remove the image preview but retain the link', [\n { text: 'Cancel', style: 'cancel' },\n { text: 'Remove', style: 'destructive', onPress: () => handleRemoveLinkPreview() },\n ])\n }, [handleRemoveLinkPreview])\n\n return (\n <FormSheet.Root style={styles.formSheetContent}>\n <View style={styles.reactionList}>\n {availableReactions.map((reaction, index) => (\n <Reaction\n key={index}\n reaction={reaction}\n onPress={() => {\n Haptic.impactLight()\n handleReactionToggle({\n value: reaction.value,\n mine: reaction.mine,\n })\n }}\n />\n ))}\n </View>\n <View style={styles.actions}>\n {repliesEnabled && !inReplyScreen && (\n <FormSheet.Action\n onPress={handleReplyPress}\n title=\"Reply to message\"\n iconName=\"registrations.undo\"\n accessibilityHint=\"Navigates to the reply screen\"\n accessibilityRole=\"link\"\n />\n )}\n <FormSheet.Action\n onPress={handleCopyPress}\n title=\"Copy text\"\n iconName=\"services.fileCopy\"\n accessibilityHint=\"Copies text and links to clipboard\"\n />\n {message?.mine && (\n <FormSheet.Action\n onPress={() => handleEditPress()}\n title=\"Edit message\"\n iconName=\"accounts.editor\"\n accessibilityHint=\"Opens existing text in the message form input.\"\n />\n )}\n {message?.mine && (\n <FormSheet.Action\n onPress={() => handleViewReadReceiptsPress()}\n title=\"View read receipts\"\n iconName=\"general.checkPerson\"\n accessibilityHint=\"Opens a modal with a list of people who read your message.\"\n />\n )}\n {message?.mine && hasExpandedLink && (\n <FormSheet.Action\n onPress={() => handleRemoveLinkPreviewConfirm()}\n title=\"Remove link preview\"\n iconName=\"general.brokenLink\"\n accessibilityHint=\"Removes an expanded link preview from the message.\"\n />\n )}\n {(message?.mine || canDeleteNonAuthoredMessages) && (\n <FormSheet.Action\n onPress={() => handleDeleteConfirm()}\n title=\"Delete message\"\n iconName=\"publishing.trash\"\n appearance=\"danger\"\n disabled={isPending}\n accessibilityHint=\"Opens a confirmation alert to delete this message permanently.\"\n />\n )}\n </View>\n </FormSheet.Root>\n )\n}\n\nconst Reaction = ({\n reaction,\n onPress,\n}: {\n reaction: { value: ReactionCountResource['value']; emoji: string; mine: boolean | undefined }\n onPress: () => void\n}) => {\n const styles = useStyles()\n const reactionStyles = useReactionStyles({ mine: reaction.mine ? 1 : 0 })\n\n const { colors } = useTheme()\n const baseRippleColor = reaction.mine ? colors.interaction : colors.fillColorNeutral060\n const androidRippleColor = useCreateAndroidRippleColor({ color: baseRippleColor })\n\n return (\n <PlatformPressable\n key={reaction.value}\n style={[reactionStyles.reaction, styles.reaction]}\n android_ripple={{ color: androidRippleColor, borderless: false, foreground: true }}\n onPress={onPress}\n >\n <Text style={styles.reactionEmoji}>{REACTION_EMOJIS[reaction.value]}</Text>\n </PlatformPressable>\n )\n}\n\nconst useStyles = () => {\n const { colors } = useTheme()\n const fontScale = useFontScale({ maxFontSizeMultiplier: 1.3 })\n\n const btnBorderWidth = 1\n const baseSize = 46 * fontScale\n const reactionBtnSize = Platform.select({\n ios: baseSize,\n android: baseSize + btnBorderWidth * 2,\n })\n\n return StyleSheet.create({\n formSheetContent: {\n paddingTop: 16,\n },\n reactionList: {\n flexDirection: 'row',\n justifyContent: 'center',\n alignItems: 'center',\n gap: 16,\n paddingTop: 8,\n paddingBottom: 16,\n borderBottomColor: colors.borderColorDefaultBase,\n borderBottomWidth: 1,\n },\n reaction: {\n height: reactionBtnSize,\n width: reactionBtnSize,\n borderWidth: btnBorderWidth,\n borderRadius: 32,\n justifyContent: 'center',\n overflow: 'hidden',\n },\n reactionEmoji: {\n fontSize: 24,\n },\n actions: {\n paddingTop: 4,\n },\n })\n}\n"]}
1
+ {"version":3,"file":"message_actions_screen.js","sourceRoot":"","sources":["../../src/screens/message_actions_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import { PlatformPressable } from '@react-navigation/elements'\nimport { StackActions, StaticScreenProps, useNavigation } from '@react-navigation/native'\nimport { useMutation } from '@tanstack/react-query'\nimport { isNil, omitBy } from 'lodash'\nimport React, { useCallback } from 'react'\nimport { Alert, Platform, StyleSheet, View } from 'react-native'\nimport { Text } from '../components'\nimport { REACTION_EMOJIS, useReactionStyles } from '../components/conversation/message_reaction'\nimport FormSheet, { getFormSheetScreenOptions } from '../components/primitive/form_sheet'\nimport { useCreateAndroidRippleColor, useFontScale, useTheme } from '../hooks'\nimport { useApiClient } from '../hooks/use_api_client'\nimport { useConversationMessages } from '../hooks/use_conversation_messages'\nimport { useMessageReactionToggle } from '../hooks/use_message_reaction_toggle'\nimport { ReactionCountResource } from '../types/resources/reaction'\nimport { Clipboard, Haptic } from '../utils/native_adapters'\nimport { MessageResource } from '../types'\nimport { availableFeatures, useFeatures } from '../hooks/use_features'\n\nexport const MessageActionsScreenOptions = getFormSheetScreenOptions({\n sheetAllowedDetents: [0.5],\n headerTitle: 'Message actions',\n})\n\nexport type MessageActionsScreenProps = StaticScreenProps<{\n message_id: string\n reply_root_author_name?: string\n conversation_id: number\n canDeleteNonAuthoredMessages?: boolean\n inReplyScreen?: boolean\n}>\n\nexport function MessageActionsScreen({ route }: MessageActionsScreenProps) {\n const {\n conversation_id,\n message_id,\n canDeleteNonAuthoredMessages,\n inReplyScreen,\n reply_root_author_name,\n } = route.params\n\n const { messages, refetch } = useConversationMessages(\n { conversation_id },\n { refetchOnMount: false }\n )\n const message = messages.find(m => m.id === message_id)\n\n if (!message) return null\n\n return (\n <MessageActionsScreenContent\n message={message}\n conversation_id={conversation_id}\n canDeleteNonAuthoredMessages={canDeleteNonAuthoredMessages || false}\n refetchMessages={refetch}\n inReplyScreen={inReplyScreen}\n replyRootAuthorName={reply_root_author_name}\n />\n )\n}\n\nfunction MessageActionsScreenContent({\n message,\n conversation_id,\n canDeleteNonAuthoredMessages,\n refetchMessages,\n inReplyScreen,\n replyRootAuthorName,\n}: {\n message: MessageResource\n conversation_id: number\n canDeleteNonAuthoredMessages: boolean\n refetchMessages: () => void\n inReplyScreen?: boolean\n replyRootAuthorName?: string\n}) {\n const navigation = useNavigation()\n const apiClient = useApiClient()\n const styles = useStyles()\n const { featureEnabled } = useFeatures()\n const repliesEnabled = featureEnabled(availableFeatures.threaded_replies)\n const expandedLink = message.attachments.find(attachment => attachment.type === 'ExpandedLink')\n const hasExpandedLink = !!expandedLink\n\n const myReactions = message?.reactionCounts\n .filter(reaction => reaction.mine)\n .map(reaction => reaction.value)\n\n const availableReactions = Object.entries(REACTION_EMOJIS).map(([value, emoji]) => {\n return {\n value: value as ReactionCountResource['value'],\n emoji,\n mine: myReactions?.includes(value as ReactionCountResource['value']),\n }\n })\n\n const attachmentForCopy = (): string => {\n const giphyTitleLink = message?.attachments.find(\n attachment => attachment.type === 'giphy'\n )?.titleLink\n\n if (giphyTitleLink) return giphyTitleLink\n return ''\n }\n\n const handleReplyPress = useCallback(() => {\n navigation.goBack()\n // Waits for the modal to be dismissed before pushing the reply screen\n requestAnimationFrame(() => {\n navigation.navigate('ConversationReply', {\n conversation_id,\n reply_root_id: message.replyRootId || message.id,\n reply_root_author_name: replyRootAuthorName,\n })\n })\n }, [navigation, conversation_id, message.id, message.replyRootId, replyRootAuthorName])\n\n const handleCopyPress = () => {\n Clipboard.setStringAsync(message?.text || attachmentForCopy() || '')\n navigation.goBack()\n }\n\n const { handleReactionToggle, isPending } = useMessageReactionToggle({\n conversation_id,\n message,\n onSuccess: () => navigation.goBack(),\n })\n\n const deleteMessage = useCallback(() => {\n const url = `/me/conversations/${conversation_id}/messages/${message.id}/`\n\n return apiClient.chat.delete({ url })\n }, [apiClient, conversation_id, message.id])\n\n const { mutate: handleDeleteMessage } = useMutation({\n mutationFn: deleteMessage,\n onSuccess: () => {\n refetchMessages()\n Haptic.notificationSuccess()\n navigation.goBack()\n },\n onError: () => {\n Alert.alert('Oops', 'We were unable to delete this message. Please try again.')\n },\n })\n\n const handleDeleteConfirm = useCallback(() => {\n Alert.alert('Delete message', 'Are you sure you want to permanently delete this message?', [\n { text: 'Cancel', style: 'cancel' },\n { text: 'Delete', style: 'destructive', onPress: () => handleDeleteMessage() },\n ])\n }, [handleDeleteMessage])\n\n const handleEditPress = useCallback(() => {\n const state = navigation.getState?.()\n const targetRouteName = inReplyScreen ? 'ConversationReply' : 'Conversation'\n const targetRoute = state?.routes?.find(r => r.name === targetRouteName)\n const params = omitBy(\n {\n ...(targetRoute?.params || {}),\n conversation_id,\n editing_message_id: message.id,\n },\n isNil\n )\n navigation.dispatch(StackActions.popTo(targetRouteName, params))\n }, [navigation, conversation_id, message.id, inReplyScreen])\n\n const handleViewReadReceiptsPress = useCallback(() => {\n Haptic.impactLight()\n const params = omitBy(\n {\n conversation_id,\n message_id: message.id,\n },\n isNil\n )\n navigation.dispatch(StackActions.popTo('MessageReadReceipts', params))\n }, [navigation, conversation_id, message.id])\n\n const removeLinkPreview = useCallback(() => {\n const url = `/me/conversations/${conversation_id}/messages/${message.id}/remove_expanded_link`\n const data = {\n data: { type: 'ExpandedLink', attributes: { expanded_link_id: expandedLink?.id } },\n }\n\n return apiClient.chat.post({ url, data })\n }, [apiClient, conversation_id, message.id, expandedLink])\n\n const { mutate: handleRemoveLinkPreview } = useMutation({\n mutationFn: removeLinkPreview,\n onSuccess: () => {\n refetchMessages()\n Haptic.notificationSuccess()\n navigation.goBack()\n },\n onError: () => {\n Alert.alert('Oops', 'We were unable to remove the preview. Please try again.')\n },\n })\n\n const handleRemoveLinkPreviewConfirm = useCallback(() => {\n Alert.alert('Remove link preview?', 'This will remove the image preview but retain the link', [\n { text: 'Cancel', style: 'cancel' },\n { text: 'Remove', style: 'destructive', onPress: () => handleRemoveLinkPreview() },\n ])\n }, [handleRemoveLinkPreview])\n\n return (\n <FormSheet.Root style={styles.formSheetContent}>\n <View style={styles.reactionList}>\n {availableReactions.map((reaction, index) => (\n <Reaction\n key={index}\n reaction={reaction}\n onPress={() => {\n Haptic.impactLight()\n handleReactionToggle({\n value: reaction.value,\n mine: reaction.mine,\n })\n }}\n />\n ))}\n </View>\n <View style={styles.actions}>\n {repliesEnabled && !inReplyScreen && (\n <FormSheet.Action\n onPress={handleReplyPress}\n title=\"Reply to message\"\n iconName=\"registrations.undo\"\n accessibilityHint=\"Navigates to the reply screen\"\n accessibilityRole=\"link\"\n />\n )}\n <FormSheet.Action\n onPress={handleCopyPress}\n title=\"Copy text\"\n iconName=\"services.fileCopy\"\n accessibilityHint=\"Copies text and links to clipboard\"\n />\n {message?.mine && (\n <FormSheet.Action\n onPress={() => handleEditPress()}\n title=\"Edit message\"\n iconName=\"accounts.editor\"\n accessibilityHint=\"Opens existing text in the message form input.\"\n />\n )}\n {message?.mine && (\n <FormSheet.Action\n onPress={() => handleViewReadReceiptsPress()}\n title=\"View read receipts\"\n iconName=\"general.checkPerson\"\n accessibilityHint=\"Opens a modal with a list of people who read your message.\"\n />\n )}\n {message?.mine && hasExpandedLink && (\n <FormSheet.Action\n onPress={() => handleRemoveLinkPreviewConfirm()}\n title=\"Remove link preview\"\n iconName=\"general.brokenLink\"\n accessibilityHint=\"Removes an expanded link preview from the message.\"\n />\n )}\n {(message?.mine || canDeleteNonAuthoredMessages) && (\n <FormSheet.Action\n onPress={() => handleDeleteConfirm()}\n title=\"Delete message\"\n iconName=\"publishing.trash\"\n appearance=\"danger\"\n disabled={isPending}\n accessibilityHint=\"Opens a confirmation alert to delete this message permanently.\"\n />\n )}\n </View>\n </FormSheet.Root>\n )\n}\n\nconst Reaction = ({\n reaction,\n onPress,\n}: {\n reaction: { value: ReactionCountResource['value']; emoji: string; mine: boolean | undefined }\n onPress: () => void\n}) => {\n const styles = useStyles()\n const reactionStyles = useReactionStyles({ mine: reaction.mine ? 1 : 0 })\n\n const { colors } = useTheme()\n const baseRippleColor = reaction.mine ? colors.interaction : colors.fillColorNeutral060\n const androidRippleColor = useCreateAndroidRippleColor({ color: baseRippleColor })\n\n return (\n <PlatformPressable\n key={reaction.value}\n style={[reactionStyles.reaction, styles.reaction]}\n android_ripple={{ color: androidRippleColor, borderless: false, foreground: true }}\n onPress={onPress}\n >\n <Text style={styles.reactionEmoji}>{REACTION_EMOJIS[reaction.value]}</Text>\n </PlatformPressable>\n )\n}\n\nconst useStyles = () => {\n const { colors } = useTheme()\n const fontScale = useFontScale({ maxFontSizeMultiplier: 1.3 })\n\n const btnBorderWidth = 1\n const baseSize = 46 * fontScale\n const reactionBtnSize = Platform.select({\n ios: baseSize,\n android: baseSize + btnBorderWidth * 2,\n })\n\n return StyleSheet.create({\n formSheetContent: {\n paddingTop: 16,\n },\n reactionList: {\n flexDirection: 'row',\n justifyContent: 'center',\n alignItems: 'center',\n gap: 16,\n paddingTop: 8,\n paddingBottom: 16,\n borderBottomColor: colors.borderColorDefaultBase,\n borderBottomWidth: 1,\n },\n reaction: {\n height: reactionBtnSize,\n width: reactionBtnSize,\n borderWidth: btnBorderWidth,\n borderRadius: 32,\n justifyContent: 'center',\n overflow: 'hidden',\n },\n reactionEmoji: {\n fontSize: 24,\n },\n actions: {\n paddingTop: 4,\n },\n })\n}\n"]}
@@ -1,7 +1,8 @@
1
1
  import { MessageResource } from '../../types';
2
- export declare function optimisticallyUpdateMessage({ conversationId, message, text, }: {
2
+ export declare function optimisticallyUpdateMessage({ conversationId, message, text, replyRootId, }: {
3
3
  conversationId: number;
4
4
  message: MessageResource;
5
5
  text: string;
6
+ replyRootId?: string | null;
6
7
  }): MessageResource;
7
8
  //# sourceMappingURL=optimistically_update_message.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"optimistically_update_message.d.ts","sourceRoot":"","sources":["../../../src/utils/cache/optimistically_update_message.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,eAAe,EAAE,MAAM,aAAa,CAAA;AAK5D,wBAAgB,2BAA2B,CAAC,EAC1C,cAAc,EACd,OAAO,EACP,IAAI,GACL,EAAE;IACD,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,eAAe,CAAA;IACxB,IAAI,EAAE,MAAM,CAAA;CACb,mBAsBA"}
1
+ {"version":3,"file":"optimistically_update_message.d.ts","sourceRoot":"","sources":["../../../src/utils/cache/optimistically_update_message.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,eAAe,EAAE,MAAM,aAAa,CAAA;AAK5D,wBAAgB,2BAA2B,CAAC,EAC1C,cAAc,EACd,OAAO,EACP,IAAI,EACJ,WAAW,GACZ,EAAE;IACD,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,eAAe,CAAA;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B,mBA0BA"}
@@ -1,8 +1,11 @@
1
1
  import { getMessagesQueryKey } from '../../utils/request/get_messages';
2
2
  import { chatQueryClient } from '../../contexts/api_provider';
3
3
  import { updateOrCreateRecordInPagesData } from './page_mutations';
4
- export function optimisticallyUpdateMessage({ conversationId, message, text, }) {
5
- const queryKey = getMessagesQueryKey({ conversation_id: conversationId });
4
+ export function optimisticallyUpdateMessage({ conversationId, message, text, replyRootId, }) {
5
+ const queryKey = getMessagesQueryKey({
6
+ conversation_id: conversationId,
7
+ reply_root_id: replyRootId,
8
+ });
6
9
  let optimisticMessage = message;
7
10
  chatQueryClient.setQueryData(queryKey, data => updateOrCreateRecordInPagesData({
8
11
  data,
@@ -1 +1 @@
1
- {"version":3,"file":"optimistically_update_message.js","sourceRoot":"","sources":["../../../src/utils/cache/optimistically_update_message.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAA;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAC7D,OAAO,EAAE,+BAA+B,EAAE,MAAM,kBAAkB,CAAA;AAElE,MAAM,UAAU,2BAA2B,CAAC,EAC1C,cAAc,EACd,OAAO,EACP,IAAI,GAKL;IAEC,MAAM,QAAQ,GAAG,mBAAmB,CAAC,EAAE,eAAe,EAAE,cAAc,EAAE,CAAC,CAAA;IAEzE,IAAI,iBAAiB,GAAG,OAAO,CAAA;IAE/B,eAAe,CAAC,YAAY,CAAY,QAAQ,EAAE,IAAI,CAAC,EAAE,CACvD,+BAA+B,CAAC;QAC9B,IAAI;QACJ,MAAM,EAAE,OAAO;QACf,aAAa,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;YAC5B,iBAAiB,GAAG;gBAClB,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;gBACjB,IAAI;gBACJ,OAAO,EAAE,IAAI;aACd,CAAA;YACD,OAAO,iBAAiB,CAAA;QAC1B,CAAC;KACF,CAAC,CACH,CAAA;IAED,OAAO,iBAAiB,CAAA;AAC1B,CAAC","sourcesContent":["import { InfiniteData } from '@tanstack/react-query'\nimport { ApiCollection, MessageResource } from '../../types'\nimport { getMessagesQueryKey } from '../../utils/request/get_messages'\nimport { chatQueryClient } from '../../contexts/api_provider'\nimport { updateOrCreateRecordInPagesData } from './page_mutations'\n\nexport function optimisticallyUpdateMessage({\n conversationId,\n message,\n text,\n}: {\n conversationId: number\n message: MessageResource\n text: string\n}) {\n type QueryData = InfiniteData<ApiCollection<MessageResource>>\n const queryKey = getMessagesQueryKey({ conversation_id: conversationId })\n\n let optimisticMessage = message\n\n chatQueryClient.setQueryData<QueryData>(queryKey, data =>\n updateOrCreateRecordInPagesData({\n data,\n record: message,\n processRecord: (next, prev) => {\n optimisticMessage = {\n ...(prev || next),\n text,\n pending: true,\n }\n return optimisticMessage\n },\n })\n )\n\n return optimisticMessage\n}\n"]}
1
+ {"version":3,"file":"optimistically_update_message.js","sourceRoot":"","sources":["../../../src/utils/cache/optimistically_update_message.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAA;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAC7D,OAAO,EAAE,+BAA+B,EAAE,MAAM,kBAAkB,CAAA;AAElE,MAAM,UAAU,2BAA2B,CAAC,EAC1C,cAAc,EACd,OAAO,EACP,IAAI,EACJ,WAAW,GAMZ;IAGC,MAAM,QAAQ,GAAG,mBAAmB,CAAC;QACnC,eAAe,EAAE,cAAc;QAC/B,aAAa,EAAE,WAAW;KAC3B,CAAC,CAAA;IAEF,IAAI,iBAAiB,GAAG,OAAO,CAAA;IAE/B,eAAe,CAAC,YAAY,CAAY,QAAQ,EAAE,IAAI,CAAC,EAAE,CACvD,+BAA+B,CAAC;QAC9B,IAAI;QACJ,MAAM,EAAE,OAAO;QACf,aAAa,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;YAC5B,iBAAiB,GAAG;gBAClB,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;gBACjB,IAAI;gBACJ,OAAO,EAAE,IAAI;aACd,CAAA;YACD,OAAO,iBAAiB,CAAA;QAC1B,CAAC;KACF,CAAC,CACH,CAAA;IAED,OAAO,iBAAiB,CAAA;AAC1B,CAAC","sourcesContent":["import { InfiniteData } from '@tanstack/react-query'\nimport { ApiCollection, MessageResource } from '../../types'\nimport { getMessagesQueryKey } from '../../utils/request/get_messages'\nimport { chatQueryClient } from '../../contexts/api_provider'\nimport { updateOrCreateRecordInPagesData } from './page_mutations'\n\nexport function optimisticallyUpdateMessage({\n conversationId,\n message,\n text,\n replyRootId,\n}: {\n conversationId: number\n message: MessageResource\n text: string\n replyRootId?: string | null\n}) {\n type QueryData = InfiniteData<ApiCollection<MessageResource>>\n\n const queryKey = getMessagesQueryKey({\n conversation_id: conversationId,\n reply_root_id: replyRootId,\n })\n\n let optimisticMessage = message\n\n chatQueryClient.setQueryData<QueryData>(queryKey, data =>\n updateOrCreateRecordInPagesData({\n data,\n record: message,\n processRecord: (next, prev) => {\n optimisticMessage = {\n ...(prev || next),\n text,\n pending: true,\n }\n return optimisticMessage\n },\n })\n )\n\n return optimisticMessage\n}\n"]}
@@ -12,6 +12,7 @@ export declare const getMessagesRequestArgs: ({ conversation_id, reply_root_id,
12
12
  };
13
13
  include: string[];
14
14
  };
15
+ reply_root_id: string | null;
15
16
  };
16
17
  export declare const getMessagesQueryKey: ({ conversation_id, reply_root_id, }: {
17
18
  conversation_id: number;
@@ -1 +1 @@
1
- {"version":3,"file":"get_messages.d.ts","sourceRoot":"","sources":["../../../src/utils/request/get_messages.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,sBAAsB,wCAGhC;IACD,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;;;;;;;;;;;CAaA,CAAA;AAED,eAAO,MAAM,mBAAmB,wCAG7B;IACD,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B,2DAGA,CAAA"}
1
+ {"version":3,"file":"get_messages.d.ts","sourceRoot":"","sources":["../../../src/utils/request/get_messages.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,sBAAsB,wCAGhC;IACD,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;;;;;;;;;;;;CAeA,CAAA;AAED,eAAO,MAAM,mBAAmB,wCAG7B;IACD,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B,2DAGA,CAAA"}
@@ -1,8 +1,9 @@
1
1
  import { getRequestQueryKey } from '../../hooks/use_suspense_api';
2
2
  import { getMessageFields, getMessagesInclude } from './messages_data_options';
3
3
  export const getMessagesRequestArgs = ({ conversation_id, reply_root_id, }) => {
4
- const url = reply_root_id
5
- ? `/me/conversations/${conversation_id}/messages/${reply_root_id}/replies`
4
+ const normalizedReplyRootId = reply_root_id ?? null;
5
+ const url = normalizedReplyRootId
6
+ ? `/me/conversations/${conversation_id}/messages/${normalizedReplyRootId}/replies`
6
7
  : `/me/conversations/${conversation_id}/messages`;
7
8
  return {
8
9
  url,
@@ -11,6 +12,7 @@ export const getMessagesRequestArgs = ({ conversation_id, reply_root_id, }) => {
11
12
  fields: getMessageFields,
12
13
  include: getMessagesInclude,
13
14
  },
15
+ reply_root_id: normalizedReplyRootId,
14
16
  };
15
17
  };
16
18
  export const getMessagesQueryKey = ({ conversation_id, reply_root_id, }) => {
@@ -1 +1 @@
1
- {"version":3,"file":"get_messages.js","sourceRoot":"","sources":["../../../src/utils/request/get_messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AACjE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAE9E,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,EACrC,eAAe,EACf,aAAa,GAId,EAAE,EAAE;IACH,MAAM,GAAG,GAAG,aAAa;QACvB,CAAC,CAAC,qBAAqB,eAAe,aAAa,aAAa,UAAU;QAC1E,CAAC,CAAC,qBAAqB,eAAe,WAAW,CAAA;IAEnD,OAAO;QACL,GAAG;QACH,IAAI,EAAE;YACJ,OAAO,EAAE,EAAE;YACX,MAAM,EAAE,gBAAgB;YACxB,OAAO,EAAE,kBAAkB;SAC5B;KACF,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,EAClC,eAAe,EACf,aAAa,GAId,EAAE,EAAE;IACH,MAAM,WAAW,GAAG,sBAAsB,CAAC,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC,CAAA;IAC9E,OAAO,kBAAkB,CAAC,WAAW,CAAC,CAAA;AACxC,CAAC,CAAA","sourcesContent":["import { getRequestQueryKey } from '../../hooks/use_suspense_api'\nimport { getMessageFields, getMessagesInclude } from './messages_data_options'\n\nexport const getMessagesRequestArgs = ({\n conversation_id,\n reply_root_id,\n}: {\n conversation_id: number\n reply_root_id?: string | null\n}) => {\n const url = reply_root_id\n ? `/me/conversations/${conversation_id}/messages/${reply_root_id}/replies`\n : `/me/conversations/${conversation_id}/messages`\n\n return {\n url,\n data: {\n perPage: 25,\n fields: getMessageFields,\n include: getMessagesInclude,\n },\n }\n}\n\nexport const getMessagesQueryKey = ({\n conversation_id,\n reply_root_id,\n}: {\n conversation_id: number\n reply_root_id?: string | null\n}) => {\n const requestArgs = getMessagesRequestArgs({ conversation_id, reply_root_id })\n return getRequestQueryKey(requestArgs)\n}\n"]}
1
+ {"version":3,"file":"get_messages.js","sourceRoot":"","sources":["../../../src/utils/request/get_messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AACjE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAE9E,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,EACrC,eAAe,EACf,aAAa,GAId,EAAE,EAAE;IACH,MAAM,qBAAqB,GAAG,aAAa,IAAI,IAAI,CAAA;IACnD,MAAM,GAAG,GAAG,qBAAqB;QAC/B,CAAC,CAAC,qBAAqB,eAAe,aAAa,qBAAqB,UAAU;QAClF,CAAC,CAAC,qBAAqB,eAAe,WAAW,CAAA;IAEnD,OAAO;QACL,GAAG;QACH,IAAI,EAAE;YACJ,OAAO,EAAE,EAAE;YACX,MAAM,EAAE,gBAAgB;YACxB,OAAO,EAAE,kBAAkB;SAC5B;QACD,aAAa,EAAE,qBAAqB;KACrC,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,EAClC,eAAe,EACf,aAAa,GAId,EAAE,EAAE;IACH,MAAM,WAAW,GAAG,sBAAsB,CAAC,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC,CAAA;IAC9E,OAAO,kBAAkB,CAAC,WAAW,CAAC,CAAA;AACxC,CAAC,CAAA","sourcesContent":["import { getRequestQueryKey } from '../../hooks/use_suspense_api'\nimport { getMessageFields, getMessagesInclude } from './messages_data_options'\n\nexport const getMessagesRequestArgs = ({\n conversation_id,\n reply_root_id,\n}: {\n conversation_id: number\n reply_root_id?: string | null\n}) => {\n const normalizedReplyRootId = reply_root_id ?? null\n const url = normalizedReplyRootId\n ? `/me/conversations/${conversation_id}/messages/${normalizedReplyRootId}/replies`\n : `/me/conversations/${conversation_id}/messages`\n\n return {\n url,\n data: {\n perPage: 25,\n fields: getMessageFields,\n include: getMessagesInclude,\n },\n reply_root_id: normalizedReplyRootId,\n }\n}\n\nexport const getMessagesQueryKey = ({\n conversation_id,\n reply_root_id,\n}: {\n conversation_id: number\n reply_root_id?: string | null\n}) => {\n const requestArgs = getMessagesRequestArgs({ conversation_id, reply_root_id })\n return getRequestQueryKey(requestArgs)\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planningcenter/chat-react-native",
3
- "version": "3.20.1-rc.1",
3
+ "version": "3.20.1-rc.2",
4
4
  "description": "",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -58,5 +58,5 @@
58
58
  "react-native-url-polyfill": "^2.0.0",
59
59
  "typescript": "<5.6.0"
60
60
  },
61
- "gitHead": "e0a908049cd839fc176a02a3addbf94ec4b9a42d"
61
+ "gitHead": "4b05560e3db64829d1b96cf712b54b41b9201f25"
62
62
  }
@@ -43,7 +43,7 @@ export function useMessageCreateOrUpdate({ conversationId, message, replyRootId
43
43
  let attributes: any = {
44
44
  text,
45
45
  ...(attachments ? { attachments } : {}),
46
- ...(replyRootId ? { reply_root: { id: replyRootId } } : {}),
46
+ ...(!isEditing && replyRootId ? { reply_root: { id: replyRootId } } : {}),
47
47
  }
48
48
  if (!isEditing) {
49
49
  const idempotentKey = insecureUUID()
@@ -83,6 +83,7 @@ export function useMessageCreateOrUpdate({ conversationId, message, replyRootId
83
83
  conversationId,
84
84
  message,
85
85
  text,
86
+ replyRootId,
86
87
  })
87
88
 
88
89
  return { message: optimisticMessage }
@@ -14,7 +14,7 @@ import { ResponseError } from '../utils/response_error'
14
14
 
15
15
  interface SuspenseGetOptions extends GetRequest {
16
16
  app?: App
17
- reply_root_id?: string
17
+ reply_root_id?: string | null
18
18
  }
19
19
 
20
20
  export type SuspenseGetQueryOptions<T extends ResourceObject | ResourceObject[]> = Omit<
@@ -152,7 +152,8 @@ function MessageActionsScreenContent({
152
152
 
153
153
  const handleEditPress = useCallback(() => {
154
154
  const state = navigation.getState?.()
155
- const targetRoute = state?.routes?.find(r => r.name === 'Conversation')
155
+ const targetRouteName = inReplyScreen ? 'ConversationReply' : 'Conversation'
156
+ const targetRoute = state?.routes?.find(r => r.name === targetRouteName)
156
157
  const params = omitBy(
157
158
  {
158
159
  ...(targetRoute?.params || {}),
@@ -161,8 +162,8 @@ function MessageActionsScreenContent({
161
162
  },
162
163
  isNil
163
164
  )
164
- navigation.dispatch(StackActions.popTo('Conversation', params))
165
- }, [navigation, conversation_id, message.id])
165
+ navigation.dispatch(StackActions.popTo(targetRouteName, params))
166
+ }, [navigation, conversation_id, message.id, inReplyScreen])
166
167
 
167
168
  const handleViewReadReceiptsPress = useCallback(() => {
168
169
  Haptic.impactLight()
@@ -8,13 +8,19 @@ export function optimisticallyUpdateMessage({
8
8
  conversationId,
9
9
  message,
10
10
  text,
11
+ replyRootId,
11
12
  }: {
12
13
  conversationId: number
13
14
  message: MessageResource
14
15
  text: string
16
+ replyRootId?: string | null
15
17
  }) {
16
18
  type QueryData = InfiniteData<ApiCollection<MessageResource>>
17
- const queryKey = getMessagesQueryKey({ conversation_id: conversationId })
19
+
20
+ const queryKey = getMessagesQueryKey({
21
+ conversation_id: conversationId,
22
+ reply_root_id: replyRootId,
23
+ })
18
24
 
19
25
  let optimisticMessage = message
20
26
 
@@ -8,8 +8,9 @@ export const getMessagesRequestArgs = ({
8
8
  conversation_id: number
9
9
  reply_root_id?: string | null
10
10
  }) => {
11
- const url = reply_root_id
12
- ? `/me/conversations/${conversation_id}/messages/${reply_root_id}/replies`
11
+ const normalizedReplyRootId = reply_root_id ?? null
12
+ const url = normalizedReplyRootId
13
+ ? `/me/conversations/${conversation_id}/messages/${normalizedReplyRootId}/replies`
13
14
  : `/me/conversations/${conversation_id}/messages`
14
15
 
15
16
  return {
@@ -19,6 +20,7 @@ export const getMessagesRequestArgs = ({
19
20
  fields: getMessageFields,
20
21
  include: getMessagesInclude,
21
22
  },
23
+ reply_root_id: normalizedReplyRootId,
22
24
  }
23
25
  }
24
26