@planningcenter/chat-react-native 3.35.0-rc.3 → 3.35.0-rc.4

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 (111) hide show
  1. package/README.md +1 -1
  2. package/build/components/conversation/jump_to_bottom_button.d.ts +2 -1
  3. package/build/components/conversation/jump_to_bottom_button.d.ts.map +1 -1
  4. package/build/components/conversation/jump_to_bottom_button.js +39 -7
  5. package/build/components/conversation/jump_to_bottom_button.js.map +1 -1
  6. package/build/components/conversation/reply_shadow_message.d.ts +1 -2
  7. package/build/components/conversation/reply_shadow_message.d.ts.map +1 -1
  8. package/build/components/conversation/reply_shadow_message.js.map +1 -1
  9. package/build/components/conversation/unread_divider.d.ts +6 -0
  10. package/build/components/conversation/unread_divider.d.ts.map +1 -0
  11. package/build/components/conversation/unread_divider.js +59 -0
  12. package/build/components/conversation/unread_divider.js.map +1 -0
  13. package/build/contexts/conversation_context.d.ts +2 -0
  14. package/build/contexts/conversation_context.d.ts.map +1 -1
  15. package/build/contexts/conversation_context.js +13 -5
  16. package/build/contexts/conversation_context.js.map +1 -1
  17. package/build/hooks/use_conversation_messages.d.ts +2 -0
  18. package/build/hooks/use_conversation_messages.d.ts.map +1 -1
  19. package/build/hooks/use_conversation_messages.js +9 -5
  20. package/build/hooks/use_conversation_messages.js.map +1 -1
  21. package/build/hooks/use_conversation_messages_jolt_events.d.ts.map +1 -1
  22. package/build/hooks/use_conversation_messages_jolt_events.js +4 -4
  23. package/build/hooks/use_conversation_messages_jolt_events.js.map +1 -1
  24. package/build/hooks/use_conversations_actions.d.ts +5 -0
  25. package/build/hooks/use_conversations_actions.d.ts.map +1 -1
  26. package/build/hooks/use_conversations_actions.js +12 -0
  27. package/build/hooks/use_conversations_actions.js.map +1 -1
  28. package/build/hooks/use_flat_list_viewability.d.ts +20 -0
  29. package/build/hooks/use_flat_list_viewability.d.ts.map +1 -0
  30. package/build/hooks/use_flat_list_viewability.js +30 -0
  31. package/build/hooks/use_flat_list_viewability.js.map +1 -0
  32. package/build/hooks/use_jump_to_bottom_action.d.ts +9 -0
  33. package/build/hooks/use_jump_to_bottom_action.d.ts.map +1 -0
  34. package/build/hooks/use_jump_to_bottom_action.js +62 -0
  35. package/build/hooks/use_jump_to_bottom_action.js.map +1 -0
  36. package/build/hooks/use_jump_to_unread_anchor.d.ts +20 -0
  37. package/build/hooks/use_jump_to_unread_anchor.d.ts.map +1 -0
  38. package/build/hooks/use_jump_to_unread_anchor.js +53 -0
  39. package/build/hooks/use_jump_to_unread_anchor.js.map +1 -0
  40. package/build/hooks/use_jump_to_unread_gates.d.ts +5 -0
  41. package/build/hooks/use_jump_to_unread_gates.d.ts.map +1 -0
  42. package/build/hooks/use_jump_to_unread_gates.js +10 -0
  43. package/build/hooks/use_jump_to_unread_gates.js.map +1 -0
  44. package/build/hooks/use_mark_latest_message_read.d.ts +1 -1
  45. package/build/hooks/use_mark_latest_message_read.d.ts.map +1 -1
  46. package/build/hooks/use_mark_latest_message_read.js +17 -1
  47. package/build/hooks/use_mark_latest_message_read.js.map +1 -1
  48. package/build/hooks/use_scroll_tracking.d.ts +13 -0
  49. package/build/hooks/use_scroll_tracking.d.ts.map +1 -0
  50. package/build/hooks/use_scroll_tracking.js +45 -0
  51. package/build/hooks/use_scroll_tracking.js.map +1 -0
  52. package/build/hooks/use_track_highest_seen_message.d.ts +4 -0
  53. package/build/hooks/use_track_highest_seen_message.d.ts.map +1 -0
  54. package/build/hooks/use_track_highest_seen_message.js +35 -0
  55. package/build/hooks/use_track_highest_seen_message.js.map +1 -0
  56. package/build/navigation/index.d.ts.map +1 -1
  57. package/build/screens/conversation_screen.d.ts.map +1 -1
  58. package/build/screens/conversation_screen.js +87 -44
  59. package/build/screens/conversation_screen.js.map +1 -1
  60. package/build/utils/cache/messages_cache.d.ts +1 -0
  61. package/build/utils/cache/messages_cache.d.ts.map +1 -1
  62. package/build/utils/cache/messages_cache.js +4 -0
  63. package/build/utils/cache/messages_cache.js.map +1 -1
  64. package/build/utils/group_messages.d.ts +9 -2
  65. package/build/utils/group_messages.d.ts.map +1 -1
  66. package/build/utils/group_messages.js +20 -1
  67. package/build/utils/group_messages.js.map +1 -1
  68. package/build/utils/highest_seen_tracker.d.ts +12 -0
  69. package/build/utils/highest_seen_tracker.d.ts.map +1 -0
  70. package/build/utils/highest_seen_tracker.js +37 -0
  71. package/build/utils/highest_seen_tracker.js.map +1 -0
  72. package/build/utils/message_viewability.d.ts +24 -0
  73. package/build/utils/message_viewability.d.ts.map +1 -0
  74. package/build/utils/message_viewability.js +29 -0
  75. package/build/utils/message_viewability.js.map +1 -0
  76. package/build/utils/unread_divider_helpers.d.ts +18 -0
  77. package/build/utils/unread_divider_helpers.d.ts.map +1 -0
  78. package/build/utils/unread_divider_helpers.js +13 -0
  79. package/build/utils/unread_divider_helpers.js.map +1 -0
  80. package/package.json +10 -4
  81. package/src/__tests__/contexts/session_context.tsx +1 -1
  82. package/src/__tests__/hooks/use_async_storage.test.tsx +1 -1
  83. package/src/__tests__/hooks/use_attachment_uploader.test.tsx +1 -1
  84. package/src/__tests__/hooks/use_chat_configuration.test.tsx +1 -1
  85. package/src/__tests__/hooks/use_conversation_messages.test.tsx +1 -1
  86. package/src/__tests__/hooks/use_mark_latest_message_read.test.tsx +154 -0
  87. package/src/__tests__/utils/cache/messages_cache.test.ts +54 -0
  88. package/src/components/conversation/jump_to_bottom_button.tsx +57 -8
  89. package/src/components/conversation/reply_shadow_message.tsx +4 -2
  90. package/src/components/conversation/unread_divider.tsx +90 -0
  91. package/src/contexts/conversation_context.tsx +15 -13
  92. package/src/hooks/use_conversation_messages.ts +19 -3
  93. package/src/hooks/use_conversation_messages_jolt_events.ts +4 -3
  94. package/src/hooks/use_conversations_actions.ts +15 -0
  95. package/src/hooks/use_flat_list_viewability.ts +50 -0
  96. package/src/hooks/use_jump_to_bottom_action.ts +75 -0
  97. package/src/hooks/use_jump_to_unread_anchor.ts +68 -0
  98. package/src/hooks/use_jump_to_unread_gates.ts +10 -0
  99. package/src/hooks/use_mark_latest_message_read.ts +16 -2
  100. package/src/hooks/use_scroll_tracking.ts +64 -0
  101. package/src/hooks/use_track_highest_seen_message.ts +43 -0
  102. package/src/screens/conversation_screen.tsx +173 -70
  103. package/src/utils/__tests__/group_messages.test.ts +71 -0
  104. package/src/utils/__tests__/highest_seen_tracker.test.ts +82 -0
  105. package/src/utils/__tests__/message_viewability.test.ts +168 -0
  106. package/src/utils/__tests__/unread_divider_helpers.test.ts +85 -0
  107. package/src/utils/cache/messages_cache.ts +5 -0
  108. package/src/utils/group_messages.ts +42 -2
  109. package/src/utils/highest_seen_tracker.ts +42 -0
  110. package/src/utils/message_viewability.ts +49 -0
  111. package/src/utils/unread_divider_helpers.ts +25 -0
