@@ -218,7 +218,7 @@ export interface UrlConfiguration {
|
||||
autoLeaveWhenOthersLeft: boolean;
|
||||
|
||||
/**
|
||||
* If the client should show behave like it is awaiting an answer if a notification was sent.
|
||||
* If the client should behave like it is awaiting an answer if a notification was sent (wait for call pick up).
|
||||
* This is a no-op if not combined with sendNotificationType.
|
||||
*
|
||||
* This entails:
|
||||
@@ -226,7 +226,7 @@ export interface UrlConfiguration {
|
||||
* - play a sound that indicates that it is awaiting an answer
|
||||
* - auto-dismiss the call widget once the notification lifetime expires on the receivers side.
|
||||
*/
|
||||
awaitingAnswer: boolean;
|
||||
shouldWaitForCallPickup: boolean;
|
||||
}
|
||||
|
||||
// If you need to add a new flag to this interface, prefer a name that describes
|
||||
@@ -358,6 +358,7 @@ export const getUrlParams = (
|
||||
returnToLobby: false,
|
||||
sendNotificationType: "notification" as RTCNotificationType,
|
||||
autoLeaveWhenOthersLeft: false,
|
||||
shouldWaitForCallPickup: false,
|
||||
};
|
||||
switch (intent) {
|
||||
case UserIntent.StartNewCall:
|
||||
@@ -377,6 +378,7 @@ export const getUrlParams = (
|
||||
...inAppDefault,
|
||||
skipLobby: true,
|
||||
autoLeaveWhenOthersLeft: true,
|
||||
shouldWaitForCallPickup: true,
|
||||
};
|
||||
break;
|
||||
case UserIntent.JoinExistingCallDM:
|
||||
@@ -402,6 +404,7 @@ export const getUrlParams = (
|
||||
returnToLobby: false,
|
||||
sendNotificationType: undefined,
|
||||
autoLeaveWhenOthersLeft: false,
|
||||
shouldWaitForCallPickup: false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -453,7 +456,7 @@ export const getUrlParams = (
|
||||
"ring",
|
||||
"notification",
|
||||
]),
|
||||
awaitingAnswer: parser.getFlag("showAwaitingAnswerFeedback"),
|
||||
shouldWaitForCallPickup: parser.getFlag("shouldWaitForCallPickup"),
|
||||
autoLeaveWhenOthersLeft: parser.getFlag("autoLeave"),
|
||||
};
|
||||
|
||||
|
||||
@@ -1231,7 +1231,7 @@ test("autoLeaveWhenOthersLeft$ doesn't emits when autoLeaveWhenOthersLeft option
|
||||
});
|
||||
});
|
||||
|
||||
describe("waitForNotificationAnswer$", () => {
|
||||
describe("shouldWaitForCallPickup$", () => {
|
||||
test("unknown -> ringing -> timeout when notified and nobody joins", () => {
|
||||
withTestScheduler(({ hot, schedule, expectObservable, scope }) => {
|
||||
// No one ever joins (only local user)
|
||||
@@ -1255,13 +1255,14 @@ describe("waitForNotificationAnswer$", () => {
|
||||
},
|
||||
});
|
||||
|
||||
expectObservable(vm.waitForNotificationAnswer$).toBe(
|
||||
"a 9ms b 29ms c",
|
||||
{ a: "unknown", b: "ringing", c: "timeout" },
|
||||
);
|
||||
expectObservable(vm.callPickupState$).toBe("a 9ms b 29ms c", {
|
||||
a: "unknown",
|
||||
b: "ringing",
|
||||
c: "timeout",
|
||||
});
|
||||
},
|
||||
{
|
||||
waitForNotificationAnswer: true,
|
||||
shouldWaitForCallPickup: true,
|
||||
encryptionSystem: { kind: E2eeType.PER_PARTICIPANT },
|
||||
},
|
||||
);
|
||||
@@ -1303,13 +1304,13 @@ describe("waitForNotificationAnswer$", () => {
|
||||
},
|
||||
});
|
||||
|
||||
expectObservable(vm.waitForNotificationAnswer$).toBe("a 2ms c", {
|
||||
expectObservable(vm.callPickupState$).toBe("a 2ms c", {
|
||||
a: "unknown",
|
||||
c: "success",
|
||||
});
|
||||
},
|
||||
{
|
||||
waitForNotificationAnswer: true,
|
||||
shouldWaitForCallPickup: true,
|
||||
encryptionSystem: { kind: E2eeType.PER_PARTICIPANT },
|
||||
},
|
||||
);
|
||||
@@ -1349,13 +1350,13 @@ describe("waitForNotificationAnswer$", () => {
|
||||
);
|
||||
},
|
||||
});
|
||||
expectObservable(vm.waitForNotificationAnswer$).toBe("a 1ms b", {
|
||||
expectObservable(vm.callPickupState$).toBe("a 1ms b", {
|
||||
a: "unknown",
|
||||
b: "success",
|
||||
});
|
||||
},
|
||||
{
|
||||
waitForNotificationAnswer: true,
|
||||
shouldWaitForCallPickup: true,
|
||||
encryptionSystem: { kind: E2eeType.PER_PARTICIPANT },
|
||||
},
|
||||
);
|
||||
@@ -1382,20 +1383,20 @@ describe("waitForNotificationAnswer$", () => {
|
||||
);
|
||||
},
|
||||
});
|
||||
expectObservable(vm.waitForNotificationAnswer$).toBe("a 9ms b", {
|
||||
expectObservable(vm.callPickupState$).toBe("a 9ms b", {
|
||||
a: "unknown",
|
||||
b: "timeout",
|
||||
});
|
||||
},
|
||||
{
|
||||
waitForNotificationAnswer: true,
|
||||
shouldWaitForCallPickup: true,
|
||||
encryptionSystem: { kind: E2eeType.PER_PARTICIPANT },
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("stays null when waitForNotificationAnswer=false", () => {
|
||||
test("stays null when shouldWaitForCallPickup=false", () => {
|
||||
withTestScheduler(({ hot, schedule, expectObservable, scope }) => {
|
||||
const remote$ = scope.behavior(
|
||||
hot("a--b", { a: [], b: [aliceParticipant] }),
|
||||
@@ -1427,12 +1428,12 @@ describe("waitForNotificationAnswer$", () => {
|
||||
);
|
||||
},
|
||||
});
|
||||
expectObservable(vm.waitForNotificationAnswer$).toBe("(n)", {
|
||||
expectObservable(vm.callPickupState$).toBe("(n)", {
|
||||
n: null,
|
||||
});
|
||||
},
|
||||
{
|
||||
waitForNotificationAnswer: false,
|
||||
shouldWaitForCallPickup: false,
|
||||
encryptionSystem: { kind: E2eeType.PER_PARTICIPANT },
|
||||
},
|
||||
);
|
||||
|
||||
@@ -116,7 +116,7 @@ export interface CallViewModelOptions {
|
||||
* If the call is started in a way where we want it to behave like a telephone usecase
|
||||
* If we sent a notification event, we want the ui to show a ringing state
|
||||
*/
|
||||
waitForNotificationAnswer?: boolean;
|
||||
shouldWaitForCallPickup?: boolean;
|
||||
}
|
||||
|
||||
// How long we wait after a focus switch before showing the real participant
|
||||
@@ -970,7 +970,7 @@ export class CallViewModel extends ViewModel {
|
||||
);
|
||||
|
||||
/**
|
||||
* The current waiting for answer state of the call.
|
||||
* The current call pickup state of the call.
|
||||
* - "ringing": The call is ringing on other devices in this room (This client should give audiovisual feedback that this is happening).
|
||||
* - "unknown": The client has not yet sent the notification event. We don't know if it will because it first needs to send its own membership.
|
||||
* Then we can conclude if we were the first one to join or not.
|
||||
@@ -979,7 +979,7 @@ export class CallViewModel extends ViewModel {
|
||||
* - "success": Someone else joined. The call is in a normal state. Stop audiovisual feedback.
|
||||
* - null: EC is configured to never show any waiting for answer state.
|
||||
*/
|
||||
public readonly waitForNotificationAnswer$: Behavior<
|
||||
public readonly callPickupState$: Behavior<
|
||||
"unknown" | "ringing" | "timeout" | "success" | null
|
||||
> = this.scope.behavior(
|
||||
combineLatest([
|
||||
@@ -988,7 +988,7 @@ export class CallViewModel extends ViewModel {
|
||||
]).pipe(
|
||||
map(([isRingingOthers, someoneJoined]) => {
|
||||
// Never enter waiting for answer state if the app is not configured with waitingForAnswer.
|
||||
if (!this.options.waitForNotificationAnswer) return null;
|
||||
if (!this.options.shouldWaitForCallPickup) return null;
|
||||
// As soon as someone joins, we can consider the call "wait for answer" successful
|
||||
if (someoneJoined) return "success";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user