@droppii-org/chat-mobile 0.2.88 → 0.2.90
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/lib/module/components/ThreadCard/ThreadCard.js +0 -1
- package/lib/module/components/ThreadCard/ThreadCard.js.map +1 -1
- package/lib/module/components/messages/LinkifiedText.js +34 -0
- package/lib/module/components/messages/LinkifiedText.js.map +1 -0
- package/lib/module/components/messages/quotedMessage/index.js +14 -2
- package/lib/module/components/messages/quotedMessage/index.js.map +1 -1
- package/lib/module/components/messages/textMessage/index.js +15 -22
- package/lib/module/components/messages/textMessage/index.js.map +1 -1
- package/lib/module/core/useChatListener.js +2 -2
- package/lib/module/core/useChatListener.js.map +1 -1
- package/lib/module/hooks/message/useMessages.js +6 -0
- package/lib/module/hooks/message/useMessages.js.map +1 -1
- package/lib/module/hooks/message/useSendMessage.js +10 -3
- package/lib/module/hooks/message/useSendMessage.js.map +1 -1
- package/lib/module/screens/ResourceCenter/ResourceCenterTabScene.js.map +1 -1
- package/lib/module/screens/chat-detail/ChatDetail.js +2 -1
- package/lib/module/screens/chat-detail/ChatDetail.js.map +1 -1
- package/lib/module/screens/chat-detail/ChatListLegend.js +235 -123
- package/lib/module/screens/chat-detail/ChatListLegend.js.map +1 -1
- package/lib/module/screens/chat-detail/PinnedMessagesSheet.js +4 -1
- package/lib/module/screens/chat-detail/PinnedMessagesSheet.js.map +1 -1
- package/lib/module/screens/chat-detail/PinnedMessagesSheetBackup.js +3 -1
- package/lib/module/screens/chat-detail/PinnedMessagesSheetBackup.js.map +1 -1
- package/lib/module/screens/chat-detail/legend/LegendChatMessage.js +11 -9
- package/lib/module/screens/chat-detail/legend/LegendChatMessage.js.map +1 -1
- package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxOverlay.js +37 -4
- package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxOverlay.js.map +1 -1
- package/lib/module/services/resourceCenter.js +45 -22
- package/lib/module/services/resourceCenter.js.map +1 -1
- package/lib/module/store/message.js +8 -1
- package/lib/module/store/message.js.map +1 -1
- package/lib/typescript/src/components/ThreadCard/ThreadCard.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/LinkifiedText.d.ts +11 -0
- package/lib/typescript/src/components/messages/LinkifiedText.d.ts.map +1 -0
- package/lib/typescript/src/components/messages/quotedMessage/index.d.ts +1 -0
- package/lib/typescript/src/components/messages/quotedMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/components/messages/textMessage/index.d.ts.map +1 -1
- package/lib/typescript/src/hooks/message/useMessages.d.ts.map +1 -1
- package/lib/typescript/src/hooks/message/useSendMessage.d.ts.map +1 -1
- package/lib/typescript/src/screens/ResourceCenter/ResourceCenterTabScene.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/ChatDetail.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/ChatListLegend.d.ts +1 -1
- package/lib/typescript/src/screens/chat-detail/ChatListLegend.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/PinnedMessagesSheet.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/PinnedMessagesSheetBackup.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts +5 -3
- package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/messageToolbox/MessageToolboxOverlay.d.ts +2 -0
- package/lib/typescript/src/screens/chat-detail/messageToolbox/MessageToolboxOverlay.d.ts.map +1 -1
- package/lib/typescript/src/services/resourceCenter.d.ts.map +1 -1
- package/lib/typescript/src/store/message.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/components/ThreadCard/ThreadCard.tsx +0 -2
- package/src/components/messages/LinkifiedText.tsx +37 -0
- package/src/components/messages/quotedMessage/index.tsx +18 -2
- package/src/components/messages/textMessage/index.tsx +18 -27
- package/src/core/useChatListener.ts +2 -2
- package/src/hooks/message/useMessages.ts +6 -0
- package/src/hooks/message/useSendMessage.ts +7 -0
- package/src/screens/ResourceCenter/ResourceCenterTabScene.tsx +0 -1
- package/src/screens/chat-detail/ChatDetail.tsx +1 -0
- package/src/screens/chat-detail/ChatListLegend.tsx +236 -136
- package/src/screens/chat-detail/PinnedMessagesSheet.tsx +6 -1
- package/src/screens/chat-detail/PinnedMessagesSheetBackup.tsx +3 -1
- package/src/screens/chat-detail/legend/LegendChatMessage.tsx +16 -11
- package/src/screens/chat-detail/messageToolbox/MessageToolboxOverlay.tsx +47 -2
- package/src/services/resourceCenter.ts +77 -36
- package/src/store/message.ts +7 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["memo","useCallback","useEffect","useRef","DeviceEventEmitter","useKeyboardScrollToEnd","useSafeAreaInsets","KContainer","useNavigation","usePinMessage","PinnedMessageBar","openPinnedMessagesSheet","MediaViewerModal","useConversation","useConversationStore","useUserStore","ChatDetailHeader","ChatListLegend","ChatComposer","shouldShowAddMember","normalizeUrl","MessageToolboxOverlay","useGetConversationDetail","useGetConversationTarget","GroupJoinSource","useMessages","ChatEvent","useSetIsShowFLashMessage","useJoinGroup","useGroupAccessGuard","jsx","_jsx","jsxs","_jsxs","ChatDetail","targetConversationId","targetUserId","targetGroupId","targetBotId","targetMessageId","showAddMember","onBack","onPressSearch","onPressAddMember","onPressMenu","onPressUrl","customMessageItemFactory","pannelActions","groupJoinSource","navigation","mediaViewerRef","messageToolboxRef","currentUser","s","user","conversationId","isLoading","isLoadingConversation","conversation","data","target","isComposeDisabled","isActive","handleBackDefault","goBack","handleMediaPress","items","index","current","show","messages","initLoading","moreOldLoading","moreNewLoading","getMoreOldMessages","getMoreNewMessages","hasMoreOld","hasMoreNew","startClientMsgId","peerType","mutate","joinGroup","isPending","isJoiningGroup","setShowFLashMessage","pinnedMessages","pinMessage","unpinMessage","getState","setCurrentConversation","undefined","handleAccessBlocked","isCheckingAccess","groupID","onBlocked","resolvedShowAddMember","insets","listRef","freeze","scrollMessageToEnd","handlePressUrl","url","handleMessageLongPress","message","rect","handlePressPinnedMessageBar","currentUserId","userID","onPressMessage","emit","ScrollToMessage","clientMessageId","clientMsgID","handlePressMenu","handlePressJoinGroup","reqMsg","joinSource","Search","groupName","showName","Page","flex","edges","children","onPressAvatar","onPress","onLoadMoreOld","onLoadMoreNew","onMediaPress","onLongPress","keyboardOffset","bottom","isEmptyMessage","length","onPressJoinGroup","ref","onPinMessage","onUnpinMessage","displayName"],"sourceRoot":"../../../../src","sources":["screens/chat-detail/ChatDetail.tsx"],"mappings":"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
|
|
1
|
+
{"version":3,"names":["memo","useCallback","useEffect","useRef","DeviceEventEmitter","useKeyboardScrollToEnd","useSafeAreaInsets","KContainer","useNavigation","usePinMessage","PinnedMessageBar","openPinnedMessagesSheet","MediaViewerModal","useConversation","useConversationStore","useUserStore","ChatDetailHeader","ChatListLegend","ChatComposer","shouldShowAddMember","normalizeUrl","MessageToolboxOverlay","useGetConversationDetail","useGetConversationTarget","GroupJoinSource","useMessages","ChatEvent","useSetIsShowFLashMessage","useJoinGroup","useGroupAccessGuard","jsx","_jsx","jsxs","_jsxs","ChatDetail","targetConversationId","targetUserId","targetGroupId","targetBotId","targetMessageId","showAddMember","onBack","onPressSearch","onPressAddMember","onPressMenu","onPressUrl","customMessageItemFactory","pannelActions","groupJoinSource","navigation","mediaViewerRef","messageToolboxRef","currentUser","s","user","conversationId","isLoading","isLoadingConversation","conversation","data","target","isComposeDisabled","isActive","handleBackDefault","goBack","handleMediaPress","items","index","current","show","messages","initLoading","moreOldLoading","moreNewLoading","getMoreOldMessages","getMoreNewMessages","hasMoreOld","hasMoreNew","startClientMsgId","peerType","mutate","joinGroup","isPending","isJoiningGroup","setShowFLashMessage","pinnedMessages","pinMessage","unpinMessage","getState","setCurrentConversation","undefined","handleAccessBlocked","isCheckingAccess","groupID","onBlocked","resolvedShowAddMember","insets","listRef","freeze","scrollMessageToEnd","handlePressUrl","url","handleMessageLongPress","message","rect","handlePressPinnedMessageBar","currentUserId","userID","onPressMessage","emit","ScrollToMessage","clientMessageId","clientMsgID","handlePressMenu","handlePressJoinGroup","reqMsg","joinSource","Search","groupName","showName","Page","flex","edges","children","onPressAvatar","onPress","onLoadMoreOld","onLoadMoreNew","onMediaPress","onLongPress","keyboardOffset","bottom","isEmptyMessage","length","onPressJoinGroup","ref","onPinMessage","onUnpinMessage","displayName"],"sourceRoot":"../../../../src","sources":["screens/chat-detail/ChatDetail.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -4,7 +4,7 @@ import { memo, useCallback, useMemo, useEffect, useRef, useState } from 'react';
|
|
|
4
4
|
import { ActivityIndicator, DeviceEventEmitter, Platform, StyleSheet, useWindowDimensions } from 'react-native';
|
|
5
5
|
import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing } from 'react-native-reanimated';
|
|
6
6
|
import { KeyboardAwareLegendList } from '@legendapp/list/keyboard';
|
|
7
|
-
import {
|
|
7
|
+
import { KeyboardEvents } from 'react-native-keyboard-controller';
|
|
8
8
|
import { KContainer, KColors, KSpacingValue, KLabel, KRadiusValue, KImage } from '@droppii/libs';
|
|
9
9
|
import { precomputeLegendListData } from "../../utils/legendListMessage.js";
|
|
10
10
|
import { getMessageRenderId } from "../../utils/message.js";
|
|
@@ -35,11 +35,16 @@ import ChatImageDimens, { CHAT_IMAGE_VIEW_SOURCE } from "../../utils/chatImageDi
|
|
|
35
35
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
36
36
|
const ROW_MARGIN_CLUSTER_END = KSpacingValue['0.5rem'];
|
|
37
37
|
const ROW_MARGIN_IN_CLUSTER = KSpacingValue['0.25rem'];
|
|
38
|
-
const
|
|
38
|
+
const BUTTON_FADE_CONFIG = {
|
|
39
|
+
duration: 200,
|
|
40
|
+
easing: Easing.out(Easing.ease)
|
|
41
|
+
};
|
|
39
42
|
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
+
// Long enough to swallow Android's willShow→willHide→willShow flapping
|
|
44
|
+
// (~1.3s period, measured), short enough that a real keyboard close still
|
|
45
|
+
// settles within one animation.
|
|
46
|
+
const KEYBOARD_HIDE_DEBOUNCE_MS = 300;
|
|
47
|
+
const getRowMarginBottom = position => position === 'last' || position === 'solo' ? ROW_MARGIN_CLUSTER_END : ROW_MARGIN_IN_CLUSTER;
|
|
43
48
|
export const ChatListLegend = /*#__PURE__*/memo(({
|
|
44
49
|
messages = [],
|
|
45
50
|
conversationId,
|
|
@@ -48,7 +53,6 @@ export const ChatListLegend = /*#__PURE__*/memo(({
|
|
|
48
53
|
moreOldLoading,
|
|
49
54
|
hasMoreOld,
|
|
50
55
|
onLoadMoreNew,
|
|
51
|
-
moreNewLoading,
|
|
52
56
|
hasMoreNew,
|
|
53
57
|
onMediaPress,
|
|
54
58
|
onPressUrl,
|
|
@@ -91,11 +95,37 @@ export const ChatListLegend = /*#__PURE__*/memo(({
|
|
|
91
95
|
const buttonOpacity = useSharedValue(0);
|
|
92
96
|
const isAtBottomRef = useRef(true);
|
|
93
97
|
const scrollDebounceRef = useRef(undefined);
|
|
98
|
+
// Current keyboard height, and the trigger for the re-anchor effect
|
|
99
|
+
// below — see the keyboard listener for how each platform uses it.
|
|
100
|
+
const [keyboardInset, setKeyboardInset] = useState(0);
|
|
101
|
+
const hasSeenFirstKeyboardInsetRef = useRef(false);
|
|
94
102
|
const rowRefsMap = useRef(new Map());
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
//
|
|
98
|
-
|
|
103
|
+
// Set on a real touch-drag (`onScrollBeginDrag`), before onStartReached/
|
|
104
|
+
// onEndReached's threshold could fire. `onMomentumScrollBegin` was tried
|
|
105
|
+
// and reverted: it only fires after the finger lifts, so the first
|
|
106
|
+
// gesture's mid-drag threshold-crossing beats it, needing a wasted
|
|
107
|
+
// second gesture to actually unlock. See
|
|
108
|
+
// project_chatlistlegend_scroll_debugging for the full history.
|
|
109
|
+
const hasUserScrolledRef = useRef(false);
|
|
110
|
+
// Old Architecture defers recomputing `alignItemsAtEndPadding` when
|
|
111
|
+
// content shrinks while `initialScrollAtEnd` is active. `estimatedItemSize`
|
|
112
|
+
// below is a deliberate lower bound to mostly avoid that; this ref
|
|
113
|
+
// backstops the rest via one forced `scrollToEnd` on mount (`handleListLoad`).
|
|
114
|
+
const hasCorrectedInitialPaddingRef = useRef(false);
|
|
115
|
+
// `messages` starts empty, so `lastMessageId`'s first real value looks
|
|
116
|
+
// identical to a new message — tracking the previous id (not a one-shot
|
|
117
|
+
// flag) lets the effect below tell the two apart.
|
|
118
|
+
const previousLastMessageIdRef = useRef(null);
|
|
119
|
+
// Read via ref (not as a dependency) by the `lastMessageId` effect below —
|
|
120
|
+
// a loading-state flip alone shouldn't re-run it.
|
|
121
|
+
const moreOldLoadingRef = useRef(moreOldLoading);
|
|
122
|
+
moreOldLoadingRef.current = moreOldLoading;
|
|
123
|
+
// Read via ref (not as a dependency) by the ScrollToMessage subscription
|
|
124
|
+
// below — the whole array changes on every new message and every old-
|
|
125
|
+
// history page, which would otherwise tear down and re-add both
|
|
126
|
+
// DeviceEventEmitter listeners on every one of those.
|
|
127
|
+
const messagesRef = useRef(messages);
|
|
128
|
+
messagesRef.current = messages;
|
|
99
129
|
const [showBadge, setShowBadge] = useState(false);
|
|
100
130
|
const [highlightedId, setHighlightedId] = useState(null);
|
|
101
131
|
const highlightTimerRef = useRef(null);
|
|
@@ -168,13 +198,14 @@ export const ChatListLegend = /*#__PURE__*/memo(({
|
|
|
168
198
|
collapsable: false,
|
|
169
199
|
children: /*#__PURE__*/_jsx(LegendChatMessage, {
|
|
170
200
|
message: message,
|
|
201
|
+
messageId: messageId,
|
|
171
202
|
isOutgoing: isOutgoing,
|
|
172
203
|
createdAtTime: createdAt,
|
|
173
204
|
onMediaPress: onMediaPress,
|
|
174
205
|
onPressUrl: onPressUrl,
|
|
175
206
|
onRetry: retryMessage,
|
|
176
|
-
onPress:
|
|
177
|
-
onLongPress: onLongPress ?
|
|
207
|
+
onPress: handleMessagePress,
|
|
208
|
+
onLongPress: onLongPress ? handleMessageLongPress : undefined,
|
|
178
209
|
customMessageItemFactory: customMessageItemFactory,
|
|
179
210
|
isHighlighted: highlightedId === messageId,
|
|
180
211
|
isTimeRevealed: revealedMessageId === messageId,
|
|
@@ -201,48 +232,33 @@ export const ChatListLegend = /*#__PURE__*/memo(({
|
|
|
201
232
|
}
|
|
202
233
|
}, [currentUserId, lastMessageId, messageDataMap, isGroupConversation, isBotConversation, onMediaPress, onPressUrl, onLongPress, handleMessageLongPress, customMessageItemFactory, onResetFlow, onRunFlow, conversationFlow?.flowCurrentStep, conversationFlow?.havingBotMessage, retryMessage, highlightedId, revealedMessageId, handleMessagePress]);
|
|
203
234
|
|
|
204
|
-
//
|
|
205
|
-
//
|
|
206
|
-
//
|
|
207
|
-
//
|
|
208
|
-
//
|
|
209
|
-
//
|
|
210
|
-
//
|
|
211
|
-
//
|
|
212
|
-
// itemLayout: !moreOldLoading,
|
|
213
|
-
// },
|
|
214
|
-
// }),
|
|
215
|
-
// [moreOldLoading]
|
|
216
|
-
// );
|
|
217
|
-
|
|
218
|
-
// Stable config so the native maintainVisibleContentPosition prop isn't toggled
|
|
219
|
-
// mid-prepend (toggling forces an extra layout recompute). `data` anchoring keeps
|
|
220
|
-
// the viewport pinned to the item being read when older messages are added on top.
|
|
235
|
+
// `maintainVisibleContentPosition` anchors a prepend to whatever native
|
|
236
|
+
// view sits at the top. Default `drawDistance` (250px) doesn't survive a
|
|
237
|
+
// ~1-1.5s history fetch if the user keeps scrolling away — the anchor
|
|
238
|
+
// unmounts and the native compensation silently drops (the "list drifts
|
|
239
|
+
// after loading old history" bug). `drawDistance` below is raised to
|
|
240
|
+
// outlast a realistic scroll during that wait (measured ~300-350px).
|
|
241
|
+
// `recycleItems` is safe again since @legendapp/list 3.3.7 fixed
|
|
242
|
+
// recycled rows flashing wrong content on prepend.
|
|
221
243
|
const maintainVisiblePositionConfig = useMemo(() => ({
|
|
222
244
|
data: true
|
|
223
245
|
}), []);
|
|
224
246
|
|
|
225
|
-
// Buckets averaging
|
|
226
|
-
//
|
|
227
|
-
//
|
|
228
|
-
//
|
|
229
|
-
// content type with an arbitrary custom node — see `LegendChatMessage`'s
|
|
230
|
-
// `customNode` short-circuit, checked before its own contentType switch)
|
|
231
|
-
// get their own bucket per content type, so a custom node's real measured
|
|
232
|
-
// height never pollutes the native component's average for that same type.
|
|
247
|
+
// Buckets LegendList's size-averaging per content type so a batch of
|
|
248
|
+
// images landing early doesn't pollute the estimate for still-unmeasured
|
|
249
|
+
// text rows. `customMessageItemFactory` nodes get their own bucket per
|
|
250
|
+
// type too, so a custom node's real height doesn't pollute that type's average.
|
|
233
251
|
const getItemType = useCallback(item => {
|
|
234
252
|
const isCustom = !!customMessageItemFactory?.(item);
|
|
235
253
|
return `${item?.contentType ?? 'default'}${isCustom ? '-custom' : ''}`;
|
|
236
254
|
}, [customMessageItemFactory]);
|
|
237
255
|
|
|
238
|
-
// Exact size for content types
|
|
239
|
-
// `plans/260728-1400-chatlist-legend-fixed-item-size/plan.md
|
|
240
|
-
// `undefined` (defer to
|
|
241
|
-
//
|
|
242
|
-
//
|
|
243
|
-
//
|
|
244
|
-
// and once it resolves a number that item is never measured again, so
|
|
245
|
-
// guessing wrong here is a permanent regression, not just an approximation.
|
|
256
|
+
// Exact size for content types knowable ahead of render (see
|
|
257
|
+
// `plans/260728-1400-chatlist-legend-fixed-item-size/plan.md`). Returns
|
|
258
|
+
// `undefined` (defer to measurement) for anything unpredictable, or
|
|
259
|
+
// carrying chrome this function doesn't account for (day-divider, flow-
|
|
260
|
+
// input-buttons row) — a resolved number is never re-measured, so
|
|
261
|
+
// guessing wrong here is permanent, not just approximate.
|
|
246
262
|
const getFixedItemSize = useCallback((item, index) => {
|
|
247
263
|
const message = item;
|
|
248
264
|
const messageId = getMessageRenderId(message, index);
|
|
@@ -294,13 +310,10 @@ export const ChatListLegend = /*#__PURE__*/memo(({
|
|
|
294
310
|
return candidateSize;
|
|
295
311
|
}, [messageDataMap, customMessageItemFactory, currentUserId, isGroupConversation, lastMessageId, isBotConversation, conversationFlow?.flowCurrentStep, windowWidth]);
|
|
296
312
|
|
|
297
|
-
// LegendList
|
|
298
|
-
//
|
|
299
|
-
//
|
|
300
|
-
// message itself
|
|
301
|
-
// 'first' into a 'middle'. messageDataMap is memoised on exactly the inputs
|
|
302
|
-
// that can move those boundaries, so including it here is what keeps a
|
|
303
|
-
// stale tail from being left behind.
|
|
313
|
+
// LegendList only re-renders an item when [itemKey, item, extraData]
|
|
314
|
+
// changes. Cluster position depends on a message's NEIGHBOURS, which can
|
|
315
|
+
// shift (prepending history can turn a 'first' into a 'middle') without
|
|
316
|
+
// the message itself changing — messageDataMap here is what catches that.
|
|
304
317
|
const listExtraData = useMemo(() => ({
|
|
305
318
|
messageDataMap,
|
|
306
319
|
flowStepId: conversationFlow?.flowCurrentStep?.id ?? '',
|
|
@@ -309,39 +322,23 @@ export const ChatListLegend = /*#__PURE__*/memo(({
|
|
|
309
322
|
revealedMessageId
|
|
310
323
|
}), [messageDataMap, conversationFlow?.flowCurrentStep?.id, lastMessageId, highlightedId, revealedMessageId]);
|
|
311
324
|
const handleStartReached = useCallback(() => {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
firstMessageId: messages[0]?.clientMsgID || messages[0]?.serverMsgID,
|
|
318
|
-
hasMoreOld,
|
|
319
|
-
moreOldLoading,
|
|
320
|
-
willLoad,
|
|
321
|
-
duringInitialSettle: !hasSettledRef.current
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
if (willLoad) {
|
|
325
|
+
// Both thresholds are checked continuously, including at mount before
|
|
326
|
+
// any gesture — `hasUserScrolledRef` is what keeps that from firing a
|
|
327
|
+
// load-more the user never asked for.
|
|
328
|
+
if (!hasUserScrolledRef.current) return;
|
|
329
|
+
if (hasMoreOld && !useMessageStore.getState().moreOldLoading) {
|
|
325
330
|
onLoadMoreOld?.(true);
|
|
326
331
|
}
|
|
327
|
-
}, [
|
|
332
|
+
}, [hasMoreOld, onLoadMoreOld]);
|
|
328
333
|
const handleEndReached = useCallback(() => {
|
|
329
|
-
|
|
330
|
-
if (
|
|
331
|
-
console.log(willLoad && !hasSettledRef.current ? '[LegendList] ⚠️ onEndReached SPURIOUS mount-time load' : '[LegendList] onEndReached triggered', {
|
|
332
|
-
conversationId,
|
|
333
|
-
messagesLength: messages.length,
|
|
334
|
-
lastMessageId: messages[messages.length - 1]?.clientMsgID,
|
|
335
|
-
hasMoreNew,
|
|
336
|
-
moreNewLoading,
|
|
337
|
-
willLoad,
|
|
338
|
-
duringInitialSettle: !hasSettledRef.current
|
|
339
|
-
});
|
|
340
|
-
}
|
|
341
|
-
if (willLoad) {
|
|
334
|
+
if (!hasUserScrolledRef.current) return;
|
|
335
|
+
if (hasMoreNew && !useMessageStore.getState().moreNewLoading) {
|
|
342
336
|
onLoadMoreNew?.(true);
|
|
343
337
|
}
|
|
344
|
-
}, [
|
|
338
|
+
}, [hasMoreNew, onLoadMoreNew]);
|
|
339
|
+
const handleScrollBeginDrag = useCallback(() => {
|
|
340
|
+
hasUserScrolledRef.current = true;
|
|
341
|
+
}, []);
|
|
345
342
|
const handleScroll = useCallback(e => {
|
|
346
343
|
const {
|
|
347
344
|
contentOffset,
|
|
@@ -357,10 +354,7 @@ export const ChatListLegend = /*#__PURE__*/memo(({
|
|
|
357
354
|
scrollDebounceRef.current = setTimeout(() => {
|
|
358
355
|
if (isAtBottomRef.current !== isAtBottom) {
|
|
359
356
|
isAtBottomRef.current = isAtBottom;
|
|
360
|
-
buttonOpacity.value = withTiming(isAtBottom ? 0 : 1,
|
|
361
|
-
duration: 200,
|
|
362
|
-
easing: Easing.out(Easing.ease)
|
|
363
|
-
});
|
|
357
|
+
buttonOpacity.value = withTiming(isAtBottom ? 0 : 1, BUTTON_FADE_CONFIG);
|
|
364
358
|
}
|
|
365
359
|
if (isAtBottom) {
|
|
366
360
|
ChatMessageAPI.markConversationAsRead(conversationId || '');
|
|
@@ -370,18 +364,20 @@ export const ChatListLegend = /*#__PURE__*/memo(({
|
|
|
370
364
|
const handleScrollToBottom = useCallback(() => {
|
|
371
365
|
if (hasMoreNew) {
|
|
372
366
|
onLoadMoreOld?.(false);
|
|
373
|
-
|
|
374
|
-
scrollMessageToEnd({
|
|
375
|
-
animated: true,
|
|
376
|
-
closeKeyboard: false
|
|
377
|
-
});
|
|
378
|
-
buttonOpacity.value = withTiming(0, {
|
|
379
|
-
duration: 200,
|
|
380
|
-
easing: Easing.out(Easing.ease)
|
|
381
|
-
});
|
|
382
|
-
isAtBottomRef.current = true;
|
|
383
|
-
setShowBadge(false);
|
|
367
|
+
return;
|
|
384
368
|
}
|
|
369
|
+
// `ChatEvent.ScrollToBottom` fires after every self-sent message, but
|
|
370
|
+
// the `lastMessageId` effect below already animates to it — re-scrolling
|
|
371
|
+
// here raced it and flickered. Only act when not already at bottom
|
|
372
|
+
// (FAB tap, or a send while scrolled away).
|
|
373
|
+
if (isAtBottomRef.current) return;
|
|
374
|
+
scrollMessageToEnd({
|
|
375
|
+
animated: true,
|
|
376
|
+
closeKeyboard: false
|
|
377
|
+
});
|
|
378
|
+
buttonOpacity.value = withTiming(0, BUTTON_FADE_CONFIG);
|
|
379
|
+
isAtBottomRef.current = true;
|
|
380
|
+
setShowBadge(false);
|
|
385
381
|
}, [hasMoreNew, onLoadMoreOld, scrollMessageToEnd, buttonOpacity]);
|
|
386
382
|
const animatedButtonStyle = useAnimatedStyle(() => ({
|
|
387
383
|
opacity: buttonOpacity.value,
|
|
@@ -397,19 +393,115 @@ export const ChatListLegend = /*#__PURE__*/memo(({
|
|
|
397
393
|
};
|
|
398
394
|
}, []);
|
|
399
395
|
|
|
400
|
-
//
|
|
401
|
-
//
|
|
402
|
-
//
|
|
403
|
-
//
|
|
396
|
+
// Tracks the keyboard's height as the trigger for the re-anchor below.
|
|
397
|
+
// The `willHide` side is debounced because Android's event stream flaps
|
|
398
|
+
// willShow→willHide→willShow roughly every 1.3s for as long as the
|
|
399
|
+
// keyboard stays open (measured on device) — without this, every flap
|
|
400
|
+
// would fire another scroll. A real close still lands, just one tick
|
|
401
|
+
// later. Setting the same height twice is a no-op for the effect below,
|
|
402
|
+
// so a stable open only ever re-anchors once.
|
|
403
|
+
//
|
|
404
|
+
// JS-thread only (no worklet), so none of the reentrant-lock crash risk
|
|
405
|
+
// that reaching into `useKeyboardHandler`'s worklets carries.
|
|
404
406
|
useEffect(() => {
|
|
405
|
-
|
|
407
|
+
let pendingHide;
|
|
408
|
+
const clearPendingHide = () => {
|
|
409
|
+
if (pendingHide) {
|
|
410
|
+
clearTimeout(pendingHide);
|
|
411
|
+
pendingHide = undefined;
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
const applyInset = nextInset => {
|
|
415
|
+
// Android only: the bottom inset the library applies there is a
|
|
416
|
+
// synthetic prop that `onScroll` does not report (its own
|
|
417
|
+
// `ScrollViewWithBottomPadding` says as much), so LegendList never
|
|
418
|
+
// learns about it, `alignItemsAtEndPadding` never shrinks, and the
|
|
419
|
+
// re-anchor below has no room to scroll into. Reporting it closes
|
|
420
|
+
// that gap. iOS needs none of this — there the inset is real and
|
|
421
|
+
// arrives through `onScroll` on its own, and overriding it here
|
|
422
|
+
// would double-count.
|
|
423
|
+
if (Platform.OS === 'android') {
|
|
424
|
+
listRef.current?.reportContentInset(nextInset > 0 ? {
|
|
425
|
+
bottom: nextInset
|
|
426
|
+
} : null);
|
|
427
|
+
}
|
|
428
|
+
setKeyboardInset(nextInset);
|
|
429
|
+
};
|
|
430
|
+
const willShow = KeyboardEvents.addListener('keyboardWillShow', e => {
|
|
431
|
+
clearPendingHide();
|
|
432
|
+
applyInset(Math.max(e.height - keyboardOffset, 0));
|
|
433
|
+
});
|
|
434
|
+
const willHide = KeyboardEvents.addListener('keyboardWillHide', () => {
|
|
435
|
+
clearPendingHide();
|
|
436
|
+
pendingHide = setTimeout(() => applyInset(0), KEYBOARD_HIDE_DEBOUNCE_MS);
|
|
437
|
+
});
|
|
438
|
+
return () => {
|
|
439
|
+
clearPendingHide();
|
|
440
|
+
willShow.remove();
|
|
441
|
+
willHide.remove();
|
|
442
|
+
};
|
|
443
|
+
}, [keyboardOffset, listRef]);
|
|
444
|
+
|
|
445
|
+
// Re-anchors to the end once the keyboard's inset has landed, which puts
|
|
446
|
+
// the last message at exactly the spacing the closed-keyboard layout has
|
|
447
|
+
// (verified on device against both a 7-message and a long conversation).
|
|
448
|
+
// Skipped when the user has scrolled away from the bottom — opening the
|
|
449
|
+
// keyboard shouldn't yank them back down.
|
|
450
|
+
useEffect(() => {
|
|
451
|
+
if (!hasSeenFirstKeyboardInsetRef.current) {
|
|
452
|
+
hasSeenFirstKeyboardInsetRef.current = true;
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
if (!isAtBottomRef.current) return;
|
|
456
|
+
scrollMessageToEnd({
|
|
457
|
+
animated: true,
|
|
458
|
+
closeKeyboard: false
|
|
459
|
+
});
|
|
460
|
+
}, [keyboardInset, scrollMessageToEnd]);
|
|
461
|
+
|
|
462
|
+
// This component can stay mounted across a conversationId change (e.g.
|
|
463
|
+
// navigation.replace reusing the same screen instance), so this ref must
|
|
464
|
+
// reset per-conversation — otherwise a leftover "user scrolled" flag from
|
|
465
|
+
// the previous conversation would wrongly let load-more fire on the
|
|
466
|
+
// newly opened one before any real scroll there.
|
|
467
|
+
useEffect(() => {
|
|
468
|
+
hasUserScrolledRef.current = false;
|
|
469
|
+
hasCorrectedInitialPaddingRef.current = false;
|
|
470
|
+
previousLastMessageIdRef.current = null;
|
|
406
471
|
}, [conversationId]);
|
|
472
|
+
|
|
473
|
+
// Single source of truth for "scroll to bottom on a new message" (self-
|
|
474
|
+
// sent or received). Skipped while prepending old history or scrolled
|
|
475
|
+
// away from the bottom. `moreOldLoading` is read via ref, not a
|
|
476
|
+
// dependency, so its own start/finish toggle doesn't re-run this.
|
|
477
|
+
useEffect(() => {
|
|
478
|
+
const previousLastMessageId = previousLastMessageIdRef.current;
|
|
479
|
+
previousLastMessageIdRef.current = lastMessageId;
|
|
480
|
+
|
|
481
|
+
// null → a real id is the initial fetch landing (initialScrollAtEnd +
|
|
482
|
+
// handleListLoad's job), not a new message; a real id → a different
|
|
483
|
+
// one is.
|
|
484
|
+
const shouldFire = previousLastMessageId !== null && !!lastMessageId && !moreOldLoadingRef.current && isAtBottomRef.current;
|
|
485
|
+
if (!shouldFire) return;
|
|
486
|
+
scrollMessageToEnd({
|
|
487
|
+
animated: true,
|
|
488
|
+
closeKeyboard: false
|
|
489
|
+
});
|
|
490
|
+
}, [lastMessageId, scrollMessageToEnd]);
|
|
491
|
+
const handleListLoad = useCallback(() => {
|
|
492
|
+
if (hasCorrectedInitialPaddingRef.current) return;
|
|
493
|
+
hasCorrectedInitialPaddingRef.current = true;
|
|
494
|
+
scrollMessageToEnd({
|
|
495
|
+
animated: false,
|
|
496
|
+
closeKeyboard: false
|
|
497
|
+
});
|
|
498
|
+
}, [scrollMessageToEnd]);
|
|
407
499
|
useEffect(() => {
|
|
408
500
|
const bottomSubscription = DeviceEventEmitter.addListener(ChatEvent.ScrollToBottom, handleScrollToBottom);
|
|
409
501
|
const subscription = DeviceEventEmitter.addListener(ChatEvent.ScrollToMessage, ({
|
|
410
502
|
clientMessageId
|
|
411
503
|
}) => {
|
|
412
|
-
const index =
|
|
504
|
+
const index = messagesRef.current.findIndex(m => m.clientMsgID === clientMessageId);
|
|
413
505
|
if (index >= 0) {
|
|
414
506
|
try {
|
|
415
507
|
listRef.current?.scrollToIndex({
|
|
@@ -441,7 +533,7 @@ export const ChatListLegend = /*#__PURE__*/memo(({
|
|
|
441
533
|
bottomSubscription.remove();
|
|
442
534
|
subscription.remove();
|
|
443
535
|
};
|
|
444
|
-
}, [
|
|
536
|
+
}, [applicationType, searchMessages, conversationId, handleScrollToBottom, listRef]);
|
|
445
537
|
if (isLoading) {
|
|
446
538
|
return /*#__PURE__*/_jsx(KContainer.View, {
|
|
447
539
|
flex: true,
|
|
@@ -453,27 +545,51 @@ export const ChatListLegend = /*#__PURE__*/memo(({
|
|
|
453
545
|
})
|
|
454
546
|
});
|
|
455
547
|
}
|
|
456
|
-
console.log('messages length: ', +messages.length);
|
|
457
548
|
return /*#__PURE__*/_jsxs(KContainer.View, {
|
|
458
549
|
flex: true,
|
|
459
550
|
background: KColors.white,
|
|
460
551
|
style: styles.container,
|
|
461
|
-
children: [/*#__PURE__*/_jsx(
|
|
552
|
+
children: [/*#__PURE__*/_jsx(KeyboardAwareLegendList, {
|
|
462
553
|
ref: listRef,
|
|
463
554
|
data: messages,
|
|
464
|
-
renderItem: renderItem
|
|
465
|
-
|
|
555
|
+
renderItem: renderItem
|
|
556
|
+
// Deliberate lower bound (not a best-guess average) — see the
|
|
557
|
+
// comment above `hasCorrectedInitialPaddingRef`. A single-line
|
|
558
|
+
// bubble floors out around 38-44px, so this stays safely under it.
|
|
559
|
+
,
|
|
560
|
+
estimatedItemSize: 36,
|
|
466
561
|
getItemType: getItemType,
|
|
467
562
|
getFixedItemSize: getFixedItemSize,
|
|
468
563
|
keyExtractor: item => String(item.clientMsgID || item.serverMsgID),
|
|
469
|
-
recycleItems:
|
|
564
|
+
recycleItems: true,
|
|
470
565
|
extraData: listExtraData,
|
|
471
566
|
alignItemsAtEnd: true,
|
|
472
|
-
|
|
567
|
+
alwaysRender: {
|
|
568
|
+
top: 10
|
|
569
|
+
},
|
|
570
|
+
maintainScrollAtEnd: true,
|
|
571
|
+
maintainVisibleContentPosition: maintainVisiblePositionConfig
|
|
572
|
+
// See the comment above `maintainVisiblePositionConfig` — this is
|
|
573
|
+
// what keeps a history prepend's anchor item mounted through a slow
|
|
574
|
+
// fetch instead of the default 250px window losing it.
|
|
575
|
+
,
|
|
576
|
+
drawDistance: 800,
|
|
473
577
|
freeze: freeze,
|
|
474
|
-
keyboardOffset: keyboardOffset
|
|
578
|
+
keyboardOffset: keyboardOffset
|
|
579
|
+
// The list's own keyboard compensation is off on both platforms —
|
|
580
|
+
// measured, it overshoots badly either way. On iOS it scrolls on
|
|
581
|
+
// top of React Native's `automaticallyAdjustContentInsets` (which
|
|
582
|
+
// already insets the scroll view by the full keyboard height), and
|
|
583
|
+
// that double lift is the blank gap. On Android it overshot by
|
|
584
|
+
// ~690px against a 128px target. What both platforms do keep from
|
|
585
|
+
// the library is the bottom inset it sets, which is the room the
|
|
586
|
+
// re-anchor above scrolls into.
|
|
587
|
+
,
|
|
588
|
+
keyboardLiftBehavior: "never",
|
|
475
589
|
scrollEventThrottle: 16,
|
|
476
590
|
onScroll: handleScroll,
|
|
591
|
+
onScrollBeginDrag: handleScrollBeginDrag,
|
|
592
|
+
onLoad: handleListLoad,
|
|
477
593
|
contentContainerStyle: styles.content,
|
|
478
594
|
scrollIndicatorInsets: {
|
|
479
595
|
right: 1
|
|
@@ -481,22 +597,18 @@ export const ChatListLegend = /*#__PURE__*/memo(({
|
|
|
481
597
|
ListHeaderComponent: /*#__PURE__*/_jsx(LegendChatLoadEarlier, {
|
|
482
598
|
isLoading: moreOldLoading
|
|
483
599
|
}),
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
},
|
|
494
|
-
onStartReached: handleStartReached,
|
|
495
|
-
onStartReachedThreshold: 0.5,
|
|
600
|
+
onStartReached: handleStartReached
|
|
601
|
+
// LegendList only re-fires onStartReached after scrolling away from
|
|
602
|
+
// the threshold by 1.3x and back. At 0.5 that distance exceeded a
|
|
603
|
+
// short conversation's whole scrollable range, so the mount-time
|
|
604
|
+
// firing we suppress in handleStartReached "used up" the only
|
|
605
|
+
// trigger. 0.3 keeps that reset distance safely under a
|
|
606
|
+
// ~1.5-screen conversation; shorter ones can still hit it.
|
|
607
|
+
,
|
|
608
|
+
onStartReachedThreshold: 0.2,
|
|
496
609
|
onEndReached: handleEndReached,
|
|
497
610
|
onEndReachedThreshold: 0.2,
|
|
498
|
-
|
|
499
|
-
initialScrollIndex: messages.length - 1
|
|
611
|
+
initialScrollAtEnd: true
|
|
500
612
|
}), /*#__PURE__*/_jsx(Animated.View, {
|
|
501
613
|
style: [styles.scrollToBottomButton, animatedButtonStyle],
|
|
502
614
|
children: /*#__PURE__*/_jsxs(KContainer.Touchable, {
|