Mark all calls read when opening calls tab
This commit is contained in:
parent
b7c17212c7
commit
344ebf494d
8 changed files with 80 additions and 17 deletions
|
@ -223,7 +223,7 @@ export class ConversationModel extends window.Backbone
|
||||||
|
|
||||||
contactCollection?: Backbone.Collection<ConversationModel>;
|
contactCollection?: Backbone.Collection<ConversationModel>;
|
||||||
|
|
||||||
debouncedUpdateLastMessage?: (() => void) & { flush(): void };
|
debouncedUpdateLastMessage: (() => void) & { flush(): void };
|
||||||
|
|
||||||
initialPromise?: Promise<unknown>;
|
initialPromise?: Promise<unknown>;
|
||||||
|
|
||||||
|
@ -1400,9 +1400,7 @@ export class ConversationModel extends window.Backbone
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await this.beforeAddSingleMessage(message);
|
await this.beforeAddSingleMessage(message);
|
||||||
this.doAddSingleMessage(message, { isJustSent });
|
this.doAddSingleMessage(message, { isJustSent });
|
||||||
|
this.debouncedUpdateLastMessage();
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
||||||
this.debouncedUpdateLastMessage!();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async beforeAddSingleMessage(message: MessageModel): Promise<void> {
|
private async beforeAddSingleMessage(message: MessageModel): Promise<void> {
|
||||||
|
@ -5221,7 +5219,7 @@ export class ConversationModel extends window.Backbone
|
||||||
|
|
||||||
async flushDebouncedUpdates(): Promise<void> {
|
async flushDebouncedUpdates(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await this.debouncedUpdateLastMessage?.flush();
|
this.debouncedUpdateLastMessage.flush();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const logId = this.idForLogging();
|
const logId = this.idForLogging();
|
||||||
log.error(
|
log.error(
|
||||||
|
|
|
@ -1148,7 +1148,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
sticker: undefined,
|
sticker: undefined,
|
||||||
...additionalProperties,
|
...additionalProperties,
|
||||||
});
|
});
|
||||||
this.getConversation()?.debouncedUpdateLastMessage?.();
|
this.getConversation()?.debouncedUpdateLastMessage();
|
||||||
|
|
||||||
if (shouldPersist) {
|
if (shouldPersist) {
|
||||||
await window.Signal.Data.saveMessage(this.attributes, {
|
await window.Signal.Data.saveMessage(this.attributes, {
|
||||||
|
@ -1485,7 +1485,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
saveErrors?: (errors: Array<Error>) => void
|
saveErrors?: (errors: Array<Error>) => void
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const updateLeftPane =
|
const updateLeftPane =
|
||||||
this.getConversation()?.debouncedUpdateLastMessage || noop;
|
this.getConversation()?.debouncedUpdateLastMessage ?? noop;
|
||||||
|
|
||||||
updateLeftPane();
|
updateLeftPane();
|
||||||
|
|
||||||
|
|
|
@ -637,6 +637,7 @@ export type DataInterface = {
|
||||||
clearCallHistory: (beforeTimestamp: number) => Promise<Array<string>>;
|
clearCallHistory: (beforeTimestamp: number) => Promise<Array<string>>;
|
||||||
getCallHistoryUnreadCount(): Promise<number>;
|
getCallHistoryUnreadCount(): Promise<number>;
|
||||||
markCallHistoryRead(callId: string): Promise<void>;
|
markCallHistoryRead(callId: string): Promise<void>;
|
||||||
|
markAllCallHistoryRead(): Promise<ReadonlyArray<string>>;
|
||||||
getCallHistoryMessageByCallId(options: {
|
getCallHistoryMessageByCallId(options: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
callId: string;
|
callId: string;
|
||||||
|
|
|
@ -308,6 +308,7 @@ const dataInterface: ServerInterface = {
|
||||||
clearCallHistory,
|
clearCallHistory,
|
||||||
getCallHistoryUnreadCount,
|
getCallHistoryUnreadCount,
|
||||||
markCallHistoryRead,
|
markCallHistoryRead,
|
||||||
|
markAllCallHistoryRead,
|
||||||
getCallHistoryMessageByCallId,
|
getCallHistoryMessageByCallId,
|
||||||
getCallHistory,
|
getCallHistory,
|
||||||
getCallHistoryGroupsCount,
|
getCallHistoryGroupsCount,
|
||||||
|
@ -3369,6 +3370,35 @@ async function markCallHistoryRead(callId: string): Promise<void> {
|
||||||
db.prepare(query).run(params);
|
db.prepare(query).run(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function markAllCallHistoryRead(): Promise<ReadonlyArray<string>> {
|
||||||
|
const db = getInstance();
|
||||||
|
|
||||||
|
return db.transaction(() => {
|
||||||
|
const where = sqlFragment`
|
||||||
|
WHERE messages.type IS 'call-history'
|
||||||
|
AND messages.readStatus IS ${READ_STATUS_UNREAD}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const [selectQuery, selectParams] = sql`
|
||||||
|
SELECT DISTINCT conversationId
|
||||||
|
FROM messages
|
||||||
|
${where};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const conversationIds = db.prepare(selectQuery).pluck().all(selectParams);
|
||||||
|
|
||||||
|
const [updateQuery, updateParams] = sql`
|
||||||
|
UPDATE messages
|
||||||
|
SET readStatus = ${READ_STATUS_READ}
|
||||||
|
${where};
|
||||||
|
`;
|
||||||
|
|
||||||
|
db.prepare(updateQuery).run(updateParams);
|
||||||
|
|
||||||
|
return conversationIds;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
function getCallHistoryGroupDataSync(
|
function getCallHistoryGroupDataSync(
|
||||||
db: Database,
|
db: Database,
|
||||||
isCount: boolean,
|
isCount: boolean,
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { ToastType } from '../../types/Toast';
|
||||||
import type { CallHistoryDetails } from '../../types/CallDisposition';
|
import type { CallHistoryDetails } from '../../types/CallDisposition';
|
||||||
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 { drop } from '../../util/drop';
|
||||||
|
|
||||||
export type CallHistoryState = ReadonlyDeep<{
|
export type CallHistoryState = ReadonlyDeep<{
|
||||||
// This informs the app that underlying call history data has changed.
|
// This informs the app that underlying call history data has changed.
|
||||||
|
@ -77,9 +78,35 @@ function markCallHistoryRead(
|
||||||
return async dispatch => {
|
return async dispatch => {
|
||||||
try {
|
try {
|
||||||
await window.Signal.Data.markCallHistoryRead(callId);
|
await window.Signal.Data.markCallHistoryRead(callId);
|
||||||
await window.ConversationController.get(conversationId)?.updateUnread();
|
drop(window.ConversationController.get(conversationId)?.updateUnread());
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error('Error marking call history read', Errors.toLogFormat(error));
|
log.error(
|
||||||
|
'markCallHistoryRead: Error marking call history read',
|
||||||
|
Errors.toLogFormat(error)
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
dispatch(updateCallHistoryUnreadCount());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function markCallsTabViewed(): ThunkAction<
|
||||||
|
void,
|
||||||
|
RootStateType,
|
||||||
|
unknown,
|
||||||
|
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 {
|
} finally {
|
||||||
dispatch(updateCallHistoryUnreadCount());
|
dispatch(updateCallHistoryUnreadCount());
|
||||||
}
|
}
|
||||||
|
@ -118,6 +145,7 @@ export const actions = {
|
||||||
clearAllCallHistory,
|
clearAllCallHistory,
|
||||||
updateCallHistoryUnreadCount,
|
updateCallHistoryUnreadCount,
|
||||||
markCallHistoryRead,
|
markCallHistoryRead,
|
||||||
|
markCallsTabViewed,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useCallHistoryActions = (): BoundActionCreatorsMapObject<
|
export const useCallHistoryActions = (): BoundActionCreatorsMapObject<
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright 2023 Signal Messenger, LLC
|
// Copyright 2023 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback, useEffect } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { useItemsActions } from '../ducks/items';
|
import { useItemsActions } from '../ducks/items';
|
||||||
import {
|
import {
|
||||||
|
@ -102,8 +102,11 @@ export function SmartCallsTab(): JSX.Element {
|
||||||
onOutgoingAudioCallInConversation,
|
onOutgoingAudioCallInConversation,
|
||||||
onOutgoingVideoCallInConversation,
|
onOutgoingVideoCallInConversation,
|
||||||
} = useCallingActions();
|
} = useCallingActions();
|
||||||
const { clearAllCallHistory: clearCallHistory, markCallHistoryRead } =
|
const {
|
||||||
useCallHistoryActions();
|
clearAllCallHistory: clearCallHistory,
|
||||||
|
markCallHistoryRead,
|
||||||
|
markCallsTabViewed,
|
||||||
|
} = useCallHistoryActions();
|
||||||
|
|
||||||
const getCallHistoryGroupsCount = useCallback(
|
const getCallHistoryGroupsCount = useCallback(
|
||||||
async (options: CallHistoryFilterOptions) => {
|
async (options: CallHistoryFilterOptions) => {
|
||||||
|
@ -149,6 +152,10 @@ export function SmartCallsTab(): JSX.Element {
|
||||||
[allConversations, regionCode, callHistoryEdition]
|
[allConversations, regionCode, callHistoryEdition]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
markCallsTabViewed();
|
||||||
|
}, [markCallsTabViewed]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CallsTab
|
<CallsTab
|
||||||
activeCall={activeCall}
|
activeCall={activeCall}
|
||||||
|
|
|
@ -59,7 +59,6 @@ import {
|
||||||
callDetailsSchema,
|
callDetailsSchema,
|
||||||
} from '../types/CallDisposition';
|
} from '../types/CallDisposition';
|
||||||
import type { ConversationType } from '../state/ducks/conversations';
|
import type { ConversationType } from '../state/ducks/conversations';
|
||||||
import { drop } from './drop';
|
|
||||||
|
|
||||||
// utils
|
// utils
|
||||||
// -----
|
// -----
|
||||||
|
@ -895,7 +894,7 @@ export async function clearCallHistoryDataAndSync(): Promise<void> {
|
||||||
messageId,
|
messageId,
|
||||||
message.get('conversationId')
|
message.get('conversationId')
|
||||||
);
|
);
|
||||||
drop(conversation.updateLastMessage());
|
conversation.debouncedUpdateLastMessage();
|
||||||
window.MessageController.unregister(messageId);
|
window.MessageController.unregister(messageId);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ export async function cleanupMessage(
|
||||||
window.reduxActions?.conversations.messageDeleted(id, conversationId);
|
window.reduxActions?.conversations.messageDeleted(id, conversationId);
|
||||||
|
|
||||||
const parentConversation = window.ConversationController.get(conversationId);
|
const parentConversation = window.ConversationController.get(conversationId);
|
||||||
parentConversation?.debouncedUpdateLastMessage?.();
|
parentConversation?.debouncedUpdateLastMessage();
|
||||||
|
|
||||||
window.MessageController.unregister(id);
|
window.MessageController.unregister(id);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue