Fix call history deletion from sync messages
This commit is contained in:
parent
20ddca9684
commit
1cc478180e
6 changed files with 84 additions and 11 deletions
|
@ -8,6 +8,7 @@ import { strictAssert } from '../util/assert';
|
||||||
let callsHistoryData: ReadonlyArray<CallHistoryDetails>;
|
let callsHistoryData: ReadonlyArray<CallHistoryDetails>;
|
||||||
|
|
||||||
export async function loadCallsHistory(): Promise<void> {
|
export async function loadCallsHistory(): Promise<void> {
|
||||||
|
await dataInterface.cleanupCallHistoryMessages();
|
||||||
callsHistoryData = await dataInterface.getAllCallHistory();
|
callsHistoryData = await dataInterface.getAllCallHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -630,6 +630,7 @@ export type DataInterface = {
|
||||||
}): Promise<MessageType | undefined>;
|
}): Promise<MessageType | undefined>;
|
||||||
getAllCallHistory: () => Promise<ReadonlyArray<CallHistoryDetails>>;
|
getAllCallHistory: () => Promise<ReadonlyArray<CallHistoryDetails>>;
|
||||||
clearCallHistory: (beforeTimestamp: number) => Promise<Array<string>>;
|
clearCallHistory: (beforeTimestamp: number) => Promise<Array<string>>;
|
||||||
|
cleanupCallHistoryMessages: () => Promise<void>;
|
||||||
getCallHistoryUnreadCount(): Promise<number>;
|
getCallHistoryUnreadCount(): Promise<number>;
|
||||||
markCallHistoryRead(callId: string): Promise<void>;
|
markCallHistoryRead(callId: string): Promise<void>;
|
||||||
markAllCallHistoryRead(): Promise<ReadonlyArray<string>>;
|
markAllCallHistoryRead(): Promise<ReadonlyArray<string>>;
|
||||||
|
|
|
@ -305,6 +305,7 @@ const dataInterface: ServerInterface = {
|
||||||
getLastConversationMessage,
|
getLastConversationMessage,
|
||||||
getAllCallHistory,
|
getAllCallHistory,
|
||||||
clearCallHistory,
|
clearCallHistory,
|
||||||
|
cleanupCallHistoryMessages,
|
||||||
getCallHistoryUnreadCount,
|
getCallHistoryUnreadCount,
|
||||||
markCallHistoryRead,
|
markCallHistoryRead,
|
||||||
markAllCallHistoryRead,
|
markAllCallHistoryRead,
|
||||||
|
@ -3294,6 +3295,24 @@ async function clearCallHistory(
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function cleanupCallHistoryMessages(): Promise<void> {
|
||||||
|
const db = getInstance();
|
||||||
|
return db
|
||||||
|
.transaction(() => {
|
||||||
|
const [query, params] = sql`
|
||||||
|
DELETE FROM messages
|
||||||
|
WHERE messages.id IN (
|
||||||
|
SELECT messages.id FROM messages
|
||||||
|
LEFT JOIN callsHistory ON callsHistory.callId IS messages.callId
|
||||||
|
WHERE messages.type IS 'call-history'
|
||||||
|
AND callsHistory.status IS ${CALL_STATUS_DELETED}
|
||||||
|
)
|
||||||
|
`;
|
||||||
|
db.prepare(query).run(params);
|
||||||
|
})
|
||||||
|
.immediate();
|
||||||
|
}
|
||||||
|
|
||||||
async function getCallHistoryMessageByCallId(options: {
|
async function getCallHistoryMessageByCallId(options: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
callId: string;
|
callId: string;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import type { ReadonlyDeep } from 'type-fest';
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type { ThunkAction } from 'redux-thunk';
|
import type { ThunkAction } from 'redux-thunk';
|
||||||
|
import { omit } from 'lodash';
|
||||||
import type { StateType as RootStateType } from '../reducer';
|
import type { StateType as RootStateType } from '../reducer';
|
||||||
import { clearCallHistoryDataAndSync } from '../../util/callDisposition';
|
import { clearCallHistoryDataAndSync } from '../../util/callDisposition';
|
||||||
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
||||||
|
@ -22,15 +23,21 @@ export type CallHistoryState = ReadonlyDeep<{
|
||||||
callHistoryByCallId: Record<string, CallHistoryDetails>;
|
callHistoryByCallId: Record<string, CallHistoryDetails>;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
const CALL_HISTORY_CACHE = 'callHistory/CACHE';
|
const CALL_HISTORY_ADD = 'callHistory/ADD';
|
||||||
|
const CALL_HISTORY_REMOVE = 'callHistory/REMOVE';
|
||||||
const CALL_HISTORY_RESET = 'callHistory/RESET';
|
const CALL_HISTORY_RESET = 'callHistory/RESET';
|
||||||
const CALL_HISTORY_UPDATE_UNREAD = 'callHistory/UPDATE_UNREAD';
|
const CALL_HISTORY_UPDATE_UNREAD = 'callHistory/UPDATE_UNREAD';
|
||||||
|
|
||||||
export type CallHistoryCache = ReadonlyDeep<{
|
export type CallHistoryAdd = ReadonlyDeep<{
|
||||||
type: typeof CALL_HISTORY_CACHE;
|
type: typeof CALL_HISTORY_ADD;
|
||||||
payload: CallHistoryDetails;
|
payload: CallHistoryDetails;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
export type CallHistoryRemove = ReadonlyDeep<{
|
||||||
|
type: typeof CALL_HISTORY_REMOVE;
|
||||||
|
payload: CallHistoryDetails['callId'];
|
||||||
|
}>;
|
||||||
|
|
||||||
export type CallHistoryReset = ReadonlyDeep<{
|
export type CallHistoryReset = ReadonlyDeep<{
|
||||||
type: typeof CALL_HISTORY_RESET;
|
type: typeof CALL_HISTORY_RESET;
|
||||||
}>;
|
}>;
|
||||||
|
@ -41,7 +48,10 @@ export type CallHistoryUpdateUnread = ReadonlyDeep<{
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export type CallHistoryAction = ReadonlyDeep<
|
export type CallHistoryAction = ReadonlyDeep<
|
||||||
CallHistoryCache | CallHistoryReset | CallHistoryUpdateUnread
|
| CallHistoryAdd
|
||||||
|
| CallHistoryRemove
|
||||||
|
| CallHistoryReset
|
||||||
|
| CallHistoryUpdateUnread
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export function getEmptyState(): CallHistoryState {
|
export function getEmptyState(): CallHistoryState {
|
||||||
|
@ -113,13 +123,26 @@ function markCallsTabViewed(): ThunkAction<
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function cacheCallHistory(callHistory: CallHistoryDetails): CallHistoryCache {
|
function addCallHistory(callHistory: CallHistoryDetails): CallHistoryAdd {
|
||||||
return {
|
return {
|
||||||
type: CALL_HISTORY_CACHE,
|
type: CALL_HISTORY_ADD,
|
||||||
payload: callHistory,
|
payload: callHistory,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function removeCallHistory(
|
||||||
|
callId: CallHistoryDetails['callId']
|
||||||
|
): CallHistoryRemove {
|
||||||
|
return {
|
||||||
|
type: CALL_HISTORY_REMOVE,
|
||||||
|
payload: callId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetCallHistory(): CallHistoryReset {
|
||||||
|
return { type: CALL_HISTORY_RESET };
|
||||||
|
}
|
||||||
|
|
||||||
function clearAllCallHistory(): ThunkAction<
|
function clearAllCallHistory(): ThunkAction<
|
||||||
void,
|
void,
|
||||||
RootStateType,
|
RootStateType,
|
||||||
|
@ -134,14 +157,16 @@ function clearAllCallHistory(): ThunkAction<
|
||||||
log.error('Error clearing call history', Errors.toLogFormat(error));
|
log.error('Error clearing call history', Errors.toLogFormat(error));
|
||||||
} finally {
|
} finally {
|
||||||
// Just force a reset, even if the clear failed.
|
// Just force a reset, even if the clear failed.
|
||||||
dispatch({ type: CALL_HISTORY_RESET });
|
dispatch(resetCallHistory());
|
||||||
dispatch(updateCallHistoryUnreadCount());
|
dispatch(updateCallHistoryUnreadCount());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
cacheCallHistory,
|
addCallHistory,
|
||||||
|
removeCallHistory,
|
||||||
|
resetCallHistory,
|
||||||
clearAllCallHistory,
|
clearAllCallHistory,
|
||||||
updateCallHistoryUnreadCount,
|
updateCallHistoryUnreadCount,
|
||||||
markCallHistoryRead,
|
markCallHistoryRead,
|
||||||
|
@ -159,7 +184,7 @@ export function reducer(
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case CALL_HISTORY_RESET:
|
case CALL_HISTORY_RESET:
|
||||||
return { ...state, edition: state.edition + 1, callHistoryByCallId: {} };
|
return { ...state, edition: state.edition + 1, callHistoryByCallId: {} };
|
||||||
case CALL_HISTORY_CACHE:
|
case CALL_HISTORY_ADD:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
callHistoryByCallId: {
|
callHistoryByCallId: {
|
||||||
|
@ -167,6 +192,11 @@ export function reducer(
|
||||||
[action.payload.callId]: action.payload,
|
[action.payload.callId]: action.payload,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
case CALL_HISTORY_REMOVE:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
callHistoryByCallId: omit(state.callHistoryByCallId, action.payload),
|
||||||
|
};
|
||||||
case CALL_HISTORY_UPDATE_UNREAD:
|
case CALL_HISTORY_UPDATE_UNREAD:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
|
|
@ -785,8 +785,18 @@ async function updateLocalCallHistory(
|
||||||
'updateLocalCallHistory: Saving call history:',
|
'updateLocalCallHistory: Saving call history:',
|
||||||
formatCallHistory(callHistory)
|
formatCallHistory(callHistory)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isDeleted =
|
||||||
|
callHistory.status === DirectCallStatus.Deleted ||
|
||||||
|
callHistory.status === GroupCallStatus.Deleted;
|
||||||
|
|
||||||
await window.Signal.Data.saveCallHistory(callHistory);
|
await window.Signal.Data.saveCallHistory(callHistory);
|
||||||
window.reduxActions.callHistory.cacheCallHistory(callHistory);
|
|
||||||
|
if (isDeleted) {
|
||||||
|
window.reduxActions.callHistory.removeCallHistory(callHistory.callId);
|
||||||
|
} else {
|
||||||
|
window.reduxActions.callHistory.addCallHistory(callHistory);
|
||||||
|
}
|
||||||
|
|
||||||
const prevMessage =
|
const prevMessage =
|
||||||
await window.Signal.Data.getCallHistoryMessageByCallId({
|
await window.Signal.Data.getCallHistoryMessageByCallId({
|
||||||
|
@ -806,6 +816,13 @@ async function updateLocalCallHistory(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isDeleted) {
|
||||||
|
if (prevMessage != null) {
|
||||||
|
await window.Signal.Data.removeMessage(prevMessage.id);
|
||||||
|
}
|
||||||
|
return callHistory;
|
||||||
|
}
|
||||||
|
|
||||||
let unread = false;
|
let unread = false;
|
||||||
if (callHistory.mode === CallMode.Direct) {
|
if (callHistory.mode === CallMode.Direct) {
|
||||||
unread =
|
unread =
|
||||||
|
|
|
@ -18,7 +18,12 @@ export async function onCallLogEventSync(
|
||||||
|
|
||||||
if (event === CallLogEvent.Clear) {
|
if (event === CallLogEvent.Clear) {
|
||||||
log.info(`onCallLogEventSync: Clearing call history before ${timestamp}`);
|
log.info(`onCallLogEventSync: Clearing call history before ${timestamp}`);
|
||||||
await window.Signal.Data.clearCallHistory(timestamp);
|
try {
|
||||||
|
await window.Signal.Data.clearCallHistory(timestamp);
|
||||||
|
} finally {
|
||||||
|
// We want to reset the call history even if the clear fails.
|
||||||
|
window.reduxActions.callHistory.resetCallHistory();
|
||||||
|
}
|
||||||
confirm();
|
confirm();
|
||||||
} else {
|
} else {
|
||||||
throw missingCaseError(event);
|
throw missingCaseError(event);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue