Move missed call chat badging to calls tab

Co-authored-by: ayumi-signal <143036029+ayumi-signal@users.noreply.github.com>
This commit is contained in:
automated-signal 2024-03-04 17:57:50 -06:00 committed by GitHub
parent 47562b9037
commit ddecf0aef5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 45 additions and 28 deletions

View file

@ -178,6 +178,7 @@ import { createEventHandler } from './quill/signal-clipboard/util';
import { onCallLogEventSync } from './util/onCallLogEventSync'; import { onCallLogEventSync } from './util/onCallLogEventSync';
import { import {
getCallsHistoryForRedux, getCallsHistoryForRedux,
getCallsHistoryUnreadCountForRedux,
loadCallsHistory, loadCallsHistory,
} from './services/callHistoryLoader'; } from './services/callHistoryLoader';
import { import {
@ -1187,6 +1188,7 @@ export async function startApp(): Promise<void> {
}) { }) {
initializeRedux({ initializeRedux({
callsHistory: getCallsHistoryForRedux(), callsHistory: getCallsHistoryForRedux(),
callsHistoryUnreadCount: getCallsHistoryUnreadCountForRedux(),
initialBadgesState, initialBadgesState,
mainWindowStats, mainWindowStats,
menuOptions, menuOptions,

View file

@ -4489,6 +4489,7 @@ export class ConversationModel extends window.Backbone
): Promise<void> { ): Promise<void> {
await markConversationRead(this.attributes, newestUnreadAt, options); await markConversationRead(this.attributes, newestUnreadAt, options);
await this.updateUnread(); await this.updateUnread();
window.reduxActions.callHistory.updateCallHistoryUnreadCount();
} }
async updateUnread(): Promise<void> { async updateUnread(): Promise<void> {
@ -4515,7 +4516,6 @@ export class ConversationModel extends window.Backbone
unreadMentionsCount, unreadMentionsCount,
}); });
window.Signal.Data.updateConversation(this.attributes); window.Signal.Data.updateConversation(this.attributes);
window.reduxActions.callHistory.updateCallHistoryUnreadCount();
} }
} }

View file

@ -6,13 +6,23 @@ import type { CallHistoryDetails } from '../types/CallDisposition';
import { strictAssert } from '../util/assert'; import { strictAssert } from '../util/assert';
let callsHistoryData: ReadonlyArray<CallHistoryDetails>; let callsHistoryData: ReadonlyArray<CallHistoryDetails>;
let callsHistoryUnreadCount: number;
export async function loadCallsHistory(): Promise<void> { export async function loadCallsHistory(): Promise<void> {
await dataInterface.cleanupCallHistoryMessages(); await dataInterface.cleanupCallHistoryMessages();
callsHistoryData = await dataInterface.getAllCallHistory(); callsHistoryData = await dataInterface.getAllCallHistory();
callsHistoryUnreadCount = await dataInterface.getCallHistoryUnreadCount();
} }
export function getCallsHistoryForRedux(): ReadonlyArray<CallHistoryDetails> { export function getCallsHistoryForRedux(): ReadonlyArray<CallHistoryDetails> {
strictAssert(callsHistoryData != null, 'callHistory has not been loaded'); strictAssert(callsHistoryData != null, 'callHistory has not been loaded');
return callsHistoryData; return callsHistoryData;
} }
export function getCallsHistoryUnreadCountForRedux(): number {
strictAssert(
callsHistoryUnreadCount != null,
'callHistory has not been loaded'
);
return callsHistoryUnreadCount;
}

View file

