@ethora/chat-component-rn 26.7.8 → 26.7.10
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/CHANGELOG.md +3 -2
- package/README.md +10 -0
- package/lib/commonjs/assets/icons.js +2 -2
- package/lib/commonjs/assets/icons.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatRoom.js +76 -19
- package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MediaMessage.js +8 -5
- package/lib/commonjs/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MessageContainer.js +5 -1
- package/lib/commonjs/components/MainComponents/MessageContainer.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MessageList.js +2 -1
- package/lib/commonjs/components/MainComponents/MessageList.js.map +1 -1
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +1 -51
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +51 -12
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/styled/LastMessageFile.js +12 -1
- package/lib/commonjs/components/RoomComponents/styled/LastMessageFile.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/styled/LastMessagePhoto.js +13 -2
- package/lib/commonjs/components/RoomComponents/styled/LastMessagePhoto.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/styled/LastMessageVideo.js +13 -2
- package/lib/commonjs/components/RoomComponents/styled/LastMessageVideo.js.map +1 -1
- package/lib/commonjs/components/styled/MessageImage.js +3 -1
- package/lib/commonjs/components/styled/MessageImage.js.map +1 -1
- package/lib/commonjs/components/styled/UnsupportedType.js +14 -4
- package/lib/commonjs/components/styled/UnsupportedType.js.map +1 -1
- package/lib/commonjs/components/styled/VideoMessage.js +3 -1
- package/lib/commonjs/components/styled/VideoMessage.js.map +1 -1
- package/lib/commonjs/context/xmppProvider.js +95 -36
- package/lib/commonjs/context/xmppProvider.js.map +1 -1
- package/lib/commonjs/helpers/createMessageFromXml.js +19 -1
- package/lib/commonjs/helpers/createMessageFromXml.js.map +1 -1
- package/lib/commonjs/helpers/getDisplayFileName.js +79 -0
- package/lib/commonjs/helpers/getDisplayFileName.js.map +1 -0
- package/lib/commonjs/helpers/getServerReadTimestamp.js +188 -0
- package/lib/commonjs/helpers/getServerReadTimestamp.js.map +1 -0
- package/lib/commonjs/helpers/initXmppRooms.js +9 -7
- package/lib/commonjs/helpers/initXmppRooms.js.map +1 -1
- package/lib/commonjs/helpers/insertMessageWithDelimiter.js +51 -9
- package/lib/commonjs/helpers/insertMessageWithDelimiter.js.map +1 -1
- package/lib/commonjs/helpers/isOwnMessage.js +75 -0
- package/lib/commonjs/helpers/isOwnMessage.js.map +1 -0
- package/lib/commonjs/helpers/keyboardLayout.js +12 -2
- package/lib/commonjs/helpers/keyboardLayout.js.map +1 -1
- package/lib/commonjs/helpers/mimeToExtension.js +6 -14
- package/lib/commonjs/helpers/mimeToExtension.js.map +1 -1
- package/lib/commonjs/helpers/msgSortableMs.js +37 -0
- package/lib/commonjs/helpers/msgSortableMs.js.map +1 -0
- package/lib/commonjs/hooks/useChatRoomFocus.js +45 -12
- package/lib/commonjs/hooks/useChatRoomFocus.js.map +1 -1
- package/lib/commonjs/hooks/useChatWrapperInit.js +12 -7
- package/lib/commonjs/hooks/useChatWrapperInit.js.map +1 -1
- package/lib/commonjs/hooks/useLogout.js +8 -0
- package/lib/commonjs/hooks/useLogout.js.map +1 -1
- package/lib/commonjs/i18n/strings.js +0 -18
- package/lib/commonjs/i18n/strings.js.map +1 -1
- package/lib/commonjs/networking/api-requests/rooms.api.js +0 -13
- package/lib/commonjs/networking/api-requests/rooms.api.js.map +1 -1
- package/lib/commonjs/networking/stanzaHandlers.js +20 -2
- package/lib/commonjs/networking/stanzaHandlers.js.map +1 -1
- package/lib/commonjs/networking/xmpp/flushLastViewedToPrivateStore.js +45 -11
- package/lib/commonjs/networking/xmpp/flushLastViewedToPrivateStore.js.map +1 -1
- package/lib/commonjs/networking/xmppClient.js +36 -2
- package/lib/commonjs/networking/xmppClient.js.map +1 -1
- package/lib/commonjs/roomStore/index.js +35 -2
- package/lib/commonjs/roomStore/index.js.map +1 -1
- package/lib/commonjs/roomStore/persistence.js +200 -11
- package/lib/commonjs/roomStore/persistence.js.map +1 -1
- package/lib/commonjs/roomStore/roomsSlice.js +148 -37
- package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
- package/lib/module/assets/icons.js +1 -1
- package/lib/module/assets/icons.js.map +1 -1
- package/lib/module/components/MainComponents/ChatRoom.js +77 -20
- package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/module/components/MainComponents/MediaMessage.js +9 -6
- package/lib/module/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/module/components/MainComponents/MessageContainer.js +5 -1
- package/lib/module/components/MainComponents/MessageContainer.js.map +1 -1
- package/lib/module/components/MainComponents/MessageList.js +2 -1
- package/lib/module/components/MainComponents/MessageList.js.map +1 -1
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +3 -53
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +52 -13
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/module/components/RoomComponents/styled/LastMessageFile.js +12 -1
- package/lib/module/components/RoomComponents/styled/LastMessageFile.js.map +1 -1
- package/lib/module/components/RoomComponents/styled/LastMessagePhoto.js +13 -2
- package/lib/module/components/RoomComponents/styled/LastMessagePhoto.js.map +1 -1
- package/lib/module/components/RoomComponents/styled/LastMessageVideo.js +13 -2
- package/lib/module/components/RoomComponents/styled/LastMessageVideo.js.map +1 -1
- package/lib/module/components/styled/MessageImage.js +3 -1
- package/lib/module/components/styled/MessageImage.js.map +1 -1
- package/lib/module/components/styled/UnsupportedType.js +14 -4
- package/lib/module/components/styled/UnsupportedType.js.map +1 -1
- package/lib/module/components/styled/VideoMessage.js +3 -1
- package/lib/module/components/styled/VideoMessage.js.map +1 -1
- package/lib/module/context/xmppProvider.js +96 -37
- package/lib/module/context/xmppProvider.js.map +1 -1
- package/lib/module/helpers/createMessageFromXml.js +19 -1
- package/lib/module/helpers/createMessageFromXml.js.map +1 -1
- package/lib/module/helpers/getDisplayFileName.js +73 -0
- package/lib/module/helpers/getDisplayFileName.js.map +1 -0
- package/lib/module/helpers/getServerReadTimestamp.js +181 -0
- package/lib/module/helpers/getServerReadTimestamp.js.map +1 -0
- package/lib/module/helpers/initXmppRooms.js +9 -7
- package/lib/module/helpers/initXmppRooms.js.map +1 -1
- package/lib/module/helpers/insertMessageWithDelimiter.js +52 -9
- package/lib/module/helpers/insertMessageWithDelimiter.js.map +1 -1
- package/lib/module/helpers/isOwnMessage.js +70 -0
- package/lib/module/helpers/isOwnMessage.js.map +1 -0
- package/lib/module/helpers/keyboardLayout.js +12 -2
- package/lib/module/helpers/keyboardLayout.js.map +1 -1
- package/lib/module/helpers/mimeToExtension.js +6 -13
- package/lib/module/helpers/mimeToExtension.js.map +1 -1
- package/lib/module/helpers/msgSortableMs.js +32 -0
- package/lib/module/helpers/msgSortableMs.js.map +1 -0
- package/lib/module/hooks/useChatRoomFocus.js +46 -13
- package/lib/module/hooks/useChatRoomFocus.js.map +1 -1
- package/lib/module/hooks/useChatWrapperInit.js +12 -7
- package/lib/module/hooks/useChatWrapperInit.js.map +1 -1
- package/lib/module/hooks/useLogout.js +8 -0
- package/lib/module/hooks/useLogout.js.map +1 -1
- package/lib/module/i18n/strings.js +0 -18
- package/lib/module/i18n/strings.js.map +1 -1
- package/lib/module/networking/api-requests/rooms.api.js +0 -12
- package/lib/module/networking/api-requests/rooms.api.js.map +1 -1
- package/lib/module/networking/stanzaHandlers.js +20 -2
- package/lib/module/networking/stanzaHandlers.js.map +1 -1
- package/lib/module/networking/xmpp/flushLastViewedToPrivateStore.js +45 -11
- package/lib/module/networking/xmpp/flushLastViewedToPrivateStore.js.map +1 -1
- package/lib/module/networking/xmppClient.js +36 -2
- package/lib/module/networking/xmppClient.js.map +1 -1
- package/lib/module/roomStore/index.js +37 -4
- package/lib/module/roomStore/index.js.map +1 -1
- package/lib/module/roomStore/persistence.js +197 -11
- package/lib/module/roomStore/persistence.js.map +1 -1
- package/lib/module/roomStore/roomsSlice.js +136 -33
- package/lib/module/roomStore/roomsSlice.js.map +1 -1
- package/lib/typescript/assets/icons.d.ts +0 -8
- package/lib/typescript/assets/icons.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MediaMessage.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MessageContainer.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MessageList.d.ts.map +1 -1
- package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
- package/lib/typescript/components/RoomComponents/styled/LastMessageFile.d.ts +1 -1
- package/lib/typescript/components/RoomComponents/styled/LastMessageFile.d.ts.map +1 -1
- package/lib/typescript/components/RoomComponents/styled/LastMessagePhoto.d.ts +1 -1
- package/lib/typescript/components/RoomComponents/styled/LastMessagePhoto.d.ts.map +1 -1
- package/lib/typescript/components/RoomComponents/styled/LastMessageVideo.d.ts +1 -1
- package/lib/typescript/components/RoomComponents/styled/LastMessageVideo.d.ts.map +1 -1
- package/lib/typescript/components/styled/MessageImage.d.ts +6 -0
- package/lib/typescript/components/styled/MessageImage.d.ts.map +1 -1
- package/lib/typescript/components/styled/UnsupportedType.d.ts.map +1 -1
- package/lib/typescript/components/styled/VideoMessage.d.ts +6 -0
- package/lib/typescript/components/styled/VideoMessage.d.ts.map +1 -1
- package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
- package/lib/typescript/helpers/createMessageFromXml.d.ts.map +1 -1
- package/lib/typescript/helpers/getAvatarColor.d.ts +1 -1
- package/lib/typescript/helpers/getDisplayFileName.d.ts +49 -0
- package/lib/typescript/helpers/getDisplayFileName.d.ts.map +1 -0
- package/lib/typescript/helpers/getServerReadTimestamp.d.ts +108 -0
- package/lib/typescript/helpers/getServerReadTimestamp.d.ts.map +1 -0
- package/lib/typescript/helpers/initXmppRooms.d.ts.map +1 -1
- package/lib/typescript/helpers/insertMessageWithDelimiter.d.ts +1 -1
- package/lib/typescript/helpers/insertMessageWithDelimiter.d.ts.map +1 -1
- package/lib/typescript/helpers/isOwnMessage.d.ts +36 -0
- package/lib/typescript/helpers/isOwnMessage.d.ts.map +1 -0
- package/lib/typescript/helpers/keyboardLayout.d.ts +5 -1
- package/lib/typescript/helpers/keyboardLayout.d.ts.map +1 -1
- package/lib/typescript/helpers/mimeToExtension.d.ts +0 -15
- package/lib/typescript/helpers/mimeToExtension.d.ts.map +1 -1
- package/lib/typescript/helpers/msgSortableMs.d.ts +2 -0
- package/lib/typescript/helpers/msgSortableMs.d.ts.map +1 -0
- package/lib/typescript/hooks/useChatRoomFocus.d.ts +4 -1
- package/lib/typescript/hooks/useChatRoomFocus.d.ts.map +1 -1
- package/lib/typescript/hooks/useChatWrapperInit.d.ts.map +1 -1
- package/lib/typescript/hooks/useLogout.d.ts.map +1 -1
- package/lib/typescript/i18n/strings.d.ts.map +1 -1
- package/lib/typescript/networking/api-requests/rooms.api.d.ts +0 -1
- package/lib/typescript/networking/api-requests/rooms.api.d.ts.map +1 -1
- package/lib/typescript/networking/stanzaHandlers.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/flushLastViewedToPrivateStore.d.ts +9 -2
- package/lib/typescript/networking/xmpp/flushLastViewedToPrivateStore.d.ts.map +1 -1
- package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
- package/lib/typescript/roomStore/index.d.ts.map +1 -1
- package/lib/typescript/roomStore/persistence.d.ts +18 -1
- package/lib/typescript/roomStore/persistence.d.ts.map +1 -1
- package/lib/typescript/roomStore/roomsSlice.d.ts +42 -3
- package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
- package/lib/typescript/types/models/room.model.d.ts +0 -1
- package/lib/typescript/types/models/room.model.d.ts.map +1 -1
- package/lib/typescript/types/types.d.ts +1 -1
- package/lib/typescript/types/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/assets/icons.tsx +0 -24
- package/src/components/MainComponents/ChatRoom.tsx +81 -19
- package/src/components/MainComponents/MediaMessage.tsx +8 -5
- package/src/components/MainComponents/MessageContainer.tsx +5 -1
- package/src/components/MainComponents/MessageList.tsx +2 -1
- package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +2 -36
- package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +63 -26
- package/src/components/RoomComponents/styled/LastMessageFile.tsx +14 -2
- package/src/components/RoomComponents/styled/LastMessagePhoto.tsx +14 -2
- package/src/components/RoomComponents/styled/LastMessageVideo.tsx +14 -2
- package/src/components/styled/MessageImage.tsx +8 -1
- package/src/components/styled/UnsupportedType.tsx +14 -4
- package/src/components/styled/VideoMessage.tsx +8 -1
- package/src/context/xmppProvider.tsx +122 -30
- package/src/helpers/createMessageFromXml.ts +20 -1
- package/src/helpers/getDisplayFileName.ts +87 -0
- package/src/helpers/getServerReadTimestamp.ts +197 -0
- package/src/helpers/initXmppRooms.tsx +9 -9
- package/src/helpers/insertMessageWithDelimiter.ts +55 -19
- package/src/helpers/isOwnMessage.ts +90 -0
- package/src/helpers/keyboardLayout.ts +23 -2
- package/src/helpers/mimeToExtension.ts +6 -22
- package/src/helpers/msgSortableMs.ts +25 -0
- package/src/hooks/useChatRoomFocus.ts +49 -9
- package/src/hooks/useChatWrapperInit.ts +12 -7
- package/src/hooks/useLogout.tsx +14 -0
- package/src/i18n/strings.ts +0 -18
- package/src/networking/api-requests/rooms.api.ts +0 -9
- package/src/networking/stanzaHandlers.ts +20 -6
- package/src/networking/xmpp/flushLastViewedToPrivateStore.ts +65 -18
- package/src/networking/xmppClient.ts +41 -2
- package/src/roomStore/index.ts +40 -4
- package/src/roomStore/persistence.ts +197 -7
- package/src/roomStore/roomsSlice.ts +158 -28
- package/src/types/models/room.model.ts +0 -1
- package/src/types/types.ts +14 -1
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
4
4
|
import { encryptForPersist, decryptFromPersist } from '../helpers/persistCrypto';
|
|
5
|
-
|
|
6
5
|
// -------------------------------------------------------------------
|
|
7
6
|
// Lightweight RN persistence layer. Mirrors what redux-persist gives
|
|
8
7
|
// the web component:
|
|
@@ -21,11 +20,23 @@ import { encryptForPersist, decryptFromPersist } from '../helpers/persistCrypto'
|
|
|
21
20
|
|
|
22
21
|
const KEY_CHAT = '@ethora/persist:chatSettingStore';
|
|
23
22
|
const KEY_ROOMS = '@ethora/persist:rooms';
|
|
23
|
+
// bug #39: a failed send needs to survive a relaunch as "failed / tap
|
|
24
|
+
// to retry", not silently render as delivered. `roomHeapStore.failedMessages`
|
|
25
|
+
// is the map the bubble reads (`isFailed = failedMessages[id]`, see
|
|
26
|
+
// Message.tsx / useMessageHeapState): it lives in a separate, previously
|
|
27
|
+
// non-persisted slice from `rooms`, so it gets its own key here.
|
|
28
|
+
const KEY_HEAP = '@ethora/persist:roomHeap';
|
|
24
29
|
|
|
25
30
|
// Per-room message cap on disk. Mirror this value in `roomsSlice`'s
|
|
26
31
|
// in-memory cap (see `enforceMessageCap`) so the runtime and persisted
|
|
27
32
|
// shapes stay aligned.
|
|
28
33
|
export const MESSAGE_LIMIT = 100;
|
|
34
|
+
|
|
35
|
+
// Defensive cap on the number of failed-message payloads written to
|
|
36
|
+
// disk. In practice this map only grows while the user is actively
|
|
37
|
+
// sending offline, but a runaway sender (or a bug that never clears an
|
|
38
|
+
// entry) must not turn this key into an unbounded write.
|
|
39
|
+
export const MAX_PERSISTED_FAILED_MESSAGES = 200;
|
|
29
40
|
const sanitizeUser = user => {
|
|
30
41
|
if (!user) {
|
|
31
42
|
return null;
|
|
@@ -50,7 +61,14 @@ const sanitizeUser = user => {
|
|
|
50
61
|
// on reload before MAM catches up. That needs the fields the bubbles and
|
|
51
62
|
// room-list previews actually read, nothing else. Everything outside this
|
|
52
63
|
// list is either re-derived on render or re-fetched from the server.
|
|
53
|
-
const PERSISTED_MESSAGE_FIELDS = ['id', 'xmppId', 'xmppFrom', 'body', 'date', 'timestamp', 'roomJid', 'isSystemMessage', 'isMediafile', 'isDeleted', 'isEdited', 'isReply', 'showInChannel', 'mainMessage', 'mimetype', 'location', 'locationPreview', 'fileName', 'originalName', 'size', 'langSource', 'callLog'
|
|
64
|
+
const PERSISTED_MESSAGE_FIELDS = ['id', 'xmppId', 'xmppFrom', 'body', 'date', 'timestamp', 'roomJid', 'isSystemMessage', 'isMediafile', 'isDeleted', 'isEdited', 'isReply', 'showInChannel', 'mainMessage', 'mimetype', 'location', 'locationPreview', 'fileName', 'originalName', 'size', 'langSource', 'callLog',
|
|
65
|
+
// bug #39: without this, a message that was still in flight (no
|
|
66
|
+
// server echo yet) at kill time comes back from disk indistinguishable
|
|
67
|
+
// from a normal delivered message, so the bubble renders it as sent.
|
|
68
|
+
// Persisting `pending` lets the boot-time scan (see
|
|
69
|
+
// computeBootTimeFailures below) find exactly the messages that never
|
|
70
|
+
// got confirmed and flip them to failed instead.
|
|
71
|
+
'pending'];
|
|
54
72
|
|
|
55
73
|
// The sender identity that rides along on every message over the wire
|
|
56
74
|
// (senderFirstName / senderLastName / photo, which createMessageFromXml
|
|
@@ -141,6 +159,167 @@ const sanitizeRooms = rooms => {
|
|
|
141
159
|
}
|
|
142
160
|
return out;
|
|
143
161
|
};
|
|
162
|
+
|
|
163
|
+
// Only the fields retryMessage actually needs to replay the send (see
|
|
164
|
+
// FailedMessagePayload / useSendMessage.retryMessage). In particular, the
|
|
165
|
+
// media `data` blob is trimmed to `uri/type/name/size` (the picker never
|
|
166
|
+
// hands us auth material, but this stays defensive against a future
|
|
167
|
+
// picker change smuggling extra fields, or a huge inline payload, into
|
|
168
|
+
// `data`).
|
|
169
|
+
const sanitizeMediaData = data => {
|
|
170
|
+
if (!data || typeof data !== 'object') {
|
|
171
|
+
return {};
|
|
172
|
+
}
|
|
173
|
+
const out = {};
|
|
174
|
+
if (typeof data.uri === 'string') {
|
|
175
|
+
out.uri = data.uri;
|
|
176
|
+
}
|
|
177
|
+
if (typeof data.type === 'string') {
|
|
178
|
+
out.type = data.type;
|
|
179
|
+
}
|
|
180
|
+
if (typeof data.name === 'string') {
|
|
181
|
+
out.name = data.name;
|
|
182
|
+
}
|
|
183
|
+
if (typeof data.size === 'number') {
|
|
184
|
+
out.size = data.size;
|
|
185
|
+
}
|
|
186
|
+
return out;
|
|
187
|
+
};
|
|
188
|
+
const sanitizeFailedMessagePayload = payload => {
|
|
189
|
+
if (!payload || typeof payload !== 'object') {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
if (!payload.id || typeof payload.id !== 'string') {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
if (!payload.roomJID || typeof payload.roomJID !== 'string') {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
if (payload.kind === 'media') {
|
|
199
|
+
return {
|
|
200
|
+
kind: 'media',
|
|
201
|
+
id: payload.id,
|
|
202
|
+
roomJID: payload.roomJID,
|
|
203
|
+
data: sanitizeMediaData(payload.data),
|
|
204
|
+
type: typeof payload.type === 'string' ? payload.type : '',
|
|
205
|
+
isReply: payload.isReply,
|
|
206
|
+
isChecked: payload.isChecked,
|
|
207
|
+
mainMessage: payload.mainMessage
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
if (payload.kind === 'text') {
|
|
211
|
+
return {
|
|
212
|
+
kind: 'text',
|
|
213
|
+
id: payload.id,
|
|
214
|
+
roomJID: payload.roomJID,
|
|
215
|
+
body: typeof payload.body === 'string' ? payload.body : '',
|
|
216
|
+
isReply: payload.isReply,
|
|
217
|
+
isChecked: payload.isChecked,
|
|
218
|
+
mainMessage: payload.mainMessage
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
return null;
|
|
222
|
+
};
|
|
223
|
+
const sanitizeFailedMessages = failedMessages => {
|
|
224
|
+
if (!failedMessages || typeof failedMessages !== 'object') {
|
|
225
|
+
return {};
|
|
226
|
+
}
|
|
227
|
+
const out = {};
|
|
228
|
+
let count = 0;
|
|
229
|
+
for (const [id, payload] of Object.entries(failedMessages)) {
|
|
230
|
+
if (count >= MAX_PERSISTED_FAILED_MESSAGES) {
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
const clean = sanitizeFailedMessagePayload(payload);
|
|
234
|
+
if (clean) {
|
|
235
|
+
out[id] = clean;
|
|
236
|
+
count++;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return out;
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
// -------------------------------------------------------------------
|
|
243
|
+
// Boot-time pending -> failed conversion (bug #39).
|
|
244
|
+
//
|
|
245
|
+
// `messageHeap` (the "still sending" buffer) is intentionally NOT
|
|
246
|
+
// persisted: it's a process-lifetime thing. That means on a cold start
|
|
247
|
+
// there is no such thing as "still sending": a persisted message that
|
|
248
|
+
// carries `pending: true` never got a server echo NOR got the chance to
|
|
249
|
+
// trip the in-session watchdog (see PENDING_WATCHDOG_MS in
|
|
250
|
+
// useSendMessage.tsx) before the process died. It must render as failed
|
|
251
|
+
// with a working retry, not as delivered and not as stuck "sending...".
|
|
252
|
+
//
|
|
253
|
+
// Reconstructs the same FailedMessagePayload shape the live send path
|
|
254
|
+
// builds in useSendMessage (markMessageFailed calls), from the fields we
|
|
255
|
+
// persist per message.
|
|
256
|
+
// -------------------------------------------------------------------
|
|
257
|
+
|
|
258
|
+
export function reconstructFailedMessagePayload(message, roomJID) {
|
|
259
|
+
if (!message?.id || !roomJID) {
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
const isReply = !!message.isReply;
|
|
263
|
+
const isChecked = message.showInChannel === 'true';
|
|
264
|
+
const mainMessage = message.mainMessage;
|
|
265
|
+
if (message.isMediafile === 'true') {
|
|
266
|
+
return {
|
|
267
|
+
kind: 'media',
|
|
268
|
+
id: message.id,
|
|
269
|
+
roomJID,
|
|
270
|
+
data: sanitizeMediaData({
|
|
271
|
+
uri: message.location,
|
|
272
|
+
name: message.fileName,
|
|
273
|
+
type: message.mimetype,
|
|
274
|
+
size: message.size !== undefined && message.size !== null ? Number(message.size) : undefined
|
|
275
|
+
}),
|
|
276
|
+
type: message.mimetype || '',
|
|
277
|
+
isReply,
|
|
278
|
+
isChecked,
|
|
279
|
+
mainMessage
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
return {
|
|
283
|
+
kind: 'text',
|
|
284
|
+
id: message.id,
|
|
285
|
+
roomJID,
|
|
286
|
+
body: message.body || '',
|
|
287
|
+
isReply,
|
|
288
|
+
isChecked,
|
|
289
|
+
mainMessage
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Scan every persisted room for messages still `pending: true` that
|
|
295
|
+
* DON'T already have a restored failure entry (those are handled by the
|
|
296
|
+
* caller separately, from the persisted `failedMessages` map), and
|
|
297
|
+
* synthesize a retry-able FailedMessagePayload for each. Pure function:
|
|
298
|
+
* the caller (roomStore/index.ts) is responsible for dispatching
|
|
299
|
+
* `markMessageFailed` for the results.
|
|
300
|
+
*/
|
|
301
|
+
export function computeBootTimeFailures(rooms, alreadyFailed) {
|
|
302
|
+
if (!rooms || typeof rooms !== 'object') {
|
|
303
|
+
return [];
|
|
304
|
+
}
|
|
305
|
+
const out = [];
|
|
306
|
+
for (const [jid, room] of Object.entries(rooms)) {
|
|
307
|
+
const messages = Array.isArray(room?.messages) ? room.messages : [];
|
|
308
|
+
for (const message of messages) {
|
|
309
|
+
if (!message || !message.pending) {
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
if (alreadyFailed && alreadyFailed[message.id]) {
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
const payload = reconstructFailedMessagePayload(message, jid);
|
|
316
|
+
if (payload) {
|
|
317
|
+
out.push(payload);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return out;
|
|
322
|
+
}
|
|
144
323
|
let writeTimer = null;
|
|
145
324
|
|
|
146
325
|
/**
|
|
@@ -150,7 +329,7 @@ let writeTimer = null;
|
|
|
150
329
|
export const persistenceMiddleware = storeAPI => next => action => {
|
|
151
330
|
const result = next(action);
|
|
152
331
|
const type = action?.type || '';
|
|
153
|
-
if (!type.startsWith('roomMessages/') && !type.startsWith('chat/setUser') && !type.startsWith('chat/updateUser') && !type.startsWith('chat/refreshTokens') && !type.startsWith('chat/logout')) {
|
|
332
|
+
if (!type.startsWith('roomMessages/') && !type.startsWith('roomHeapStore/') && !type.startsWith('chat/setUser') && !type.startsWith('chat/updateUser') && !type.startsWith('chat/refreshTokens') && !type.startsWith('chat/logout')) {
|
|
154
333
|
return result;
|
|
155
334
|
}
|
|
156
335
|
if (writeTimer) {
|
|
@@ -166,8 +345,11 @@ export const persistenceMiddleware = storeAPI => next => action => {
|
|
|
166
345
|
const roomsPayload = {
|
|
167
346
|
rooms: sanitizeRooms(state.rooms?.rooms || {})
|
|
168
347
|
};
|
|
169
|
-
const
|
|
170
|
-
|
|
348
|
+
const heapPayload = {
|
|
349
|
+
failedMessages: sanitizeFailedMessages(state.roomHeapSlice?.failedMessages)
|
|
350
|
+
};
|
|
351
|
+
const [chatCipher, roomsCipher, heapCipher] = await Promise.all([encryptForPersist(JSON.stringify(chatPayload)), encryptForPersist(JSON.stringify(roomsPayload)), encryptForPersist(JSON.stringify(heapPayload))]);
|
|
352
|
+
await AsyncStorage.multiSet([[KEY_CHAT, chatCipher], [KEY_ROOMS, roomsCipher], [KEY_HEAP, heapCipher]]);
|
|
171
353
|
} catch (e) {
|
|
172
354
|
console.warn('persist write failed', e);
|
|
173
355
|
}
|
|
@@ -183,8 +365,8 @@ export const persistenceMiddleware = storeAPI => next => action => {
|
|
|
183
365
|
*/
|
|
184
366
|
export async function readPersistedState() {
|
|
185
367
|
try {
|
|
186
|
-
const [chatRaw, roomsRaw] = await AsyncStorage.multiGet([KEY_CHAT, KEY_ROOMS]);
|
|
187
|
-
const [chatPlain, roomsPlain] = await Promise.all([chatRaw[1] ? decryptFromPersist(chatRaw[1]) : Promise.resolve(null), roomsRaw[1] ? decryptFromPersist(roomsRaw[1]) : Promise.resolve(null)]);
|
|
368
|
+
const [chatRaw, roomsRaw, heapRaw] = await AsyncStorage.multiGet([KEY_CHAT, KEY_ROOMS, KEY_HEAP]);
|
|
369
|
+
const [chatPlain, roomsPlain, heapPlain] = await Promise.all([chatRaw[1] ? decryptFromPersist(chatRaw[1]) : Promise.resolve(null), roomsRaw[1] ? decryptFromPersist(roomsRaw[1]) : Promise.resolve(null), heapRaw[1] ? decryptFromPersist(heapRaw[1]) : Promise.resolve(null)]);
|
|
188
370
|
// `decryptFromPersist` returns null both for "nothing stored" and
|
|
189
371
|
// for "stored value isn't a valid envelope for the current key" —
|
|
190
372
|
// notably a plaintext blob left over from a pre-encryption install.
|
|
@@ -192,27 +374,31 @@ export async function readPersistedState() {
|
|
|
192
374
|
// as a cold start and re-hydrates from the server.
|
|
193
375
|
const chat = chatPlain ? JSON.parse(chatPlain) : null;
|
|
194
376
|
const rooms = roomsPlain ? JSON.parse(roomsPlain) : null;
|
|
377
|
+
const heap = heapPlain ? JSON.parse(heapPlain) : null;
|
|
195
378
|
return {
|
|
196
379
|
chat,
|
|
197
|
-
rooms
|
|
380
|
+
rooms,
|
|
381
|
+
heap
|
|
198
382
|
};
|
|
199
383
|
} catch (e) {
|
|
200
384
|
console.warn('persist read failed', e);
|
|
201
385
|
return {
|
|
202
386
|
chat: null,
|
|
203
|
-
rooms: null
|
|
387
|
+
rooms: null,
|
|
388
|
+
heap: null
|
|
204
389
|
};
|
|
205
390
|
}
|
|
206
391
|
}
|
|
207
392
|
export async function clearPersistedState() {
|
|
208
393
|
try {
|
|
209
|
-
await AsyncStorage.multiRemove([KEY_CHAT, KEY_ROOMS]);
|
|
394
|
+
await AsyncStorage.multiRemove([KEY_CHAT, KEY_ROOMS, KEY_HEAP]);
|
|
210
395
|
} catch (e) {
|
|
211
396
|
console.warn('persist clear failed', e);
|
|
212
397
|
}
|
|
213
398
|
}
|
|
214
399
|
export const PERSIST_KEYS = {
|
|
215
400
|
KEY_CHAT,
|
|
216
|
-
KEY_ROOMS
|
|
401
|
+
KEY_ROOMS,
|
|
402
|
+
KEY_HEAP
|
|
217
403
|
};
|
|
218
404
|
//# sourceMappingURL=persistence.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["AsyncStorage","encryptForPersist","decryptFromPersist","KEY_CHAT","KEY_ROOMS","MESSAGE_LIMIT","sanitizeUser","user","token","_token","refreshToken","_refreshToken","xmppPassword","_xmppPassword","rest","PERSISTED_MESSAGE_FIELDS","PERSISTED_MESSAGE_USER_FIELDS","REFETCHED_ROOM_FIELDS","pickDefined","source","keys","out","key","value","undefined","compactMessageForPersist","message","compact","sanitizeMessages","messages","Array","isArray","capped","length","slice","map","sanitizeRooms","rooms","jid","room","Object","entries","includes","compactRoom","usersCnt","members","field","composing","composingList","isLoading","historyPreloadState","writeTimer","persistenceMiddleware","storeAPI","next","action","result","type","startsWith","clearTimeout","setTimeout","state","getState","chatPayload","chatSettingStore","roomsPayload","chatCipher","roomsCipher","Promise","all","JSON","stringify","multiSet","e","console","warn","readPersistedState","chatRaw","roomsRaw","multiGet","chatPlain","roomsPlain","resolve","chat","parse","clearPersistedState","multiRemove","PERSIST_KEYS"],"sourceRoot":"../../../src","sources":["roomStore/persistence.ts"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["AsyncStorage","encryptForPersist","decryptFromPersist","KEY_CHAT","KEY_ROOMS","KEY_HEAP","MESSAGE_LIMIT","MAX_PERSISTED_FAILED_MESSAGES","sanitizeUser","user","token","_token","refreshToken","_refreshToken","xmppPassword","_xmppPassword","rest","PERSISTED_MESSAGE_FIELDS","PERSISTED_MESSAGE_USER_FIELDS","REFETCHED_ROOM_FIELDS","pickDefined","source","keys","out","key","value","undefined","compactMessageForPersist","message","compact","sanitizeMessages","messages","Array","isArray","capped","length","slice","map","sanitizeRooms","rooms","jid","room","Object","entries","includes","compactRoom","usersCnt","members","field","composing","composingList","isLoading","historyPreloadState","sanitizeMediaData","data","uri","type","name","size","sanitizeFailedMessagePayload","payload","id","roomJID","kind","isReply","isChecked","mainMessage","body","sanitizeFailedMessages","failedMessages","count","clean","reconstructFailedMessagePayload","showInChannel","isMediafile","location","fileName","mimetype","Number","computeBootTimeFailures","alreadyFailed","pending","push","writeTimer","persistenceMiddleware","storeAPI","next","action","result","startsWith","clearTimeout","setTimeout","state","getState","chatPayload","chatSettingStore","roomsPayload","heapPayload","roomHeapSlice","chatCipher","roomsCipher","heapCipher","Promise","all","JSON","stringify","multiSet","e","console","warn","readPersistedState","chatRaw","roomsRaw","heapRaw","multiGet","chatPlain","roomsPlain","heapPlain","resolve","chat","parse","heap","clearPersistedState","multiRemove","PERSIST_KEYS"],"sourceRoot":"../../../src","sources":["roomStore/persistence.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
|
|
4
4
|
import { insertMessageWithDelimiter } from '../helpers/insertMessageWithDelimiter';
|
|
5
|
+
import { msgSortableMs } from '../helpers/msgSortableMs';
|
|
5
6
|
// Per-room runtime message cap. Mirrors the persistence layer's
|
|
6
7
|
// MESSAGE_LIMIT so what's in memory matches what's on disk; otherwise
|
|
7
8
|
// long sessions grow the array unbounded (memory leak) and reload
|
|
@@ -127,7 +128,6 @@ function mergeHistoryIntoCache(existing, fetched) {
|
|
|
127
128
|
// fetched MAM page (the live-stream swallow doesn't cover history).
|
|
128
129
|
const ex = stripCallSignals(existing);
|
|
129
130
|
const fe = stripCallSignals(fetched);
|
|
130
|
-
const pending = ex.filter(m => m?.pending);
|
|
131
131
|
const realExisting = ex.filter(m => m && !m.pending && m.id !== 'delimiter-new');
|
|
132
132
|
const realFetched = fe.filter(m => m && m.id !== 'delimiter-new');
|
|
133
133
|
|
|
@@ -135,6 +135,28 @@ function mergeHistoryIntoCache(existing, fetched) {
|
|
|
135
135
|
if (realFetched.length === 0) {
|
|
136
136
|
return ex;
|
|
137
137
|
}
|
|
138
|
+
|
|
139
|
+
// Optimistic sends are preserved across a history merge - EXCEPT the
|
|
140
|
+
// ones the fetched page proves the server already has. That happens
|
|
141
|
+
// whenever a send reached the server but its echo did not reach us
|
|
142
|
+
// before the process died: the optimistic bubble is restored from disk
|
|
143
|
+
// still `pending: true` (and, since bug #39, flagged failed at boot),
|
|
144
|
+
// while MAM hands back the very same message under its ARCHIVE id.
|
|
145
|
+
// Keying only on `id` never matched those two, so the room ended up
|
|
146
|
+
// showing the message twice - once for real and once as a bubble stuck
|
|
147
|
+
// on "sending…"/"Failed" that nothing could ever clear. The archived
|
|
148
|
+
// copy carries our original stanza id as `xmppId` (getDataFromXml), so
|
|
149
|
+
// match on that too and drop the local ghost.
|
|
150
|
+
const fetchedKeys = new Set();
|
|
151
|
+
for (const m of realFetched) {
|
|
152
|
+
if (m?.id != null) {
|
|
153
|
+
fetchedKeys.add(String(m.id));
|
|
154
|
+
}
|
|
155
|
+
if (m?.xmppId) {
|
|
156
|
+
fetchedKeys.add(String(m.xmppId));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
const pending = ex.filter(m => m?.pending && !fetchedKeys.has(String(m.id)) && !(m.xmppId && fetchedKeys.has(String(m.xmppId))));
|
|
138
160
|
const byMs = (a, b) => msgSortableMs(a) - msgSortableMs(b);
|
|
139
161
|
const capTail = arr => arr.length > RUNTIME_MESSAGE_LIMIT ? arr.slice(-RUNTIME_MESSAGE_LIMIT) : arr;
|
|
140
162
|
const existingIds = new Set(realExisting.map(m => String(m.id)));
|
|
@@ -178,7 +200,8 @@ const initialState = {
|
|
|
178
200
|
text: ''
|
|
179
201
|
},
|
|
180
202
|
pendingNotificationJid: null,
|
|
181
|
-
privateStoreMarkers: {}
|
|
203
|
+
privateStoreMarkers: {},
|
|
204
|
+
readBoundaries: {}
|
|
182
205
|
};
|
|
183
206
|
const isValidRoomJid = jid => {
|
|
184
207
|
if (typeof jid !== 'string' || !jid) return false;
|
|
@@ -423,7 +446,7 @@ const reducers = {
|
|
|
423
446
|
roomMessages.unshift(message);
|
|
424
447
|
} else {
|
|
425
448
|
const lastViewedValue = state.rooms[roomJID].lastViewedTimestamp;
|
|
426
|
-
const lastViewedTimestamp = state.visibleRoomJID === roomJID ? null : lastViewedValue ?
|
|
449
|
+
const lastViewedTimestamp = state.visibleRoomJID === roomJID ? null : lastViewedValue ? lastViewedValue : null;
|
|
427
450
|
insertMessageWithDelimiter(roomMessages, message, lastViewedTimestamp);
|
|
428
451
|
}
|
|
429
452
|
|
|
@@ -439,6 +462,7 @@ const reducers = {
|
|
|
439
462
|
state.rooms = {};
|
|
440
463
|
state.visibleRoomJID = null;
|
|
441
464
|
state.privateStoreMarkers = {};
|
|
465
|
+
state.readBoundaries = {};
|
|
442
466
|
state.isUnreadSyncing = false;
|
|
443
467
|
},
|
|
444
468
|
setComposing(state, action) {
|
|
@@ -497,7 +521,19 @@ const reducers = {
|
|
|
497
521
|
*
|
|
498
522
|
* Monotonic: a marker only ever moves a baseline FORWARD, so a stale
|
|
499
523
|
* server value can't resurrect already-read messages and a more-recent
|
|
500
|
-
* local read (tab blur stamping
|
|
524
|
+
* local read (tab blur stamping the server read timestamp) always wins.
|
|
525
|
+
*
|
|
526
|
+
* Bug #38 self-heal: forward-only is correct for a SANE existing
|
|
527
|
+
* value, but a device whose clock was ahead may have already stamped
|
|
528
|
+
* a marker in the future (either persisted locally from a previous
|
|
529
|
+
* session, or fetched from the server before this fix existed). To
|
|
530
|
+
* "only ever move forward" from a corrupt future value is to never
|
|
531
|
+
* move at all - the room would stay stuck at `unreadMessages: 0`
|
|
532
|
+
* forever. When the room is loaded, detect a marker that sits well
|
|
533
|
+
* past the newest message we actually know it has and waive the
|
|
534
|
+
* forward-only check for that one comparison, so the incoming
|
|
535
|
+
* (already-clamped, see xmppClient.getChatsPrivateStoreRequestStanza)
|
|
536
|
+
* value can correct it even though it's numerically smaller.
|
|
501
537
|
*/
|
|
502
538
|
applyPrivateStoreMarkers: (state, action) => {
|
|
503
539
|
const markers = action.payload;
|
|
@@ -512,20 +548,73 @@ const reducers = {
|
|
|
512
548
|
if (!jid || !Number.isFinite(ts) || ts <= 0) {
|
|
513
549
|
continue;
|
|
514
550
|
}
|
|
551
|
+
const room = state.rooms[jid];
|
|
552
|
+
const newestKnownMs = room ? newestAckedMessageMs(room.messages) : 0;
|
|
553
|
+
// Mirrors isCorruptFutureReadMarker in helpers/getServerReadTimestamp.ts
|
|
554
|
+
// (duplicated to avoid a roomStore <-> helpers import cycle):
|
|
555
|
+
// BOTH signals are required. "Further ahead than the newest
|
|
556
|
+
// message this room has locally" happens all the time on a room
|
|
557
|
+
// whose history hasn't synced yet, and healing on that alone
|
|
558
|
+
// would drop a legitimate marker another device wrote after
|
|
559
|
+
// reading newer messages. A real read marker can never be ahead
|
|
560
|
+
// of real time, so that second signal is what distinguishes a
|
|
561
|
+
// stale cache from a wrong clock.
|
|
562
|
+
const nowMs = Date.now();
|
|
563
|
+
const looksCorrupt = existing => newestKnownMs > 0 && existing > newestKnownMs + FUTURE_MARKER_TOLERANCE_MS && existing > nowMs + FUTURE_MARKER_TOLERANCE_MS;
|
|
564
|
+
|
|
515
565
|
// Remember the marker so rooms that load LATER (via addRoom)
|
|
516
566
|
// inherit it even though they don't exist in the store yet.
|
|
517
|
-
|
|
567
|
+
const cachedMarker = state.privateStoreMarkers[jid] || 0;
|
|
568
|
+
if (ts > cachedMarker || looksCorrupt(cachedMarker)) {
|
|
518
569
|
state.privateStoreMarkers[jid] = ts;
|
|
519
570
|
}
|
|
520
571
|
// Upgrade an already-loaded room's baseline + recompute its badge.
|
|
521
|
-
//
|
|
522
|
-
|
|
523
|
-
if (room && ts > (room.lastViewedTimestamp || 0)) {
|
|
572
|
+
// Forward-only, unless the room's CURRENT baseline is itself the
|
|
573
|
+
// corrupt value being corrected.
|
|
574
|
+
if (room && (ts > (room.lastViewedTimestamp || 0) || looksCorrupt(room.lastViewedTimestamp || 0))) {
|
|
524
575
|
room.lastViewedTimestamp = ts;
|
|
525
576
|
room.unreadMessages = countNewerMessages(room.messages, ts);
|
|
526
577
|
}
|
|
527
578
|
}
|
|
528
579
|
},
|
|
580
|
+
/**
|
|
581
|
+
* Set (or clear) the "read up to here, but not further" boundary for
|
|
582
|
+
* a room - see `readBoundaries` on `RoomMessagesState` for the full
|
|
583
|
+
* contract. `ts` is the msgSortableMs of the newest message the user
|
|
584
|
+
* actually reached before scrolling away from the bottom; `null`/`0`
|
|
585
|
+
* clears it (the user is at the bottom, or nothing was reached yet).
|
|
586
|
+
*/
|
|
587
|
+
setReadBoundary: (state, action) => {
|
|
588
|
+
const {
|
|
589
|
+
jid,
|
|
590
|
+
ts
|
|
591
|
+
} = action.payload;
|
|
592
|
+
if (!jid) {
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
if (!state.readBoundaries) {
|
|
596
|
+
state.readBoundaries = {};
|
|
597
|
+
}
|
|
598
|
+
if (typeof ts === 'number' && Number.isFinite(ts) && ts > 0) {
|
|
599
|
+
state.readBoundaries[jid] = ts;
|
|
600
|
+
} else {
|
|
601
|
+
delete state.readBoundaries[jid];
|
|
602
|
+
}
|
|
603
|
+
},
|
|
604
|
+
/**
|
|
605
|
+
* Release a room's read boundary once it has been consumed by a
|
|
606
|
+
* genuine "leave" (ChatRoom unmount, or a tab-navigator focus hook
|
|
607
|
+
* switching to a different room) - see `readBoundaries` for why the
|
|
608
|
+
* background/`isVisible=false` paths deliberately do NOT call this.
|
|
609
|
+
*/
|
|
610
|
+
clearReadBoundary: (state, action) => {
|
|
611
|
+
const {
|
|
612
|
+
jid
|
|
613
|
+
} = action.payload;
|
|
614
|
+
if (jid && state.readBoundaries) {
|
|
615
|
+
delete state.readBoundaries[jid];
|
|
616
|
+
}
|
|
617
|
+
},
|
|
529
618
|
setRoomRole: (state, action) => {
|
|
530
619
|
const {
|
|
531
620
|
chatJID,
|
|
@@ -605,6 +694,7 @@ const reducers = {
|
|
|
605
694
|
state.isLoading = false;
|
|
606
695
|
state.isUnreadSyncing = false;
|
|
607
696
|
state.privateStoreMarkers = {};
|
|
697
|
+
state.readBoundaries = {};
|
|
608
698
|
},
|
|
609
699
|
setActiveMessage: (state, action) => {
|
|
610
700
|
const {
|
|
@@ -707,31 +797,13 @@ export const roomsStore = createSlice({
|
|
|
707
797
|
reducers
|
|
708
798
|
});
|
|
709
799
|
|
|
710
|
-
//
|
|
711
|
-
//
|
|
712
|
-
//
|
|
713
|
-
//
|
|
714
|
-
//
|
|
715
|
-
//
|
|
716
|
-
|
|
717
|
-
// user's own messages (parity with unreadMiddleware's isOwnMessage
|
|
718
|
-
// filter — without this, the reducer and the middleware disagree about
|
|
719
|
-
// the count and we get a flicker as the badge gets written twice with
|
|
720
|
-
// different values on every message).
|
|
721
|
-
export const msgSortableMs = msg => {
|
|
722
|
-
const id = String(msg?.id || '');
|
|
723
|
-
const m = /^(\d{13})/.exec(id);
|
|
724
|
-
if (m) {
|
|
725
|
-
return Number(m[1]);
|
|
726
|
-
}
|
|
727
|
-
if (msg?.date) {
|
|
728
|
-
const t = new Date(msg.date).getTime();
|
|
729
|
-
if (Number.isFinite(t)) {
|
|
730
|
-
return t;
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
return 0;
|
|
734
|
-
};
|
|
800
|
+
// Re-exported for backward compatibility - every existing call site
|
|
801
|
+
// imports `msgSortableMs` from here. The implementation now lives in
|
|
802
|
+
// helpers/msgSortableMs.ts (imported above), so insertMessageWithDelimiter.ts
|
|
803
|
+
// (which this file itself imports) can use the SAME ordering source
|
|
804
|
+
// without a roomStore <-> helpers import cycle. See that file for the
|
|
805
|
+
// full rationale (server id vs. client `date`).
|
|
806
|
+
export { msgSortableMs };
|
|
735
807
|
const norm = s => {
|
|
736
808
|
if (s == null) {
|
|
737
809
|
return '';
|
|
@@ -757,6 +829,35 @@ const isOwn = (msg, selfXmpp, selfWallet) => {
|
|
|
757
829
|
}
|
|
758
830
|
return false;
|
|
759
831
|
};
|
|
832
|
+
|
|
833
|
+
// Bug #38 tolerance: a stored read marker more than this far past the
|
|
834
|
+
// newest message a room actually has is not "the user is a little
|
|
835
|
+
// ahead" - it's a leftover from a device whose clock was wrong when it
|
|
836
|
+
// stamped the marker. Kept in sync with (but duplicated from, to avoid
|
|
837
|
+
// a roomStore ↔ helpers import cycle) FUTURE_READ_MARKER_TOLERANCE_MS
|
|
838
|
+
// in helpers/getServerReadTimestamp.ts.
|
|
839
|
+
const FUTURE_MARKER_TOLERANCE_MS = 5 * 60 * 1000;
|
|
840
|
+
|
|
841
|
+
// Newest message in `messages` this room actually has proof the server
|
|
842
|
+
// accepted - used only to sanity-check an already-stored read marker
|
|
843
|
+
// against reality (see applyPrivateStoreMarkers's self-heal). Excludes
|
|
844
|
+
// pending/optimistic sends via the `pending` flag alone: unlike
|
|
845
|
+
// getServerReadTimestamp, this runs inside a reducer and can't reach
|
|
846
|
+
// across to the roomHeapSlice slice, but `pending` already identifies
|
|
847
|
+
// every optimistic send that matters for this comparison.
|
|
848
|
+
const newestAckedMessageMs = messages => {
|
|
849
|
+
let newest = 0;
|
|
850
|
+
for (const m of messages || []) {
|
|
851
|
+
if (!m || m.id === 'delimiter-new' || m.pending) {
|
|
852
|
+
continue;
|
|
853
|
+
}
|
|
854
|
+
const ms = msgSortableMs(m);
|
|
855
|
+
if (ms > newest) {
|
|
856
|
+
newest = ms;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
return newest;
|
|
860
|
+
};
|
|
760
861
|
const countNewerMessages = (messages, timestamp, selfXmpp = '', selfWallet = '') => {
|
|
761
862
|
if (!messages?.length || !timestamp) {
|
|
762
863
|
return 0;
|
|
@@ -789,6 +890,8 @@ export const {
|
|
|
789
890
|
setUnreadSyncing,
|
|
790
891
|
setLastViewedTimestamp,
|
|
791
892
|
applyPrivateStoreMarkers,
|
|
893
|
+
setReadBoundary,
|
|
894
|
+
clearReadBoundary,
|
|
792
895
|
setRoomNoMessages,
|
|
793
896
|
setCurrentRoom,
|
|
794
897
|
setVisibleRoom,
|