New ringing UI
This implements the new ringing UI by showing a placeholder tile for the participant being dialed, rather than an overlay.
This commit is contained in:
@@ -7,13 +7,17 @@ Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { type Behavior } from "../Behavior";
|
||||
import { type RingingMediaViewModel } from "./RingingMediaViewModel";
|
||||
import { type ScreenShareViewModel } from "./ScreenShareViewModel";
|
||||
import { type UserMediaViewModel } from "./UserMediaViewModel";
|
||||
|
||||
/**
|
||||
* A participant's media.
|
||||
*/
|
||||
export type MediaViewModel = UserMediaViewModel | ScreenShareViewModel;
|
||||
export type MediaViewModel =
|
||||
| UserMediaViewModel
|
||||
| ScreenShareViewModel
|
||||
| RingingMediaViewModel;
|
||||
|
||||
/**
|
||||
* Properties which are common to all MediaViewModels.
|
||||
|
||||
@@ -38,6 +38,8 @@ import { type ObservableScope } from "../ObservableScope";
|
||||
import { observeTrackReference$ } from "../observeTrackReference";
|
||||
import { E2eeType } from "../../e2ee/e2eeType";
|
||||
import { observeInboundRtpStreamStats$ } from "./observeRtpStreamStats";
|
||||
import { type UserMediaViewModel } from "./UserMediaViewModel";
|
||||
import { type ScreenShareViewModel } from "./ScreenShareViewModel";
|
||||
|
||||
// TODO: Encryption status is kinda broken and thus unused right now. Remove?
|
||||
export enum EncryptionStatus {
|
||||
@@ -49,9 +51,9 @@ export enum EncryptionStatus {
|
||||
}
|
||||
|
||||
/**
|
||||
* Media belonging to an active member of the RTC session.
|
||||
* Properties common to all MemberMediaViewModels.
|
||||
*/
|
||||
export interface MemberMediaViewModel extends BaseMediaViewModel {
|
||||
export interface BaseMemberMediaViewModel extends BaseMediaViewModel {
|
||||
/**
|
||||
* The LiveKit video track for this media.
|
||||
*/
|
||||
@@ -88,7 +90,7 @@ export function createMemberMedia(
|
||||
encryptionSystem,
|
||||
...inputs
|
||||
}: MemberMediaInputs,
|
||||
): MemberMediaViewModel {
|
||||
): BaseMemberMediaViewModel {
|
||||
const trackBehavior$ = (
|
||||
source: Track.Source,
|
||||
): Behavior<TrackReference | undefined> =>
|
||||
@@ -270,3 +272,8 @@ function observeRemoteTrackReceivingOkay$(
|
||||
startWith(undefined),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Media belonging to an active member of the call.
|
||||
*/
|
||||
export type MemberMediaViewModel = UserMediaViewModel | ScreenShareViewModel;
|
||||
|
||||
51
src/state/media/RingingMediaViewModel.ts
Normal file
51
src/state/media/RingingMediaViewModel.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright 2026 Element Creations Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { type Behavior } from "../Behavior";
|
||||
import { type MuteStates } from "../MuteStates";
|
||||
import {
|
||||
type BaseMediaInputs,
|
||||
type BaseMediaViewModel,
|
||||
createBaseMedia,
|
||||
} from "./MediaViewModel";
|
||||
|
||||
/**
|
||||
* Media representing a user who is not yet part of the call — one that we are
|
||||
* *ringing*.
|
||||
*/
|
||||
export interface RingingMediaViewModel extends BaseMediaViewModel {
|
||||
type: "ringing";
|
||||
pickupState$: Behavior<"ringing" | "timeout" | "decline">;
|
||||
/**
|
||||
* Whether this media would be expected to have video, were it not simply a
|
||||
* placeholder.
|
||||
*/
|
||||
videoEnabled$: Behavior<boolean>;
|
||||
}
|
||||
|
||||
export interface RingingMediaInputs extends BaseMediaInputs {
|
||||
pickupState$: Behavior<"ringing" | "timeout" | "decline">;
|
||||
/**
|
||||
* The local user's own mute states.
|
||||
*/
|
||||
muteStates: MuteStates;
|
||||
}
|
||||
|
||||
export function createRingingMedia({
|
||||
pickupState$,
|
||||
muteStates,
|
||||
...inputs
|
||||
}: RingingMediaInputs): RingingMediaViewModel {
|
||||
return {
|
||||
...createBaseMedia(inputs),
|
||||
type: "ringing",
|
||||
pickupState$,
|
||||
// If our own video is enabled, then this is a video call and we would
|
||||
// expect remote media to have video as well
|
||||
videoEnabled$: muteStates.video.enabled$,
|
||||
};
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import { type LocalScreenShareViewModel } from "./LocalScreenShareViewModel";
|
||||
import {
|
||||
createMemberMedia,
|
||||
type MemberMediaInputs,
|
||||
type MemberMediaViewModel,
|
||||
type BaseMemberMediaViewModel,
|
||||
} from "./MemberMediaViewModel";
|
||||
import { type RemoteScreenShareViewModel } from "./RemoteScreenShareViewModel";
|
||||
|
||||
@@ -27,7 +27,7 @@ export type ScreenShareViewModel =
|
||||
/**
|
||||
* Properties which are common to all ScreenShareViewModels.
|
||||
*/
|
||||
export interface BaseScreenShareViewModel extends MemberMediaViewModel {
|
||||
export interface BaseScreenShareViewModel extends BaseMemberMediaViewModel {
|
||||
type: "screen share";
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import { type LocalUserMediaViewModel } from "./LocalUserMediaViewModel";
|
||||
import {
|
||||
createMemberMedia,
|
||||
type MemberMediaInputs,
|
||||
type MemberMediaViewModel,
|
||||
type BaseMemberMediaViewModel,
|
||||
} from "./MemberMediaViewModel";
|
||||
import { type RemoteUserMediaViewModel } from "./RemoteUserMediaViewModel";
|
||||
import { type ObservableScope } from "../ObservableScope";
|
||||
@@ -42,7 +42,7 @@ export type UserMediaViewModel =
|
||||
| LocalUserMediaViewModel
|
||||
| RemoteUserMediaViewModel;
|
||||
|
||||
export interface BaseUserMediaViewModel extends MemberMediaViewModel {
|
||||
export interface BaseUserMediaViewModel extends BaseMemberMediaViewModel {
|
||||
type: "user";
|
||||
speaking$: Behavior<boolean>;
|
||||
audioEnabled$: Behavior<boolean>;
|
||||
|
||||
@@ -194,5 +194,3 @@ export function createWrappedUserMedia(
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
export type MediaItem = WrappedUserMediaViewModel | ScreenShareViewModel;
|
||||
Reference in New Issue
Block a user