Save call history when peeking and discovering active call links
This commit is contained in:
parent
b6ce2f957d
commit
d9f514fe96
5 changed files with 77 additions and 13 deletions
|
@ -602,6 +602,7 @@ message SyncMessage {
|
||||||
ACCEPTED = 1;
|
ACCEPTED = 1;
|
||||||
NOT_ACCEPTED = 2;
|
NOT_ACCEPTED = 2;
|
||||||
DELETE = 3;
|
DELETE = 3;
|
||||||
|
OBSERVED = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Data identifying a conversation. The service ID for 1:1, the group ID for
|
/* Data identifying a conversation. The service ID for 1:1, the group ID for
|
||||||
|
|
|
@ -3189,22 +3189,25 @@ export class CallingClass {
|
||||||
const callId = getCallIdFromEra(peekInfo.eraId);
|
const callId = getCallIdFromEra(peekInfo.eraId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// We only log events confirmed joined. If admin approval is required, then
|
let localCallEvent;
|
||||||
// the call begins in the Pending state and we don't want history for that.
|
if (joinState === GroupCallJoinState.Joined) {
|
||||||
if (joinState !== GroupCallJoinState.Joined) {
|
localCallEvent = LocalCallEvent.Accepted;
|
||||||
|
} else if (peekInfo && peekInfo.devices.length > 0) {
|
||||||
|
localCallEvent = LocalCallEvent.Started;
|
||||||
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const callDetails = getCallDetailsForAdhocCall(roomId, callId);
|
const callDetails = getCallDetailsForAdhocCall(roomId, callId);
|
||||||
const callEvent = getCallEventDetails(
|
const callEvent = getCallEventDetails(
|
||||||
callDetails,
|
callDetails,
|
||||||
LocalCallEvent.Accepted,
|
localCallEvent,
|
||||||
'CallingClass.updateCallHistoryForGroupCallOnLocalChanged'
|
'CallingClass.updateCallHistoryForAdhocCall'
|
||||||
);
|
);
|
||||||
await updateAdhocCallHistory(callEvent);
|
await updateAdhocCallHistory(callEvent);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error(
|
log.error(
|
||||||
'CallingClass.updateCallHistoryForGroupCallOnLocalChanged: Error updating state',
|
'CallingClass.updateCallHistoryForAdhocCall: Error updating state',
|
||||||
Errors.toLogFormat(error)
|
Errors.toLogFormat(error)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -536,11 +536,10 @@ const doGroupCallPeek = ({
|
||||||
|
|
||||||
log.info(`doGroupCallPeek/${logId}: Found ${peekInfo.deviceCount} devices`);
|
log.info(`doGroupCallPeek/${logId}: Found ${peekInfo.deviceCount} devices`);
|
||||||
|
|
||||||
|
const joinState = isGroupOrAdhocCallState(existingCall)
|
||||||
|
? existingCall.joinState
|
||||||
|
: null;
|
||||||
if (callMode === CallMode.Group) {
|
if (callMode === CallMode.Group) {
|
||||||
const joinState = isGroupOrAdhocCallState(existingCall)
|
|
||||||
? existingCall.joinState
|
|
||||||
: null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await calling.updateCallHistoryForGroupCallOnPeek(
|
await calling.updateCallHistoryForGroupCallOnPeek(
|
||||||
conversationId,
|
conversationId,
|
||||||
|
@ -555,6 +554,12 @@ const doGroupCallPeek = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(updateLastMessage(conversationId));
|
dispatch(updateLastMessage(conversationId));
|
||||||
|
} else if (callMode === CallMode.Adhoc) {
|
||||||
|
await calling.updateCallHistoryForAdhocCall(
|
||||||
|
conversationId,
|
||||||
|
joinState,
|
||||||
|
peekInfo
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const formattedPeekInfo = calling.formatGroupCallPeekInfoForRedux(peekInfo);
|
const formattedPeekInfo = calling.formatGroupCallPeekInfoForRedux(peekInfo);
|
||||||
|
|
|
@ -44,6 +44,7 @@ export enum RemoteCallEvent {
|
||||||
Accepted = 'Accepted',
|
Accepted = 'Accepted',
|
||||||
NotAccepted = 'NotAccepted',
|
NotAccepted = 'NotAccepted',
|
||||||
Delete = 'Delete',
|
Delete = 'Delete',
|
||||||
|
Observed = 'Observed',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CallEvent = LocalCallEvent | RemoteCallEvent;
|
export type CallEvent = LocalCallEvent | RemoteCallEvent;
|
||||||
|
@ -55,6 +56,7 @@ export enum CallStatusValue {
|
||||||
Declined = 'Declined',
|
Declined = 'Declined',
|
||||||
Deleted = 'Deleted',
|
Deleted = 'Deleted',
|
||||||
GenericGroupCall = 'GenericGroupCall',
|
GenericGroupCall = 'GenericGroupCall',
|
||||||
|
GenericAdhocCall = 'GenericAdhocCall',
|
||||||
OutgoingRing = 'OutgoingRing',
|
OutgoingRing = 'OutgoingRing',
|
||||||
Ringing = 'Ringing',
|
Ringing = 'Ringing',
|
||||||
Joined = 'Joined',
|
Joined = 'Joined',
|
||||||
|
@ -81,6 +83,7 @@ export enum GroupCallStatus {
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum AdhocCallStatus {
|
export enum AdhocCallStatus {
|
||||||
|
Generic = CallStatusValue.GenericAdhocCall,
|
||||||
Pending = CallStatusValue.Pending,
|
Pending = CallStatusValue.Pending,
|
||||||
Joined = CallStatusValue.JoinedAdhoc,
|
Joined = CallStatusValue.JoinedAdhoc,
|
||||||
Deleted = CallStatusValue.Deleted,
|
Deleted = CallStatusValue.Deleted,
|
||||||
|
|
|
@ -67,6 +67,7 @@ import {
|
||||||
import type { ConversationType } from '../state/ducks/conversations';
|
import type { ConversationType } from '../state/ducks/conversations';
|
||||||
import type { ConversationModel } from '../models/conversations';
|
import type { ConversationModel } from '../models/conversations';
|
||||||
import { drop } from './drop';
|
import { drop } from './drop';
|
||||||
|
import { sendCallLinkUpdateSync } from './sendCallLinkUpdateSync';
|
||||||
|
|
||||||
// utils
|
// utils
|
||||||
// -----
|
// -----
|
||||||
|
@ -234,6 +235,8 @@ export function getCallEventForProto(
|
||||||
event = RemoteCallEvent.NotAccepted;
|
event = RemoteCallEvent.NotAccepted;
|
||||||
} else if (callEvent.event === Proto.SyncMessage.CallEvent.Event.DELETE) {
|
} else if (callEvent.event === Proto.SyncMessage.CallEvent.Event.DELETE) {
|
||||||
event = RemoteCallEvent.Delete;
|
event = RemoteCallEvent.Delete;
|
||||||
|
} else if (callEvent.event === Proto.SyncMessage.CallEvent.Event.OBSERVED) {
|
||||||
|
event = RemoteCallEvent.Observed;
|
||||||
} else {
|
} else {
|
||||||
throw new TypeError(`Unknown call event ${callEvent.event}`);
|
throw new TypeError(`Unknown call event ${callEvent.event}`);
|
||||||
}
|
}
|
||||||
|
@ -301,6 +304,8 @@ const statusToProto: Record<
|
||||||
[CallStatusValue.Missed]: null,
|
[CallStatusValue.Missed]: null,
|
||||||
[CallStatusValue.Pending]: null,
|
[CallStatusValue.Pending]: null,
|
||||||
[CallStatusValue.GenericGroupCall]: null,
|
[CallStatusValue.GenericGroupCall]: null,
|
||||||
|
[CallStatusValue.GenericAdhocCall]:
|
||||||
|
Proto.SyncMessage.CallEvent.Event.OBSERVED,
|
||||||
[CallStatusValue.OutgoingRing]: null,
|
[CallStatusValue.OutgoingRing]: null,
|
||||||
[CallStatusValue.Ringing]: null,
|
[CallStatusValue.Ringing]: null,
|
||||||
[CallStatusValue.Joined]: null,
|
[CallStatusValue.Joined]: null,
|
||||||
|
@ -650,6 +655,15 @@ function transitionTimestamp(
|
||||||
return callHistory.timestamp;
|
return callHistory.timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Observed call history should only be changed if we get a remote observed
|
||||||
|
// event with possibly a better timestamp.
|
||||||
|
if (callHistory.status === AdhocCallStatus.Generic) {
|
||||||
|
if (callEvent.event === RemoteCallEvent.Observed) {
|
||||||
|
return latestTimestamp;
|
||||||
|
}
|
||||||
|
return callHistory.timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
// Declined call history should only be changed if if we transition to an
|
// Declined call history should only be changed if if we transition to an
|
||||||
// accepted state or get a remote 'not accepted' event with possibly a better
|
// accepted state or get a remote 'not accepted' event with possibly a better
|
||||||
// timestamp.
|
// timestamp.
|
||||||
|
@ -713,6 +727,12 @@ function transitionDirectCallStatus(
|
||||||
return DirectCallStatus.Missed;
|
return DirectCallStatus.Missed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (callEvent === RemoteCallEvent.Observed) {
|
||||||
|
throw new Error(
|
||||||
|
`callHistoryDetails: Direct calls shouldn't send ${callEvent}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (callEvent === LocalCallEvent.Missed) {
|
if (callEvent === LocalCallEvent.Missed) {
|
||||||
return DirectCallStatus.Missed;
|
return DirectCallStatus.Missed;
|
||||||
}
|
}
|
||||||
|
@ -766,7 +786,10 @@ function transitionGroupCallStatus(
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event === RemoteCallEvent.NotAccepted) {
|
if (
|
||||||
|
event === RemoteCallEvent.NotAccepted ||
|
||||||
|
event === RemoteCallEvent.Observed
|
||||||
|
) {
|
||||||
throw new Error(`callHistoryDetails: Group calls shouldn't send ${event}`);
|
throw new Error(`callHistoryDetails: Group calls shouldn't send ${event}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -859,6 +882,13 @@ function transitionAdhocCallStatus(
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
callEvent === RemoteCallEvent.Observed ||
|
||||||
|
callEvent === LocalCallEvent.Started
|
||||||
|
) {
|
||||||
|
return AdhocCallStatus.Generic;
|
||||||
|
}
|
||||||
|
|
||||||
// For Adhoc calls, ringing and corresponding events are not supported currently.
|
// For Adhoc calls, ringing and corresponding events are not supported currently.
|
||||||
// However we handle those events here to be exhaustive.
|
// However we handle those events here to be exhaustive.
|
||||||
if (
|
if (
|
||||||
|
@ -867,7 +897,6 @@ function transitionAdhocCallStatus(
|
||||||
callEvent === LocalCallEvent.Declined ||
|
callEvent === LocalCallEvent.Declined ||
|
||||||
callEvent === LocalCallEvent.Hangup ||
|
callEvent === LocalCallEvent.Hangup ||
|
||||||
callEvent === LocalCallEvent.RemoteHangup ||
|
callEvent === LocalCallEvent.RemoteHangup ||
|
||||||
callEvent === LocalCallEvent.Started ||
|
|
||||||
// never actually happens, but need for exhaustive check
|
// never actually happens, but need for exhaustive check
|
||||||
callEvent === LocalCallEvent.Ringing
|
callEvent === LocalCallEvent.Ringing
|
||||||
) {
|
) {
|
||||||
|
@ -985,7 +1014,8 @@ export async function updateLocalAdhocCallHistory(
|
||||||
}
|
}
|
||||||
|
|
||||||
strictAssert(
|
strictAssert(
|
||||||
callHistory.status === AdhocCallStatus.Pending ||
|
callHistory.status === AdhocCallStatus.Generic ||
|
||||||
|
callHistory.status === AdhocCallStatus.Pending ||
|
||||||
callHistory.status === AdhocCallStatus.Joined ||
|
callHistory.status === AdhocCallStatus.Joined ||
|
||||||
callHistory.status === AdhocCallStatus.Deleted,
|
callHistory.status === AdhocCallStatus.Deleted,
|
||||||
`updateAdhocCallHistory: callHistory must have adhoc status (was ${callHistory.status})`
|
`updateAdhocCallHistory: callHistory must have adhoc status (was ${callHistory.status})`
|
||||||
|
@ -1002,6 +1032,28 @@ export async function updateLocalAdhocCallHistory(
|
||||||
formatCallHistory(callHistory)
|
formatCallHistory(callHistory)
|
||||||
);
|
);
|
||||||
await window.Signal.Data.saveCallHistory(callHistory);
|
await window.Signal.Data.saveCallHistory(callHistory);
|
||||||
|
|
||||||
|
/*
|
||||||
|
If we're not a call link admin and this is the first call history for this link,
|
||||||
|
then it means we clicked someone else's link and discovered it was active. We
|
||||||
|
sync this newly observed call link so the subsequent call event OBSERVED sync
|
||||||
|
message refers to a valid call link.
|
||||||
|
*/
|
||||||
|
if (prevCallHistory == null) {
|
||||||
|
const callLink = await window.Signal.Data.getCallLinkByRoomId(
|
||||||
|
callEvent.peerId
|
||||||
|
);
|
||||||
|
if (callLink) {
|
||||||
|
log.info(
|
||||||
|
`updateAdhocCallHistory: Syncing new observed call link ${callEvent.peerId}`
|
||||||
|
);
|
||||||
|
drop(sendCallLinkUpdateSync(callLink));
|
||||||
|
} else {
|
||||||
|
log.error(
|
||||||
|
`updateAdhocCallHistory: New observed call link missing in DB: ${callEvent.peerId}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDeleted) {
|
if (isDeleted) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue