Handle new sync message MarkedAsRead for Calls Tab

This commit is contained in:
ayumi-signal 2024-03-11 11:18:55 -07:00 committed by GitHub
parent b410d14753
commit c332bd240f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 72 additions and 16 deletions

View file

@ -614,6 +614,7 @@ message SyncMessage {
message CallLogEvent {
enum Type {
CLEAR = 0;
MARKED_AS_READ = 1;
}
optional Type type = 1;

View file

@ -649,7 +649,9 @@ export type DataInterface = {
cleanupCallHistoryMessages: () => Promise<void>;
getCallHistoryUnreadCount(): Promise<number>;
markCallHistoryRead(callId: string): Promise<void>;
markAllCallHistoryRead(): Promise<ReadonlyArray<string>>;
markAllCallHistoryRead(
beforeTimestamp: number
): Promise<ReadonlyArray<string>>;
getCallHistoryMessageByCallId(options: {
conversationId: string;
callId: string;

View file

@ -3487,13 +3487,16 @@ async function markCallHistoryRead(callId: string): Promise<void> {
db.prepare(query).run(params);
}
async function markAllCallHistoryRead(): Promise<ReadonlyArray<string>> {
async function markAllCallHistoryRead(
beforeTimestamp: number
): Promise<ReadonlyArray<string>> {
const db = await getWritableInstance();
return db.transaction(() => {
const where = sqlFragment`
WHERE messages.type IS 'call-history'
AND messages.seenStatus IS ${SEEN_STATUS_UNSEEN}
AND messages.sent_at <= ${beforeTimestamp};
`;
const [selectQuery, selectParams] = sql`

View file

@ -5,7 +5,10 @@ import type { ReadonlyDeep } from 'type-fest';
import type { ThunkAction } from 'redux-thunk';
import { omit } from 'lodash';
import type { StateType as RootStateType } from '../reducer';
import { clearCallHistoryDataAndSync } from '../../util/callDisposition';
import {
clearCallHistoryDataAndSync,
markAllCallHistoryReadAndSync,
} from '../../util/callDisposition';
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
import { useBoundActions } from '../../hooks/useBoundActions';
import type { ToastActionType } from './toast';
@ -107,19 +110,8 @@ function markCallsTabViewed(): ThunkAction<
CallHistoryUpdateUnread
> {
return async dispatch => {
try {
const conversationIds = await window.Signal.Data.markAllCallHistoryRead();
for (const conversationId of conversationIds) {
drop(window.ConversationController.get(conversationId)?.updateUnread());
}
} catch (error) {
log.error(
'markCallsTabViewed: Error marking all call history read',
Errors.toLogFormat(error)
);
} finally {
dispatch(updateCallHistoryUnreadCount());
}
await markAllCallHistoryReadAndSync();
dispatch(updateCallHistoryUnreadCount());
};
}

View file

@ -3505,6 +3505,10 @@ export default class MessageReceiver
callLogEvent.type === Proto.SyncMessage.CallLogEvent.Type.CLEAR
) {
event = CallLogEvent.Clear;
} else if (
callLogEvent.type === Proto.SyncMessage.CallLogEvent.Type.MARKED_AS_READ
) {
event = CallLogEvent.MarkedAsRead;
} else {
throw new Error(
`MessageReceiver.handleCallLogEvent: unknown type ${callLogEvent.type}`

View file

@ -23,6 +23,7 @@ export enum CallDirection {
export enum CallLogEvent {
Clear = 'Clear',
MarkedAsRead = 'MarkedAsRead',
}
export enum LocalCallEvent {

View file

@ -1056,6 +1056,49 @@ export async function clearCallHistoryDataAndSync(): Promise<void> {
}
}
export async function markAllCallHistoryReadAndSync(): Promise<void> {
try {
const timestamp = Date.now();
log.info(
`markAllCallHistoryReadAndSync: Marking call history read before ${timestamp}`
);
await window.Signal.Data.markAllCallHistoryRead(timestamp);
const ourAci = window.textsecure.storage.user.getCheckedAci();
const callLogEvent = new Proto.SyncMessage.CallLogEvent({
type: Proto.SyncMessage.CallLogEvent.Type.MARKED_AS_READ,
timestamp: Long.fromNumber(timestamp),
});
const syncMessage = MessageSender.createSyncMessage();
syncMessage.callLogEvent = callLogEvent;
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
log.info('markAllCallHistoryReadAndSync: Queueing sync message');
await singleProtoJobQueue.add({
contentHint: ContentHint.RESENDABLE,
serviceId: ourAci,
isSyncMessage: true,
protoBase64: Bytes.toBase64(
Proto.Content.encode(contentMessage).finish()
),
type: 'callLogEventSync',
urgent: false,
});
} catch (error) {
log.error(
'markAllCallHistoryReadAndSync: Failed to mark call history read',
error
);
}
}
export async function updateLocalGroupCallHistoryTimestamp(
conversationId: string,
callId: string,

View file

@ -25,6 +25,16 @@ export async function onCallLogEventSync(
window.reduxActions.callHistory.resetCallHistory();
}
confirm();
} else if (event === CallLogEvent.MarkedAsRead) {
log.info(
`onCallLogEventSync: Marking call history read before ${timestamp}`
);
try {
await window.Signal.Data.markAllCallHistoryRead(timestamp);
} finally {
window.reduxActions.callHistory.updateCallHistoryUnreadCount();
}
confirm();
} else {
throw missingCaseError(event);
}