@ -2250,16 +2250,24 @@ export class CallingClass {
}); });
} }
const localEvent = getLocalCallEventFromRingUpdate(update); const localEventFromRing = getLocalCallEventFromRingUpdate(update);
if (localEvent != null) { if (localEventFromRing != null) {
const callId = getCallIdFromRing(ringId); const callId = getCallIdFromRing(ringId);
const callDetails = getCallDetailsFromGroupCallMeta(groupId, { const callDetails = getCallDetailsFromGroupCallMeta(groupId, {
callId, callId,
ringerId: ringerUuid, ringerId: ringerUuid,
}); });
let localEventForCall;
if (localEventFromRing === LocalCallEvent.Missed) {
localEventForCall = LocalCallEvent.Missed;
} else {
localEventForCall = shouldRing
? LocalCallEvent.Ringing
: LocalCallEvent.Started;
}
const callEvent = getCallEventDetails( const callEvent = getCallEventDetails(
callDetails, callDetails,
shouldRing ? LocalCallEvent.Ringing : LocalCallEvent.Started, localEventForCall,
'CallingClass.handleGroupCallRingUpdate' 'CallingClass.handleGroupCallRingUpdate'
); );
await updateCallHistoryFromLocalEvent(callEvent, null); await updateCallHistoryFromLocalEvent(callEvent, null);

View file

@ -3448,8 +3448,8 @@ async function getCallHistory(
return callHistoryDetailsSchema.parse(row); return callHistoryDetailsSchema.parse(row);
} }
const READ_STATUS_UNREAD = sqlConstant(ReadStatus.Unread); const SEEN_STATUS_UNSEEN = sqlConstant(SeenStatus.Unseen);
const READ_STATUS_READ = sqlConstant(ReadStatus.Read); const SEEN_STATUS_SEEN = sqlConstant(SeenStatus.Seen);
const CALL_STATUS_MISSED = sqlConstant(DirectCallStatus.Missed); const CALL_STATUS_MISSED = sqlConstant(DirectCallStatus.Missed);
const CALL_STATUS_DELETED = sqlConstant(DirectCallStatus.Deleted); const CALL_STATUS_DELETED = sqlConstant(DirectCallStatus.Deleted);
const CALL_STATUS_INCOMING = sqlConstant(CallDirection.Incoming); const CALL_STATUS_INCOMING = sqlConstant(CallDirection.Incoming);
@ -3461,7 +3461,7 @@ async function getCallHistoryUnreadCount(): Promise<number> {
SELECT count(*) FROM messages SELECT count(*) FROM messages
LEFT JOIN callsHistory ON callsHistory.callId = messages.callId LEFT JOIN callsHistory ON callsHistory.callId = messages.callId
WHERE messages.type IS 'call-history' 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.status IS ${CALL_STATUS_MISSED}
AND callsHistory.direction IS ${CALL_STATUS_INCOMING} AND callsHistory.direction IS ${CALL_STATUS_INCOMING}
`; `;
@ -3473,7 +3473,7 @@ async function markCallHistoryRead(callId: string): Promise<void> {
const db = await getWritableInstance(); const db = await getWritableInstance();
const [query, params] = sql` const [query, params] = sql`
UPDATE messages UPDATE messages
SET readStatus = ${READ_STATUS_READ} SET seenStatus = ${SEEN_STATUS_UNSEEN}
WHERE type IS 'call-history' WHERE type IS 'call-history'
AND callId IS ${callId} AND callId IS ${callId}
`; `;
@ -3486,7 +3486,7 @@ async function markAllCallHistoryRead(): Promise<ReadonlyArray<string>> {
return db.transaction(() => { return db.transaction(() => {
const where = sqlFragment` const where = sqlFragment`
WHERE messages.type IS 'call-history' WHERE messages.type IS 'call-history'
AND messages.readStatus IS ${READ_STATUS_UNREAD} AND messages.seenStatus IS ${SEEN_STATUS_UNSEEN}
`; `;
const [selectQuery, selectParams] = sql` const [selectQuery, selectParams] = sql`
@ -3499,7 +3499,7 @@ async function markAllCallHistoryRead(): Promise<ReadonlyArray<string>> {
const [updateQuery, updateParams] = sql` const [updateQuery, updateParams] = sql`
UPDATE messages UPDATE messages
SET readStatus = ${READ_STATUS_READ} SET seenStatus = ${SEEN_STATUS_SEEN}
${where}; ${where};
`; `;

View file

@ -45,6 +45,7 @@ import type { CallHistoryDetails } from '../types/CallDisposition';
export function getInitialState({ export function getInitialState({
badges, badges,
callsHistory, callsHistory,
callsHistoryUnreadCount,
stories, stories,
storyDistributionLists, storyDistributionLists,
mainWindowStats, mainWindowStats,
@ -52,6 +53,7 @@ export function getInitialState({
}: { }: {
badges: BadgesStateType; badges: BadgesStateType;
callsHistory: ReadonlyArray<CallHistoryDetails>; callsHistory: ReadonlyArray<CallHistoryDetails>;
callsHistoryUnreadCount: number;
stories: Array<StoryDataType>; stories: Array<StoryDataType>;
storyDistributionLists: Array<StoryDistributionListDataType>; storyDistributionLists: Array<StoryDistributionListDataType>;
mainWindowStats: MainWindowStatsType; mainWindowStats: MainWindowStatsType;
@ -91,6 +93,7 @@ export function getInitialState({
callHistory: { callHistory: {
...callHistory(), ...callHistory(),
callHistoryByCallId: makeLookup(callsHistory, 'callId'), callHistoryByCallId: makeLookup(callsHistory, 'callId'),
unreadCount: callsHistoryUnreadCount,
}, },
calling: calling(), calling: calling(),
composer: composer(), composer: composer(),

View file

@ -14,6 +14,7 @@ import { getInitialState } from './getInitialState';
export function initializeRedux({ export function initializeRedux({
callsHistory, callsHistory,
callsHistoryUnreadCount,
initialBadgesState, initialBadgesState,
mainWindowStats, mainWindowStats,
menuOptions, menuOptions,
@ -21,6 +22,7 @@ export function initializeRedux({
storyDistributionLists, storyDistributionLists,
}: { }: {
callsHistory: ReadonlyArray<CallHistoryDetails>; callsHistory: ReadonlyArray<CallHistoryDetails>;
callsHistoryUnreadCount: number;
initialBadgesState: BadgesStateType; initialBadgesState: BadgesStateType;
mainWindowStats: MainWindowStatsType; mainWindowStats: MainWindowStatsType;
menuOptions: MenuOptionsType; menuOptions: MenuOptionsType;
@ -30,6 +32,7 @@ export function initializeRedux({
const initialState = getInitialState({ const initialState = getInitialState({
badges: initialBadgesState, badges: initialBadgesState,
callsHistory, callsHistory,
callsHistoryUnreadCount,
mainWindowStats, mainWindowStats,
menuOptions, menuOptions,
stories, stories,

View file

@ -27,7 +27,7 @@ import { isMe } from './whatTypeOfConversation';
import * as log from '../logging/log'; import * as log from '../logging/log';
import * as Errors from '../types/errors'; import * as Errors from '../types/errors';
import { incrementMessageCounter } from './incrementMessageCounter'; import { incrementMessageCounter } from './incrementMessageCounter';
import { ReadStatus, maxReadStatus } from '../messages/MessageReadStatus'; import { ReadStatus } from '../messages/MessageReadStatus';
import { SeenStatus, maxSeenStatus } from '../MessageSeenStatus'; import { SeenStatus, maxSeenStatus } from '../MessageSeenStatus';
import { canConversationBeUnarchived } from './canConversationBeUnarchived'; import { canConversationBeUnarchived } from './canConversationBeUnarchived';
import type { import type {
@ -855,26 +855,21 @@ async function saveCallHistory(
return callHistory; return callHistory;
} }
let unread = false; let unseen = false;
if (callHistory.mode === CallMode.Direct) { if (callHistory.mode === CallMode.Direct) {
unread = unseen =
callHistory.direction === CallDirection.Incoming && callHistory.direction === CallDirection.Incoming &&
(callHistory.status === DirectCallStatus.Missed || (callHistory.status === DirectCallStatus.Missed ||
callHistory.status === DirectCallStatus.Pending); callHistory.status === DirectCallStatus.Pending);
} else if (callHistory.mode === CallMode.Group) { } else if (callHistory.mode === CallMode.Group) {
unread = unseen =
callHistory.direction === CallDirection.Incoming && callHistory.direction === CallDirection.Incoming &&
(callHistory.status === GroupCallStatus.Ringing || (callHistory.status === GroupCallStatus.Ringing ||
callHistory.status === GroupCallStatus.GenericGroupCall || callHistory.status === GroupCallStatus.GenericGroupCall ||
callHistory.status === GroupCallStatus.Missed); callHistory.status === GroupCallStatus.Missed);
} }
let readStatus = unread ? ReadStatus.Unread : ReadStatus.Read; let seenStatus = unseen ? SeenStatus.Unseen : SeenStatus.NotApplicable;
let seenStatus = unread ? SeenStatus.Unseen : SeenStatus.NotApplicable;
if (prevMessage?.readStatus != null) {
readStatus = maxReadStatus(readStatus, prevMessage.readStatus);
}
if (prevMessage?.seenStatus != null) { if (prevMessage?.seenStatus != null) {
seenStatus = maxSeenStatus(seenStatus, prevMessage.seenStatus); seenStatus = maxSeenStatus(seenStatus, prevMessage.seenStatus);
} }
@ -890,7 +885,7 @@ async function saveCallHistory(
receivedAtCounter ?? receivedAtCounter ??
incrementMessageCounter(), incrementMessageCounter(),
received_at_ms: prevMessage?.received_at_ms ?? callHistory.timestamp, received_at_ms: prevMessage?.received_at_ms ?? callHistory.timestamp,
readStatus, readStatus: ReadStatus.Read,
seenStatus, seenStatus,
callId: callHistory.callId, 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( conversation.set(
'active_at', 'active_at',
Math.max(conversation.get('active_at') ?? 0, callHistory.timestamp) Math.max(conversation.get('active_at') ?? 0, callHistory.timestamp)
@ -945,6 +933,8 @@ async function saveCallHistory(
window.Signal.Data.updateConversation(conversation.attributes); window.Signal.Data.updateConversation(conversation.attributes);
} }
window.reduxActions.callHistory.updateCallHistoryUnreadCount();
return callHistory; return callHistory;
} }

View file

@ -36,6 +36,7 @@ window.testUtilities = {
initializeRedux({ initializeRedux({
callsHistory: [], callsHistory: [],
callsHistoryUnreadCount: 0,
initialBadgesState: { byId: {} }, initialBadgesState: { byId: {} },
mainWindowStats: { mainWindowStats: {
isFullScreen: false, isFullScreen: false,