diff --git a/ts/components/SessionInboxView.tsx b/ts/components/SessionInboxView.tsx index 95f7b4c1e..bc69090b2 100644 --- a/ts/components/SessionInboxView.tsx +++ b/ts/components/SessionInboxView.tsx @@ -104,6 +104,7 @@ async function setupLeftPane(forceUpdateInboxComponent: () => void) { window.inboxStore.dispatch(updateAllOnStorageReady()); window.inboxStore.dispatch(groupInfoActions.loadMetaDumpsFromDB()); // this loads the dumps from DB and fills the 03-groups slice with the corresponding details forceUpdateInboxComponent(); + window.getState = window.inboxStore.getState; } const SomeDeviceOutdatedSyncingNotice = () => { diff --git a/ts/receiver/closedGroups.ts b/ts/receiver/closedGroups.ts index c48d27327..fedef5201 100644 --- a/ts/receiver/closedGroups.ts +++ b/ts/receiver/closedGroups.ts @@ -634,6 +634,7 @@ async function handleClosedGroupNameChanged( sender: envelope.senderIdentity, sentAt: toNumber(envelope.timestamp), expireUpdate, + markAlreadySent: false, // legacy groups support will be removed eventually }); if (!shouldOnlyAddUpdateMessage) { convo.set({ displayNameInProfile: newName }); @@ -697,6 +698,7 @@ async function handleClosedGroupMembersAdded( sender: envelope.senderIdentity, sentAt: toNumber(envelope.timestamp), expireUpdate, + markAlreadySent: false, // legacy groups support will be removed eventually }); if (!shouldOnlyAddUpdateMessage) { @@ -787,6 +789,7 @@ async function handleClosedGroupMembersRemoved( sender: envelope.senderIdentity, sentAt: toNumber(envelope.timestamp), expireUpdate, + markAlreadySent: false, // legacy groups support will be removed eventually }); convo.updateLastMessage(); } @@ -919,6 +922,7 @@ async function handleClosedGroupMemberLeft( sender: envelope.senderIdentity, sentAt: toNumber(envelope.timestamp), expireUpdate, + markAlreadySent: false, // legacy groups support will be removed eventually }); convo.updateLastMessage(); // if a user just left and we are the admin, we remove him right away for everyone by sending a MEMBERS_REMOVED message so no need to add him as a zombie diff --git a/ts/receiver/groupv2/handleGroupV2Message.ts b/ts/receiver/groupv2/handleGroupV2Message.ts index d687c21d4..16ad8d0fa 100644 --- a/ts/receiver/groupv2/handleGroupV2Message.ts +++ b/ts/receiver/groupv2/handleGroupV2Message.ts @@ -205,6 +205,7 @@ async function handleGroupInfoChangeMessage({ sender: author, sentAt: signatureTimestamp, expireUpdate: null, + markAlreadySent: true, }); break; @@ -216,6 +217,7 @@ async function handleGroupInfoChangeMessage({ sender: author, sentAt: signatureTimestamp, expireUpdate: null, + markAlreadySent: true, }); break; } @@ -280,6 +282,7 @@ async function handleGroupMemberChangeMessage({ sender: author, sentAt: signatureTimestamp, expireUpdate: null, + markAlreadySent: true, }; switch (change.type) { @@ -339,6 +342,7 @@ async function handleGroupMemberLeftMessage({ sender: author, sentAt: signatureTimestamp, expireUpdate: null, + markAlreadySent: true, }); convo.set({ diff --git a/ts/session/group/closed-group.ts b/ts/session/group/closed-group.ts index 551ee4ae3..f2ab73d14 100644 --- a/ts/session/group/closed-group.ts +++ b/ts/session/group/closed-group.ts @@ -115,6 +115,7 @@ async function initiateClosedGroupUpdate( // Note: we agreed that legacy group control messages do not expire expireUpdate: null, convo, + markAlreadySent: false, }; if (diff.type === 'name' && diff.newName?.length) { @@ -155,12 +156,14 @@ export async function addUpdateMessage({ sender, sentAt, expireUpdate, + markAlreadySent, }: { convo: ConversationModel; diff: GroupDiff; sender: string; sentAt: number; expireUpdate: DisappearingMessageUpdate | null; + markAlreadySent: boolean; }): Promise { const groupUpdate: MessageGroupUpdate = {}; @@ -185,7 +188,7 @@ export async function addUpdateMessage({ } const isUs = UserUtils.isUsFromCache(sender); - const msgModel: MessageAttributesOptionals = { + const msgAttrs: MessageAttributesOptionals = { sent_at: sentAt, group_update: groupUpdate, source: sender, @@ -193,16 +196,26 @@ export async function addUpdateMessage({ type: isUs ? 'outgoing' : 'incoming', }; + /** + * When we receive an update from our linked device, it is an outgoing message + * but which was obviously already synced (as we got it). + * When that's the case we need to makr the message as sent right away, + * so the MessageStatus 'sending' state is not shown for the last message in the left pane. + */ + if (msgAttrs.type === 'outgoing' && markAlreadySent) { + msgAttrs.sent = true; + } + if (convo && expireUpdate && expireUpdate.expirationType && expireUpdate.expirationTimer > 0) { const { expirationTimer, expirationType, isLegacyDataMessage } = expireUpdate; - msgModel.expirationType = expirationType === 'deleteAfterSend' ? 'deleteAfterSend' : 'unknown'; - msgModel.expireTimer = msgModel.expirationType === 'deleteAfterSend' ? expirationTimer : 0; + msgAttrs.expirationType = expirationType === 'deleteAfterSend' ? 'deleteAfterSend' : 'unknown'; + msgAttrs.expireTimer = msgAttrs.expirationType === 'deleteAfterSend' ? expirationTimer : 0; // NOTE Triggers disappearing for an incoming groupUpdate message // TODO legacy messages support will be removed in a future release if (isLegacyDataMessage || expirationType === 'deleteAfterSend') { - msgModel.expirationStartTimestamp = DisappearingMessages.setExpirationStartTimestamp( + msgAttrs.expirationStartTimestamp = DisappearingMessages.setExpirationStartTimestamp( isLegacyDataMessage ? 'legacy' : expirationType === 'unknown' ? 'off' : expirationType, sentAt, 'addUpdateMessage' @@ -211,9 +224,9 @@ export async function addUpdateMessage({ } return isUs - ? convo.addSingleOutgoingMessage(msgModel) + ? convo.addSingleOutgoingMessage(msgAttrs) : convo.addSingleIncomingMessage({ - ...msgModel, + ...msgAttrs, source: sender, }); } diff --git a/ts/state/ducks/metaGroups.ts b/ts/state/ducks/metaGroups.ts index fcca693b5..f51a764f4 100644 --- a/ts/state/ducks/metaGroups.ts +++ b/ts/state/ducks/metaGroups.ts @@ -205,6 +205,7 @@ const initNewGroupInWrapper = createAsyncThunk( sender: us, sentAt, convo, + markAlreadySent: false, // the store below will mark the message as sent with dbMsgIdentifier }); const groupChange = await getWithoutHistoryControlMessage({ adminSecretKey: groupSecretKey, @@ -830,6 +831,7 @@ async function handleMemberAddedFromUI({ ? createAtNetworkTimestamp + expiringDetails.expireTimer : null, }, + markAlreadySent: false, // the store below will mark the message as sent with dbMsgIdentifier }; const updateMessagesToPush: Array = []; @@ -961,6 +963,7 @@ async function handleMemberRemovedFromUI({ const msgModel = await ClosedGroup.addUpdateMessage({ diff: { type: 'kicked', kicked: removed }, ...shared, + markAlreadySent: false, // the store below will mark the message as sent with dbMsgIdentifier }); const removedControlMessage = await getRemovedControlMessage({ adminSecretKey: group.secretKey, @@ -1017,6 +1020,7 @@ async function handleNameChangeFromUI({ sender: us, sentAt: createAtNetworkTimestamp, expireUpdate: null, + markAlreadySent: false, // the store below will mark the message as sent with dbMsgIdentifier }); // we want to send an update only if the change was made locally. diff --git a/ts/window.d.ts b/ts/window.d.ts index 6d1034143..195871940 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -78,6 +78,7 @@ declare global { setMenuBarVisibility: (val: boolean) => void; contextMenuShown: boolean; inboxStore?: Store; + getState: () => unknown; openConversationWithMessages: (args: { conversationKey: string; messageId: string | null;