mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-07-08 06:14:14 +01:00
Fix call log sync when call isnt latest message
This commit is contained in:
@@ -1003,6 +1003,10 @@ type ReadableInterface = {
|
||||
conversationId: string,
|
||||
eraId: string
|
||||
) => boolean;
|
||||
getPrevUnreadCallIdInConversation: (
|
||||
conversationId: string,
|
||||
receivedAt: number
|
||||
) => string | null;
|
||||
callLinkExists: (roomId: string) => boolean;
|
||||
defunctCallLinkExists: (roomId: string) => boolean;
|
||||
getAllCallLinks: () => ReadonlyArray<CallLinkType>;
|
||||
@@ -1232,11 +1236,6 @@ type WritableInterface = {
|
||||
readAt?: number;
|
||||
storyId?: string;
|
||||
}) => GetUnreadByConversationAndMarkReadResultType;
|
||||
getUnreadCallMessagesAndMarkRead: (options: {
|
||||
conversationId: string;
|
||||
readMessageReceivedAt: number;
|
||||
activeCallIds: Set<string>;
|
||||
}) => GetUnreadByConversationAndMarkReadResultType;
|
||||
getUnreadEditedMessagesAndMarkRead: (options: {
|
||||
conversationId: string;
|
||||
readMessageReceivedAt: number;
|
||||
|
||||
+22
-35
@@ -493,6 +493,7 @@ export const DataReader: ServerReadableInterface = {
|
||||
getCallHistoryGroupsCount,
|
||||
getCallHistoryGroups,
|
||||
hasGroupCallHistoryMessage,
|
||||
getPrevUnreadCallIdInConversation,
|
||||
|
||||
hasMedia,
|
||||
getSortedMedia,
|
||||
@@ -647,7 +648,6 @@ export const DataWriter: ServerWritableInterface = {
|
||||
updateAllConversationColors,
|
||||
removeAllProfileKeyCredentials,
|
||||
getUnreadByConversationAndMarkRead,
|
||||
getUnreadCallMessagesAndMarkRead,
|
||||
getUnreadEditedMessagesAndMarkRead,
|
||||
getUnreadReactionsAndMarkRead,
|
||||
getUnreadPollVotesAndMarkRead,
|
||||
@@ -5496,6 +5496,27 @@ function hasGroupCallHistoryMessage(
|
||||
return exists === 1;
|
||||
}
|
||||
|
||||
function getPrevUnreadCallIdInConversation(
|
||||
db: ReadableDB,
|
||||
conversationId: string,
|
||||
receivedAt: number
|
||||
): string | null {
|
||||
const [query, params] = sql`
|
||||
SELECT messages.callId FROM messages
|
||||
INNER JOIN callsHistory ON callsHistory.callId = messages.callId
|
||||
WHERE messages.conversationId = ${conversationId}
|
||||
AND messages.type IS 'call-history'
|
||||
AND messages.seenStatus IS ${SEEN_STATUS_UNSEEN}
|
||||
AND callsHistory.direction IS ${CALL_STATUS_INCOMING}
|
||||
AND messages.received_at <= ${receivedAt}
|
||||
ORDER BY messages.received_at DESC, messages.sent_at DESC
|
||||
LIMIT 1
|
||||
`;
|
||||
|
||||
const callId = db.prepare(query, { pluck: true }).get<string>(params);
|
||||
return callId ?? null;
|
||||
}
|
||||
|
||||
function hasMedia(db: ReadableDB, conversationId: string): boolean {
|
||||
return db.transaction(() => {
|
||||
let hasAttachments: boolean;
|
||||
@@ -9513,40 +9534,6 @@ function _getAllEditedMessages(
|
||||
.all({});
|
||||
}
|
||||
|
||||
function getUnreadCallMessagesAndMarkRead(
|
||||
db: WritableDB,
|
||||
{
|
||||
conversationId,
|
||||
readMessageReceivedAt,
|
||||
activeCallIds,
|
||||
}: {
|
||||
conversationId: string;
|
||||
readMessageReceivedAt: number;
|
||||
activeCallIds: Set<string>;
|
||||
}
|
||||
): GetUnreadByConversationAndMarkReadResultType {
|
||||
const [query, params] = sql`
|
||||
UPDATE messages
|
||||
SET
|
||||
expirationStartTimestamp = ${readMessageReceivedAt}
|
||||
WHERE type IS 'call-history'
|
||||
AND messages.conversationId IS ${conversationId}
|
||||
AND messages.seenStatus IS ${SEEN_STATUS_SEEN}
|
||||
AND messages.received_at <= ${readMessageReceivedAt}
|
||||
AND messages.hasExpireTimer IS 1
|
||||
AND messages.expirationStartTimestamp IS NULL
|
||||
AND messages.callId NOT IN (${sqlJoin(Array.from(activeCallIds))})
|
||||
RETURNING *
|
||||
`;
|
||||
|
||||
const rows = db.prepare(query).all<MessageTypeUnhydrated>(params);
|
||||
const messages = hydrateMessages(db, rows);
|
||||
|
||||
return messages.map(message => {
|
||||
return { ...message, originalReadStatus: undefined };
|
||||
});
|
||||
}
|
||||
|
||||
function getUnreadEditedMessagesAndMarkRead(
|
||||
db: WritableDB,
|
||||
{
|
||||
|
||||
@@ -292,6 +292,7 @@ export const actions = {
|
||||
clearAllCallHistory,
|
||||
updateCallHistoryUnreadCount,
|
||||
markCallHistoryRead,
|
||||
markCallHistoryReadInConversation,
|
||||
markCallsTabViewed,
|
||||
};
|
||||
|
||||
|
||||
@@ -274,6 +274,7 @@ describe('calling/callHistoryExpiration', function (this: Mocha.Suite) {
|
||||
|
||||
describe('1:1 calls', () => {
|
||||
it('expire missed call: read by opening chat', async () => {
|
||||
const { phone } = bootstrap;
|
||||
const page = await app.getWindow();
|
||||
const chatListItem = $chatListItem(page, contact.device.aci);
|
||||
const unreadBadge = $unreadBadge(page, contact.device.aci);
|
||||
@@ -312,6 +313,17 @@ describe('calling/callHistoryExpiration', function (this: Mocha.Suite) {
|
||||
await expect($navTabUnreadBadge(page, 'Calls')).not.toBeVisible();
|
||||
await expect($missedCall(page)).toBeVisible();
|
||||
|
||||
debug('waiting for sync message');
|
||||
const syncMessage = await phone.waitForSyncMessage(entry => {
|
||||
return (
|
||||
entry.syncMessage.content?.callLogEvent?.type ===
|
||||
Proto.SyncMessage.CallLogEvent.Type.MARKED_AS_READ_IN_CONVERSATION
|
||||
);
|
||||
});
|
||||
expect(syncMessage.syncMessage.content?.callLogEvent?.callId).toBe(
|
||||
BigInt(callTimestamp)
|
||||
);
|
||||
|
||||
debug('waiting for message to expire');
|
||||
await delay(EXPIRE_TIMER_MS);
|
||||
await expect($missedCall(page)).not.toBeVisible();
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import lodash from 'lodash';
|
||||
|
||||
import type { ConversationAttributesType } from '../model-types.d.ts';
|
||||
import { DataWriter } from '../sql/Client.preload.ts';
|
||||
import { DataReader, DataWriter } from '../sql/Client.preload.ts';
|
||||
import { hasErrors } from '../state/selectors/message.preload.ts';
|
||||
import { readSyncJobQueue } from '../jobs/readSyncJobQueue.preload.ts';
|
||||
import { notificationService } from '../services/notifications.preload.ts';
|
||||
@@ -28,7 +28,6 @@ import { isAciString } from './isAciString.std.ts';
|
||||
import type { MessageModel } from '../models/messages.preload.ts';
|
||||
import { postSaveUpdates } from './cleanup.preload.ts';
|
||||
import { itemStorage } from '../textsecure/Storage.preload.ts';
|
||||
import { calling } from '../services/calling.preload.ts';
|
||||
|
||||
const { isNumber, pick } = lodash;
|
||||
|
||||
@@ -48,10 +47,10 @@ export async function markConversationRead(
|
||||
|
||||
const [
|
||||
unreadMessages,
|
||||
unreadCallMessages,
|
||||
unreadEditedMessages,
|
||||
unreadReactions,
|
||||
unreadPollVotes,
|
||||
lastUnreadCallId,
|
||||
] = await Promise.all([
|
||||
DataWriter.getUnreadByConversationAndMarkRead({
|
||||
conversationId,
|
||||
@@ -59,11 +58,6 @@ export async function markConversationRead(
|
||||
readAt: options.readAt,
|
||||
includeStoryReplies: !isGroup(conversationAttrs),
|
||||
}),
|
||||
DataWriter.getUnreadCallMessagesAndMarkRead({
|
||||
conversationId,
|
||||
readMessageReceivedAt: readMessage.received_at,
|
||||
activeCallIds: calling.getActiveCallIds(),
|
||||
}),
|
||||
DataWriter.getUnreadEditedMessagesAndMarkRead({
|
||||
conversationId,
|
||||
readMessageReceivedAt: readMessage.received_at,
|
||||
@@ -76,6 +70,10 @@ export async function markConversationRead(
|
||||
conversationId,
|
||||
readMessageReceivedAt: readMessage.received_at,
|
||||
}),
|
||||
DataReader.getPrevUnreadCallIdInConversation(
|
||||
conversationId,
|
||||
readMessage.received_at
|
||||
),
|
||||
]);
|
||||
|
||||
const convoId = getConversationIdForLogging(conversationAttrs);
|
||||
@@ -87,7 +85,6 @@ export async function markConversationRead(
|
||||
receivedAt: readMessage.received_at,
|
||||
},
|
||||
unreadMessages: unreadMessages.length,
|
||||
unreadCallMessages: unreadCallMessages.length,
|
||||
unreadEditedMessages: unreadEditedMessages.length,
|
||||
unreadReactions: unreadReactions.length,
|
||||
unreadPollVotes: unreadPollVotes.length,
|
||||
@@ -95,10 +92,10 @@ export async function markConversationRead(
|
||||
|
||||
if (
|
||||
!unreadMessages.length &&
|
||||
!unreadCallMessages.length &&
|
||||
!unreadEditedMessages.length &&
|
||||
!unreadReactions.length &&
|
||||
!unreadPollVotes.length
|
||||
!unreadPollVotes.length &&
|
||||
lastUnreadCallId == null
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
@@ -148,11 +145,7 @@ export async function markConversationRead(
|
||||
});
|
||||
});
|
||||
|
||||
const allUnreadMessages = [
|
||||
...unreadMessages,
|
||||
...unreadCallMessages,
|
||||
...unreadEditedMessages,
|
||||
];
|
||||
const allUnreadMessages = [...unreadMessages, ...unreadEditedMessages];
|
||||
|
||||
const updatedMessages: Array<MessageModel> = [];
|
||||
|
||||
@@ -274,6 +267,12 @@ export async function markConversationRead(
|
||||
}
|
||||
}
|
||||
|
||||
if (lastUnreadCallId != null) {
|
||||
window.reduxActions.callHistory.markCallHistoryReadInConversation(
|
||||
lastUnreadCallId
|
||||
);
|
||||
}
|
||||
|
||||
updateExpiringMessagesService();
|
||||
tapToViewMessagesDeletionService.update();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user