@planningcenter/chat-react-native 4.2.0-rc.0 → 4.2.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/build/components/conversation/message.d.ts +3 -2
  2. package/build/components/conversation/message.d.ts.map +1 -1
  3. package/build/components/conversation/message.js +23 -22
  4. package/build/components/conversation/message.js.map +1 -1
  5. package/build/components/conversation/message_list.d.ts +21 -0
  6. package/build/components/conversation/message_list.d.ts.map +1 -0
  7. package/build/components/conversation/message_list.js +273 -0
  8. package/build/components/conversation/message_list.js.map +1 -0
  9. package/build/components/conversation/message_read_receipts.d.ts +2 -4
  10. package/build/components/conversation/message_read_receipts.d.ts.map +1 -1
  11. package/build/components/conversation/message_read_receipts.js +2 -3
  12. package/build/components/conversation/message_read_receipts.js.map +1 -1
  13. package/build/components/conversation/reply_shadow_message.d.ts +2 -1
  14. package/build/components/conversation/reply_shadow_message.d.ts.map +1 -1
  15. package/build/components/conversation/reply_shadow_message.js +47 -46
  16. package/build/components/conversation/reply_shadow_message.js.map +1 -1
  17. package/build/hooks/use_conversation_messages.d.ts.map +1 -1
  18. package/build/hooks/use_conversation_messages.js +40 -28
  19. package/build/hooks/use_conversation_messages.js.map +1 -1
  20. package/build/hooks/use_conversation_messages_jolt_events.d.ts.map +1 -1
  21. package/build/hooks/use_conversation_messages_jolt_events.js +6 -1
  22. package/build/hooks/use_conversation_messages_jolt_events.js.map +1 -1
  23. package/build/screens/conversation_screen.d.ts.map +1 -1
  24. package/build/screens/conversation_screen.js +184 -365
  25. package/build/screens/conversation_screen.js.map +1 -1
  26. package/build/types/resources/message.d.ts +1 -0
  27. package/build/types/resources/message.d.ts.map +1 -1
  28. package/build/types/resources/message.js.map +1 -1
  29. package/build/utils/cache/messages_cache.d.ts +1 -0
  30. package/build/utils/cache/messages_cache.d.ts.map +1 -1
  31. package/build/utils/cache/messages_cache.js +10 -1
  32. package/build/utils/cache/messages_cache.js.map +1 -1
  33. package/build/utils/client/transform_response.d.ts.map +1 -1
  34. package/build/utils/client/transform_response.js +9 -5
  35. package/build/utils/client/transform_response.js.map +1 -1
  36. package/build/utils/group_messages.d.ts +1 -0
  37. package/build/utils/group_messages.d.ts.map +1 -1
  38. package/build/utils/group_messages.js +10 -1
  39. package/build/utils/group_messages.js.map +1 -1
  40. package/build/utils/replace_equal_by_id.d.ts +6 -0
  41. package/build/utils/replace_equal_by_id.d.ts.map +1 -0
  42. package/build/utils/replace_equal_by_id.js +41 -0
  43. package/build/utils/replace_equal_by_id.js.map +1 -0
  44. package/build/utils/request/messages_data_options.d.ts.map +1 -1
  45. package/build/utils/request/messages_data_options.js +1 -1
  46. package/build/utils/request/messages_data_options.js.map +1 -1
  47. package/package.json +2 -2
  48. package/src/components/conversation/__tests__/message_list.test.tsx +277 -0
  49. package/src/components/conversation/__tests__/reply_shadow_message.test.tsx +119 -0
  50. package/src/components/conversation/message.tsx +15 -18
  51. package/src/components/conversation/message_list.tsx +157 -0
  52. package/src/components/conversation/message_read_receipts.tsx +3 -5
  53. package/src/components/conversation/reply_shadow_message.tsx +9 -7
  54. package/src/hooks/use_conversation_messages.ts +5 -1
  55. package/src/hooks/use_conversation_messages_jolt_events.ts +7 -0
  56. package/src/screens/conversation_screen.tsx +11 -104
  57. package/src/types/resources/message.ts +1 -0
  58. package/src/utils/__tests__/group_messages.test.ts +48 -0
  59. package/src/utils/__tests__/replace_equal_by_id.test.ts +73 -0
  60. package/src/utils/cache/__tests__/messages_cache_reply_roots.test.ts +70 -0
  61. package/src/utils/cache/messages_cache.ts +21 -1
  62. package/src/utils/client/__tests__/transform_response.test.ts +62 -0
  63. package/src/utils/client/transform_response.ts +7 -5
  64. package/src/utils/group_messages.ts +18 -1
  65. package/src/utils/replace_equal_by_id.ts +42 -0
  66. package/src/utils/request/messages_data_options.ts +1 -1
@@ -10,6 +10,7 @@ export type ReplyShadowMessage = {
10
10
  type: 'ReplyShadowMessage'
11
11
  id: string
12
12
  messageId: string
13
+ replyRoot: MessageResource | null
13
14
  isReplyShadowMessage: boolean
14
15
  nextRendersAuthor: boolean
15
16
  }
@@ -23,6 +24,7 @@ interface GroupMessagesProps {
23
24
 
24
25
  export function groupMessages({ ms, inReplyScreen }: GroupMessagesProps): EnrichedMessage[] {
25
26
  const items: EnrichedMessage[] = []
27
+ const messagesById = new Map(ms.map(message => [message.id, message]))
26
28
  let myLatestSeen = false
27
29
  let nextNeighborEnriched: MessageResource | undefined
28
30
 
@@ -41,7 +43,13 @@ export function groupMessages({ ms, inReplyScreen }: GroupMessagesProps): Enrich
41
43
  const isMyLatest = !myLatestSeen && message.mine
42
44
  if (isMyLatest) myLatestSeen = true
43
45
 
44
- const enriched = enrichRegularMessage(message, prev, next, isMyLatest, !!inReplyScreen)
46
+ const enriched = enrichRegularMessage(
47
+ { ...message, replyRoot: resolveReplyRoot(message, messagesById) },
48
+ prev,
49
+ next,
50
+ isMyLatest,
51
+ !!inReplyScreen
52
+ )
45
53
  items.push(enriched)
46
54
 
47
55
  const shadow = replyShadowFor(enriched, prev)
@@ -61,6 +69,14 @@ function neighborsOf<T>(arr: T[], i: number): { prev: T | undefined; next: T | u
61
69
  return { prev: arr[i + 1], next: arr[i - 1] }
62
70
  }
63
71
 
72
+ function resolveReplyRoot(
73
+ message: MessageResource,
74
+ messagesById: Map<string, MessageResource>
75
+ ): MessageResource | null {
76
+ if (!message.replyRootId || message.replyRootId === message.id) return null
77
+ return messagesById.get(message.replyRootId) ?? message.replyRoot ?? null
78
+ }
79
+
64
80
  function enrichSystemMessage(
65
81
  message: MessageResource,
66
82
  next: MessageResource | undefined
@@ -171,6 +187,7 @@ function replyShadowFor(
171
187
  type: 'ReplyShadowMessage',
172
188
  id: `${message.id}-${message.replyRootId}`,
173
189
  messageId: message.replyRootId,
190
+ replyRoot: message.replyRoot ?? null,
174
191
  isReplyShadowMessage: true,
175
192
  nextRendersAuthor: message.renderAuthor ?? false,
176
193
  }
@@ -0,0 +1,42 @@
1
+ import { InfiniteData, replaceEqualDeep } from '@tanstack/react-query'
2
+ import { ApiCollection, ResourceObject } from '../types'
3
+
4
+ type Pages = InfiniteData<ApiCollection<ResourceObject>>
5
+
6
+ /** replaceEqualById
7
+ * TanStack's default structural sharing compares arrays by index, so an insert or
8
+ * delete gives every shifted record a new identity. Match by id instead.
9
+ */
10
+ export function replaceEqualById(oldData: unknown, newData: unknown): unknown {
11
+ const prev = oldData as Pages | undefined
12
+ const next = newData as Pages
13
+ if (!prev?.pages || !next?.pages) return replaceEqualDeep(prev, next)
14
+
15
+ const prevById = new Map<ResourceObject['id'], ResourceObject>()
16
+ prev.pages.forEach(page => page.data.forEach(record => prevById.set(record.id, record)))
17
+
18
+ let changed = prev.pages.length !== next.pages.length
19
+ const pages = next.pages.map((page, index) => {
20
+ const prevPage = prev.pages[index]
21
+ const data = page.data.map(record => {
22
+ const previous = prevById.get(record.id)
23
+ return previous ? replaceEqualDeep(previous, record) : record
24
+ })
25
+ const links = replaceEqualDeep(prevPage?.links, page.links)
26
+ const meta = replaceEqualDeep(prevPage?.meta, page.meta)
27
+ const sameRecords =
28
+ !!prevPage &&
29
+ data.length === prevPage.data.length &&
30
+ data.every((record, i) => record === prevPage.data[i])
31
+
32
+ if (prevPage && sameRecords && links === prevPage.links && meta === prevPage.meta) {
33
+ return prevPage
34
+ }
35
+ changed = true
36
+ return { ...page, data, links, meta }
37
+ })
38
+ const pageParams = replaceEqualDeep(prev.pageParams, next.pageParams)
39
+
40
+ if (!changed && pageParams === prev.pageParams) return prev
41
+ return { ...next, pages, pageParams }
42
+ }
@@ -19,4 +19,4 @@ export const getMessageFields = {
19
19
  ReactionCount: ['value', 'count', 'mine', 'message_id', 'author_ids'],
20
20
  }
21
21
 
22
- export const getMessagesInclude = ['author', 'reaction_counts']
22
+ export const getMessagesInclude = ['author', 'reaction_counts', 'reply_root', 'reply_root.author']