@planningcenter/chat-react-native 3.38.0-rc.9 → 3.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/build/components/conversation/jump_to_bottom_button.d.ts +1 -2
  2. package/build/components/conversation/jump_to_bottom_button.d.ts.map +1 -1
  3. package/build/components/conversation/jump_to_bottom_button.js +7 -39
  4. package/build/components/conversation/jump_to_bottom_button.js.map +1 -1
  5. package/build/components/conversation/reply_shadow_message.d.ts +2 -1
  6. package/build/components/conversation/reply_shadow_message.d.ts.map +1 -1
  7. package/build/components/conversation/reply_shadow_message.js.map +1 -1
  8. package/build/contexts/conversation_context.d.ts +1 -8
  9. package/build/contexts/conversation_context.d.ts.map +1 -1
  10. package/build/contexts/conversation_context.js +3 -21
  11. package/build/contexts/conversation_context.js.map +1 -1
  12. package/build/hooks/use_conversation_messages.d.ts +6 -15
  13. package/build/hooks/use_conversation_messages.d.ts.map +1 -1
  14. package/build/hooks/use_conversation_messages.js +9 -62
  15. package/build/hooks/use_conversation_messages.js.map +1 -1
  16. package/build/hooks/use_conversation_messages_jolt_events.d.ts.map +1 -1
  17. package/build/hooks/use_conversation_messages_jolt_events.js +4 -4
  18. package/build/hooks/use_conversation_messages_jolt_events.js.map +1 -1
  19. package/build/hooks/use_conversations_actions.d.ts +0 -5
  20. package/build/hooks/use_conversations_actions.d.ts.map +1 -1
  21. package/build/hooks/use_conversations_actions.js +0 -12
  22. package/build/hooks/use_conversations_actions.js.map +1 -1
  23. package/build/hooks/use_features.d.ts +0 -1
  24. package/build/hooks/use_features.d.ts.map +1 -1
  25. package/build/hooks/use_features.js +0 -1
  26. package/build/hooks/use_features.js.map +1 -1
  27. package/build/hooks/use_mark_latest_message_read.d.ts +1 -1
  28. package/build/hooks/use_mark_latest_message_read.d.ts.map +1 -1
  29. package/build/hooks/use_mark_latest_message_read.js +1 -17
  30. package/build/hooks/use_mark_latest_message_read.js.map +1 -1
  31. package/build/hooks/use_suspense_api.d.ts +0 -1
  32. package/build/hooks/use_suspense_api.d.ts.map +1 -1
  33. package/build/hooks/use_suspense_api.js +1 -1
  34. package/build/hooks/use_suspense_api.js.map +1 -1
  35. package/build/screens/conversation_filter_recipients/components/header_row.d.ts.map +1 -1
  36. package/build/screens/conversation_filter_recipients/components/header_row.js +3 -2
  37. package/build/screens/conversation_filter_recipients/components/header_row.js.map +1 -1
  38. package/build/screens/conversation_filter_recipients/hooks/use_flattened_array_of_service_types_with_teams.d.ts.map +1 -1
  39. package/build/screens/conversation_filter_recipients/hooks/use_flattened_array_of_service_types_with_teams.js +47 -18
  40. package/build/screens/conversation_filter_recipients/hooks/use_flattened_array_of_service_types_with_teams.js.map +1 -1
  41. package/build/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.d.ts +2 -1
  42. package/build/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.d.ts.map +1 -1
  43. package/build/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.js +23 -26
  44. package/build/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.js.map +1 -1
  45. package/build/screens/conversation_filter_recipients/types.d.ts +1 -1
  46. package/build/screens/conversation_filter_recipients/types.d.ts.map +1 -1
  47. package/build/screens/conversation_filter_recipients/types.js.map +1 -1
  48. package/build/screens/conversation_screen.d.ts +0 -1
  49. package/build/screens/conversation_screen.d.ts.map +1 -1
  50. package/build/screens/conversation_screen.js +48 -95
  51. package/build/screens/conversation_screen.js.map +1 -1
  52. package/build/screens/conversation_select_recipients/components/recipient_link_row.d.ts +1 -1
  53. package/build/screens/conversation_select_recipients/components/recipient_link_row.d.ts.map +1 -1
  54. package/build/screens/conversation_select_recipients/components/recipient_link_row.js +3 -3
  55. package/build/screens/conversation_select_recipients/components/recipient_link_row.js.map +1 -1
  56. package/build/screens/conversation_select_recipients/components/team_recipient_row.d.ts.map +1 -1
  57. package/build/screens/conversation_select_recipients/components/team_recipient_row.js +1 -1
  58. package/build/screens/conversation_select_recipients/components/team_recipient_row.js.map +1 -1
  59. package/build/utils/cache/messages_cache.d.ts +0 -1
  60. package/build/utils/cache/messages_cache.d.ts.map +1 -1
  61. package/build/utils/cache/messages_cache.js +0 -4
  62. package/build/utils/cache/messages_cache.js.map +1 -1
  63. package/build/utils/group_messages.d.ts +2 -9
  64. package/build/utils/group_messages.d.ts.map +1 -1
  65. package/build/utils/group_messages.js +1 -20
  66. package/build/utils/group_messages.js.map +1 -1
  67. package/package.json +3 -3
  68. package/src/components/conversation/jump_to_bottom_button.tsx +8 -57
  69. package/src/components/conversation/reply_shadow_message.tsx +1 -1
  70. package/src/contexts/conversation_context.tsx +2 -30
  71. package/src/hooks/use_conversation_messages.ts +20 -120
  72. package/src/hooks/use_conversation_messages_jolt_events.ts +3 -4
  73. package/src/hooks/use_conversations_actions.ts +0 -15
  74. package/src/hooks/use_features.ts +0 -1
  75. package/src/hooks/use_mark_latest_message_read.ts +2 -16
  76. package/src/hooks/use_suspense_api.ts +1 -1
  77. package/src/screens/conversation_filter_recipients/components/header_row.tsx +3 -2
  78. package/src/screens/conversation_filter_recipients/hooks/__tests__/use_service_types_with_teams.test.ts +108 -0
  79. package/src/screens/conversation_filter_recipients/hooks/use_flattened_array_of_service_types_with_teams.tsx +46 -19
  80. package/src/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.ts +31 -29
  81. package/src/screens/conversation_filter_recipients/types.tsx +1 -1
  82. package/src/screens/conversation_screen.tsx +76 -184
  83. package/src/screens/conversation_select_recipients/components/recipient_link_row.tsx +6 -4
  84. package/src/screens/conversation_select_recipients/components/team_recipient_row.tsx +2 -1
  85. package/src/utils/__tests__/group_messages.test.ts +0 -71
  86. package/src/utils/cache/messages_cache.ts +0 -5
  87. package/src/utils/group_messages.ts +2 -42
  88. package/build/components/conversation/unread_divider.d.ts +0 -6
  89. package/build/components/conversation/unread_divider.d.ts.map +0 -1
  90. package/build/components/conversation/unread_divider.js +0 -59
  91. package/build/components/conversation/unread_divider.js.map +0 -1
  92. package/build/hooks/use_flat_list_viewability.d.ts +0 -20
  93. package/build/hooks/use_flat_list_viewability.d.ts.map +0 -1
  94. package/build/hooks/use_flat_list_viewability.js +0 -30
  95. package/build/hooks/use_flat_list_viewability.js.map +0 -1
  96. package/build/hooks/use_jump_to_bottom_action.d.ts +0 -9
  97. package/build/hooks/use_jump_to_bottom_action.d.ts.map +0 -1
  98. package/build/hooks/use_jump_to_bottom_action.js +0 -62
  99. package/build/hooks/use_jump_to_bottom_action.js.map +0 -1
  100. package/build/hooks/use_jump_to_unread_anchor.d.ts +0 -20
  101. package/build/hooks/use_jump_to_unread_anchor.d.ts.map +0 -1
  102. package/build/hooks/use_jump_to_unread_anchor.js +0 -53
  103. package/build/hooks/use_jump_to_unread_anchor.js.map +0 -1
  104. package/build/hooks/use_jump_to_unread_gates.d.ts +0 -5
  105. package/build/hooks/use_jump_to_unread_gates.d.ts.map +0 -1
  106. package/build/hooks/use_jump_to_unread_gates.js +0 -10
  107. package/build/hooks/use_jump_to_unread_gates.js.map +0 -1
  108. package/build/hooks/use_scroll_tracking.d.ts +0 -13
  109. package/build/hooks/use_scroll_tracking.d.ts.map +0 -1
  110. package/build/hooks/use_scroll_tracking.js +0 -45
  111. package/build/hooks/use_scroll_tracking.js.map +0 -1
  112. package/build/hooks/use_track_highest_seen_message.d.ts +0 -4
  113. package/build/hooks/use_track_highest_seen_message.d.ts.map +0 -1
  114. package/build/hooks/use_track_highest_seen_message.js +0 -35
  115. package/build/hooks/use_track_highest_seen_message.js.map +0 -1
  116. package/build/utils/conversation_messages.d.ts +0 -10
  117. package/build/utils/conversation_messages.d.ts.map +0 -1
  118. package/build/utils/conversation_messages.js +0 -22
  119. package/build/utils/conversation_messages.js.map +0 -1
  120. package/build/utils/highest_seen_tracker.d.ts +0 -12
  121. package/build/utils/highest_seen_tracker.d.ts.map +0 -1
  122. package/build/utils/highest_seen_tracker.js +0 -37
  123. package/build/utils/highest_seen_tracker.js.map +0 -1
  124. package/build/utils/message_viewability.d.ts +0 -24
  125. package/build/utils/message_viewability.d.ts.map +0 -1
  126. package/build/utils/message_viewability.js +0 -29
  127. package/build/utils/message_viewability.js.map +0 -1
  128. package/build/utils/unread_divider_helpers.d.ts +0 -18
  129. package/build/utils/unread_divider_helpers.d.ts.map +0 -1
  130. package/build/utils/unread_divider_helpers.js +0 -13
  131. package/build/utils/unread_divider_helpers.js.map +0 -1
  132. package/src/__tests__/hooks/use_conversation_messages.test.tsx +0 -109
  133. package/src/__tests__/hooks/use_mark_latest_message_read.test.tsx +0 -154
  134. package/src/__tests__/utils/cache/messages_cache.test.ts +0 -54
  135. package/src/components/conversation/unread_divider.tsx +0 -90
  136. package/src/hooks/use_flat_list_viewability.ts +0 -50
  137. package/src/hooks/use_jump_to_bottom_action.ts +0 -75
  138. package/src/hooks/use_jump_to_unread_anchor.ts +0 -68
  139. package/src/hooks/use_jump_to_unread_gates.ts +0 -10
  140. package/src/hooks/use_scroll_tracking.ts +0 -64
  141. package/src/hooks/use_track_highest_seen_message.ts +0 -43
  142. package/src/utils/__tests__/conversation_messages.test.ts +0 -105
  143. package/src/utils/__tests__/highest_seen_tracker.test.ts +0 -82
  144. package/src/utils/__tests__/message_viewability.test.ts +0 -168
  145. package/src/utils/__tests__/unread_divider_helpers.test.ts +0 -85
  146. package/src/utils/conversation_messages.ts +0 -37
  147. package/src/utils/highest_seen_tracker.ts +0 -42
  148. package/src/utils/message_viewability.ts +0 -49
  149. package/src/utils/unread_divider_helpers.ts +0 -25
