@planningcenter/chat-react-native 3.38.0-rc.1 → 3.38.0-rc.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/components/conversation/jump_to_bottom_button.d.ts +1 -2
- package/build/components/conversation/jump_to_bottom_button.d.ts.map +1 -1
- package/build/components/conversation/jump_to_bottom_button.js +7 -39
- package/build/components/conversation/jump_to_bottom_button.js.map +1 -1
- package/build/components/conversation/message_list.d.ts +10 -0
- package/build/components/conversation/message_list.d.ts.map +1 -0
- package/build/components/conversation/message_list.js +13 -0
- package/build/components/conversation/message_list.js.map +1 -0
- package/build/components/conversation/reply_shadow_message.d.ts +2 -1
- package/build/components/conversation/reply_shadow_message.d.ts.map +1 -1
- package/build/components/conversation/reply_shadow_message.js.map +1 -1
- package/build/components/display/conversation_avatar.d.ts +2 -1
- package/build/components/display/conversation_avatar.d.ts.map +1 -1
- package/build/components/display/conversation_avatar.js +6 -5
- package/build/components/display/conversation_avatar.js.map +1 -1
- package/build/components/display/emoji_avatar.d.ts +3 -1
- package/build/components/display/emoji_avatar.d.ts.map +1 -1
- package/build/components/display/emoji_avatar.js +2 -2
- package/build/components/display/emoji_avatar.js.map +1 -1
- package/build/components/display/icon_avatar.d.ts +3 -1
- package/build/components/display/icon_avatar.d.ts.map +1 -1
- package/build/components/display/icon_avatar.js +2 -2
- package/build/components/display/icon_avatar.js.map +1 -1
- package/build/contexts/conversation_context.d.ts +1 -8
- package/build/contexts/conversation_context.d.ts.map +1 -1
- package/build/contexts/conversation_context.js +3 -21
- package/build/contexts/conversation_context.js.map +1 -1
- package/build/hooks/groups/use_group_chat_conversation_payload.d.ts.map +1 -1
- package/build/hooks/groups/use_group_chat_conversation_payload.js +1 -0
- package/build/hooks/groups/use_group_chat_conversation_payload.js.map +1 -1
- package/build/hooks/index.d.ts +1 -0
- package/build/hooks/index.d.ts.map +1 -1
- package/build/hooks/index.js +1 -0
- package/build/hooks/index.js.map +1 -1
- package/build/hooks/use_conversation_messages.d.ts +6 -15
- package/build/hooks/use_conversation_messages.d.ts.map +1 -1
- package/build/hooks/use_conversation_messages.js +9 -62
- package/build/hooks/use_conversation_messages.js.map +1 -1
- package/build/hooks/use_conversation_messages_jolt_events.d.ts.map +1 -1
- package/build/hooks/use_conversation_messages_jolt_events.js +4 -4
- package/build/hooks/use_conversation_messages_jolt_events.js.map +1 -1
- package/build/hooks/use_conversations_actions.d.ts +0 -5
- package/build/hooks/use_conversations_actions.d.ts.map +1 -1
- package/build/hooks/use_conversations_actions.js +0 -12
- package/build/hooks/use_conversations_actions.js.map +1 -1
- package/build/hooks/use_features.d.ts +0 -1
- package/build/hooks/use_features.d.ts.map +1 -1
- package/build/hooks/use_features.js +0 -1
- package/build/hooks/use_features.js.map +1 -1
- package/build/hooks/use_mark_latest_message_read.d.ts +1 -1
- package/build/hooks/use_mark_latest_message_read.d.ts.map +1 -1
- package/build/hooks/use_mark_latest_message_read.js +1 -17
- package/build/hooks/use_mark_latest_message_read.js.map +1 -1
- package/build/hooks/use_preview_avatar_diameter.d.ts +2 -0
- package/build/hooks/use_preview_avatar_diameter.d.ts.map +1 -0
- package/build/hooks/use_preview_avatar_diameter.js +11 -0
- package/build/hooks/use_preview_avatar_diameter.js.map +1 -0
- package/build/hooks/use_suspense_api.d.ts +0 -1
- package/build/hooks/use_suspense_api.d.ts.map +1 -1
- package/build/hooks/use_suspense_api.js +1 -1
- package/build/hooks/use_suspense_api.js.map +1 -1
- package/build/jest.js +1 -1
- package/build/jest.js.map +1 -1
- package/build/screens/avatar_picker/avatar_picker_screen.d.ts.map +1 -1
- package/build/screens/avatar_picker/avatar_picker_screen.js +11 -9
- package/build/screens/avatar_picker/avatar_picker_screen.js.map +1 -1
- package/build/screens/avatar_picker/avatar_preview.d.ts.map +1 -1
- package/build/screens/avatar_picker/avatar_preview.js +13 -5
- package/build/screens/avatar_picker/avatar_preview.js.map +1 -1
- package/build/screens/avatar_picker/emoji_tab.d.ts.map +1 -1
- package/build/screens/avatar_picker/emoji_tab.js +3 -7
- package/build/screens/avatar_picker/emoji_tab.js.map +1 -1
- package/build/screens/avatar_picker/upload_tab.d.ts.map +1 -1
- package/build/screens/avatar_picker/upload_tab.js +2 -1
- package/build/screens/avatar_picker/upload_tab.js.map +1 -1
- package/build/screens/conversation_details_screen.d.ts.map +1 -1
- package/build/screens/conversation_details_screen.js +5 -2
- package/build/screens/conversation_details_screen.js.map +1 -1
- package/build/screens/conversation_filter_recipients/components/header_row.d.ts.map +1 -1
- package/build/screens/conversation_filter_recipients/components/header_row.js +3 -2
- package/build/screens/conversation_filter_recipients/components/header_row.js.map +1 -1
- package/build/screens/conversation_filter_recipients/hooks/use_flattened_array_of_service_types_with_teams.d.ts.map +1 -1
- package/build/screens/conversation_filter_recipients/hooks/use_flattened_array_of_service_types_with_teams.js +47 -18
- package/build/screens/conversation_filter_recipients/hooks/use_flattened_array_of_service_types_with_teams.js.map +1 -1
- package/build/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.d.ts +2 -1
- package/build/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.d.ts.map +1 -1
- package/build/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.js +23 -26
- package/build/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.js.map +1 -1
- package/build/screens/conversation_filter_recipients/types.d.ts +1 -1
- package/build/screens/conversation_filter_recipients/types.d.ts.map +1 -1
- package/build/screens/conversation_filter_recipients/types.js.map +1 -1
- package/build/screens/conversation_screen.d.ts +0 -1
- package/build/screens/conversation_screen.d.ts.map +1 -1
- package/build/screens/conversation_screen.js +45 -96
- package/build/screens/conversation_screen.js.map +1 -1
- package/build/screens/conversation_select_recipients/components/recipient_link_row.d.ts +1 -1
- package/build/screens/conversation_select_recipients/components/recipient_link_row.d.ts.map +1 -1
- package/build/screens/conversation_select_recipients/components/recipient_link_row.js +3 -3
- package/build/screens/conversation_select_recipients/components/recipient_link_row.js.map +1 -1
- package/build/screens/conversation_select_recipients/components/team_recipient_row.d.ts.map +1 -1
- package/build/screens/conversation_select_recipients/components/team_recipient_row.js +1 -1
- package/build/screens/conversation_select_recipients/components/team_recipient_row.js.map +1 -1
- package/build/screens/team_conversation_screen.d.ts.map +1 -1
- package/build/screens/team_conversation_screen.js +24 -1
- package/build/screens/team_conversation_screen.js.map +1 -1
- package/build/utils/cache/messages_cache.d.ts +0 -1
- package/build/utils/cache/messages_cache.d.ts.map +1 -1
- package/build/utils/cache/messages_cache.js +0 -4
- package/build/utils/cache/messages_cache.js.map +1 -1
- package/build/utils/client/client.d.ts +1 -1
- package/build/utils/client/client.d.ts.map +1 -1
- package/build/utils/client/client.js +7 -6
- package/build/utils/client/client.js.map +1 -1
- package/build/utils/client/instrumented_fetch.js +3 -5
- package/build/utils/client/instrumented_fetch.js.map +1 -1
- package/build/utils/group_messages.d.ts +2 -9
- package/build/utils/group_messages.d.ts.map +1 -1
- package/build/utils/group_messages.js +1 -20
- package/build/utils/group_messages.js.map +1 -1
- package/package.json +4 -4
- package/src/__tests__/hooks/use_group_chat_conversation_payload.test.tsx +50 -0
- package/src/__tests__/jest.ts +1 -1
- package/src/__tests__/utils/client.ts +32 -0
- package/src/components/conversation/__tests__/message_list.test.tsx +14 -0
- package/src/components/conversation/jump_to_bottom_button.tsx +8 -57
- package/src/components/conversation/message_list.tsx +42 -0
- package/src/components/conversation/reply_shadow_message.tsx +1 -1
- package/src/components/display/conversation_avatar.tsx +7 -5
- package/src/components/display/emoji_avatar.tsx +10 -2
- package/src/components/display/icon_avatar.tsx +10 -2
- package/src/contexts/conversation_context.tsx +2 -30
- package/src/hooks/groups/use_group_chat_conversation_payload.ts +1 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use_conversation_messages.ts +20 -120
- package/src/hooks/use_conversation_messages_jolt_events.ts +3 -4
- package/src/hooks/use_conversations_actions.ts +0 -15
- package/src/hooks/use_features.ts +0 -1
- package/src/hooks/use_mark_latest_message_read.ts +2 -16
- package/src/hooks/use_preview_avatar_diameter.ts +12 -0
- package/src/hooks/use_suspense_api.ts +1 -1
- package/src/jest.ts +1 -1
- package/src/screens/avatar_picker/avatar_picker_screen.tsx +25 -9
- package/src/screens/avatar_picker/avatar_preview.tsx +14 -5
- package/src/screens/avatar_picker/emoji_tab.tsx +3 -6
- package/src/screens/avatar_picker/upload_tab.tsx +2 -0
- package/src/screens/conversation_details_screen.tsx +10 -1
- package/src/screens/conversation_filter_recipients/components/header_row.tsx +3 -2
- package/src/screens/conversation_filter_recipients/hooks/__tests__/use_service_types_with_teams.test.ts +108 -0
- package/src/screens/conversation_filter_recipients/hooks/use_flattened_array_of_service_types_with_teams.tsx +46 -19
- package/src/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.ts +31 -29
- package/src/screens/conversation_filter_recipients/types.tsx +1 -1
- package/src/screens/conversation_screen.tsx +69 -186
- package/src/screens/conversation_select_recipients/components/recipient_link_row.tsx +6 -4
- package/src/screens/conversation_select_recipients/components/team_recipient_row.tsx +2 -1
- package/src/screens/team_conversation_screen.tsx +33 -1
- package/src/utils/__tests__/group_messages.test.ts +0 -71
- package/src/utils/cache/messages_cache.ts +0 -5
- package/src/utils/client/__tests__/instrumented_fetch.test.ts +9 -5
- package/src/utils/client/client.ts +9 -7
- package/src/utils/client/instrumented_fetch.ts +3 -6
- package/src/utils/group_messages.ts +2 -42
- package/build/components/conversation/unread_divider.d.ts +0 -6
- package/build/components/conversation/unread_divider.d.ts.map +0 -1
- package/build/components/conversation/unread_divider.js +0 -59
- package/build/components/conversation/unread_divider.js.map +0 -1
- package/build/hooks/use_flat_list_viewability.d.ts +0 -20
- package/build/hooks/use_flat_list_viewability.d.ts.map +0 -1
- package/build/hooks/use_flat_list_viewability.js +0 -30
- package/build/hooks/use_flat_list_viewability.js.map +0 -1
- package/build/hooks/use_jump_to_bottom_action.d.ts +0 -9
- package/build/hooks/use_jump_to_bottom_action.d.ts.map +0 -1
- package/build/hooks/use_jump_to_bottom_action.js +0 -62
- package/build/hooks/use_jump_to_bottom_action.js.map +0 -1
- package/build/hooks/use_jump_to_unread_anchor.d.ts +0 -20
- package/build/hooks/use_jump_to_unread_anchor.d.ts.map +0 -1
- package/build/hooks/use_jump_to_unread_anchor.js +0 -53
- package/build/hooks/use_jump_to_unread_anchor.js.map +0 -1
- package/build/hooks/use_jump_to_unread_gates.d.ts +0 -5
- package/build/hooks/use_jump_to_unread_gates.d.ts.map +0 -1
- package/build/hooks/use_jump_to_unread_gates.js +0 -10
- package/build/hooks/use_jump_to_unread_gates.js.map +0 -1
- package/build/hooks/use_scroll_tracking.d.ts +0 -13
- package/build/hooks/use_scroll_tracking.d.ts.map +0 -1
- package/build/hooks/use_scroll_tracking.js +0 -45
- package/build/hooks/use_scroll_tracking.js.map +0 -1
- package/build/hooks/use_track_highest_seen_message.d.ts +0 -4
- package/build/hooks/use_track_highest_seen_message.d.ts.map +0 -1
- package/build/hooks/use_track_highest_seen_message.js +0 -35
- package/build/hooks/use_track_highest_seen_message.js.map +0 -1
- package/build/utils/conversation_messages.d.ts +0 -10
- package/build/utils/conversation_messages.d.ts.map +0 -1
- package/build/utils/conversation_messages.js +0 -22
- package/build/utils/conversation_messages.js.map +0 -1
- package/build/utils/highest_seen_tracker.d.ts +0 -12
- package/build/utils/highest_seen_tracker.d.ts.map +0 -1
- package/build/utils/highest_seen_tracker.js +0 -37
- package/build/utils/highest_seen_tracker.js.map +0 -1
- package/build/utils/message_viewability.d.ts +0 -24
- package/build/utils/message_viewability.d.ts.map +0 -1
- package/build/utils/message_viewability.js +0 -29
- package/build/utils/message_viewability.js.map +0 -1
- package/build/utils/unread_divider_helpers.d.ts +0 -18
- package/build/utils/unread_divider_helpers.d.ts.map +0 -1
- package/build/utils/unread_divider_helpers.js +0 -13
- package/build/utils/unread_divider_helpers.js.map +0 -1
- package/src/__tests__/hooks/use_conversation_messages.test.tsx +0 -109
- package/src/__tests__/hooks/use_mark_latest_message_read.test.tsx +0 -154
- package/src/__tests__/utils/cache/messages_cache.test.ts +0 -54
- package/src/components/conversation/unread_divider.tsx +0 -90
- package/src/hooks/use_flat_list_viewability.ts +0 -50
- package/src/hooks/use_jump_to_bottom_action.ts +0 -75
- package/src/hooks/use_jump_to_unread_anchor.ts +0 -68
- package/src/hooks/use_jump_to_unread_gates.ts +0 -10
- package/src/hooks/use_scroll_tracking.ts +0 -64
- package/src/hooks/use_track_highest_seen_message.ts +0 -43
- package/src/utils/__tests__/conversation_messages.test.ts +0 -105
- package/src/utils/__tests__/highest_seen_tracker.test.ts +0 -82
- package/src/utils/__tests__/message_viewability.test.ts +0 -168
- package/src/utils/__tests__/unread_divider_helpers.test.ts +0 -85
- package/src/utils/conversation_messages.ts +0 -37
- package/src/utils/highest_seen_tracker.ts +0 -42
- package/src/utils/message_viewability.ts +0 -49
- 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
|
-
}
|