@droppii-org/chat-mobile 0.2.93 → 0.2.95
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/screens/chat-detail/ChatDetail.js +15 -11
- package/lib/module/screens/chat-detail/ChatDetail.js.map +1 -1
- package/lib/module/screens/chat-detail/ChatListLegend.js +233 -74
- package/lib/module/screens/chat-detail/ChatListLegend.js.map +1 -1
- package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxOverlay.js +16 -9
- package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxOverlay.js.map +1 -1
- package/lib/module/store/message.js +9 -5
- package/lib/module/store/message.js.map +1 -1
- package/lib/module/types/events.js +1 -0
- package/lib/module/types/events.js.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.map +1 -1
- package/lib/typescript/src/screens/chat-detail/messageToolbox/MessageToolboxOverlay.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/messageToolbox/types.d.ts +3 -1
- package/lib/typescript/src/screens/chat-detail/messageToolbox/types.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/types.d.ts +2 -2
- package/lib/typescript/src/screens/chat-detail/types.d.ts.map +1 -1
- package/lib/typescript/src/store/message.d.ts.map +1 -1
- package/lib/typescript/src/types/events.d.ts +2 -1
- package/lib/typescript/src/types/events.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/screens/chat-detail/ChatDetail.tsx +23 -14
- package/src/screens/chat-detail/ChatListLegend.tsx +249 -73
- package/src/screens/chat-detail/messageToolbox/MessageToolboxOverlay.tsx +26 -7
- package/src/screens/chat-detail/messageToolbox/types.ts +8 -1
- package/src/screens/chat-detail/types.ts +2 -2
- package/src/store/message.ts +14 -5
- package/src/types/events.ts +1 -0
|
@@ -24,7 +24,6 @@ import { ChatEvent } from "../../types/events.js";
|
|
|
24
24
|
import { useSetIsShowFLashMessage } from "../../context/global.js";
|
|
25
25
|
import { useJoinGroup } from "../../hooks/groups/useJoinGroup.js";
|
|
26
26
|
import { useGroupAccessGuard } from "../../hooks/groups/useGroupAccessGuard.js";
|
|
27
|
-
import { isMessageRevoked } from "../../utils/messageUtils.js";
|
|
28
27
|
import { UIUtils } from "../../utils/UIUtils.js";
|
|
29
28
|
import { trans } from "../../translation/index.js";
|
|
30
29
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
@@ -110,8 +109,19 @@ const ChatDetail = /*#__PURE__*/memo(({
|
|
|
110
109
|
onBlocked: handleAccessBlocked
|
|
111
110
|
});
|
|
112
111
|
|
|
113
|
-
//
|
|
114
|
-
|
|
112
|
+
// Go back if the target message is not available
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
const subscription = DeviceEventEmitter.addListener(ChatEvent.TargetMessageUnavailable, () => {
|
|
115
|
+
UIUtils.toast.open({
|
|
116
|
+
title: trans('chat:target_message_unavailable'),
|
|
117
|
+
theme: 'error'
|
|
118
|
+
});
|
|
119
|
+
(onBack ?? handleBackDefault)();
|
|
120
|
+
});
|
|
121
|
+
return () => subscription.remove();
|
|
122
|
+
}, [onBack, handleBackDefault]);
|
|
123
|
+
|
|
124
|
+
// Handle re-open the same deeplink
|
|
115
125
|
const params = useRoute().params;
|
|
116
126
|
useEffect(() => {
|
|
117
127
|
if (!targetMessageId || initLoading) return;
|
|
@@ -120,12 +130,6 @@ const ChatDetail = /*#__PURE__*/memo(({
|
|
|
120
130
|
DeviceEventEmitter.emit(ChatEvent.ScrollToMessage, {
|
|
121
131
|
clientMessageId: targetMessageId
|
|
122
132
|
});
|
|
123
|
-
if (isMessageRevoked(targetMessage)) {
|
|
124
|
-
UIUtils.toast.open({
|
|
125
|
-
title: trans('chat:target_message_unavailable'),
|
|
126
|
-
theme: 'error'
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
133
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
130
134
|
}, [params]);
|
|
131
135
|
const resolvedShowAddMember = showAddMember ?? shouldShowAddMember(conversation);
|
|
@@ -140,8 +144,8 @@ const ChatDetail = /*#__PURE__*/memo(({
|
|
|
140
144
|
const handlePressUrl = useCallback(url => {
|
|
141
145
|
onPressUrl?.(normalizeUrl(url));
|
|
142
146
|
}, [onPressUrl]);
|
|
143
|
-
const handleMessageLongPress = useCallback((message, rect) => {
|
|
144
|
-
messageToolboxRef.current?.show(message, rect);
|
|
147
|
+
const handleMessageLongPress = useCallback((message, rect, groupPosition) => {
|
|
148
|
+
messageToolboxRef.current?.show(message, rect, groupPosition);
|
|
145
149
|
}, []);
|
|
146
150
|
const handlePressPinnedMessageBar = useCallback(() => {
|
|
147
151
|
openPinnedMessagesSheet({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["memo","useCallback","useEffect","useRef","ActivityIndicator","DeviceEventEmitter","useKeyboardScrollToEnd","useSafeAreaInsets","KColors","KContainer","KNavigation","useNavigation","useRoute","usePinMessage","PinnedMessageBar","openPinnedMessagesSheet","MediaViewerModal","useConversation","useConversationStore","useUserStore","ChatDetailHeader","ChatListLegend","ChatComposer","shouldShowAddMember","normalizeUrl","MessageToolboxOverlay","useGetConversationDetail","useGetConversationTarget","GroupJoinSource","useMessages","ChatEvent","useSetIsShowFLashMessage","useJoinGroup","useGroupAccessGuard","isMessageRevoked","UIUtils","trans","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","params","targetMessage","find","m","clientMsgID","emit","ScrollToMessage","clientMessageId","toast","open","title","theme","resolvedShowAddMember","insets","listRef","freeze","scrollMessageToEnd","handlePressUrl","url","handleMessageLongPress","message","rect","handlePressPinnedMessageBar","currentUserId","userID","onPressMessage","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","props","isUserLoaded","Header","alignment","size","disableCenterSpace","shadow","leftButton","id","icon","vectorName","vectorProvider","tintColor","primary","normal","View","center","color"],"sourceRoot":"../../../../src","sources":["screens/chat-detail/ChatDetail.tsx"],"mappings":";;AAAA,SAASA,IAAI,EAAEC,WAAW,EAAEC,SAAS,EAAEC,MAAM,QAAQ,OAAO;AAC5D,SAASC,iBAAiB,EAAEC,kBAAkB,QAAQ,cAAc;AAEpE,SAASC,sBAAsB,QAAQ,0BAA0B;AAEjE,SAASC,iBAAiB,QAAQ,gCAAgC;AAClE,SAASC,OAAO,EAAEC,UAAU,EAAEC,WAAW,QAAQ,eAAe;AAChE,SAASC,aAAa,EAAEC,QAAQ,QAAQ,0BAA0B;AAClE,SAASC,aAAa,QAAQ,sCAAmC;AACjE,SAASC,gBAAgB,QAAQ,uBAAoB;AACrD,SAASC,uBAAuB,QAAQ,0BAAuB;AAC/D,SACEC,gBAAgB,QAEX,sCAAmC;AAC1C,SACEC,eAAe,EACfC,oBAAoB,EACpBC,YAAY,QACP,sBAAa;AACpB,OAAOC,gBAAgB,MAAM,uBAAoB;AACjD,SAASC,cAAc,QAAQ,qBAAkB;AACjD,SAASC,YAAY,QAAQ,mBAAgB;AAC7C,SAASC,mBAAmB,QAAQ,+BAA4B;AAEhE,SAASC,YAAY,QAAQ,oBAAiB;AAC9C,SAASC,qBAAqB,QAAQ,2CAAwC;AAE9E,SACEC,wBAAwB,EACxBC,wBAAwB,QACnB,sDAAmD;AAC1D,SACEC,eAAe,QAEV,+BAA+B;AACtC,SAASC,WAAW,QAAQ,oCAAiC;AAC7D,SAASC,SAAS,QAAQ,uBAAoB;AAC9C,SAASC,wBAAwB,QAAQ,yBAAsB;AAC/D,SAASC,YAAY,QAAQ,oCAAiC;AAC9D,SAASC,mBAAmB,QAAQ,2CAAwC;AAC5E,SAASC,gBAAgB,QAAQ,6BAA0B;AAC3D,SAASC,OAAO,QAAQ,wBAAqB;AAC7C,SAASC,KAAK,QAAQ,4BAAmB;AAAC,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAE1C,MAAMC,UAAU,gBAAGzC,IAAI,CACrB,CAAC;EACC0C,oBAAoB,GAAG,EAAE;EACzBC,YAAY,GAAG,EAAE;EACjBC,aAAa,GAAG,EAAE;EAClBC,WAAW,GAAG,EAAE;EAChBC,eAAe,GAAG,EAAE;EACpBC,aAAa;EACbC,MAAM;EACNC,aAAa;EACbC,gBAAgB;EAChBC,WAAW;EACXC,UAAU;EACVC,wBAAwB;EACxBC,aAAa;EACbC;AACe,CAAC,KAAK;EACrB,MAAMC,UAAU,GAAG7C,aAAa,CAAC,CAAC;EAClC,MAAM8C,cAAc,GAAGtD,MAAM,CAAyB,IAAI,CAAC;EAC3D,MAAMuD,iBAAiB,GAAGvD,MAAM,CAAoB,IAAI,CAAC;EACzD,MAAMwD,WAAW,GAAGxC,YAAY,CAAEyC,CAAC,IAAKA,CAAC,CAACC,IAAI,CAAC;EAE/C,MAAM;IAAEC,cAAc;IAAEC,SAAS,EAAEC;EAAsB,CAAC,GACxDtC,wBAAwB,CAAC;IACvBgB,oBAAoB;IACpBC,YAAY;IACZC,aAAa;IACbC;EACF,CAAC,CAAC;EAEJ,MAAMoB,YAAY,GAAGhD,eAAe,CAAC6C,cAAc,CAAC;EAEpD,MAAM;IAAEI,IAAI,EAAEC;EAAO,CAAC,GAAGxC,wBAAwB,CAACmC,cAAc,CAAC;EACjE,MAAMM,iBAAiB,GAAG,CAAC,CAACD,MAAM,IAAI,CAACA,MAAM,CAACE,QAAQ;EAEtD,MAAMC,iBAAiB,GAAGrE,WAAW,CAAC,MAAM;IAC1CuD,UAAU,CAACe,MAAM,CAAC,CAAC;EACrB,CAAC,EAAE,CAACf,UAAU,CAAC,CAAC;EAEhB,MAAMgB,gBAAgB,GAAGvE,WAAW,CAClC,CACEwE,KAAoD,EACpDC,KAAc,KACX;IACHjB,cAAc,CAACkB,OAAO,EAAEC,IAAI,CAACH,KAAK,EAAEC,KAAK,CAAC;EAC5C,CAAC,EACD,EACF,CAAC;EAED,MAAM;IACJG,QAAQ;IACRC,WAAW;IACXC,cAAc;IACdC,cAAc;IACdC,kBAAkB;IAClBC,kBAAkB;IAClBC,UAAU;IACVC;EACF,CAAC,GAAGvD,WAAW,CAAC;IACdiC,cAAc;IACduB,gBAAgB,EAAEvC,eAAe;IACjCwC,QAAQ,EAAErB,YAAY,EAAEqB;EAC1B,CAAC,CAAC;EAEF,MAAM;IAAEC,MAAM,EAAEC,SAAS;IAAEC,SAAS,EAAEC;EAAe,CAAC,GAAG1D,YAAY,CAAC,CAAC;EAEvE,MAAM2D,mBAAmB,GAAG5D,wBAAwB,CAAC,CAAC;EAEtD,MAAM;IAAE6D,cAAc;IAAEC,UAAU;IAAEC;EAAa,CAAC,GAChDjF,aAAa,CAACiD,cAAc,CAAC;EAE/B5D,SAAS,CAAC,MAAM;IACdgB,oBAAoB,CACjB6E,QAAQ,CAAC,CAAC,CACVC,sBAAsB,CAAClC,cAAc,EAAEnB,YAAY,EAAEC,aAAa,CAAC;IACtE+C,mBAAmB,CAAC,KAAK,CAAC;IAC1B,OAAO,MAAM;MACXzE,oBAAoB,CACjB6E,QAAQ,CAAC,CAAC,CACVC,sBAAsB,CAACC,SAAS,EAAEA,SAAS,EAAEA,SAAS,CAAC;MAC1DN,mBAAmB,CAAC,IAAI,CAAC;IAC3B,CAAC;EACH,CAAC,EAAE,CAAC7B,cAAc,EAAEnB,YAAY,EAAEC,aAAa,EAAE+C,mBAAmB,CAAC,CAAC;EAEtE,MAAMO,mBAAmB,GAAGjG,WAAW,CAAC,MAAM;IAC5C,CAAC+C,MAAM,IAAIsB,iBAAiB,EAAE,CAAC;EACjC,CAAC,EAAE,CAACtB,MAAM,EAAEsB,iBAAiB,CAAC,CAAC;EAE/B,MAAM;IAAE6B;EAAiB,CAAC,GAAGlE,mBAAmB,CAAC;IAC/CmE,OAAO,EAAEnC,YAAY,EAAEmC,OAAO,IAAIxD,aAAa;IAC/CyD,SAAS,EAAEH;EACb,CAAC,CAAC;;EAEF;EACA;EACA,MAAMI,MAAM,GAAG1F,QAAQ,CAAC,CAAC,CAAC0F,MAAM;EAChCpG,SAAS,CAAC,MAAM;IACd,IAAI,CAAC4C,eAAe,IAAIgC,WAAW,EAAE;IACrC,MAAMyB,aAAa,GAAG1B,QAAQ,CAAC2B,IAAI,CAChCC,CAAC,IAAKA,CAAC,CAACC,WAAW,KAAK5D,eAC3B,CAAC;IACD,IAAI,CAACyD,aAAa,EAAE;IAEpBlG,kBAAkB,CAACsG,IAAI,CAAC7E,SAAS,CAAC8E,eAAe,EAAE;MACjDC,eAAe,EAAE/D;IACnB,CAAC,CAAC;IAEF,IAAIZ,gBAAgB,CAACqE,aAAa,CAAC,EAAE;MACnCpE,OAAO,CAAC2E,KAAK,CAACC,IAAI,CAAC;QACjBC,KAAK,EAAE5E,KAAK,CAAC,iCAAiC,CAAC;QAC/C6E,KAAK,EAAE;MACT,CAAC,CAAC;IACJ;IACA;EACF,CAAC,EAAE,CAACX,MAAM,CAAC,CAAC;EAEZ,MAAMY,qBAAqB,GACzBnE,aAAa,IAAIxB,mBAAmB,CAAC0C,YAAY,CAAC;EAEpD,MAAMkD,MAAM,GAAG5G,iBAAiB,CAAC,CAAC;EAElC,MAAM6G,OAAO,GAAGjH,MAAM,CAAgB,IAAI,CAAC;EAC3C,MAAM;IAAEkH,MAAM;IAAEC;EAAmB,CAAC,GAAGhH,sBAAsB,CAAC;IAC5D8G;EACF,CAAC,CAAC;EAEF,MAAMG,cAAc,GAAGtH,WAAW,CAC/BuH,GAAW,IAAK;IACfpE,UAAU,GAAG5B,YAAY,CAACgG,GAAG,CAAC,CAAC;EACjC,CAAC,EACD,CAACpE,UAAU,CACb,CAAC;EAED,MAAMqE,sBAAsB,GAAGxH,WAAW,CACxC,CAACyH,OAAoB,EAAEC,IAAkB,KAAK;IAC5CjE,iBAAiB,CAACiB,OAAO,EAAEC,IAAI,CAAC8C,OAAO,EAAEC,IAAI,CAAC;EAChD,CAAC,EACD,EACF,CAAC;EAED,MAAMC,2BAA2B,GAAG3H,WAAW,CAAC,MAAM;IACpDc,uBAAuB,CAAC;MACtB8G,aAAa,EAAElE,WAAW,EAAEmE,MAAM;MAClChC,YAAY;MACZzC,wBAAwB;MACxB0E,cAAc,EAAGL,OAAoB,IAAK;QACxCrH,kBAAkB,CAACsG,IAAI,CAAC7E,SAAS,CAAC8E,eAAe,EAAE;UACjDC,eAAe,EAAEa,OAAO,EAAEhB;QAC5B,CAAC,CAAC;MACJ;IACF,CAAC,CAAC;EACJ,CAAC,EAAE,CAAC/C,WAAW,EAAEmC,YAAY,EAAEzC,wBAAwB,CAAC,CAAC;EAEzD,MAAM2E,eAAe,GAAG/H,WAAW,CAAC,MAAM;IACxCkD,WAAW,GAAGW,cAAc,CAAC;EAC/B,CAAC,EAAE,CAACA,cAAc,EAAEX,WAAW,CAAC,CAAC;EAEjC,MAAM8E,oBAAoB,GAAGhI,WAAW,CAAC,MAAM;IAC7C,IAAI,CAACgE,YAAY,EAAEmC,OAAO,EAAE;IAC5BZ,SAAS,CAAC;MACRY,OAAO,EAAEnC,YAAY,EAAEmC,OAAO;MAC9B8B,MAAM,EAAE,EAAE;MACVC,UAAU,EAAE5E,eAAe,IAAI3B,eAAe,CAACwG,MAAM;MACrDC,SAAS,EAAEpE,YAAY,EAAEqE,QAAQ,IAAI;IACvC,CAAC,CAAC;EACJ,CAAC,EAAE,CACD/E,eAAe,EACfU,YAAY,EAAEmC,OAAO,EACrBZ,SAAS,EACTvB,YAAY,EAAEqE,QAAQ,CACvB,CAAC;EAEF,oBACE9F,KAAA,CAAC/B,UAAU,CAAC8H,IAAI;IAACC,IAAI;IAACC,KAAK,EAAE,CAAC,QAAQ,CAAE;IAAAC,QAAA,gBACtCpG,IAAA,CAAClB,gBAAgB;MACf0C,cAAc,EAAEA,cAAe;MAC/BnB,YAAY,EAAEA,YAAa;MAC3BI,aAAa,EAAEmE,qBAAsB;MACrClE,MAAM,EAAEA,MAAM,IAAIsB,iBAAkB;MACpCrB,aAAa,EAAEA,aAAc;MAC7BC,gBAAgB,EAAEA,gBAAiB;MACnCC,WAAW,EAAE6E,eAAgB;MAC7BW,aAAa,EAAEX;IAAgB,CAChC,CAAC,eAEF1F,IAAA,CAACxB,gBAAgB;MACf+D,QAAQ,EAAEe,cAAe;MACzBiC,aAAa,EAAElE,WAAW,EAAEmE,MAAO;MACnCc,OAAO,EAAEhB;IAA4B,CACtC,CAAC,eAEFtF,IAAA,CAACjB,cAAc;MACbwD,QAAQ,EAAEA,QAAS;MACnBf,cAAc,EAAEA,cAAe;MAC/BT,wBAAwB,EAAEA,wBAAyB;MACnDU,SAAS,EAAEe,WAAW,IAAId,qBAAqB,IAAImC,gBAAiB;MACpE0C,aAAa,EAAE5D,kBAAmB;MAClCE,UAAU,EAAEA,UAAW;MACvBJ,cAAc,EAAEA,cAAe;MAC/B+D,aAAa,EAAE5D,kBAAmB;MAClCE,UAAU,EAAEA,UAAW;MACvBJ,cAAc,EAAEA,cAAe;MAC/B+D,YAAY,EAAEvE,gBAAiB;MAC/BpB,UAAU,EAAEmE,cAAe;MAC3ByB,WAAW,EAAEvB,sBAAuB;MACpCL,OAAO,EAAEA,OAAQ;MACjBC,MAAM,EAAEA,MAAO;MACfC,kBAAkB,EAAEA,kBAAmB;MACvC2B,cAAc,EAAE9B,MAAM,CAAC+B;IAAO,CAC/B,CAAC,eAEF5G,IAAA,CAAChB,YAAY;MACX6H,cAAc,EAAEtE,QAAQ,EAAEuE,MAAM,KAAK,CAAE;MACvC9F,aAAa,EAAEA,aAAc;MAC7Bc,iBAAiB,EAAEA,iBAAkB;MACrCiF,gBAAgB,EAAEpB,oBAAqB;MACvCvC,cAAc,EAAEA;IAAe,CAChC,CAAC,eAEFpD,IAAA,CAACtB,gBAAgB;MAACsI,GAAG,EAAE7F;IAAe,CAAE,CAAC,eACzCnB,IAAA,CAACb,qBAAqB;MACpB6H,GAAG,EAAE5F,iBAAkB;MACvBmE,aAAa,EAAElE,WAAW,EAAEmE,MAAO;MACnCzE,wBAAwB,EAAEA,wBAAyB;MACnDkG,YAAY,EAAE1D,UAAW;MACzB2D,cAAc,EAAE1D,YAAa;MAC7BuB,MAAM,EAAEA;IAAO,CAChB,CAAC;EAAA,CACa,CAAC;AAEtB,CACF,CAAC;AAED,eAAgBoC,KAAsB,IAAK;EACzC,MAAMC,YAAY,GAAGvI,YAAY,CAAEyC,CAAC,IAAKA,CAAC,CAACC,IAAI,IAAI,IAAI,CAAC;EAExD,MAAML,UAAU,GAAG7C,aAAa,CAAC,CAAC;;EAElC;EACA,IAAI,CAAC+I,YAAY,EAAE;IACjB,oBACElH,KAAA,CAAC/B,UAAU,CAAC8H,IAAI;MAACC,IAAI;MAACC,KAAK,EAAE,CAAC,QAAQ,CAAE;MAAAC,QAAA,gBACtCpG,IAAA,CAAC5B,WAAW,CAACiJ,MAAM;QACjB1C,KAAK,EAAC,OAAO;QACb2C,SAAS,EAAC,MAAM;QAChBC,IAAI,EAAC,OAAO;QACZC,kBAAkB;QAClBC,MAAM;QACNC,UAAU,EAAE;UACVC,EAAE,EAAE,MAAM;UACVC,IAAI,EAAE;YACJL,IAAI,EAAE,EAAE;YACRM,UAAU,EAAE,cAAc;YAC1BC,cAAc,EAAE,YAAY;YAC5BC,SAAS,EAAE7J,OAAO,CAAC8J,OAAO,CAACC;UAC7B,CAAC;UACD3B,OAAO,EAAEpF,UAAU,CAACe;QACtB;MAAE,CACH,CAAC,eACFjC,IAAA,CAAC7B,UAAU,CAAC+J,IAAI;QAAChC,IAAI;QAACiC,MAAM;QAAA/B,QAAA,eAC1BpG,IAAA,CAAClC,iBAAiB;UAACyJ,IAAI,EAAC,OAAO;UAACa,KAAK,EAAElK,OAAO,CAAC8J,OAAO,CAACC;QAAO,CAAE;MAAC,CAClD,CAAC;IAAA,CACH,CAAC;EAEtB;EAEA,oBAAOjI,IAAA,CAACG,UAAU;IAAA,GAAKgH;EAAK,CAAG,CAAC;AAClC,CAAC","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["memo","useCallback","useEffect","useRef","ActivityIndicator","DeviceEventEmitter","useKeyboardScrollToEnd","useSafeAreaInsets","KColors","KContainer","KNavigation","useNavigation","useRoute","usePinMessage","PinnedMessageBar","openPinnedMessagesSheet","MediaViewerModal","useConversation","useConversationStore","useUserStore","ChatDetailHeader","ChatListLegend","ChatComposer","shouldShowAddMember","normalizeUrl","MessageToolboxOverlay","useGetConversationDetail","useGetConversationTarget","GroupJoinSource","useMessages","ChatEvent","useSetIsShowFLashMessage","useJoinGroup","useGroupAccessGuard","UIUtils","trans","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","subscription","addListener","TargetMessageUnavailable","toast","open","title","theme","remove","params","targetMessage","find","m","clientMsgID","emit","ScrollToMessage","clientMessageId","resolvedShowAddMember","insets","listRef","freeze","scrollMessageToEnd","handlePressUrl","url","handleMessageLongPress","message","rect","groupPosition","handlePressPinnedMessageBar","currentUserId","userID","onPressMessage","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","props","isUserLoaded","Header","alignment","size","disableCenterSpace","shadow","leftButton","id","icon","vectorName","vectorProvider","tintColor","primary","normal","View","center","color"],"sourceRoot":"../../../../src","sources":["screens/chat-detail/ChatDetail.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import { memo, useCallback, useMemo, useEffect, useRef, useState } from 'react';
|
|
4
|
-
import { ActivityIndicator, DeviceEventEmitter,
|
|
4
|
+
import { ActivityIndicator, DeviceEventEmitter, 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 { KeyboardEvents } from 'react-native-keyboard-controller';
|
|
7
|
+
import { KeyboardEvents, useGenericKeyboardHandler } 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";
|
|
@@ -39,11 +39,36 @@ const BUTTON_FADE_CONFIG = {
|
|
|
39
39
|
duration: 200,
|
|
40
40
|
easing: Easing.out(Easing.ease)
|
|
41
41
|
};
|
|
42
|
+
const CONTENT_PADDING_VERTICAL = KSpacingValue['0.75rem'];
|
|
42
43
|
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
//
|
|
46
|
-
|
|
44
|
+
// How long past the duration the keyboard event reported the following loop
|
|
45
|
+
// keeps waiting for the live height to actually reach its target before giving
|
|
46
|
+
// up and snapping to it. Only a fallback: normally the loop ends the frame the
|
|
47
|
+
// keyboard does.
|
|
48
|
+
const FOLLOW_FALLBACK_MS = 120;
|
|
49
|
+
|
|
50
|
+
// How long the keyboard-following loop keeps claiming the list after its last
|
|
51
|
+
// frame. That frame's `setState` renders, lays out and emits its scroll event
|
|
52
|
+
// after the loop has returned, and that trailing event carries the same
|
|
53
|
+
// half-applied geometry the rest of the transition does.
|
|
54
|
+
const FOLLOW_SETTLE_MS = 200;
|
|
55
|
+
|
|
56
|
+
// Frames the keyboard-following loop keeps pinning after the reserved room has
|
|
57
|
+
// reached its target. The pin in the frame that sets the final padding runs
|
|
58
|
+
// before React has rendered it and before the native layout has applied, so it
|
|
59
|
+
// finds no room to scroll into. On iOS that goes unnoticed — the loop has many
|
|
60
|
+
// frames and a later one does the work — but Android's first loop frame
|
|
61
|
+
// already reports the finished height, so without a tail nothing ever scrolls
|
|
62
|
+
// and the last message stays behind the keyboard.
|
|
63
|
+
const FOLLOW_TAIL_FRAMES = 3;
|
|
64
|
+
|
|
65
|
+
// Passed as the list's `keyboardOffset` to switch KeyboardChatScrollView's own
|
|
66
|
+
// native `contentInset` off while leaving the rest of the component in place.
|
|
67
|
+
// Its `getEffectiveHeight` interpolates the live keyboard height into
|
|
68
|
+
// `[0, max(keyboardHeight - offset, 0)]`, so an offset no keyboard can exceed
|
|
69
|
+
// pins the inset at 0 for every frame of the transition. The keyboard's room is
|
|
70
|
+
// reserved as real content padding instead — see the keyboard effect below.
|
|
71
|
+
const DISABLE_NATIVE_KEYBOARD_INSET = 1_000_000;
|
|
47
72
|
const getRowMarginBottom = position => position === 'last' || position === 'solo' ? ROW_MARGIN_CLUSTER_END : ROW_MARGIN_IN_CLUSTER;
|
|
48
73
|
export const ChatListLegend = /*#__PURE__*/memo(({
|
|
49
74
|
messages = [],
|
|
@@ -95,10 +120,36 @@ export const ChatListLegend = /*#__PURE__*/memo(({
|
|
|
95
120
|
const buttonOpacity = useSharedValue(0);
|
|
96
121
|
const isAtBottomRef = useRef(true);
|
|
97
122
|
const scrollDebounceRef = useRef(undefined);
|
|
98
|
-
//
|
|
99
|
-
//
|
|
123
|
+
// The state drives the content's bottom padding; the ref is the last
|
|
124
|
+
// value acted on, read synchronously inside the keyboard listener to
|
|
125
|
+
// drop Android's repeat events before they reach React.
|
|
126
|
+
const keyboardInsetRef = useRef(0);
|
|
100
127
|
const [keyboardInset, setKeyboardInset] = useState(0);
|
|
101
|
-
|
|
128
|
+
// The keyboard's live height, written on the UI thread and sampled from
|
|
129
|
+
// the JS thread by the tween below, so the content tracks the keyboard's
|
|
130
|
+
// real position instead of a guessed easing curve.
|
|
131
|
+
//
|
|
132
|
+
// `useGenericKeyboardHandler` rather than `useKeyboardHandler` /
|
|
133
|
+
// `useReanimatedKeyboardAnimation`: those call `useResizeMode()`, which
|
|
134
|
+
// reaches in and sets Android's soft input mode — `KeyboardProvider`
|
|
135
|
+
// already owns that here. The worklet only writes a SharedValue; calling
|
|
136
|
+
// `runOnJS` (or anything that reaches JS) from a keyboard worklet
|
|
137
|
+
// reliably crashes Reanimated with a reentrant-lock assertion.
|
|
138
|
+
// True while the keyboard-following loop below is driving the list.
|
|
139
|
+
const isFollowingKeyboardRef = useRef(false);
|
|
140
|
+
const liveKeyboardHeight = useSharedValue(0);
|
|
141
|
+
useGenericKeyboardHandler({
|
|
142
|
+
onMove: e => {
|
|
143
|
+
'worklet';
|
|
144
|
+
|
|
145
|
+
liveKeyboardHeight.value = e.height;
|
|
146
|
+
},
|
|
147
|
+
onEnd: e => {
|
|
148
|
+
'worklet';
|
|
149
|
+
|
|
150
|
+
liveKeyboardHeight.value = e.height;
|
|
151
|
+
}
|
|
152
|
+
}, []);
|
|
102
153
|
const rowRefsMap = useRef(new Map());
|
|
103
154
|
// Set on a real touch-drag (`onScrollBeginDrag`), before onStartReached/
|
|
104
155
|
// onEndReached's threshold could fire. `onMomentumScrollBegin` was tried
|
|
@@ -140,14 +191,15 @@ export const ChatListLegend = /*#__PURE__*/memo(({
|
|
|
140
191
|
const node = rowRefsMap.current.get(messageId);
|
|
141
192
|
node?.measureInWindow((x, y, width, height) => {
|
|
142
193
|
if (x == null || y == null || width == null || height == null) return;
|
|
194
|
+
const groupPosition = messageDataMap.get(messageId)?.groupPosition;
|
|
143
195
|
onLongPress?.(message, {
|
|
144
196
|
x,
|
|
145
197
|
y,
|
|
146
198
|
width,
|
|
147
199
|
height
|
|
148
|
-
});
|
|
200
|
+
}, groupPosition);
|
|
149
201
|
});
|
|
150
|
-
}, [onLongPress]);
|
|
202
|
+
}, [onLongPress, messageDataMap]);
|
|
151
203
|
const onRunFlow = useCallback(payload => {
|
|
152
204
|
runFlow(payload);
|
|
153
205
|
}, [runFlow]);
|
|
@@ -340,6 +392,14 @@ export const ChatListLegend = /*#__PURE__*/memo(({
|
|
|
340
392
|
hasUserScrolledRef.current = true;
|
|
341
393
|
}, []);
|
|
342
394
|
const handleScroll = useCallback(e => {
|
|
395
|
+
// The keyboard-following loop re-pins to the end on every frame, so
|
|
396
|
+
// the list is at the bottom for the whole transition by construction.
|
|
397
|
+
// The intermediate events it produces are not: content size and
|
|
398
|
+
// offset move a frame apart, and a reading taken between them says
|
|
399
|
+
// "not at bottom" and latches the scroll-to-bottom button on. The
|
|
400
|
+
// loop only runs when the list was already at the bottom, so there is
|
|
401
|
+
// nothing here to detect while it does.
|
|
402
|
+
if (isFollowingKeyboardRef.current) return;
|
|
343
403
|
const {
|
|
344
404
|
contentOffset,
|
|
345
405
|
contentSize,
|
|
@@ -379,6 +439,13 @@ export const ChatListLegend = /*#__PURE__*/memo(({
|
|
|
379
439
|
isAtBottomRef.current = true;
|
|
380
440
|
setShowBadge(false);
|
|
381
441
|
}, [hasMoreNew, onLoadMoreOld, scrollMessageToEnd, buttonOpacity]);
|
|
442
|
+
|
|
443
|
+
// `paddingBottom` here replaces the one `styles.content` sets via
|
|
444
|
+
// `paddingVertical`, so the base spacing has to be added back or the last
|
|
445
|
+
// message ends up flush against the composer.
|
|
446
|
+
const contentContainerStyle = useMemo(() => [styles.content, {
|
|
447
|
+
paddingBottom: CONTENT_PADDING_VERTICAL + keyboardInset
|
|
448
|
+
}], [keyboardInset]);
|
|
382
449
|
const animatedButtonStyle = useAnimatedStyle(() => ({
|
|
383
450
|
opacity: buttonOpacity.value,
|
|
384
451
|
pointerEvents: buttonOpacity.value === 0 ? 'none' : 'auto'
|
|
@@ -393,71 +460,157 @@ export const ChatListLegend = /*#__PURE__*/memo(({
|
|
|
393
460
|
};
|
|
394
461
|
}, []);
|
|
395
462
|
|
|
396
|
-
//
|
|
397
|
-
//
|
|
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.
|
|
463
|
+
// Reserves the keyboard's room on the content and keeps the list pinned
|
|
464
|
+
// to the end for the length of each keyboard transition.
|
|
403
465
|
//
|
|
404
|
-
// JS
|
|
405
|
-
// that reaching into `useKeyboardHandler`'s worklets carries.
|
|
466
|
+
// JS thread only: no worklet, so none of the reentrant-lock crash risk
|
|
467
|
+
// that reaching into `useKeyboardHandler`'s worklets carries. The one
|
|
468
|
+
// worklet involved only writes `liveKeyboardHeight`, which this reads.
|
|
406
469
|
useEffect(() => {
|
|
407
|
-
let
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
470
|
+
let pendingSettle;
|
|
471
|
+
let pendingFrame;
|
|
472
|
+
const clearPending = () => {
|
|
473
|
+
if (pendingSettle) {
|
|
474
|
+
clearTimeout(pendingSettle);
|
|
475
|
+
pendingSettle = undefined;
|
|
412
476
|
}
|
|
477
|
+
if (pendingFrame !== undefined) {
|
|
478
|
+
cancelAnimationFrame(pendingFrame);
|
|
479
|
+
pendingFrame = undefined;
|
|
480
|
+
}
|
|
481
|
+
isFollowingKeyboardRef.current = false;
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
// Follows the keyboard frame by frame instead of setting the reserved
|
|
485
|
+
// room in one step.
|
|
486
|
+
//
|
|
487
|
+
// Set in one step the layout lift lands in a single frame — measured,
|
|
488
|
+
// 72 of the 302px the content had to travel arrived as an instant jump
|
|
489
|
+
// while only the remaining 230 were animated, and `scrollToEnd`'s own
|
|
490
|
+
// ~324ms curve then finished about 100ms after the keyboard had already
|
|
491
|
+
// stopped. Sampling `liveKeyboardHeight` each frame instead means the
|
|
492
|
+
// padding, and with it the content, is wherever the keyboard actually
|
|
493
|
+
// is — no easing curve to guess at, and the two cannot drift apart.
|
|
494
|
+
//
|
|
495
|
+
// `duration` is only a bound, for a transition whose reported height
|
|
496
|
+
// never quite reaches the event's target.
|
|
497
|
+
const followKeyboard = (to, duration) => {
|
|
498
|
+
const startedAt = Date.now();
|
|
499
|
+
const startedFrom = Math.max(Math.abs(liveKeyboardHeight.value) - keyboardOffset, 0);
|
|
500
|
+
let tailFrames = 0;
|
|
501
|
+
isFollowingKeyboardRef.current = true;
|
|
502
|
+
const step = () => {
|
|
503
|
+
const live = Math.max(Math.abs(liveKeyboardHeight.value) - keyboardOffset, 0);
|
|
504
|
+
// Tracks the keyboard rather than a timer, so the content never
|
|
505
|
+
// keeps travelling after the keyboard has stopped. The elapsed
|
|
506
|
+
// check is only a fallback for a transition whose reported height
|
|
507
|
+
// never quite reaches the target.
|
|
508
|
+
const reached = Math.abs(live - to) <= 1;
|
|
509
|
+
const timedOut = !reached && Date.now() - startedAt >= duration + FOLLOW_FALLBACK_MS;
|
|
510
|
+
// Whether the keyboard moved at all decides what a timeout means. A
|
|
511
|
+
// `keyboardWillHide` the keyboard does not act on leaves the live
|
|
512
|
+
// height exactly where it was, and forcing the target there would
|
|
513
|
+
// collapse the room out from under a keyboard that is still up —
|
|
514
|
+
// which is what the old hide debounce was guarding against, at the
|
|
515
|
+
// cost of the list dropping a beat after the keyboard had gone. A
|
|
516
|
+
// real transition that merely stops a few px short of the height
|
|
517
|
+
// the event reported (iOS, measured ~4px) still has to land exactly
|
|
518
|
+
// on the target.
|
|
519
|
+
const moved = Math.abs(live - startedFrom) > 1;
|
|
520
|
+
if (reached) {
|
|
521
|
+
tailFrames += 1;
|
|
522
|
+
}
|
|
523
|
+
const done = timedOut || tailFrames >= FOLLOW_TAIL_FRAMES;
|
|
524
|
+
const settleTo = reached || timedOut && moved ? to : live;
|
|
525
|
+
setKeyboardInset(settleTo);
|
|
526
|
+
if (settleTo !== to) {
|
|
527
|
+
// Record what the room actually ended up as, or the dedupe in
|
|
528
|
+
// `applyInset` would swallow the next real transition to `to`.
|
|
529
|
+
keyboardInsetRef.current = settleTo;
|
|
530
|
+
}
|
|
531
|
+
// Re-pin every frame. Growing the padding only moves the content on
|
|
532
|
+
// its own while there is `alignItemsAtEndPadding` left to absorb
|
|
533
|
+
// it; once that is gone — any conversation taller than the viewport
|
|
534
|
+
// — the padding just extends the range and nothing moves until
|
|
535
|
+
// something scrolls, and `maintainScrollAtEnd` does not follow a
|
|
536
|
+
// content size change frame by frame (measured: one scroll event,
|
|
537
|
+
// at the very end). Unanimated on purpose: the keyboard is the
|
|
538
|
+
// animation, and an animated scroll here would start a second curve
|
|
539
|
+
// on top of it every frame.
|
|
540
|
+
listRef.current?.scrollToEnd({
|
|
541
|
+
animated: false
|
|
542
|
+
});
|
|
543
|
+
if (done) {
|
|
544
|
+
pendingFrame = undefined;
|
|
545
|
+
// The loop only runs from a list that was at the bottom and it
|
|
546
|
+
// has just pinned it there again, so record that rather than
|
|
547
|
+
// waiting to re-derive it from a scroll event.
|
|
548
|
+
isAtBottomRef.current = true;
|
|
549
|
+
buttonOpacity.value = withTiming(0, BUTTON_FADE_CONFIG);
|
|
550
|
+
setShowBadge(false);
|
|
551
|
+
pendingSettle = setTimeout(() => {
|
|
552
|
+
pendingSettle = undefined;
|
|
553
|
+
isFollowingKeyboardRef.current = false;
|
|
554
|
+
}, FOLLOW_SETTLE_MS);
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
pendingFrame = requestAnimationFrame(step);
|
|
558
|
+
};
|
|
559
|
+
pendingFrame = requestAnimationFrame(step);
|
|
413
560
|
};
|
|
414
|
-
const applyInset = nextInset => {
|
|
415
|
-
// Android
|
|
416
|
-
//
|
|
417
|
-
//
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
//
|
|
422
|
-
//
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
561
|
+
const applyInset = (nextInset, duration) => {
|
|
562
|
+
// Android's event stream flaps willShow -> willHide -> willShow every
|
|
563
|
+
// ~1.3s for as long as the keyboard stays open (measured), so a
|
|
564
|
+
// repeated height must not restart the follow loop.
|
|
565
|
+
if (keyboardInsetRef.current === nextInset) return;
|
|
566
|
+
keyboardInsetRef.current = nextInset;
|
|
567
|
+
|
|
568
|
+
// Reserve the keyboard's room as real bottom padding on the content
|
|
569
|
+
// and let LegendList own it end to end. The native `contentInset` is
|
|
570
|
+
// switched off (see `keyboardOffset` on the list below), so this is
|
|
571
|
+
// the only thing compensating for the keyboard.
|
|
572
|
+
//
|
|
573
|
+
// The point is an invariant, not an offset: the scroll view's
|
|
574
|
+
// maximum content offset has to BE the visually correct position.
|
|
575
|
+
// Otherwise there is a band of legal resting offsets that all look
|
|
576
|
+
// wrong, and a drag settles somewhere inside it — which is the blank
|
|
577
|
+
// gap above the composer.
|
|
578
|
+
//
|
|
579
|
+
// A native inset cannot hold that invariant here. It widens the
|
|
580
|
+
// scroll range by the full keyboard height, but LegendList
|
|
581
|
+
// independently shrinks `alignItemsAtEndPadding` by the same amount
|
|
582
|
+
// and lifts the content through layout as well. Measured on a short
|
|
583
|
+
// conversation: the layout lift covered 258 of the 302 needed, so
|
|
584
|
+
// only 44 of scrolling was left to do while the range still ran to
|
|
585
|
+
// 302 — 258px of pure slack. As content padding the same 302 goes
|
|
586
|
+
// into `contentSize`, so `alignItemsAtEndPadding` falls out to zero,
|
|
587
|
+
// the range is exactly the lift required, and `scrollToEnd` (which
|
|
588
|
+
// reads LegendList's own metrics, and already offsets itself by
|
|
589
|
+
// `stylePaddingBottom`) lands on it.
|
|
590
|
+
//
|
|
591
|
+
// Skipped when the user has scrolled away from the bottom — opening
|
|
592
|
+
// the keyboard shouldn't yank them back down — but the padding still
|
|
593
|
+
// has to change, or the range would be wrong for them too.
|
|
594
|
+
if (!isAtBottomRef.current) {
|
|
595
|
+
setKeyboardInset(nextInset);
|
|
596
|
+
return;
|
|
427
597
|
}
|
|
428
|
-
|
|
598
|
+
followKeyboard(nextInset, duration);
|
|
429
599
|
};
|
|
430
600
|
const willShow = KeyboardEvents.addListener('keyboardWillShow', e => {
|
|
431
|
-
|
|
432
|
-
applyInset(Math.max(e.height - keyboardOffset, 0));
|
|
601
|
+
clearPending();
|
|
602
|
+
applyInset(Math.max(e.height - keyboardOffset, 0), e.duration);
|
|
433
603
|
});
|
|
434
|
-
const willHide = KeyboardEvents.addListener('keyboardWillHide',
|
|
435
|
-
|
|
436
|
-
|
|
604
|
+
const willHide = KeyboardEvents.addListener('keyboardWillHide', e => {
|
|
605
|
+
clearPending();
|
|
606
|
+
applyInset(0, e.duration);
|
|
437
607
|
});
|
|
438
608
|
return () => {
|
|
439
|
-
|
|
609
|
+
clearPending();
|
|
440
610
|
willShow.remove();
|
|
441
611
|
willHide.remove();
|
|
442
612
|
};
|
|
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]);
|
|
613
|
+
}, [buttonOpacity, keyboardOffset, listRef, liveKeyboardHeight]);
|
|
461
614
|
|
|
462
615
|
// This component can stay mounted across a conversationId change (e.g.
|
|
463
616
|
// navigation.replace reusing the same screen instance), so this ref must
|
|
@@ -575,22 +728,28 @@ export const ChatListLegend = /*#__PURE__*/memo(({
|
|
|
575
728
|
,
|
|
576
729
|
drawDistance: 800,
|
|
577
730
|
freeze: freeze,
|
|
578
|
-
keyboardOffset:
|
|
579
|
-
//
|
|
580
|
-
//
|
|
581
|
-
// top
|
|
582
|
-
//
|
|
583
|
-
//
|
|
584
|
-
//
|
|
585
|
-
//
|
|
586
|
-
// re-
|
|
731
|
+
keyboardOffset: DISABLE_NATIVE_KEYBOARD_INSET
|
|
732
|
+
// iOS only. Left on, React Native recomputes and applies its own
|
|
733
|
+
// `contentInset` every time the keyboard moves — measured here as
|
|
734
|
+
// {top: 59, bottom: keyboardHeight}, both wrong. The bottom value
|
|
735
|
+
// over-insets by the safe area, and the phantom top one is worse:
|
|
736
|
+
// iOS rests a scroll view at `-contentInset.top`.
|
|
737
|
+
// That resting offset is what put the content 59pt low and hid the
|
|
738
|
+
// last message behind the composer the moment a touch let UIKit
|
|
739
|
+
// re-clamp. legend-list's own KeyboardAvoidingLegendList disables
|
|
740
|
+
// this for the same reason.
|
|
741
|
+
,
|
|
742
|
+
automaticallyAdjustContentInsets: false
|
|
743
|
+
// No scroll shift from the library either — the content padding
|
|
744
|
+
// above is the single compensator. Measured with it on: a 302px
|
|
745
|
+
// keyboard produced a 604px lift, exactly double.
|
|
587
746
|
,
|
|
588
747
|
keyboardLiftBehavior: "never",
|
|
589
748
|
scrollEventThrottle: 16,
|
|
590
749
|
onScroll: handleScroll,
|
|
591
750
|
onScrollBeginDrag: handleScrollBeginDrag,
|
|
592
751
|
onLoad: handleListLoad,
|
|
593
|
-
contentContainerStyle:
|
|
752
|
+
contentContainerStyle: contentContainerStyle,
|
|
594
753
|
scrollIndicatorInsets: {
|
|
595
754
|
right: 1
|
|
596
755
|
},
|
|
@@ -635,7 +794,7 @@ const styles = StyleSheet.create({
|
|
|
635
794
|
position: 'relative'
|
|
636
795
|
},
|
|
637
796
|
content: {
|
|
638
|
-
paddingVertical:
|
|
797
|
+
paddingVertical: CONTENT_PADDING_VERTICAL,
|
|
639
798
|
flexGrow: 1
|
|
640
799
|
},
|
|
641
800
|
scrollToBottomButton: {
|