@@ -1,168 +0,0 @@
1
- import {
2
- detectDividerExitTowardNewer,
3
- reportViewableMessages,
4
- type ViewabilityEvent,
5
- } from '../message_viewability'
6
-
7
- type Msg = { id: string; type: 'Message' }
8
-
9
- const event = (overrides: Partial<ViewabilityEvent<Msg>> = {}): ViewabilityEvent<Msg> => ({
10
- viewableItems: [],
11
- changed: [],
12
- userHasScrolled: true,
13
- ...overrides,
14
- })
15
-
16
- describe('reportViewableMessages', () => {
17
- it('fires onMessageSeen for every viewable Message item by id', () => {
18
- const onSeen = jest.fn()
19
- const observer = reportViewableMessages<Msg>(onSeen)
20
-
21
- observer(
22
- event({
23
- viewableItems: [
24
- { key: '10', isViewable: true, item: { id: '10', type: 'Message' } },
25
- { key: '11', isViewable: true, item: { id: '11', type: 'Message' } },
26
- ],
27
- })
28
- )
29
-
30
- expect(onSeen).toHaveBeenCalledTimes(2)
31
- expect(onSeen).toHaveBeenNthCalledWith(1, '10')
32
- expect(onSeen).toHaveBeenNthCalledWith(2, '11')
33
- })
34
-
35
- it('skips non-Message items (dividers, separators, shadows)', () => {
36
- const onSeen = jest.fn()
37
- const observer = reportViewableMessages<{ id?: string; type?: string }>(onSeen)
38
-
39
- observer(
40
- event({
41
- viewableItems: [
42
- { key: 'divider', isViewable: true, item: { id: 'divider', type: 'UnreadDivider' } },
43
- {
44
- key: 'day-divider-05',
45
- isViewable: true,
46
- item: { id: 'day-divider-05', type: 'DateSeparator' },
47
- },
48
- { key: '5', isViewable: true, item: { id: '5', type: 'Message' } },
49
- ],
50
- })
51
- )
52
-
53
- expect(onSeen).toHaveBeenCalledTimes(1)
54
- expect(onSeen).toHaveBeenCalledWith('5')
55
- })
56
-
57
- it('does not fire before the user has scrolled', () => {
58
- const onSeen = jest.fn()
59
- const observer = reportViewableMessages<Msg>(onSeen)
60
-
61
- observer(
62
- event({
63
- userHasScrolled: false,
64
- viewableItems: [{ key: '10', isViewable: true, item: { id: '10', type: 'Message' } }],
65
- })
66
- )
67
-
68
- expect(onSeen).not.toHaveBeenCalled()
69
- })
70
- })
71
-
72
- describe('detectDividerExitTowardNewer', () => {
73
- const baseArgs = { dividerKey: 'unread-divider', initialMessageId: '050' }
74
-
75
- it('fires onExited when the divider leaves and only newer messages remain visible', () => {
76
- const onExited = jest.fn()
77
- const observer = detectDividerExitTowardNewer<{ id: string; type?: string }>({
78
- ...baseArgs,
79
- onExited,
80
- })
81
-
82
- observer(
83
- event({
84
- changed: [
85
- {
86
- key: 'unread-divider',
87
- isViewable: false,
88
- item: { id: 'unread-divider', type: 'UnreadDivider' },
89
- },
90
- ],
91
- viewableItems: [
92
- { key: '055', isViewable: true, item: { id: '055', type: 'Message' } },
93
- { key: '056', isViewable: true, item: { id: '056', type: 'Message' } },
94
- ],
95
- })
96
- )
97
-
98
- expect(onExited).toHaveBeenCalledTimes(1)
99
- })
100
-
101
- it('does not fire when divider leaves toward older messages', () => {
102
- const onExited = jest.fn()
103
- const observer = detectDividerExitTowardNewer<{ id: string; type?: string }>({
104
- ...baseArgs,
105
- onExited,
106
- })
107
-
108
- observer(
109
- event({
110
- changed: [
111
- {
112
- key: 'unread-divider',
113
- isViewable: false,
114
- item: { id: 'unread-divider', type: 'UnreadDivider' },
115
- },
116
- ],
117
- viewableItems: [
118
- { key: '045', isViewable: true, item: { id: '045', type: 'Message' } },
119
- { key: '048', isViewable: true, item: { id: '048', type: 'Message' } },
120
- ],
121
- })
122
- )
123
-
124
- expect(onExited).not.toHaveBeenCalled()
125
- })
126
-
127
- it('does not fire before the user has scrolled', () => {
128
- const onExited = jest.fn()
129
- const observer = detectDividerExitTowardNewer<{ id: string; type?: string }>({
130
- ...baseArgs,
131
- onExited,
132
- })
133
-
134
- observer(
135
- event({
136
- userHasScrolled: false,
137
- changed: [
138
- {
139
- key: 'unread-divider',
140
- isViewable: false,
141
- item: { id: 'unread-divider', type: 'UnreadDivider' },
142
- },
143
- ],
144
- viewableItems: [{ key: '055', isViewable: true, item: { id: '055', type: 'Message' } }],
145
- })
146
- )
147
-
148
- expect(onExited).not.toHaveBeenCalled()
149
- })
150
-
151
- it('no-ops when initialMessageId is null (observer is always installed)', () => {
152
- const onExited = jest.fn()
153
- const observer = detectDividerExitTowardNewer<{ id: string; type?: string }>({
154
- dividerKey: 'unread-divider',
155
- initialMessageId: null,
156
- onExited,
157
- })
158
-
159
- observer(
160
- event({
161
- changed: [{ key: 'unread-divider', isViewable: false, item: { id: 'unread-divider' } }],
162
- viewableItems: [{ key: '055', isViewable: true, item: { id: '055' } }],
163
- })
164
- )
165
-
166
- expect(onExited).not.toHaveBeenCalled()
167
- })
168
- })
@@ -1,85 +0,0 @@
1
- import { dividerExitedTowardNewer } from '../unread_divider_helpers'
2
-
3
- const dividerKey = 'unread-divider'
4
- const initialMessageId = '050'
5
- const msg = (id: string) => ({ item: { id, type: 'Message' } })
6
-
7
- describe('dividerExitedTowardNewer', () => {
8
- it('returns false while the divider is still viewable', () => {
9
- const result = dividerExitedTowardNewer({
10
- changed: [{ key: dividerKey, isViewable: true }],
11
- viewableItems: [
12
- msg('049'),
13
- { item: { id: dividerKey, type: 'UnreadDivider' } },
14
- msg('050'),
15
- msg('051'),
16
- ],
17
- dividerKey,
18
- initialMessageId,
19
- })
20
- expect(result).toBe(false)
21
- })
22
-
23
- it('returns true when divider exits and only newer messages are visible (scrolled toward newer)', () => {
24
- const result = dividerExitedTowardNewer({
25
- changed: [{ key: dividerKey, isViewable: false }],
26
- viewableItems: [msg('055'), msg('056'), msg('057')],
27
- dividerKey,
28
- initialMessageId,
29
- })
30
- expect(result).toBe(true)
31
- })
32
-
33
- it('returns false when divider exits and only older messages are visible (scrolled toward older)', () => {
34
- const result = dividerExitedTowardNewer({
35
- changed: [{ key: dividerKey, isViewable: false }],
36
- viewableItems: [msg('040'), msg('045'), msg('048')],
37
- dividerKey,
38
- initialMessageId,
39
- })
40
- expect(result).toBe(false)
41
- })
42
-
43
- it('returns false when divider exits but the visible window straddles the boundary', () => {
44
- const result = dividerExitedTowardNewer({
45
- changed: [{ key: dividerKey, isViewable: false }],
46
- viewableItems: [msg('048'), msg('049'), msg('055')],
47
- dividerKey,
48
- initialMessageId,
49
- })
50
- expect(result).toBe(false)
51
- })
52
-
53
- it('returns false when the divider entry is not in the changed set', () => {
54
- const result = dividerExitedTowardNewer({
55
- changed: [{ key: '055', isViewable: true }],
56
- viewableItems: [msg('055'), msg('056')],
57
- dividerKey,
58
- initialMessageId,
59
- })
60
- expect(result).toBe(false)
61
- })
62
-
63
- it('returns false when no message items are visible (only the divider was)', () => {
64
- const result = dividerExitedTowardNewer({
65
- changed: [{ key: dividerKey, isViewable: false }],
66
- viewableItems: [],
67
- dividerKey,
68
- initialMessageId,
69
- })
70
- expect(result).toBe(false)
71
- })
72
-
73
- it('ignores non-Message items (date separators, reply shadows) when deciding direction', () => {
74
- const result = dividerExitedTowardNewer({
75
- changed: [{ key: dividerKey, isViewable: false }],
76
- viewableItems: [
77
- { item: { id: 'day-divider-200', type: 'DateSeparator' } },
78
- { item: { id: '055-rootA', type: 'ReplyShadowMessage' } },
79
- ],
80
- dividerKey,
81
- initialMessageId,
82
- })
83
- expect(result).toBe(false)
84
- })
85
- })
@@ -1,37 +0,0 @@
1
- import { ApiCollection, MessageResource } from '../types'
2
- import { RequestData } from './client'
3
-
4
- export type MessagesPageParam = Partial<RequestData> & {
5
- order?: 'asc' | 'desc'
6
- }
7
-
8
- export const anchoredSeedPageParams = (anchor: string): MessagesPageParam[] => [
9
- { where: { id_gte: anchor }, order: 'asc' },
10
- { where: { id_lt: anchor }, order: 'desc' },
11
- ]
12
-
13
- export const olderPageParam = (
14
- page: ApiCollection<MessageResource>
15
- ): MessagesPageParam | undefined => {
16
- const idLt = page.meta?.next?.idLt
17
- if (!idLt) return undefined
18
- return { where: { id_lt: idLt }, order: 'desc' }
19
- }
20
-
21
- export const newerPageParam = (
22
- page: ApiCollection<MessageResource>
23
- ): MessagesPageParam | undefined => {
24
- const idGt = page.meta?.next?.idGt
25
- if (!idGt) return undefined
26
- return { where: { id_gt: idGt }, order: 'asc' }
27
- }
28
-
29
- export const sortAndFilterMessages = (pages: ApiCollection<MessageResource>[]): MessageResource[] =>
30
- pages
31
- .flatMap(page => page.data)
32
- .filter(
33
- message =>
34
- (!message.deletedAt || message.replyRootId) &&
35
- (message.attachments?.length || message.text?.length)
36
- )
37
- .sort((a, b) => -a.id.localeCompare(b.id))
@@ -1,42 +0,0 @@
1
- export const FLUSH_DELAY_MS = 2000
2
-
3
- type SendFn = (args: { conversationId: number; sortKey: string }) => void
4
-
5
- export function makeHighestSeenTracker(
6
- conversationId: number,
7
- send: SendFn,
8
- flushDelayMs: number = FLUSH_DELAY_MS
9
- ) {
10
- let highest: string | null = null
11
- let lastSent: string | null = null
12
- let timer: ReturnType<typeof setTimeout> | null = null
13
-
14
- const fire = () => {
15
- timer = null
16
- if (!highest || highest === lastSent) return
17
- lastSent = highest
18
- send({ conversationId, sortKey: highest })
19
- }
20
-
21
- return {
22
- onSeen(sortKey: string) {
23
- if (highest && sortKey.localeCompare(highest) <= 0) return
24
- highest = sortKey
25
- if (timer) clearTimeout(timer)
26
- timer = setTimeout(fire, flushDelayMs)
27
- },
28
- flushNow() {
29
- if (timer) {
30
- clearTimeout(timer)
31
- timer = null
32
- }
33
- fire()
34
- },
35
- cancel() {
36
- if (timer) {
37
- clearTimeout(timer)
38
- timer = null
39
- }
40
- },
41
- }
42
- }
@@ -1,49 +0,0 @@
1
- import { dividerExitedTowardNewer } from './unread_divider_helpers'
2
-
3
- export interface ViewableEntry<Item> {
4
- key: string
5
- isViewable: boolean
6
- item: Item
7
- }
8
-
9
- export interface ViewabilityEvent<Item> {
10
- viewableItems: ViewableEntry<Item>[]
11
- changed: ViewableEntry<Item>[]
12
- userHasScrolled: boolean
13
- }
14
-
15
- export type ViewabilityObserver<Item> = (event: ViewabilityEvent<Item>) => void
16
-
17
- export function reportViewableMessages<Item extends { id?: string; type?: string }>(
18
- onMessageSeen: (id: string) => void
19
- ): ViewabilityObserver<Item> {
20
- return ({ viewableItems, userHasScrolled }) => {
21
- if (!userHasScrolled) return
22
- for (const entry of viewableItems) {
23
- if (entry.item?.type !== 'Message') continue
24
- const id = entry.item?.id
25
- if (typeof id === 'string') onMessageSeen(id)
26
- }
27
- }
28
- }
29
-
30
- export function detectDividerExitTowardNewer<Item extends { id?: string; type?: string }>({
31
- dividerKey,
32
- initialMessageId,
33
- onExited,
34
- }: {
35
- dividerKey: string
36
- initialMessageId: string | null
37
- onExited: () => void
38
- }): ViewabilityObserver<Item> {
39
- return ({ viewableItems, changed, userHasScrolled }) => {
40
- if (!userHasScrolled || !initialMessageId) return
41
- const exited = dividerExitedTowardNewer({
42
- changed,
43
- viewableItems,
44
- dividerKey,
45
- initialMessageId,
46
- })
47
- if (exited) onExited()
48
- }
49
- }
@@ -1,25 +0,0 @@
1
- type ViewableChangeEntry = { key: string; isViewable: boolean }
2
- type ViewableItem = { item: { id?: string; type?: string } }
3
-
4
- export function dividerExitedTowardNewer({
5
- changed,
6
- viewableItems,
7
- dividerKey,
8
- initialMessageId,
9
- }: {
10
- changed: ViewableChangeEntry[]
11
- viewableItems: ViewableItem[]
12
- dividerKey: string
13
- initialMessageId: string
14
- }): boolean {
15
- const dividerExited = changed.some(c => c.key === dividerKey && !c.isViewable)
16
- if (!dividerExited) return false
17
-
18
- const visibleMessageIds = viewableItems
19
- .filter(v => v.item?.type === 'Message')
20
- .map(v => v.item?.id)
21
- .filter((id): id is string => !!id)
22
- if (visibleMessageIds.length === 0) return false
23
-
24
- return visibleMessageIds.every(id => id.localeCompare(initialMessageId) > 0)
25
- }