@@ -149,6 +149,11 @@ export declare const useConversationsMute: ({ conversation }: {
149
149
  muted: boolean;
150
150
  setMuted: import("@tanstack/react-query").UseMutateFunction<ApiResource<ConversationResource>, Error, boolean, void>;
151
151
  };
152
+ export declare const useConversationsMarkReadUpTo: ({ conversationId }: {
153
+ conversationId: number;
154
+ }) => import("@tanstack/react-query").UseMutationResult<import("..").ApiCollection | ApiResource, Error, {
155
+ sortKey: string;
156
+ }, unknown>;
152
157
  export declare const useMarkAllRead: () => {
153
158
  data: undefined;
154
159
  variables: undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"use_conversations_actions.d.ts","sourceRoot":"","sources":["../../src/hooks/use_conversations_actions.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAK5D,eAAO,MAAM,wBAAwB,GAAI,mBAEtC;IACD,YAAY,EAAE,oBAAoB,CAAA;CACnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6CA,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAI,kBAAkB;IAAE,YAAY,EAAE,oBAAoB,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuC5F,CAAA;AAED,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsB1B,CAAA"}
1
+ {"version":3,"file":"use_conversations_actions.d.ts","sourceRoot":"","sources":["../../src/hooks/use_conversations_actions.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAK5D,eAAO,MAAM,wBAAwB,GAAI,mBAEtC;IACD,YAAY,EAAE,oBAAoB,CAAA;CACnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6CA,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAI,kBAAkB;IAAE,YAAY,EAAE,oBAAoB,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuC5F,CAAA;AAED,eAAO,MAAM,4BAA4B,GAAI,oBAAoB;IAAE,cAAc,EAAE,MAAM,CAAA;CAAE;aAK5C,MAAM;WAQpD,CAAA;AAED,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsB1B,CAAA"}
@@ -83,6 +83,18 @@ export const useConversationsMute = ({ conversation }) => {
83
83
  ...mutation,
84
84
  };
85
85
  };
86
+ export const useConversationsMarkReadUpTo = ({ conversationId }) => {
87
+ const apiClient = useApiClient();
88
+ return useMutation({
89
+ mutationKey: ['markReadUpTo', conversationId],
90
+ mutationFn: async ({ sortKey }) => apiClient.chat.post({
91
+ url: `/me/conversations/${conversationId}/mark_read_up_to`,
92
+ data: {
93
+ data: { type: 'Conversation', attributes: { sort_key: sortKey } },
94
+ },
95
+ }),
96
+ });
97
+ };
86
98
  export const useMarkAllRead = () => {
87
99
  const apiClient = useApiClient();
88
100
  const { args } = useConversationsContext();
@@ -1 +1 @@
1
- {"version":3,"file":"use_conversations_actions.js","sourceRoot":"","sources":["../../src/hooks/use_conversations_actions.ts"],"names":[],"mappings":"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","sourcesContent":["import { useMutation } from '@tanstack/react-query'\nimport { Alert } from 'react-native'\nimport { useConversationsContext } from '../contexts/conversations_context'\nimport { ApiResource, ConversationResource } from '../types'\nimport { useApiClient } from './use_api_client'\nimport { useConversationsCache } from './use_conversations_cache'\nimport { useCurrentPersonCache } from './use_current_person'\n\nexport const useConversationsMarkRead = ({\n conversation,\n}: {\n conversation: ConversationResource\n}) => {\n const apiClient = useApiClient()\n const { args } = useConversationsContext()\n const currentPersonCache = useCurrentPersonCache()\n const { update, invalidate, fetchUpdate } = useConversationsCache(args)\n\n function handlePersonUnreadCount(read: boolean) {\n currentPersonCache.update({}, person => {\n const currentUnread = person.unreadCount\n const updatedUnread = read ? Math.max(currentUnread - 1, 0) : currentUnread + 1\n return { ...person, unreadCount: updatedUnread, unreadReactionCount: 0 }\n })\n }\n\n const { mutate: handleMarkRead, ...mutation } = useMutation({\n onMutate: async (read: boolean) => {\n update({\n ...conversation,\n unreadCount: read ? 0 : 1,\n })\n handlePersonUnreadCount(read)\n },\n mutationKey: ['markRead', conversation.id],\n mutationFn: async (read: boolean) => {\n const action = read ? 'mark_read' : 'mark_unread'\n\n return apiClient.chat.post({\n url: `/me/conversations/${conversation.id}/${action}`,\n data: { data: { type: '', attributes: {} }, fields: { Conversation: 'unread_count,id' } },\n })\n },\n onSuccess: () => {\n fetchUpdate(conversation)\n },\n onError: () => {\n Alert.alert('Oops', 'Something went wrong updating this conversation, please try again')\n invalidate()\n },\n })\n\n return {\n read: conversation.unreadCount < 1, // prefer cache\n markRead: handleMarkRead,\n ...mutation,\n }\n}\n\nexport const useConversationsMute = ({ conversation }: { conversation: ConversationResource }) => {\n const apiClient = useApiClient()\n const { args } = useConversationsContext()\n const { update, invalidate } = useConversationsCache(args)\n\n const { mutate: setMuted, ...mutation } = useMutation({\n onMutate: async (muted: boolean) => {\n update({\n ...conversation,\n muted,\n conversationMembership: {\n ...conversation?.conversationMembership,\n muted,\n },\n })\n },\n mutationKey: ['muteConversation'],\n mutationFn: async (muted: boolean) => {\n const action = muted ? 'mute' : 'unmute'\n\n return apiClient.chat.post<ApiResource<ConversationResource>>({\n url: `/me/conversations/${conversation.id}/${action}`,\n data: { data: { type: '', attributes: {} }, fields: { Conversation: 'muted' } },\n })\n },\n onSuccess: (response: ApiResource<ConversationResource>) => {\n update(response.data)\n },\n onError: () => {\n Alert.alert('Oops', 'Something went wrong muting this conversation, please try again')\n invalidate()\n },\n })\n\n return {\n muted: conversation.muted, // prefer cache\n setMuted,\n ...mutation,\n }\n}\n\nexport const useMarkAllRead = () => {\n const apiClient = useApiClient()\n const { args } = useConversationsContext()\n const { invalidate, updateAll } = useConversationsCache(args)\n const { mutate: markAllRead, ...query } = useMutation({\n onMutate: () => {\n updateAll({\n unreadCount: 0,\n })\n },\n mutationKey: ['markAllRead', args],\n mutationFn: () =>\n apiClient.chat.post({\n url: '/me/mark_all_read',\n }),\n onSettled: invalidate,\n })\n\n return {\n markAllRead,\n ...query,\n }\n}\n"]}
1
+ {"version":3,"file":"use_conversations_actions.js","sourceRoot":"","sources":["../../src/hooks/use_conversations_actions.ts"],"names":[],"mappings":"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","sourcesContent":["import { useMutation } from '@tanstack/react-query'\nimport { Alert } from 'react-native'\nimport { useConversationsContext } from '../contexts/conversations_context'\nimport { ApiResource, ConversationResource } from '../types'\nimport { useApiClient } from './use_api_client'\nimport { useConversationsCache } from './use_conversations_cache'\nimport { useCurrentPersonCache } from './use_current_person'\n\nexport const useConversationsMarkRead = ({\n conversation,\n}: {\n conversation: ConversationResource\n}) => {\n const apiClient = useApiClient()\n const { args } = useConversationsContext()\n const currentPersonCache = useCurrentPersonCache()\n const { update, invalidate, fetchUpdate } = useConversationsCache(args)\n\n function handlePersonUnreadCount(read: boolean) {\n currentPersonCache.update({}, person => {\n const currentUnread = person.unreadCount\n const updatedUnread = read ? Math.max(currentUnread - 1, 0) : currentUnread + 1\n return { ...person, unreadCount: updatedUnread, unreadReactionCount: 0 }\n })\n }\n\n const { mutate: handleMarkRead, ...mutation } = useMutation({\n onMutate: async (read: boolean) => {\n update({\n ...conversation,\n unreadCount: read ? 0 : 1,\n })\n handlePersonUnreadCount(read)\n },\n mutationKey: ['markRead', conversation.id],\n mutationFn: async (read: boolean) => {\n const action = read ? 'mark_read' : 'mark_unread'\n\n return apiClient.chat.post({\n url: `/me/conversations/${conversation.id}/${action}`,\n data: { data: { type: '', attributes: {} }, fields: { Conversation: 'unread_count,id' } },\n })\n },\n onSuccess: () => {\n fetchUpdate(conversation)\n },\n onError: () => {\n Alert.alert('Oops', 'Something went wrong updating this conversation, please try again')\n invalidate()\n },\n })\n\n return {\n read: conversation.unreadCount < 1, // prefer cache\n markRead: handleMarkRead,\n ...mutation,\n }\n}\n\nexport const useConversationsMute = ({ conversation }: { conversation: ConversationResource }) => {\n const apiClient = useApiClient()\n const { args } = useConversationsContext()\n const { update, invalidate } = useConversationsCache(args)\n\n const { mutate: setMuted, ...mutation } = useMutation({\n onMutate: async (muted: boolean) => {\n update({\n ...conversation,\n muted,\n conversationMembership: {\n ...conversation?.conversationMembership,\n muted,\n },\n })\n },\n mutationKey: ['muteConversation'],\n mutationFn: async (muted: boolean) => {\n const action = muted ? 'mute' : 'unmute'\n\n return apiClient.chat.post<ApiResource<ConversationResource>>({\n url: `/me/conversations/${conversation.id}/${action}`,\n data: { data: { type: '', attributes: {} }, fields: { Conversation: 'muted' } },\n })\n },\n onSuccess: (response: ApiResource<ConversationResource>) => {\n update(response.data)\n },\n onError: () => {\n Alert.alert('Oops', 'Something went wrong muting this conversation, please try again')\n invalidate()\n },\n })\n\n return {\n muted: conversation.muted, // prefer cache\n setMuted,\n ...mutation,\n }\n}\n\nexport const useConversationsMarkReadUpTo = ({ conversationId }: { conversationId: number }) => {\n const apiClient = useApiClient()\n\n return useMutation({\n mutationKey: ['markReadUpTo', conversationId],\n mutationFn: async ({ sortKey }: { sortKey: string }) =>\n apiClient.chat.post({\n url: `/me/conversations/${conversationId}/mark_read_up_to`,\n data: {\n data: { type: 'Conversation', attributes: { sort_key: sortKey } },\n },\n }),\n })\n}\n\nexport const useMarkAllRead = () => {\n const apiClient = useApiClient()\n const { args } = useConversationsContext()\n const { invalidate, updateAll } = useConversationsCache(args)\n const { mutate: markAllRead, ...query } = useMutation({\n onMutate: () => {\n updateAll({\n unreadCount: 0,\n })\n },\n mutationKey: ['markAllRead', args],\n mutationFn: () =>\n apiClient.chat.post({\n url: '/me/mark_all_read',\n }),\n onSettled: invalidate,\n })\n\n return {\n markAllRead,\n ...query,\n }\n}\n"]}
@@ -0,0 +1,20 @@
1
+ import type { ViewToken } from 'react-native';
2
+ import type { ViewabilityObserver } from '../utils/message_viewability';
3
+ interface UseFlatListViewabilityArgs<Item> {
4
+ observers: ViewabilityObserver<Item>[];
5
+ itemVisiblePercentThreshold?: number;
6
+ }
7
+ export declare function useFlatListViewability<Item>({ observers, itemVisiblePercentThreshold, }: UseFlatListViewabilityArgs<Item>): {
8
+ viewabilityConfigCallbackPairs: {
9
+ viewabilityConfig: {
10
+ itemVisiblePercentThreshold: number;
11
+ };
12
+ onViewableItemsChanged: ({ viewableItems, changed, }: {
13
+ viewableItems: ViewToken[];
14
+ changed: ViewToken[];
15
+ }) => void;
16
+ }[];
17
+ onScrollBeginDrag: () => void;
18
+ };
19
+ export {};
20
+ //# sourceMappingURL=use_flat_list_viewability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_flat_list_viewability.d.ts","sourceRoot":"","sources":["../../src/hooks/use_flat_list_viewability.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAEvE,UAAU,0BAA0B,CAAC,IAAI;IACvC,SAAS,EAAE,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAA;IACtC,2BAA2B,CAAC,EAAE,MAAM,CAAA;CACrC;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,EAC3C,SAAS,EACT,2BAAgC,GACjC,EAAE,0BAA0B,CAAC,IAAI,CAAC;;;;;8DAkB1B;YACD,aAAa,EAAE,SAAS,EAAE,CAAA;YAC1B,OAAO,EAAE,SAAS,EAAE,CAAA;SACrB;;;EAYN"}
@@ -0,0 +1,30 @@
1
+ import { useCallback, useEffect, useRef } from 'react';
2
+ export function useFlatListViewability({ observers, itemVisiblePercentThreshold = 50, }) {
3
+ const userHasScrolledRef = useRef(false);
4
+ const observersRef = useRef(observers);
5
+ useEffect(() => {
6
+ observersRef.current = observers;
7
+ });
8
+ const onScrollBeginDrag = useCallback(() => {
9
+ userHasScrolledRef.current = true;
10
+ }, []);
11
+ const viewabilityConfigCallbackPairs = useRef([
12
+ {
13
+ viewabilityConfig: { itemVisiblePercentThreshold },
14
+ onViewableItemsChanged: ({ viewableItems, changed, }) => {
15
+ const event = {
16
+ viewableItems: viewableItems.map((toEntry)),
17
+ changed: changed.map((toEntry)),
18
+ userHasScrolled: userHasScrolledRef.current,
19
+ };
20
+ for (const observer of observersRef.current)
21
+ observer(event);
22
+ },
23
+ },
24
+ ]).current;
25
+ return { viewabilityConfigCallbackPairs, onScrollBeginDrag };
26
+ }
27
+ function toEntry(token) {
28
+ return { key: token.key, isViewable: !!token.isViewable, item: token.item };
29
+ }
30
+ //# sourceMappingURL=use_flat_list_viewability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_flat_list_viewability.js","sourceRoot":"","sources":["../../src/hooks/use_flat_list_viewability.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAStD,MAAM,UAAU,sBAAsB,CAAO,EAC3C,SAAS,EACT,2BAA2B,GAAG,EAAE,GACC;IACjC,MAAM,kBAAkB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IACxC,MAAM,YAAY,GAAG,MAAM,CAAC,SAAS,CAAC,CAAA;IAEtC,SAAS,CAAC,GAAG,EAAE;QACb,YAAY,CAAC,OAAO,GAAG,SAAS,CAAA;IAClC,CAAC,CAAC,CAAA;IAEF,MAAM,iBAAiB,GAAG,WAAW,CAAC,GAAG,EAAE;QACzC,kBAAkB,CAAC,OAAO,GAAG,IAAI,CAAA;IACnC,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,MAAM,8BAA8B,GAAG,MAAM,CAAC;QAC5C;YACE,iBAAiB,EAAE,EAAE,2BAA2B,EAAE;YAClD,sBAAsB,EAAE,CAAC,EACvB,aAAa,EACb,OAAO,GAIR,EAAE,EAAE;gBACH,MAAM,KAAK,GAAG;oBACZ,aAAa,EAAE,aAAa,CAAC,GAAG,CAAC,CAAA,OAAa,CAAA,CAAC;oBAC/C,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAA,OAAa,CAAA,CAAC;oBACnC,eAAe,EAAE,kBAAkB,CAAC,OAAO;iBAC5C,CAAA;gBACD,KAAK,MAAM,QAAQ,IAAI,YAAY,CAAC,OAAO;oBAAE,QAAQ,CAAC,KAAK,CAAC,CAAA;YAC9D,CAAC;SACF;KACF,CAAC,CAAC,OAAO,CAAA;IAEV,OAAO,EAAE,8BAA8B,EAAE,iBAAiB,EAAE,CAAA;AAC9D,CAAC;AAED,SAAS,OAAO,CAAO,KAAgB;IACrC,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE,KAAK,CAAC,IAAY,EAAE,CAAA;AACrF,CAAC","sourcesContent":["import { useCallback, useEffect, useRef } from 'react'\nimport type { ViewToken } from 'react-native'\nimport type { ViewabilityObserver } from '../utils/message_viewability'\n\ninterface UseFlatListViewabilityArgs<Item> {\n observers: ViewabilityObserver<Item>[]\n itemVisiblePercentThreshold?: number\n}\n\nexport function useFlatListViewability<Item>({\n observers,\n itemVisiblePercentThreshold = 50,\n}: UseFlatListViewabilityArgs<Item>) {\n const userHasScrolledRef = useRef(false)\n const observersRef = useRef(observers)\n\n useEffect(() => {\n observersRef.current = observers\n })\n\n const onScrollBeginDrag = useCallback(() => {\n userHasScrolledRef.current = true\n }, [])\n\n const viewabilityConfigCallbackPairs = useRef([\n {\n viewabilityConfig: { itemVisiblePercentThreshold },\n onViewableItemsChanged: ({\n viewableItems,\n changed,\n }: {\n viewableItems: ViewToken[]\n changed: ViewToken[]\n }) => {\n const event = {\n viewableItems: viewableItems.map(toEntry<Item>),\n changed: changed.map(toEntry<Item>),\n userHasScrolled: userHasScrolledRef.current,\n }\n for (const observer of observersRef.current) observer(event)\n },\n },\n ]).current\n\n return { viewabilityConfigCallbackPairs, onScrollBeginDrag }\n}\n\nfunction toEntry<Item>(token: ViewToken) {\n return { key: token.key, isViewable: !!token.isViewable, item: token.item as Item }\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import { RefObject } from 'react';
2
+ import type { FlatList } from 'react-native';
3
+ export declare function useJumpToBottomAction({ listRef }: {
4
+ listRef: RefObject<FlatList | null>;
5
+ }): {
6
+ handleJumpToBottom: () => void;
7
+ isJumpingToBottom: boolean;
8
+ };
9
+ //# sourceMappingURL=use_jump_to_bottom_action.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_jump_to_bottom_action.d.ts","sourceRoot":"","sources":["../../src/hooks/use_jump_to_bottom_action.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAA4C,MAAM,OAAO,CAAA;AAC3E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAU5C,wBAAgB,qBAAqB,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,SAAS,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAA;CAAE;;;EA8DzF"}
@@ -0,0 +1,62 @@
1
+ import { useQueryClient } from '@tanstack/react-query';
2
+ import { useCallback, useEffect, useRef, useState } from 'react';
3
+ import { useConversationContext } from '../contexts/conversation_context';
4
+ import { Haptic } from '../utils/native_adapters';
5
+ import { getMessagesQueryKey, getMessagesRequestArgs } from '../utils/request/get_messages';
6
+ import { useApiClient } from './use_api_client';
7
+ import { useJumpToUnreadGates } from './use_jump_to_unread_gates';
8
+ const LATEST_PAGE_SIZE = 25;
9
+ export function useJumpToBottomAction({ listRef }) {
10
+ const { jumpToUnreadEnabled } = useJumpToUnreadGates();
11
+ const { conversationId, currentPageReplyRootId, initialMessageId, setInitialMessageId } = useConversationContext();
12
+ const queryClient = useQueryClient();
13
+ const apiClient = useApiClient();
14
+ const [isJumpingToBottom, setIsJumpingToBottom] = useState(false);
15
+ const mountedRef = useRef(true);
16
+ useEffect(() => () => {
17
+ mountedRef.current = false;
18
+ }, []);
19
+ const handleJumpToBottom = useCallback(() => {
20
+ Haptic.impactLight();
21
+ listRef.current?.scrollToOffset({ offset: 0, animated: true });
22
+ if (!jumpToUnreadEnabled || !initialMessageId)
23
+ return;
24
+ const queryKey = getMessagesQueryKey({
25
+ conversation_id: conversationId,
26
+ reply_root_id: currentPageReplyRootId,
27
+ });
28
+ const args = getMessagesRequestArgs({
29
+ conversation_id: conversationId,
30
+ reply_root_id: currentPageReplyRootId,
31
+ });
32
+ setIsJumpingToBottom(true);
33
+ queryClient
34
+ .cancelQueries({ queryKey })
35
+ .then(() => apiClient.chat.get({
36
+ url: args.url,
37
+ data: { ...args.data, perPage: LATEST_PAGE_SIZE },
38
+ }))
39
+ .then(latest => {
40
+ if (!mountedRef.current)
41
+ return;
42
+ queryClient.setQueryData(queryKey, { pages: [latest], pageParams: [{}] });
43
+ setInitialMessageId(null);
44
+ listRef.current?.scrollToOffset({ offset: 0, animated: false });
45
+ })
46
+ .finally(() => {
47
+ if (mountedRef.current)
48
+ setIsJumpingToBottom(false);
49
+ });
50
+ }, [
51
+ jumpToUnreadEnabled,
52
+ initialMessageId,
53
+ setInitialMessageId,
54
+ queryClient,
55
+ apiClient,
56
+ conversationId,
57
+ currentPageReplyRootId,
58
+ listRef,
59
+ ]);
60
+ return { handleJumpToBottom, isJumpingToBottom };
61
+ }
62
+ //# sourceMappingURL=use_jump_to_bottom_action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_jump_to_bottom_action.js","sourceRoot":"","sources":["../../src/hooks/use_jump_to_bottom_action.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAa,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAE3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAA;AAEzE,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAA;AACjD,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AAC3F,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAEjE,MAAM,gBAAgB,GAAG,EAAE,CAAA;AAE3B,MAAM,UAAU,qBAAqB,CAAC,EAAE,OAAO,EAA2C;IACxF,MAAM,EAAE,mBAAmB,EAAE,GAAG,oBAAoB,EAAE,CAAA;IACtD,MAAM,EAAE,cAAc,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,GACrF,sBAAsB,EAAE,CAAA;IAC1B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAA;IACpC,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;IAChC,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAEjE,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,CAAA;IAC/B,SAAS,CACP,GAAG,EAAE,CAAC,GAAG,EAAE;QACT,UAAU,CAAC,OAAO,GAAG,KAAK,CAAA;IAC5B,CAAC,EACD,EAAE,CACH,CAAA;IAED,MAAM,kBAAkB,GAAG,WAAW,CAAC,GAAG,EAAE;QAC1C,MAAM,CAAC,WAAW,EAAE,CAAA;QACpB,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;QAE9D,IAAI,CAAC,mBAAmB,IAAI,CAAC,gBAAgB;YAAE,OAAM;QAErD,MAAM,QAAQ,GAAG,mBAAmB,CAAC;YACnC,eAAe,EAAE,cAAc;YAC/B,aAAa,EAAE,sBAAsB;SACtC,CAAC,CAAA;QACF,MAAM,IAAI,GAAG,sBAAsB,CAAC;YAClC,eAAe,EAAE,cAAc;YAC/B,aAAa,EAAE,sBAAsB;SACtC,CAAC,CAAA;QAEF,oBAAoB,CAAC,IAAI,CAAC,CAAA;QAE1B,WAAW;aACR,aAAa,CAAC,EAAE,QAAQ,EAAE,CAAC;aAC3B,IAAI,CAAC,GAAG,EAAE,CACT,SAAS,CAAC,IAAI,CAAC,GAAG,CAAiC;YACjD,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,gBAAgB,EAAE;SAClD,CAAC,CACH;aACA,IAAI,CAAC,MAAM,CAAC,EAAE;YACb,IAAI,CAAC,UAAU,CAAC,OAAO;gBAAE,OAAM;YAC/B,WAAW,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;YACzE,mBAAmB,CAAC,IAAI,CAAC,CAAA;YACzB,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAA;QACjE,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACZ,IAAI,UAAU,CAAC,OAAO;gBAAE,oBAAoB,CAAC,KAAK,CAAC,CAAA;QACrD,CAAC,CAAC,CAAA;IACN,CAAC,EAAE;QACD,mBAAmB;QACnB,gBAAgB;QAChB,mBAAmB;QACnB,WAAW;QACX,SAAS;QACT,cAAc;QACd,sBAAsB;QACtB,OAAO;KACR,CAAC,CAAA;IAEF,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,CAAA;AAClD,CAAC","sourcesContent":["import { useQueryClient } from '@tanstack/react-query'\nimport { RefObject, useCallback, useEffect, useRef, useState } from 'react'\nimport type { FlatList } from 'react-native'\nimport { useConversationContext } from '../contexts/conversation_context'\nimport { ApiCollection, MessageResource } from '../types'\nimport { Haptic } from '../utils/native_adapters'\nimport { getMessagesQueryKey, getMessagesRequestArgs } from '../utils/request/get_messages'\nimport { useApiClient } from './use_api_client'\nimport { useJumpToUnreadGates } from './use_jump_to_unread_gates'\n\nconst LATEST_PAGE_SIZE = 25\n\nexport function useJumpToBottomAction({ listRef }: { listRef: RefObject<FlatList | null> }) {\n const { jumpToUnreadEnabled } = useJumpToUnreadGates()\n const { conversationId, currentPageReplyRootId, initialMessageId, setInitialMessageId } =\n useConversationContext()\n const queryClient = useQueryClient()\n const apiClient = useApiClient()\n const [isJumpingToBottom, setIsJumpingToBottom] = useState(false)\n\n const mountedRef = useRef(true)\n useEffect(\n () => () => {\n mountedRef.current = false\n },\n []\n )\n\n const handleJumpToBottom = useCallback(() => {\n Haptic.impactLight()\n listRef.current?.scrollToOffset({ offset: 0, animated: true })\n\n if (!jumpToUnreadEnabled || !initialMessageId) return\n\n const queryKey = getMessagesQueryKey({\n conversation_id: conversationId,\n reply_root_id: currentPageReplyRootId,\n })\n const args = getMessagesRequestArgs({\n conversation_id: conversationId,\n reply_root_id: currentPageReplyRootId,\n })\n\n setIsJumpingToBottom(true)\n\n queryClient\n .cancelQueries({ queryKey })\n .then(() =>\n apiClient.chat.get<ApiCollection<MessageResource>>({\n url: args.url,\n data: { ...args.data, perPage: LATEST_PAGE_SIZE },\n })\n )\n .then(latest => {\n if (!mountedRef.current) return\n queryClient.setQueryData(queryKey, { pages: [latest], pageParams: [{}] })\n setInitialMessageId(null)\n listRef.current?.scrollToOffset({ offset: 0, animated: false })\n })\n .finally(() => {\n if (mountedRef.current) setIsJumpingToBottom(false)\n })\n }, [\n jumpToUnreadEnabled,\n initialMessageId,\n setInitialMessageId,\n queryClient,\n apiClient,\n conversationId,\n currentPageReplyRootId,\n listRef,\n ])\n\n return { handleJumpToBottom, isJumpingToBottom }\n}\n"]}
@@ -0,0 +1,20 @@
1
+ import { RefObject } from 'react';
2
+ import type { FlatList } from 'react-native';
3
+ interface UseJumpToUnreadAnchorArgs<T> {
4
+ listRef: RefObject<FlatList<T> | null>;
5
+ items: T[];
6
+ }
7
+ interface ScrollToIndexFailInfo {
8
+ index: number;
9
+ highestMeasuredFrameIndex: number;
10
+ averageItemLength: number;
11
+ }
12
+ export declare function useJumpToUnreadAnchor<T extends {
13
+ id?: string | number;
14
+ }>({ listRef, items, }: UseJumpToUnreadAnchorArgs<T>): {
15
+ onScrollBeginDrag: () => void;
16
+ onContentSizeChange: () => void;
17
+ onScrollToIndexFailed: (info: ScrollToIndexFailInfo) => void;
18
+ };
19
+ export {};
20
+ //# sourceMappingURL=use_jump_to_unread_anchor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_jump_to_unread_anchor.d.ts","sourceRoot":"","sources":["../../src/hooks/use_jump_to_unread_anchor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAkC,MAAM,OAAO,CAAA;AACjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAI5C,UAAU,yBAAyB,CAAC,CAAC;IACnC,OAAO,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;IACtC,KAAK,EAAE,CAAC,EAAE,CAAA;CACX;AAED,UAAU,qBAAqB;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,yBAAyB,EAAE,MAAM,CAAA;IACjC,iBAAiB,EAAE,MAAM,CAAA;CAC1B;AAED,wBAAgB,qBAAqB,CAAC,CAAC,SAAS;IAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,EAAE,EACxE,OAAO,EACP,KAAK,GACN,EAAE,yBAAyB,CAAC,CAAC,CAAC;;;kCAiCpB,qBAAqB;EAe/B"}
@@ -0,0 +1,53 @@
1
+ import { useCallback, useEffect, useRef } from 'react';
2
+ import { useConversationContext } from '../contexts/conversation_context';
3
+ import { useJumpToUnreadGates } from './use_jump_to_unread_gates';
4
+ export function useJumpToUnreadAnchor({ listRef, items, }) {
5
+ const { jumpToUnreadActive } = useJumpToUnreadGates();
6
+ const { initialMessageId } = useConversationContext();
7
+ const hasAnchoredRef = useRef(false);
8
+ const userTouchedRef = useRef(false);
9
+ const retryTimerRef = useRef(null);
10
+ useEffect(() => {
11
+ return () => {
12
+ if (retryTimerRef.current)
13
+ clearTimeout(retryTimerRef.current);
14
+ retryTimerRef.current = null;
15
+ };
16
+ }, []);
17
+ const onScrollBeginDrag = useCallback(() => {
18
+ userTouchedRef.current = true;
19
+ if (retryTimerRef.current) {
20
+ clearTimeout(retryTimerRef.current);
21
+ retryTimerRef.current = null;
22
+ }
23
+ }, []);
24
+ const onContentSizeChange = useCallback(() => {
25
+ if (hasAnchoredRef.current)
26
+ return;
27
+ if (!jumpToUnreadActive || !initialMessageId)
28
+ return;
29
+ if (userTouchedRef.current)
30
+ return;
31
+ const index = items.findIndex(item => String(item.id ?? '') === initialMessageId);
32
+ if (index < 0)
33
+ return;
34
+ hasAnchoredRef.current = true;
35
+ listRef.current?.scrollToIndex({ index, viewPosition: 0.25, animated: false });
36
+ }, [jumpToUnreadActive, initialMessageId, items, listRef]);
37
+ const onScrollToIndexFailed = useCallback((info) => {
38
+ if (userTouchedRef.current)
39
+ return;
40
+ const offset = info.averageItemLength * info.index;
41
+ listRef.current?.scrollToOffset({ offset, animated: false });
42
+ if (retryTimerRef.current)
43
+ clearTimeout(retryTimerRef.current);
44
+ retryTimerRef.current = setTimeout(() => {
45
+ retryTimerRef.current = null;
46
+ if (userTouchedRef.current)
47
+ return;
48
+ listRef.current?.scrollToIndex({ index: info.index, viewPosition: 0.25, animated: false });
49
+ }, 50);
50
+ }, [listRef]);
51
+ return { onScrollBeginDrag, onContentSizeChange, onScrollToIndexFailed };
52
+ }
53
+ //# sourceMappingURL=use_jump_to_unread_anchor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_jump_to_unread_anchor.js","sourceRoot":"","sources":["../../src/hooks/use_jump_to_unread_anchor.ts"],"names":[],"mappings":"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","sourcesContent":["import { RefObject, useCallback, useEffect, useRef } from 'react'\nimport type { FlatList } from 'react-native'\nimport { useConversationContext } from '../contexts/conversation_context'\nimport { useJumpToUnreadGates } from './use_jump_to_unread_gates'\n\ninterface UseJumpToUnreadAnchorArgs<T> {\n listRef: RefObject<FlatList<T> | null>\n items: T[]\n}\n\ninterface ScrollToIndexFailInfo {\n index: number\n highestMeasuredFrameIndex: number\n averageItemLength: number\n}\n\nexport function useJumpToUnreadAnchor<T extends { id?: string | number }>({\n listRef,\n items,\n}: UseJumpToUnreadAnchorArgs<T>) {\n const { jumpToUnreadActive } = useJumpToUnreadGates()\n const { initialMessageId } = useConversationContext()\n const hasAnchoredRef = useRef(false)\n const userTouchedRef = useRef(false)\n const retryTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n useEffect(() => {\n return () => {\n if (retryTimerRef.current) clearTimeout(retryTimerRef.current)\n retryTimerRef.current = null\n }\n }, [])\n\n const onScrollBeginDrag = useCallback(() => {\n userTouchedRef.current = true\n if (retryTimerRef.current) {\n clearTimeout(retryTimerRef.current)\n retryTimerRef.current = null\n }\n }, [])\n\n const onContentSizeChange = useCallback(() => {\n if (hasAnchoredRef.current) return\n if (!jumpToUnreadActive || !initialMessageId) return\n if (userTouchedRef.current) return\n const index = items.findIndex(item => String(item.id ?? '') === initialMessageId)\n if (index < 0) return\n hasAnchoredRef.current = true\n listRef.current?.scrollToIndex({ index, viewPosition: 0.25, animated: false })\n }, [jumpToUnreadActive, initialMessageId, items, listRef])\n\n const onScrollToIndexFailed = useCallback(\n (info: ScrollToIndexFailInfo) => {\n if (userTouchedRef.current) return\n const offset = info.averageItemLength * info.index\n listRef.current?.scrollToOffset({ offset, animated: false })\n if (retryTimerRef.current) clearTimeout(retryTimerRef.current)\n retryTimerRef.current = setTimeout(() => {\n retryTimerRef.current = null\n if (userTouchedRef.current) return\n listRef.current?.scrollToIndex({ index: info.index, viewPosition: 0.25, animated: false })\n }, 50)\n },\n [listRef]\n )\n\n return { onScrollBeginDrag, onContentSizeChange, onScrollToIndexFailed }\n}\n"]}
@@ -0,0 +1,5 @@
1
+ export declare function useJumpToUnreadGates(): {
2
+ jumpToUnreadEnabled: boolean;
3
+ jumpToUnreadActive: boolean;
4
+ };
5
+ //# sourceMappingURL=use_jump_to_unread_gates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_jump_to_unread_gates.d.ts","sourceRoot":"","sources":["../../src/hooks/use_jump_to_unread_gates.ts"],"names":[],"mappings":"AAGA,wBAAgB,oBAAoB;;;EAMnC"}
@@ -0,0 +1,10 @@
1
+ import { useConversationContext } from '../contexts/conversation_context';
2
+ import { useFeatures } from './use_features';
3
+ export function useJumpToUnreadGates() {
4
+ const { featureEnabled } = useFeatures();
5
+ const { initialMessageIdIsAnchor } = useConversationContext();
6
+ const jumpToUnreadEnabled = featureEnabled('jump_to_unread');
7
+ const jumpToUnreadActive = jumpToUnreadEnabled && initialMessageIdIsAnchor;
8
+ return { jumpToUnreadEnabled, jumpToUnreadActive };
9
+ }
10
+ //# sourceMappingURL=use_jump_to_unread_gates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_jump_to_unread_gates.js","sourceRoot":"","sources":["../../src/hooks/use_jump_to_unread_gates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAA;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE5C,MAAM,UAAU,oBAAoB;IAClC,MAAM,EAAE,cAAc,EAAE,GAAG,WAAW,EAAE,CAAA;IACxC,MAAM,EAAE,wBAAwB,EAAE,GAAG,sBAAsB,EAAE,CAAA;IAC7D,MAAM,mBAAmB,GAAG,cAAc,CAAC,gBAAgB,CAAC,CAAA;IAC5D,MAAM,kBAAkB,GAAG,mBAAmB,IAAI,wBAAwB,CAAA;IAC1E,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,CAAA;AACpD,CAAC","sourcesContent":["import { useConversationContext } from '../contexts/conversation_context'\nimport { useFeatures } from './use_features'\n\nexport function useJumpToUnreadGates() {\n const { featureEnabled } = useFeatures()\n const { initialMessageIdIsAnchor } = useConversationContext()\n const jumpToUnreadEnabled = featureEnabled('jump_to_unread')\n const jumpToUnreadActive = jumpToUnreadEnabled && initialMessageIdIsAnchor\n return { jumpToUnreadEnabled, jumpToUnreadActive }\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { ConversationResource, MessageResource } from '../types';
2
2
  interface Props {
3
3
  conversation: ConversationResource;
4
- messages: MessageResource[];
4
+ messages?: MessageResource[];
5
5
  }
6
6
  export declare function useMarkLatestMessageRead({ conversation }: Props): void;
7
7
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"use_mark_latest_message_read.d.ts","sourceRoot":"","sources":["../../src/hooks/use_mark_latest_message_read.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAIhE,UAAU,KAAK;IACb,YAAY,EAAE,oBAAoB,CAAA;IAClC,QAAQ,EAAE,eAAe,EAAE,CAAA;CAC5B;AAED,wBAAgB,wBAAwB,CAAC,EAAE,YAAY,EAAE,EAAE,KAAK,QAsB/D"}
1
+ {"version":3,"file":"use_mark_latest_message_read.d.ts","sourceRoot":"","sources":["../../src/hooks/use_mark_latest_message_read.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAKhE,UAAU,KAAK;IACb,YAAY,EAAE,oBAAoB,CAAA;IAClC,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAA;CAC7B;AAED,wBAAgB,wBAAwB,CAAC,EAAE,YAAY,EAAE,EAAE,KAAK,QAkC/D"}
@@ -1,8 +1,12 @@
1
1
  import { debounce } from 'lodash';
2
2
  import { useEffect, useMemo, useRef } from 'react';
3
+ import { useConversationContext } from '../contexts/conversation_context';
3
4
  import { useAppState } from './use_app_state';
4
5
  import { useConversationsMarkRead } from './use_conversations_actions';
6
+ import { useJumpToUnreadGates } from './use_jump_to_unread_gates';
5
7
  export function useMarkLatestMessageRead({ conversation }) {
8
+ const { jumpToUnreadActive } = useJumpToUnreadGates();
9
+ const { currentPageReplyRootId, atEndOfMessageHistory } = useConversationContext();
6
10
  const firedOnce = useRef(false);
7
11
  const { markRead } = useConversationsMarkRead({ conversation });
8
12
  const debouncedMarkRead = useMemo(() => debounce(markRead, 1000, { leading: true, trailing: true }), [markRead]);
@@ -14,9 +18,21 @@ export function useMarkLatestMessageRead({ conversation }) {
14
18
  useEffect(() => {
15
19
  if (!isActive || !shouldMarkRead)
16
20
  return;
21
+ if (currentPageReplyRootId)
22
+ return;
23
+ if (jumpToUnreadActive && !atEndOfMessageHistory)
24
+ return;
17
25
  firedOnce.current = true;
18
26
  debouncedMarkRead(true);
19
27
  // keeping unreadReactionCount in the dependency array to watch for changes
20
- }, [debouncedMarkRead, isActive, shouldMarkRead, unreadReactionCount]);
28
+ }, [
29
+ debouncedMarkRead,
30
+ isActive,
31
+ shouldMarkRead,
32
+ unreadReactionCount,
33
+ currentPageReplyRootId,
34
+ jumpToUnreadActive,
35
+ atEndOfMessageHistory,
36
+ ]);
21
37
  }
22
38
  //# sourceMappingURL=use_mark_latest_message_read.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use_mark_latest_message_read.js","sourceRoot":"","sources":["../../src/hooks/use_mark_latest_message_read.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AACjC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAElD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAA;AAOtE,MAAM,UAAU,wBAAwB,CAAC,EAAE,YAAY,EAAS;IAC9D,MAAM,SAAS,GAAG,MAAM,CAAU,KAAK,CAAC,CAAA;IACxC,MAAM,EAAE,QAAQ,EAAE,GAAG,wBAAwB,CAAC,EAAE,YAAY,EAAE,CAAC,CAAA;IAC/D,MAAM,iBAAiB,GAAG,OAAO,CAC/B,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EACjE,CAAC,QAAQ,CAAC,CACX,CAAA;IACD,MAAM,WAAW,GAAG,YAAY,CAAC,WAAW,CAAA;IAC5C,MAAM,mBAAmB,GAAG,YAAY,CAAC,mBAAmB,IAAI,CAAC,CAAA;IAEjE,MAAM,cAAc,GAAG,OAAO,CAAC,WAAW,IAAI,CAAC,IAAI,mBAAmB,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;IACjG,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAA;IAC9B,MAAM,QAAQ,GAAG,QAAQ,KAAK,QAAQ,CAAA;IAEtC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,QAAQ,IAAI,CAAC,cAAc;YAAE,OAAM;QAExC,SAAS,CAAC,OAAO,GAAG,IAAI,CAAA;QAExB,iBAAiB,CAAC,IAAI,CAAC,CAAA;QACvB,2EAA2E;IAC7E,CAAC,EAAE,CAAC,iBAAiB,EAAE,QAAQ,EAAE,cAAc,EAAE,mBAAmB,CAAC,CAAC,CAAA;AACxE,CAAC","sourcesContent":["import { debounce } from 'lodash'\nimport { useEffect, useMemo, useRef } from 'react'\nimport { ConversationResource, MessageResource } from '../types'\nimport { useAppState } from './use_app_state'\nimport { useConversationsMarkRead } from './use_conversations_actions'\n\ninterface Props {\n conversation: ConversationResource\n messages: MessageResource[]\n}\n\nexport function useMarkLatestMessageRead({ conversation }: Props) {\n const firedOnce = useRef<boolean>(false)\n const { markRead } = useConversationsMarkRead({ conversation })\n const debouncedMarkRead = useMemo(\n () => debounce(markRead, 1000, { leading: true, trailing: true }),\n [markRead]\n )\n const unreadCount = conversation.unreadCount\n const unreadReactionCount = conversation.unreadReactionCount || 0\n\n const shouldMarkRead = Boolean(unreadCount >= 1 || unreadReactionCount > 0 || !firedOnce.current)\n const appState = useAppState()\n const isActive = appState === 'active'\n\n useEffect(() => {\n if (!isActive || !shouldMarkRead) return\n\n firedOnce.current = true\n\n debouncedMarkRead(true)\n // keeping unreadReactionCount in the dependency array to watch for changes\n }, [debouncedMarkRead, isActive, shouldMarkRead, unreadReactionCount])\n}\n"]}
1
+ {"version":3,"file":"use_mark_latest_message_read.js","sourceRoot":"","sources":["../../src/hooks/use_mark_latest_message_read.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AACjC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAA;AAEzE,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAA;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAOjE,MAAM,UAAU,wBAAwB,CAAC,EAAE,YAAY,EAAS;IAC9D,MAAM,EAAE,kBAAkB,EAAE,GAAG,oBAAoB,EAAE,CAAA;IACrD,MAAM,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,GAAG,sBAAsB,EAAE,CAAA;IAClF,MAAM,SAAS,GAAG,MAAM,CAAU,KAAK,CAAC,CAAA;IACxC,MAAM,EAAE,QAAQ,EAAE,GAAG,wBAAwB,CAAC,EAAE,YAAY,EAAE,CAAC,CAAA;IAC/D,MAAM,iBAAiB,GAAG,OAAO,CAC/B,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EACjE,CAAC,QAAQ,CAAC,CACX,CAAA;IACD,MAAM,WAAW,GAAG,YAAY,CAAC,WAAW,CAAA;IAC5C,MAAM,mBAAmB,GAAG,YAAY,CAAC,mBAAmB,IAAI,CAAC,CAAA;IAEjE,MAAM,cAAc,GAAG,OAAO,CAAC,WAAW,IAAI,CAAC,IAAI,mBAAmB,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;IACjG,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAA;IAC9B,MAAM,QAAQ,GAAG,QAAQ,KAAK,QAAQ,CAAA;IAEtC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,QAAQ,IAAI,CAAC,cAAc;YAAE,OAAM;QACxC,IAAI,sBAAsB;YAAE,OAAM;QAClC,IAAI,kBAAkB,IAAI,CAAC,qBAAqB;YAAE,OAAM;QAExD,SAAS,CAAC,OAAO,GAAG,IAAI,CAAA;QAExB,iBAAiB,CAAC,IAAI,CAAC,CAAA;QACvB,2EAA2E;IAC7E,CAAC,EAAE;QACD,iBAAiB;QACjB,QAAQ;QACR,cAAc;QACd,mBAAmB;QACnB,sBAAsB;QACtB,kBAAkB;QAClB,qBAAqB;KACtB,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import { debounce } from 'lodash'\nimport { useEffect, useMemo, useRef } from 'react'\nimport { useConversationContext } from '../contexts/conversation_context'\nimport { ConversationResource, MessageResource } from '../types'\nimport { useAppState } from './use_app_state'\nimport { useConversationsMarkRead } from './use_conversations_actions'\nimport { useJumpToUnreadGates } from './use_jump_to_unread_gates'\n\ninterface Props {\n conversation: ConversationResource\n messages?: MessageResource[]\n}\n\nexport function useMarkLatestMessageRead({ conversation }: Props) {\n const { jumpToUnreadActive } = useJumpToUnreadGates()\n const { currentPageReplyRootId, atEndOfMessageHistory } = useConversationContext()\n const firedOnce = useRef<boolean>(false)\n const { markRead } = useConversationsMarkRead({ conversation })\n const debouncedMarkRead = useMemo(\n () => debounce(markRead, 1000, { leading: true, trailing: true }),\n [markRead]\n )\n const unreadCount = conversation.unreadCount\n const unreadReactionCount = conversation.unreadReactionCount || 0\n\n const shouldMarkRead = Boolean(unreadCount >= 1 || unreadReactionCount > 0 || !firedOnce.current)\n const appState = useAppState()\n const isActive = appState === 'active'\n\n useEffect(() => {\n if (!isActive || !shouldMarkRead) return\n if (currentPageReplyRootId) return\n if (jumpToUnreadActive && !atEndOfMessageHistory) return\n\n firedOnce.current = true\n\n debouncedMarkRead(true)\n // keeping unreadReactionCount in the dependency array to watch for changes\n }, [\n debouncedMarkRead,\n isActive,\n shouldMarkRead,\n unreadReactionCount,\n currentPageReplyRootId,\n jumpToUnreadActive,\n atEndOfMessageHistory,\n ])\n}\n"]}
@@ -0,0 +1,13 @@
1
+ import type { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';
2
+ interface UseScrollTrackingArgs {
3
+ hasMoreNewerMessages: boolean;
4
+ isFetchingNewerMessages: boolean;
5
+ fetchNewerMessages: () => void;
6
+ cancelFetchNewerMessages: () => void;
7
+ }
8
+ export declare function useScrollTracking({ hasMoreNewerMessages, isFetchingNewerMessages, fetchNewerMessages, cancelFetchNewerMessages, }: UseScrollTrackingArgs): {
9
+ onScroll: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
10
+ showJumpToBottomButton: boolean;
11
+ };
12
+ export {};
13
+ //# sourceMappingURL=use_scroll_tracking.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_scroll_tracking.d.ts","sourceRoot":"","sources":["../../src/hooks/use_scroll_tracking.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAO3E,UAAU,qBAAqB;IAC7B,oBAAoB,EAAE,OAAO,CAAA;IAC7B,uBAAuB,EAAE,OAAO,CAAA;IAChC,kBAAkB,EAAE,MAAM,IAAI,CAAA;IAC9B,wBAAwB,EAAE,MAAM,IAAI,CAAA;CACrC;AAED,wBAAgB,iBAAiB,CAAC,EAChC,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,EAClB,wBAAwB,GACzB,EAAE,qBAAqB;sBAgBZ,oBAAoB,CAAC,iBAAiB,CAAC;;EA2BlD"}
@@ -0,0 +1,45 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react';
2
+ import { useConversationContext } from '../contexts/conversation_context';
3
+ const JUMP_TO_BOTTOM_OFFSET_THRESHOLD = 200;
4
+ const AT_BOTTOM_OFFSET_TOLERANCE = 5;
5
+ const FETCH_NEWER_OFFSET_THRESHOLD = 600;
6
+ export function useScrollTracking({ hasMoreNewerMessages, isFetchingNewerMessages, fetchNewerMessages, cancelFetchNewerMessages, }) {
7
+ const { atEndOfMessageHistory, setAtEndOfMessageHistory } = useConversationContext();
8
+ const [showJumpToBottomButton, setShowJumpToBottomButton] = useState(false);
9
+ const withinBoundaryRef = useRef(false);
10
+ useEffect(() => {
11
+ return () => {
12
+ cancelFetchNewerMessages();
13
+ };
14
+ }, [cancelFetchNewerMessages]);
15
+ useEffect(() => {
16
+ if (!isFetchingNewerMessages)
17
+ withinBoundaryRef.current = false;
18
+ }, [isFetchingNewerMessages]);
19
+ const onScroll = useCallback((event) => {
20
+ const offsetY = event.nativeEvent.contentOffset.y;
21
+ setShowJumpToBottomButton(offsetY > JUMP_TO_BOTTOM_OFFSET_THRESHOLD);
22
+ const atBottom = offsetY < AT_BOTTOM_OFFSET_TOLERANCE;
23
+ const atEnd = atBottom && !hasMoreNewerMessages;
24
+ if (atEnd !== atEndOfMessageHistory)
25
+ setAtEndOfMessageHistory(atEnd);
26
+ if (offsetY >= FETCH_NEWER_OFFSET_THRESHOLD) {
27
+ withinBoundaryRef.current = false;
28
+ return;
29
+ }
30
+ if (withinBoundaryRef.current)
31
+ return;
32
+ if (!hasMoreNewerMessages || isFetchingNewerMessages)
33
+ return;
34
+ withinBoundaryRef.current = true;
35
+ fetchNewerMessages();
36
+ }, [
37
+ hasMoreNewerMessages,
38
+ isFetchingNewerMessages,
39
+ fetchNewerMessages,
40
+ atEndOfMessageHistory,
41
+ setAtEndOfMessageHistory,
42
+ ]);
43
+ return { onScroll, showJumpToBottomButton };
44
+ }
45
+ //# sourceMappingURL=use_scroll_tracking.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_scroll_tracking.js","sourceRoot":"","sources":["../../src/hooks/use_scroll_tracking.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEhE,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAA;AAEzE,MAAM,+BAA+B,GAAG,GAAG,CAAA;AAC3C,MAAM,0BAA0B,GAAG,CAAC,CAAA;AACpC,MAAM,4BAA4B,GAAG,GAAG,CAAA;AASxC,MAAM,UAAU,iBAAiB,CAAC,EAChC,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,EAClB,wBAAwB,GACF;IACtB,MAAM,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,GAAG,sBAAsB,EAAE,CAAA;IACpF,MAAM,CAAC,sBAAsB,EAAE,yBAAyB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC3E,MAAM,iBAAiB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAEvC,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,GAAG,EAAE;YACV,wBAAwB,EAAE,CAAA;QAC5B,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,CAAA;IAE9B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,uBAAuB;YAAE,iBAAiB,CAAC,OAAO,GAAG,KAAK,CAAA;IACjE,CAAC,EAAE,CAAC,uBAAuB,CAAC,CAAC,CAAA;IAE7B,MAAM,QAAQ,GAAG,WAAW,CAC1B,CAAC,KAA8C,EAAE,EAAE;QACjD,MAAM,OAAO,GAAG,KAAK,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAA;QACjD,yBAAyB,CAAC,OAAO,GAAG,+BAA+B,CAAC,CAAA;QAEpE,MAAM,QAAQ,GAAG,OAAO,GAAG,0BAA0B,CAAA;QACrD,MAAM,KAAK,GAAG,QAAQ,IAAI,CAAC,oBAAoB,CAAA;QAC/C,IAAI,KAAK,KAAK,qBAAqB;YAAE,wBAAwB,CAAC,KAAK,CAAC,CAAA;QAEpE,IAAI,OAAO,IAAI,4BAA4B,EAAE,CAAC;YAC5C,iBAAiB,CAAC,OAAO,GAAG,KAAK,CAAA;YACjC,OAAM;QACR,CAAC;QACD,IAAI,iBAAiB,CAAC,OAAO;YAAE,OAAM;QACrC,IAAI,CAAC,oBAAoB,IAAI,uBAAuB;YAAE,OAAM;QAC5D,iBAAiB,CAAC,OAAO,GAAG,IAAI,CAAA;QAChC,kBAAkB,EAAE,CAAA;IACtB,CAAC,EACD;QACE,oBAAoB;QACpB,uBAAuB;QACvB,kBAAkB;QAClB,qBAAqB;QACrB,wBAAwB;KACzB,CACF,CAAA;IAED,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,CAAA;AAC7C,CAAC","sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react'\nimport type { NativeScrollEvent, NativeSyntheticEvent } from 'react-native'\nimport { useConversationContext } from '../contexts/conversation_context'\n\nconst JUMP_TO_BOTTOM_OFFSET_THRESHOLD = 200\nconst AT_BOTTOM_OFFSET_TOLERANCE = 5\nconst FETCH_NEWER_OFFSET_THRESHOLD = 600\n\ninterface UseScrollTrackingArgs {\n hasMoreNewerMessages: boolean\n isFetchingNewerMessages: boolean\n fetchNewerMessages: () => void\n cancelFetchNewerMessages: () => void\n}\n\nexport function useScrollTracking({\n hasMoreNewerMessages,\n isFetchingNewerMessages,\n fetchNewerMessages,\n cancelFetchNewerMessages,\n}: UseScrollTrackingArgs) {\n const { atEndOfMessageHistory, setAtEndOfMessageHistory } = useConversationContext()\n const [showJumpToBottomButton, setShowJumpToBottomButton] = useState(false)\n const withinBoundaryRef = useRef(false)\n\n useEffect(() => {\n return () => {\n cancelFetchNewerMessages()\n }\n }, [cancelFetchNewerMessages])\n\n useEffect(() => {\n if (!isFetchingNewerMessages) withinBoundaryRef.current = false\n }, [isFetchingNewerMessages])\n\n const onScroll = useCallback(\n (event: NativeSyntheticEvent<NativeScrollEvent>) => {\n const offsetY = event.nativeEvent.contentOffset.y\n setShowJumpToBottomButton(offsetY > JUMP_TO_BOTTOM_OFFSET_THRESHOLD)\n\n const atBottom = offsetY < AT_BOTTOM_OFFSET_TOLERANCE\n const atEnd = atBottom && !hasMoreNewerMessages\n if (atEnd !== atEndOfMessageHistory) setAtEndOfMessageHistory(atEnd)\n\n if (offsetY >= FETCH_NEWER_OFFSET_THRESHOLD) {\n withinBoundaryRef.current = false\n return\n }\n if (withinBoundaryRef.current) return\n if (!hasMoreNewerMessages || isFetchingNewerMessages) return\n withinBoundaryRef.current = true\n fetchNewerMessages()\n },\n [\n hasMoreNewerMessages,\n isFetchingNewerMessages,\n fetchNewerMessages,\n atEndOfMessageHistory,\n setAtEndOfMessageHistory,\n ]\n )\n\n return { onScroll, showJumpToBottomButton }\n}\n"]}
@@ -0,0 +1,4 @@
1
+ export declare function useTrackHighestSeenMessage(): {
2
+ onMessageSeen: (sortKey: string) => void;
3
+ };
4
+ //# sourceMappingURL=use_track_highest_seen_message.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_track_highest_seen_message.d.ts","sourceRoot":"","sources":["../../src/hooks/use_track_highest_seen_message.ts"],"names":[],"mappings":"AAOA,wBAAgB,0BAA0B;6BAY5B,MAAM;EAuBnB"}
@@ -0,0 +1,35 @@
1
+ import { useCallback, useEffect, useMemo } from 'react';
2
+ import { AppState } from 'react-native';
3
+ import { useConversationContext } from '../contexts/conversation_context';
4
+ import { makeHighestSeenTracker } from '../utils/highest_seen_tracker';
5
+ import { useConversationsMarkReadUpTo } from './use_conversations_actions';
6
+ import { useJumpToUnreadGates } from './use_jump_to_unread_gates';
7
+ export function useTrackHighestSeenMessage() {
8
+ const { conversationId, currentPageReplyRootId } = useConversationContext();
9
+ const { jumpToUnreadActive } = useJumpToUnreadGates();
10
+ const enabled = jumpToUnreadActive && !currentPageReplyRootId;
11
+ const { mutate: markReadUpTo } = useConversationsMarkReadUpTo({ conversationId });
12
+ const tracker = useMemo(() => makeHighestSeenTracker(conversationId, ({ sortKey }) => markReadUpTo({ sortKey })), [conversationId, markReadUpTo]);
13
+ const onMessageSeen = useCallback((sortKey) => {
14
+ if (!enabled)
15
+ return;
16
+ tracker.onSeen(sortKey);
17
+ }, [enabled, tracker]);
18
+ useEffect(() => {
19
+ if (!enabled)
20
+ return;
21
+ const sub = AppState.addEventListener('change', state => {
22
+ if (state !== 'active')
23
+ tracker.flushNow();
24
+ });
25
+ return () => sub.remove();
26
+ }, [enabled, tracker]);
27
+ useEffect(() => {
28
+ return () => {
29
+ tracker.flushNow();
30
+ tracker.cancel();
31
+ };
32
+ }, [tracker]);
33
+ return { onMessageSeen };
34
+ }
35
+ //# sourceMappingURL=use_track_highest_seen_message.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_track_highest_seen_message.js","sourceRoot":"","sources":["../../src/hooks/use_track_highest_seen_message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAA;AACzE,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AACtE,OAAO,EAAE,4BAA4B,EAAE,MAAM,6BAA6B,CAAA;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAEjE,MAAM,UAAU,0BAA0B;IACxC,MAAM,EAAE,cAAc,EAAE,sBAAsB,EAAE,GAAG,sBAAsB,EAAE,CAAA;IAC3E,MAAM,EAAE,kBAAkB,EAAE,GAAG,oBAAoB,EAAE,CAAA;IACrD,MAAM,OAAO,GAAG,kBAAkB,IAAI,CAAC,sBAAsB,CAAA;IAC7D,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,4BAA4B,CAAC,EAAE,cAAc,EAAE,CAAC,CAAA;IAEjF,MAAM,OAAO,GAAG,OAAO,CACrB,GAAG,EAAE,CAAC,sBAAsB,CAAC,cAAc,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,EACxF,CAAC,cAAc,EAAE,YAAY,CAAC,CAC/B,CAAA;IAED,MAAM,aAAa,GAAG,WAAW,CAC/B,CAAC,OAAe,EAAE,EAAE;QAClB,IAAI,CAAC,OAAO;YAAE,OAAM;QACpB,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IACzB,CAAC,EACD,CAAC,OAAO,EAAE,OAAO,CAAC,CACnB,CAAA;IAED,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO;YAAE,OAAM;QACpB,MAAM,GAAG,GAAG,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE;YACtD,IAAI,KAAK,KAAK,QAAQ;gBAAE,OAAO,CAAC,QAAQ,EAAE,CAAA;QAC5C,CAAC,CAAC,CAAA;QACF,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,CAAA;IAC3B,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;IAEtB,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,GAAG,EAAE;YACV,OAAO,CAAC,QAAQ,EAAE,CAAA;YAClB,OAAO,CAAC,MAAM,EAAE,CAAA;QAClB,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAA;IAEb,OAAO,EAAE,aAAa,EAAE,CAAA;AAC1B,CAAC","sourcesContent":["import { useCallback, useEffect, useMemo } from 'react'\nimport { AppState } from 'react-native'\nimport { useConversationContext } from '../contexts/conversation_context'\nimport { makeHighestSeenTracker } from '../utils/highest_seen_tracker'\nimport { useConversationsMarkReadUpTo } from './use_conversations_actions'\nimport { useJumpToUnreadGates } from './use_jump_to_unread_gates'\n\nexport function useTrackHighestSeenMessage() {\n const { conversationId, currentPageReplyRootId } = useConversationContext()\n const { jumpToUnreadActive } = useJumpToUnreadGates()\n const enabled = jumpToUnreadActive && !currentPageReplyRootId\n const { mutate: markReadUpTo } = useConversationsMarkReadUpTo({ conversationId })\n\n const tracker = useMemo(\n () => makeHighestSeenTracker(conversationId, ({ sortKey }) => markReadUpTo({ sortKey })),\n [conversationId, markReadUpTo]\n )\n\n const onMessageSeen = useCallback(\n (sortKey: string) => {\n if (!enabled) return\n tracker.onSeen(sortKey)\n },\n [enabled, tracker]\n )\n\n useEffect(() => {\n if (!enabled) return\n const sub = AppState.addEventListener('change', state => {\n if (state !== 'active') tracker.flushNow()\n })\n return () => sub.remove()\n }, [enabled, tracker])\n\n useEffect(() => {\n return () => {\n tracker.flushNow()\n tracker.cancel()\n }\n }, [tracker])\n\n return { onMessageSeen }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/navigation/index.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,EAEL,2BAA2B,EAC5B,MAAM,gCAAgC,CAAA;AACvC,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AAChE,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,OAAO,EACL,uBAAuB,EAExB,MAAM,yDAAyD,CAAA;AAChE,OAAO,EACL,kBAAkB,EAGnB,MAAM,+CAA+C,CAAA;AACtD,OAAO,EAAE,eAAe,EAA0B,MAAM,8BAA8B,CAAA;AACtF,OAAO,EACL,yBAAyB,EAE1B,MAAM,sDAAsD,CAAA;AAC7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,wCAAwC,CAAA;AAWlF,OAAO,EACL,yCAAyC,EAE1C,MAAM,0DAA0D,CAAA;AACjE,OAAO,EAEL,kBAAkB,EAEnB,MAAM,gCAAgC,CAAA;AAKvC,OAAO,EACL,4BAA4B,EAE7B,MAAM,4CAA4C,CAAA;AACnD,OAAO,EACL,8BAA8B,EAE/B,MAAM,4DAA4D,CAAA;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,+CAA+C,CAAA;AAEnF,OAAO,EACL,kCAAkC,EAEnC,MAAM,mDAAmD,CAAA;AAC1D,OAAO,EAAE,+BAA+B,EAAE,MAAM,+CAA+C,CAAA;AAC/F,OAAO,EACL,oBAAoB,EAErB,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EAAE,mBAAmB,EAA8B,MAAM,kCAAkC,CAAA;AAClG,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAA;AACpF,OAAO,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAA;AACvF,OAAO,EAAE,eAAe,EAA0B,MAAM,6BAA6B,CAAA;AACrF,OAAO,EAAE,eAAe,EAA0B,MAAM,8BAA8B,CAAA;AACtF,OAAO,EACL,yBAAyB,EAE1B,MAAM,yCAAyC,CAAA;AAEhD,OAAO,EAAE,8BAA8B,EAAE,MAAM,gBAAgB,CAAA;AAO/D,eAAO,MAAM,oBAAoB;;;;;;;;;uOA5E5B,mBAAmB;;;;;;;;;;;;;uBA4XgkK,gBAAiB,KAAK;;;qCArSjlK,2BAA2B;;;;;;;;;uBAqSgiK,gBAAiB,KAAK;;;qCA3RjlK,2BAA2B;;;;;;;;uBA2RgiK,gBAAiB,KAAK;;;qCA9QjlK,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;uBA8QgiK,gBAAiB,KAAK;;;;qCA5PjlK,2BAA2B;;;;;;;;EAkBtD,CAAA;AAEF,eAAO,MAAM,SAAS;;;;;;;;;uOApJjB,mBAAmB;;;;;;;;;;;;uBA4XgkK,gBAAiB,KAAK;;;;qCA7NjlK,2BAA2B;;;;;;;;;;;;uBA6NgiK,gBAAiB,KAAK;;qCA7MjlK,2BAA2B;qCAgB3B,2BAA2B;;;;;;;;;uBA6LgiK,gBAAiB,KAAK;;;;;;;;;;;;;;;;;;;;uBAAtB,gBAAiB,KAAK;;;;qCAxIjlK,2BAA2B;;;;;;;;;;;;uBAwIgiK,gBAAiB,KAAK;;;;qCA1HjlK,2BAA2B;;;;;;;;;;;;;;uBA0HgiK,gBAAiB,KAAK;;;qCA3GjlK,2BAA2B;;;;;;;;;;;;;;;;;;;;;mPAjRnD,mBAAmB;;;;;;;;;;;;;mCA4XgkK,gBAAiB,KAAK;;;iDArSjlK,2BAA2B;;;;;;;;;mCAqSgiK,gBAAiB,KAAK;;;iDA3RjlK,2BAA2B;;;;;;;;mCA2RgiK,gBAAiB,KAAK;;;iDA9QjlK,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;mCA8QgiK,gBAAiB,KAAK;;;;iDA5PjlK,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBA4PgiK,gBAAiB,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAAtB,gBAAiB,KAAK;;;;;;;;;;;;;;;;;;EAT5mK,CAAA;AAEF,KAAK,kBAAkB,GAAG,eAAe,CAAC,OAAO,SAAS,CAAC,CAAA;AAE3D,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,eAAe,CAAC;QACxB,UAAU,aAAc,SAAQ,kBAAkB;SAAG;KACtD;CACF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/navigation/index.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,EAEL,2BAA2B,EAC5B,MAAM,gCAAgC,CAAA;AACvC,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AAChE,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,OAAO,EACL,uBAAuB,EAExB,MAAM,yDAAyD,CAAA;AAChE,OAAO,EACL,kBAAkB,EAGnB,MAAM,+CAA+C,CAAA;AACtD,OAAO,EAAE,eAAe,EAA0B,MAAM,8BAA8B,CAAA;AACtF,OAAO,EACL,yBAAyB,EAE1B,MAAM,sDAAsD,CAAA;AAC7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,wCAAwC,CAAA;AAWlF,OAAO,EACL,yCAAyC,EAE1C,MAAM,0DAA0D,CAAA;AACjE,OAAO,EAEL,kBAAkB,EAEnB,MAAM,gCAAgC,CAAA;AAKvC,OAAO,EACL,4BAA4B,EAE7B,MAAM,4CAA4C,CAAA;AACnD,OAAO,EACL,8BAA8B,EAE/B,MAAM,4DAA4D,CAAA;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,+CAA+C,CAAA;AAEnF,OAAO,EACL,kCAAkC,EAEnC,MAAM,mDAAmD,CAAA;AAC1D,OAAO,EAAE,+BAA+B,EAAE,MAAM,+CAA+C,CAAA;AAC/F,OAAO,EACL,oBAAoB,EAErB,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EAAE,mBAAmB,EAA8B,MAAM,kCAAkC,CAAA;AAClG,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAA;AACpF,OAAO,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAA;AACvF,OAAO,EAAE,eAAe,EAA0B,MAAM,6BAA6B,CAAA;AACrF,OAAO,EAAE,eAAe,EAA0B,MAAM,8BAA8B,CAAA;AACtF,OAAO,EACL,yBAAyB,EAE1B,MAAM,yCAAyC,CAAA;AAEhD,OAAO,EAAE,8BAA8B,EAAE,MAAM,gBAAgB,CAAA;AAO/D,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;qCAWJ,2BAA2B;;;;;;;;;;;;qCAU3B,2BAA2B;;;;;;;;;;;qCAa3B,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qCAkB3B,2BAA2B;;;;;;;;EAkBtD,CAAA;AAEF,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;qCAWO,2BAA2B;;;;;;;;;;;;;;qCAgB3B,2BAA2B;qCAgB3B,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qCAqD3B,2BAA2B;;;;;;;;;;;;;;;;qCAc3B,2BAA2B;;;;;;;;;;;;;;;;;qCAe3B,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iDA1L3B,2BAA2B;;;;;;;;;;;;iDAU3B,2BAA2B;;;;;;;;;;;iDAa3B,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iDAkB3B,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmPtD,CAAA;AAEF,KAAK,kBAAkB,GAAG,eAAe,CAAC,OAAO,SAAS,CAAC,CAAA;AAE3D,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,eAAe,CAAC;QACxB,UAAU,aAAc,SAAQ,kBAAkB;SAAG;KACtD;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"conversation_screen.d.ts","sourceRoot":"","sources":["../../src/screens/conversation_screen.tsx"],"names":[],"mappings":"AACA,OAAO,EAAe,gBAAgB,EAAqB,MAAM,4BAA4B,CAAA;AAC7F,OAAO,EAGL,iBAAiB,EAIlB,MAAM,0BAA0B,CAAA;AACjC,OAAO,KAAmD,MAAM,OAAO,CAAA;AA6BvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAA;AAMjF,MAAM,MAAM,sBAAsB,GAAG;IACnC,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,CAAC,sBAAsB,CAAC,CAAA;AAE/E,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,EAAE,uBAAuB,qBA0BpE;AAuMD,UAAU,4BAA6B,SAAQ,gBAAgB;IAC7D,eAAe,EAAE,MAAM,CAAA;IACvB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,eAAO,MAAM,uBAAuB,GAAI,8DAOrC,4BAA4B,sBAoC9B,CAAA"}
1
+ {"version":3,"file":"conversation_screen.d.ts","sourceRoot":"","sources":["../../src/screens/conversation_screen.tsx"],"names":[],"mappings":"AACA,OAAO,EAAe,gBAAgB,EAAqB,MAAM,4BAA4B,CAAA;AAC7F,OAAO,EAGL,iBAAiB,EAIlB,MAAM,0BAA0B,CAAA;AACjC,OAAO,KAA4D,MAAM,OAAO,CAAA;AAwChF,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAA;AAgBjF,MAAM,MAAM,sBAAsB,GAAG;IACnC,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,CAAC,sBAAsB,CAAC,CAAA;AAK/E,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,EAAE,uBAAuB,qBA2BpE;AAiRD,UAAU,4BAA6B,SAAQ,gBAAgB;IAC7D,eAAe,EAAE,MAAM,CAAA;IACvB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,eAAO,MAAM,uBAAuB,GAAI,8DAOrC,4BAA4B,sBAoC9B,CAAA"}