diff --git a/ts/background.ts b/ts/background.ts index b582a417f0..04cfd22304 100644 --- a/ts/background.ts +++ b/ts/background.ts @@ -178,6 +178,7 @@ import { createEventHandler } from './quill/signal-clipboard/util'; import { onCallLogEventSync } from './util/onCallLogEventSync'; import { getCallsHistoryForRedux, + getCallsHistoryUnreadCountForRedux, loadCallsHistory, } from './services/callHistoryLoader'; import { @@ -1187,6 +1188,7 @@ export async function startApp(): Promise { }) { initializeRedux({ callsHistory: getCallsHistoryForRedux(), + callsHistoryUnreadCount: getCallsHistoryUnreadCountForRedux(), initialBadgesState, mainWindowStats, menuOptions, diff --git a/ts/models/conversations.ts b/ts/models/conversations.ts index 852bf04203..5699374481 100644 --- a/ts/models/conversations.ts +++ b/ts/models/conversations.ts @@ -4489,6 +4489,7 @@ export class ConversationModel extends window.Backbone ): Promise { await markConversationRead(this.attributes, newestUnreadAt, options); await this.updateUnread(); + window.reduxActions.callHistory.updateCallHistoryUnreadCount(); } async updateUnread(): Promise { @@ -4515,7 +4516,6 @@ export class ConversationModel extends window.Backbone unreadMentionsCount, }); window.Signal.Data.updateConversation(this.attributes); - window.reduxActions.callHistory.updateCallHistoryUnreadCount(); } } diff --git a/ts/services/callHistoryLoader.ts b/ts/services/callHistoryLoader.ts index b31a8a7217..e4d27c0d0f 100644 --- a/ts/services/callHistoryLoader.ts +++ b/ts/services/callHistoryLoader.ts @@ -6,13 +6,23 @@ import type { CallHistoryDetails } from '../types/CallDisposition'; import { strictAssert } from '../util/assert'; let callsHistoryData: ReadonlyArray; +let callsHistoryUnreadCount: number; export async function loadCallsHistory(): Promise { await dataInterface.cleanupCallHistoryMessages(); callsHistoryData = await dataInterface.getAllCallHistory(); + callsHistoryUnreadCount = await dataInterface.getCallHistoryUnreadCount(); } export function getCallsHistoryForRedux(): ReadonlyArray { strictAssert(callsHistoryData != null, 'callHistory has not been loaded'); return callsHistoryData; } + +export function getCallsHistoryUnreadCountForRedux(): number { + strictAssert( + callsHistoryUnreadCount != null, + 'callHistory has not been loaded' + ); + return callsHistoryUnreadCount; +} diff --git a/ts/services/calling.ts b/ts/services/calling.ts index fc120df518..80833d25ce 100644 --- a/ts/services/calling.ts +++ b/ts/services/calling.ts @@ -2250,16 +2250,24 @@ export class CallingClass { }); } - const localEvent = getLocalCallEventFromRingUpdate(update); - if (localEvent != null) { + const localEventFromRing = getLocalCallEventFromRingUpdate(update); + if (localEventFromRing != null) { const callId = getCallIdFromRing(ringId); const callDetails = getCallDetailsFromGroupCallMeta(groupId, { callId, ringerId: ringerUuid, }); + let localEventForCall; + if (localEventFromRing === LocalCallEvent.Missed) { + localEventForCall = LocalCallEvent.Missed; + } else { + localEventForCall = shouldRing + ? LocalCallEvent.Ringing + : LocalCallEvent.Started; + } const callEvent = getCallEventDetails( callDetails, - shouldRing ? LocalCallEvent.Ringing : LocalCallEvent.Started, + localEventForCall, 'CallingClass.handleGroupCallRingUpdate' ); await updateCallHistoryFromLocalEvent(callEvent, null); diff --git a/ts/sql/Server.ts b/ts/sql/Server.ts index 563da98089..5ca33cffcc 100644 --- a/ts/sql/Server.ts +++ b/ts/sql/Server.ts @@ -3448,8 +3448,8 @@ async function getCallHistory( return callHistoryDetailsSchema.parse(row); } -const READ_STATUS_UNREAD = sqlConstant(ReadStatus.Unread); -const READ_STATUS_READ = sqlConstant(ReadStatus.Read); +const SEEN_STATUS_UNSEEN = sqlConstant(SeenStatus.Unseen); +const SEEN_STATUS_SEEN = sqlConstant(SeenStatus.Seen); const CALL_STATUS_MISSED = sqlConstant(DirectCallStatus.Missed); const CALL_STATUS_DELETED = sqlConstant(DirectCallStatus.Deleted); const CALL_STATUS_INCOMING = sqlConstant(CallDirection.Incoming); @@ -3461,7 +3461,7 @@ async function getCallHistoryUnreadCount(): Promise { SELECT count(*) FROM messages LEFT JOIN callsHistory ON callsHistory.callId = messages.callId WHERE messages.type IS 'call-history' - AND messages.readStatus IS ${READ_STATUS_UNREAD} + AND messages.seenStatus IS ${SEEN_STATUS_UNSEEN} AND callsHistory.status IS ${CALL_STATUS_MISSED} AND callsHistory.direction IS ${CALL_STATUS_INCOMING} `; @@ -3473,7 +3473,7 @@ async function markCallHistoryRead(callId: string): Promise { const db = await getWritableInstance(); const [query, params] = sql` UPDATE messages - SET readStatus = ${READ_STATUS_READ} + SET seenStatus = ${SEEN_STATUS_UNSEEN} WHERE type IS 'call-history' AND callId IS ${callId} `; @@ -3486,7 +3486,7 @@ async function markAllCallHistoryRead(): Promise> { return db.transaction(() => { const where = sqlFragment` WHERE messages.type IS 'call-history' - AND messages.readStatus IS ${READ_STATUS_UNREAD} + AND messages.seenStatus IS ${SEEN_STATUS_UNSEEN} `; const [selectQuery, selectParams] = sql` @@ -3499,7 +3499,7 @@ async function markAllCallHistoryRead(): Promise> { const [updateQuery, updateParams] = sql` UPDATE messages - SET readStatus = ${READ_STATUS_READ} + SET seenStatus = ${SEEN_STATUS_SEEN} ${where}; `; diff --git a/ts/state/getInitialState.ts b/ts/state/getInitialState.ts index 270c38e23e..f91b70a6f1 100644 --- a/ts/state/getInitialState.ts +++ b/ts/state/getInitialState.ts @@ -45,6 +45,7 @@ import type { CallHistoryDetails } from '../types/CallDisposition'; export function getInitialState({ badges, callsHistory, + callsHistoryUnreadCount, stories, storyDistributionLists, mainWindowStats, @@ -52,6 +53,7 @@ export function getInitialState({ }: { badges: BadgesStateType; callsHistory: ReadonlyArray; + callsHistoryUnreadCount: number; stories: Array; storyDistributionLists: Array; mainWindowStats: MainWindowStatsType; @@ -91,6 +93,7 @@ export function getInitialState({ callHistory: { ...callHistory(), callHistoryByCallId: makeLookup(callsHistory, 'callId'), + unreadCount: callsHistoryUnreadCount, }, calling: calling(), composer: composer(), diff --git a/ts/state/initializeRedux.ts b/ts/state/initializeRedux.ts index 9a86d7b5f4..27ddab69a1 100644 --- a/ts/state/initializeRedux.ts +++ b/ts/state/initializeRedux.ts @@ -14,6 +14,7 @@ import { getInitialState } from './getInitialState'; export function initializeRedux({ callsHistory, + callsHistoryUnreadCount, initialBadgesState, mainWindowStats, menuOptions, @@ -21,6 +22,7 @@ export function initializeRedux({ storyDistributionLists, }: { callsHistory: ReadonlyArray; + callsHistoryUnreadCount: number; initialBadgesState: BadgesStateType; mainWindowStats: MainWindowStatsType; menuOptions: MenuOptionsType; @@ -30,6 +32,7 @@ export function initializeRedux({ const initialState = getInitialState({ badges: initialBadgesState, callsHistory, + callsHistoryUnreadCount, mainWindowStats, menuOptions, stories, diff --git a/ts/util/callDisposition.ts b/ts/util/callDisposition.ts index a37e7034b9..ec1fcd6ff4 100644 --- a/ts/util/callDisposition.ts +++ b/ts/util/callDisposition.ts @@ -27,7 +27,7 @@ import { isMe } from './whatTypeOfConversation'; import * as log from '../logging/log'; import * as Errors from '../types/errors'; import { incrementMessageCounter } from './incrementMessageCounter'; -import { ReadStatus, maxReadStatus } from '../messages/MessageReadStatus'; +import { ReadStatus } from '../messages/MessageReadStatus'; import { SeenStatus, maxSeenStatus } from '../MessageSeenStatus'; import { canConversationBeUnarchived } from './canConversationBeUnarchived'; import type { @@ -855,26 +855,21 @@ async function saveCallHistory( return callHistory; } - let unread = false; + let unseen = false; if (callHistory.mode === CallMode.Direct) { - unread = + unseen = callHistory.direction === CallDirection.Incoming && (callHistory.status === DirectCallStatus.Missed || callHistory.status === DirectCallStatus.Pending); } else if (callHistory.mode === CallMode.Group) { - unread = + unseen = callHistory.direction === CallDirection.Incoming && (callHistory.status === GroupCallStatus.Ringing || callHistory.status === GroupCallStatus.GenericGroupCall || callHistory.status === GroupCallStatus.Missed); } - let readStatus = unread ? ReadStatus.Unread : ReadStatus.Read; - let seenStatus = unread ? SeenStatus.Unseen : SeenStatus.NotApplicable; - - if (prevMessage?.readStatus != null) { - readStatus = maxReadStatus(readStatus, prevMessage.readStatus); - } + let seenStatus = unseen ? SeenStatus.Unseen : SeenStatus.NotApplicable; if (prevMessage?.seenStatus != null) { seenStatus = maxSeenStatus(seenStatus, prevMessage.seenStatus); } @@ -890,7 +885,7 @@ async function saveCallHistory( receivedAtCounter ?? incrementMessageCounter(), received_at_ms: prevMessage?.received_at_ms ?? callHistory.timestamp, - readStatus, + readStatus: ReadStatus.Read, seenStatus, callId: callHistory.callId, }; @@ -927,13 +922,6 @@ async function saveCallHistory( ); }); - await conversation.updateUnread().catch(error => { - log.error( - 'saveCallHistory: Failed to update unread', - Errors.toLogFormat(error) - ); - }); - conversation.set( 'active_at', Math.max(conversation.get('active_at') ?? 0, callHistory.timestamp) @@ -945,6 +933,8 @@ async function saveCallHistory( window.Signal.Data.updateConversation(conversation.attributes); } + window.reduxActions.callHistory.updateCallHistoryUnreadCount(); + return callHistory; } diff --git a/ts/windows/main/preload_test.ts b/ts/windows/main/preload_test.ts index 6d40ffd8e5..941893f263 100644 --- a/ts/windows/main/preload_test.ts +++ b/ts/windows/main/preload_test.ts @@ -36,6 +36,7 @@ window.testUtilities = { initializeRedux({ callsHistory: [], + callsHistoryUnreadCount: 0, initialBadgesState: { byId: {} }, mainWindowStats: { isFullScreen: false,