@planningcenter/chat-react-native 3.38.0-rc.10 → 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/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/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/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_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/screens/conversation_screen.d.ts +0 -1
- package/build/screens/conversation_screen.d.ts.map +1 -1
- package/build/screens/conversation_screen.js +48 -95
- package/build/screens/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/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 +3 -3
- package/src/components/conversation/jump_to_bottom_button.tsx +8 -57
- package/src/components/conversation/reply_shadow_message.tsx +1 -1
- package/src/contexts/conversation_context.tsx +2 -30
- 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_suspense_api.ts +1 -1
- package/src/screens/conversation_screen.tsx +76 -184
- package/src/utils/__tests__/group_messages.test.ts +0 -71
- package/src/utils/cache/messages_cache.ts +0 -5
- 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 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"unread_divider.js","sourceRoot":"","sources":["../../../src/components/conversation/unread_divider.tsx"],"names":[],"mappings":"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","sourcesContent":["import { StyleSheet, View } from 'react-native'\nimport Animated, { FadeIn, FadeOut } from 'react-native-reanimated'\nimport Svg, { Defs, Path, Pattern, Rect } from 'react-native-svg'\nimport { useConversationContext } from '../../contexts/conversation_context'\nimport { useTheme } from '../../hooks'\nimport { CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL } from '../../utils/styles'\nimport { Text } from '../display'\n\ninterface UnreadDividerProps {\n scrolledPast?: boolean\n}\n\nconst WAVE_WIDTH = 16\nconst WAVE_HEIGHT = 8\nconst FADE_DURATION = 750\n\nexport function UnreadDivider({ scrolledPast = false }: UnreadDividerProps) {\n const styles = useStyles()\n const { atEndOfMessageHistory } = useConversationContext()\n\n if (scrolledPast || atEndOfMessageHistory) return null\n\n return (\n <Animated.View\n entering={FadeIn.duration(FADE_DURATION)}\n exiting={FadeOut.duration(FADE_DURATION)}\n style={styles.container}\n accessibilityRole=\"header\"\n accessibilityLabel=\"Unread messages start here\"\n >\n <SquigglyLine />\n <Text variant=\"footnote\" style={styles.label}>\n New\n </Text>\n <SquigglyLine />\n </Animated.View>\n )\n}\n\nfunction SquigglyLine() {\n const { colors } = useTheme()\n return (\n <View style={squigglyStyle.container}>\n <Svg width=\"100%\" height={WAVE_HEIGHT}>\n <Defs>\n <Pattern\n id=\"wave\"\n x=\"0\"\n y=\"0\"\n width={WAVE_WIDTH}\n height={WAVE_HEIGHT}\n patternUnits=\"userSpaceOnUse\"\n >\n <Path\n d=\"M 0 4 Q 4 0 8 4 T 16 4\"\n stroke={colors.interaction}\n strokeWidth={1.5}\n fill=\"none\"\n />\n </Pattern>\n </Defs>\n <Rect x=\"0\" y=\"0\" width=\"100%\" height={WAVE_HEIGHT} fill=\"url(#wave)\" />\n </Svg>\n </View>\n )\n}\n\nconst squigglyStyle = StyleSheet.create({\n container: {\n flex: 1,\n height: WAVE_HEIGHT,\n },\n})\n\nconst useStyles = () => {\n const { colors } = useTheme()\n return StyleSheet.create({\n container: {\n alignItems: 'center',\n flexDirection: 'row',\n paddingHorizontal: CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL,\n paddingVertical: 8,\n gap: 8,\n },\n label: {\n color: colors.interaction,\n fontWeight: '600',\n },\n })\n}\n"]}
|
|
@@ -1,20 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1,30 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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"]}
|
|
@@ -1,9 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1,62 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use_jump_to_bottom_action.js","sourceRoot":"","sources":["../../src/hooks/use_jump_to_bottom_action.ts"],"names":[],"mappings":"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","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"]}
|
|
@@ -1,20 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1,53 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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"]}
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { useConversationContext } from '../contexts/conversation_context';
|
|
2
|
-
import { availableFeatures, useFeatures } from './use_features';
|
|
3
|
-
export function useJumpToUnreadGates() {
|
|
4
|
-
const { featureEnabled } = useFeatures();
|
|
5
|
-
const { initialMessageIdIsAnchor } = useConversationContext();
|
|
6
|
-
const jumpToUnreadEnabled = featureEnabled(availableFeatures.jump_to_unread);
|
|
7
|
-
const jumpToUnreadActive = jumpToUnreadEnabled && initialMessageIdIsAnchor;
|
|
8
|
-
return { jumpToUnreadEnabled, jumpToUnreadActive };
|
|
9
|
-
}
|
|
10
|
-
//# sourceMappingURL=use_jump_to_unread_gates.js.map
|
|
@@ -1 +0,0 @@
|
|
|
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,iBAAiB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE/D,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,iBAAiB,CAAC,cAAc,CAAC,CAAA;IAC5E,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 { availableFeatures, useFeatures } from './use_features'\n\nexport function useJumpToUnreadGates() {\n const { featureEnabled } = useFeatures()\n const { initialMessageIdIsAnchor } = useConversationContext()\n const jumpToUnreadEnabled = featureEnabled(availableFeatures.jump_to_unread)\n const jumpToUnreadActive = jumpToUnreadEnabled && initialMessageIdIsAnchor\n return { jumpToUnreadEnabled, jumpToUnreadActive }\n}\n"]}
|
|
@@ -1,13 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1,45 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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"]}
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1,35 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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,10 +0,0 @@
|
|
|
1
|
-
import { ApiCollection, MessageResource } from '../types';
|
|
2
|
-
import { RequestData } from './client';
|
|
3
|
-
export type MessagesPageParam = Partial<RequestData> & {
|
|
4
|
-
order?: 'asc' | 'desc';
|
|
5
|
-
};
|
|
6
|
-
export declare const anchoredSeedPageParams: (anchor: string) => MessagesPageParam[];
|
|
7
|
-
export declare const olderPageParam: (page: ApiCollection<MessageResource>) => MessagesPageParam | undefined;
|
|
8
|
-
export declare const newerPageParam: (page: ApiCollection<MessageResource>) => MessagesPageParam | undefined;
|
|
9
|
-
export declare const sortAndFilterMessages: (pages: ApiCollection<MessageResource>[]) => MessageResource[];
|
|
10
|
-
//# sourceMappingURL=conversation_messages.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"conversation_messages.d.ts","sourceRoot":"","sources":["../../src/utils/conversation_messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAEtC,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG;IACrD,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;CACvB,CAAA;AAED,eAAO,MAAM,sBAAsB,GAAI,QAAQ,MAAM,KAAG,iBAAiB,EAGxE,CAAA;AAED,eAAO,MAAM,cAAc,GACzB,MAAM,aAAa,CAAC,eAAe,CAAC,KACnC,iBAAiB,GAAG,SAItB,CAAA;AAED,eAAO,MAAM,cAAc,GACzB,MAAM,aAAa,CAAC,eAAe,CAAC,KACnC,iBAAiB,GAAG,SAItB,CAAA;AAED,eAAO,MAAM,qBAAqB,GAAI,OAAO,aAAa,CAAC,eAAe,CAAC,EAAE,KAAG,eAAe,EAQjD,CAAA"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export const anchoredSeedPageParams = (anchor) => [
|
|
2
|
-
{ where: { id_gte: anchor }, order: 'asc' },
|
|
3
|
-
{ where: { id_lt: anchor }, order: 'desc' },
|
|
4
|
-
];
|
|
5
|
-
export const olderPageParam = (page) => {
|
|
6
|
-
const idLt = page.meta?.next?.idLt;
|
|
7
|
-
if (!idLt)
|
|
8
|
-
return undefined;
|
|
9
|
-
return { where: { id_lt: idLt }, order: 'desc' };
|
|
10
|
-
};
|
|
11
|
-
export const newerPageParam = (page) => {
|
|
12
|
-
const idGt = page.meta?.next?.idGt;
|
|
13
|
-
if (!idGt)
|
|
14
|
-
return undefined;
|
|
15
|
-
return { where: { id_gt: idGt }, order: 'asc' };
|
|
16
|
-
};
|
|
17
|
-
export const sortAndFilterMessages = (pages) => pages
|
|
18
|
-
.flatMap(page => page.data)
|
|
19
|
-
.filter(message => (!message.deletedAt || message.replyRootId) &&
|
|
20
|
-
(message.attachments?.length || message.text?.length))
|
|
21
|
-
.sort((a, b) => -a.id.localeCompare(b.id));
|
|
22
|
-
//# sourceMappingURL=conversation_messages.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"conversation_messages.js","sourceRoot":"","sources":["../../src/utils/conversation_messages.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,MAAc,EAAuB,EAAE,CAAC;IAC7E,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE;IAC3C,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;CAC5C,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,IAAoC,EACL,EAAE;IACjC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAA;IAClC,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAA;IAC3B,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAA;AAClD,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,IAAoC,EACL,EAAE;IACjC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAA;IAClC,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAA;IAC3B,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;AACjD,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,KAAuC,EAAqB,EAAE,CAClG,KAAK;KACF,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;KAC1B,MAAM,CACL,OAAO,CAAC,EAAE,CACR,CAAC,CAAC,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,WAAW,CAAC;IAC3C,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,IAAI,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CACxD;KACA,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA","sourcesContent":["import { ApiCollection, MessageResource } from '../types'\nimport { RequestData } from './client'\n\nexport type MessagesPageParam = Partial<RequestData> & {\n order?: 'asc' | 'desc'\n}\n\nexport const anchoredSeedPageParams = (anchor: string): MessagesPageParam[] => [\n { where: { id_gte: anchor }, order: 'asc' },\n { where: { id_lt: anchor }, order: 'desc' },\n]\n\nexport const olderPageParam = (\n page: ApiCollection<MessageResource>\n): MessagesPageParam | undefined => {\n const idLt = page.meta?.next?.idLt\n if (!idLt) return undefined\n return { where: { id_lt: idLt }, order: 'desc' }\n}\n\nexport const newerPageParam = (\n page: ApiCollection<MessageResource>\n): MessagesPageParam | undefined => {\n const idGt = page.meta?.next?.idGt\n if (!idGt) return undefined\n return { where: { id_gt: idGt }, order: 'asc' }\n}\n\nexport const sortAndFilterMessages = (pages: ApiCollection<MessageResource>[]): MessageResource[] =>\n pages\n .flatMap(page => page.data)\n .filter(\n message =>\n (!message.deletedAt || message.replyRootId) &&\n (message.attachments?.length || message.text?.length)\n )\n .sort((a, b) => -a.id.localeCompare(b.id))\n"]}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export declare const FLUSH_DELAY_MS = 2000;
|
|
2
|
-
type SendFn = (args: {
|
|
3
|
-
conversationId: number;
|
|
4
|
-
sortKey: string;
|
|
5
|
-
}) => void;
|
|
6
|
-
export declare function makeHighestSeenTracker(conversationId: number, send: SendFn, flushDelayMs?: number): {
|
|
7
|
-
onSeen(sortKey: string): void;
|
|
8
|
-
flushNow(): void;
|
|
9
|
-
cancel(): void;
|
|
10
|
-
};
|
|
11
|
-
export {};
|
|
12
|
-
//# sourceMappingURL=highest_seen_tracker.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"highest_seen_tracker.d.ts","sourceRoot":"","sources":["../../src/utils/highest_seen_tracker.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,OAAO,CAAA;AAElC,KAAK,MAAM,GAAG,CAAC,IAAI,EAAE;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,CAAA;AAEzE,wBAAgB,sBAAsB,CACpC,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,MAAM,EACZ,YAAY,GAAE,MAAuB;oBAcnB,MAAM;;;EAoBzB"}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
export const FLUSH_DELAY_MS = 2000;
|
|
2
|
-
export function makeHighestSeenTracker(conversationId, send, flushDelayMs = FLUSH_DELAY_MS) {
|
|
3
|
-
let highest = null;
|
|
4
|
-
let lastSent = null;
|
|
5
|
-
let timer = null;
|
|
6
|
-
const fire = () => {
|
|
7
|
-
timer = null;
|
|
8
|
-
if (!highest || highest === lastSent)
|
|
9
|
-
return;
|
|
10
|
-
lastSent = highest;
|
|
11
|
-
send({ conversationId, sortKey: highest });
|
|
12
|
-
};
|
|
13
|
-
return {
|
|
14
|
-
onSeen(sortKey) {
|
|
15
|
-
if (highest && sortKey.localeCompare(highest) <= 0)
|
|
16
|
-
return;
|
|
17
|
-
highest = sortKey;
|
|
18
|
-
if (timer)
|
|
19
|
-
clearTimeout(timer);
|
|
20
|
-
timer = setTimeout(fire, flushDelayMs);
|
|
21
|
-
},
|
|
22
|
-
flushNow() {
|
|
23
|
-
if (timer) {
|
|
24
|
-
clearTimeout(timer);
|
|
25
|
-
timer = null;
|
|
26
|
-
}
|
|
27
|
-
fire();
|
|
28
|
-
},
|
|
29
|
-
cancel() {
|
|
30
|
-
if (timer) {
|
|
31
|
-
clearTimeout(timer);
|
|
32
|
-
timer = null;
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
//# sourceMappingURL=highest_seen_tracker.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"highest_seen_tracker.js","sourceRoot":"","sources":["../../src/utils/highest_seen_tracker.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAA;AAIlC,MAAM,UAAU,sBAAsB,CACpC,cAAsB,EACtB,IAAY,EACZ,eAAuB,cAAc;IAErC,IAAI,OAAO,GAAkB,IAAI,CAAA;IACjC,IAAI,QAAQ,GAAkB,IAAI,CAAA;IAClC,IAAI,KAAK,GAAyC,IAAI,CAAA;IAEtD,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,KAAK,GAAG,IAAI,CAAA;QACZ,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,QAAQ;YAAE,OAAM;QAC5C,QAAQ,GAAG,OAAO,CAAA;QAClB,IAAI,CAAC,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAA;IAC5C,CAAC,CAAA;IAED,OAAO;QACL,MAAM,CAAC,OAAe;YACpB,IAAI,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC;gBAAE,OAAM;YAC1D,OAAO,GAAG,OAAO,CAAA;YACjB,IAAI,KAAK;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAA;YAC9B,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,YAAY,CAAC,CAAA;QACxC,CAAC;QACD,QAAQ;YACN,IAAI,KAAK,EAAE,CAAC;gBACV,YAAY,CAAC,KAAK,CAAC,CAAA;gBACnB,KAAK,GAAG,IAAI,CAAA;YACd,CAAC;YACD,IAAI,EAAE,CAAA;QACR,CAAC;QACD,MAAM;YACJ,IAAI,KAAK,EAAE,CAAC;gBACV,YAAY,CAAC,KAAK,CAAC,CAAA;gBACnB,KAAK,GAAG,IAAI,CAAA;YACd,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC","sourcesContent":["export const FLUSH_DELAY_MS = 2000\n\ntype SendFn = (args: { conversationId: number; sortKey: string }) => void\n\nexport function makeHighestSeenTracker(\n conversationId: number,\n send: SendFn,\n flushDelayMs: number = FLUSH_DELAY_MS\n) {\n let highest: string | null = null\n let lastSent: string | null = null\n let timer: ReturnType<typeof setTimeout> | null = null\n\n const fire = () => {\n timer = null\n if (!highest || highest === lastSent) return\n lastSent = highest\n send({ conversationId, sortKey: highest })\n }\n\n return {\n onSeen(sortKey: string) {\n if (highest && sortKey.localeCompare(highest) <= 0) return\n highest = sortKey\n if (timer) clearTimeout(timer)\n timer = setTimeout(fire, flushDelayMs)\n },\n flushNow() {\n if (timer) {\n clearTimeout(timer)\n timer = null\n }\n fire()\n },\n cancel() {\n if (timer) {\n clearTimeout(timer)\n timer = null\n }\n },\n }\n}\n"]}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export interface ViewableEntry<Item> {
|
|
2
|
-
key: string;
|
|
3
|
-
isViewable: boolean;
|
|
4
|
-
item: Item;
|
|
5
|
-
}
|
|
6
|
-
export interface ViewabilityEvent<Item> {
|
|
7
|
-
viewableItems: ViewableEntry<Item>[];
|
|
8
|
-
changed: ViewableEntry<Item>[];
|
|
9
|
-
userHasScrolled: boolean;
|
|
10
|
-
}
|
|
11
|
-
export type ViewabilityObserver<Item> = (event: ViewabilityEvent<Item>) => void;
|
|
12
|
-
export declare function reportViewableMessages<Item extends {
|
|
13
|
-
id?: string;
|
|
14
|
-
type?: string;
|
|
15
|
-
}>(onMessageSeen: (id: string) => void): ViewabilityObserver<Item>;
|
|
16
|
-
export declare function detectDividerExitTowardNewer<Item extends {
|
|
17
|
-
id?: string;
|
|
18
|
-
type?: string;
|
|
19
|
-
}>({ dividerKey, initialMessageId, onExited, }: {
|
|
20
|
-
dividerKey: string;
|
|
21
|
-
initialMessageId: string | null;
|
|
22
|
-
onExited: () => void;
|
|
23
|
-
}): ViewabilityObserver<Item>;
|
|
24
|
-
//# sourceMappingURL=message_viewability.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"message_viewability.d.ts","sourceRoot":"","sources":["../../src/utils/message_viewability.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa,CAAC,IAAI;IACjC,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,OAAO,CAAA;IACnB,IAAI,EAAE,IAAI,CAAA;CACX;AAED,MAAM,WAAW,gBAAgB,CAAC,IAAI;IACpC,aAAa,EAAE,aAAa,CAAC,IAAI,CAAC,EAAE,CAAA;IACpC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,EAAE,CAAA;IAC9B,eAAe,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,MAAM,mBAAmB,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,gBAAgB,CAAC,IAAI,CAAC,KAAK,IAAI,CAAA;AAE/E,wBAAgB,sBAAsB,CAAC,IAAI,SAAS;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EAChF,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,GAClC,mBAAmB,CAAC,IAAI,CAAC,CAS3B;AAED,wBAAgB,4BAA4B,CAAC,IAAI,SAAS;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,EACxF,UAAU,EACV,gBAAgB,EAChB,QAAQ,GACT,EAAE;IACD,UAAU,EAAE,MAAM,CAAA;IAClB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,QAAQ,EAAE,MAAM,IAAI,CAAA;CACrB,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAW5B"}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { dividerExitedTowardNewer } from './unread_divider_helpers';
|
|
2
|
-
export function reportViewableMessages(onMessageSeen) {
|
|
3
|
-
return ({ viewableItems, userHasScrolled }) => {
|
|
4
|
-
if (!userHasScrolled)
|
|
5
|
-
return;
|
|
6
|
-
for (const entry of viewableItems) {
|
|
7
|
-
if (entry.item?.type !== 'Message')
|
|
8
|
-
continue;
|
|
9
|
-
const id = entry.item?.id;
|
|
10
|
-
if (typeof id === 'string')
|
|
11
|
-
onMessageSeen(id);
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
export function detectDividerExitTowardNewer({ dividerKey, initialMessageId, onExited, }) {
|
|
16
|
-
return ({ viewableItems, changed, userHasScrolled }) => {
|
|
17
|
-
if (!userHasScrolled || !initialMessageId)
|
|
18
|
-
return;
|
|
19
|
-
const exited = dividerExitedTowardNewer({
|
|
20
|
-
changed,
|
|
21
|
-
viewableItems,
|
|
22
|
-
dividerKey,
|
|
23
|
-
initialMessageId,
|
|
24
|
-
});
|
|
25
|
-
if (exited)
|
|
26
|
-
onExited();
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
//# sourceMappingURL=message_viewability.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"message_viewability.js","sourceRoot":"","sources":["../../src/utils/message_viewability.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAA;AAgBnE,MAAM,UAAU,sBAAsB,CACpC,aAAmC;IAEnC,OAAO,CAAC,EAAE,aAAa,EAAE,eAAe,EAAE,EAAE,EAAE;QAC5C,IAAI,CAAC,eAAe;YAAE,OAAM;QAC5B,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;YAClC,IAAI,KAAK,CAAC,IAAI,EAAE,IAAI,KAAK,SAAS;gBAAE,SAAQ;YAC5C,MAAM,EAAE,GAAG,KAAK,CAAC,IAAI,EAAE,EAAE,CAAA;YACzB,IAAI,OAAO,EAAE,KAAK,QAAQ;gBAAE,aAAa,CAAC,EAAE,CAAC,CAAA;QAC/C,CAAC;IACH,CAAC,CAAA;AACH,CAAC;AAED,MAAM,UAAU,4BAA4B,CAA8C,EACxF,UAAU,EACV,gBAAgB,EAChB,QAAQ,GAKT;IACC,OAAO,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE;QACrD,IAAI,CAAC,eAAe,IAAI,CAAC,gBAAgB;YAAE,OAAM;QACjD,MAAM,MAAM,GAAG,wBAAwB,CAAC;YACtC,OAAO;YACP,aAAa;YACb,UAAU;YACV,gBAAgB;SACjB,CAAC,CAAA;QACF,IAAI,MAAM;YAAE,QAAQ,EAAE,CAAA;IACxB,CAAC,CAAA;AACH,CAAC","sourcesContent":["import { dividerExitedTowardNewer } from './unread_divider_helpers'\n\nexport interface ViewableEntry<Item> {\n key: string\n isViewable: boolean\n item: Item\n}\n\nexport interface ViewabilityEvent<Item> {\n viewableItems: ViewableEntry<Item>[]\n changed: ViewableEntry<Item>[]\n userHasScrolled: boolean\n}\n\nexport type ViewabilityObserver<Item> = (event: ViewabilityEvent<Item>) => void\n\nexport function reportViewableMessages<Item extends { id?: string; type?: string }>(\n onMessageSeen: (id: string) => void\n): ViewabilityObserver<Item> {\n return ({ viewableItems, userHasScrolled }) => {\n if (!userHasScrolled) return\n for (const entry of viewableItems) {\n if (entry.item?.type !== 'Message') continue\n const id = entry.item?.id\n if (typeof id === 'string') onMessageSeen(id)\n }\n }\n}\n\nexport function detectDividerExitTowardNewer<Item extends { id?: string; type?: string }>({\n dividerKey,\n initialMessageId,\n onExited,\n}: {\n dividerKey: string\n initialMessageId: string | null\n onExited: () => void\n}): ViewabilityObserver<Item> {\n return ({ viewableItems, changed, userHasScrolled }) => {\n if (!userHasScrolled || !initialMessageId) return\n const exited = dividerExitedTowardNewer({\n changed,\n viewableItems,\n dividerKey,\n initialMessageId,\n })\n if (exited) onExited()\n }\n}\n"]}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
type ViewableChangeEntry = {
|
|
2
|
-
key: string;
|
|
3
|
-
isViewable: boolean;
|
|
4
|
-
};
|
|
5
|
-
type ViewableItem = {
|
|
6
|
-
item: {
|
|
7
|
-
id?: string;
|
|
8
|
-
type?: string;
|
|
9
|
-
};
|
|
10
|
-
};
|
|
11
|
-
export declare function dividerExitedTowardNewer({ changed, viewableItems, dividerKey, initialMessageId, }: {
|
|
12
|
-
changed: ViewableChangeEntry[];
|
|
13
|
-
viewableItems: ViewableItem[];
|
|
14
|
-
dividerKey: string;
|
|
15
|
-
initialMessageId: string;
|
|
16
|
-
}): boolean;
|
|
17
|
-
export {};
|
|
18
|
-
//# sourceMappingURL=unread_divider_helpers.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"unread_divider_helpers.d.ts","sourceRoot":"","sources":["../../src/utils/unread_divider_helpers.ts"],"names":[],"mappings":"AAAA,KAAK,mBAAmB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CAAA;AAC/D,KAAK,YAAY,GAAG;IAAE,IAAI,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAA;AAE5D,wBAAgB,wBAAwB,CAAC,EACvC,OAAO,EACP,aAAa,EACb,UAAU,EACV,gBAAgB,GACjB,EAAE;IACD,OAAO,EAAE,mBAAmB,EAAE,CAAA;IAC9B,aAAa,EAAE,YAAY,EAAE,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,gBAAgB,EAAE,MAAM,CAAA;CACzB,GAAG,OAAO,CAWV"}
|