mirror of
https://github.com/vector-im/element-call.git
synced 2026-08-02 19:49:23 +00:00
back
This commit is contained in:
@@ -379,7 +379,6 @@ export class CallViewModel extends ViewModel {
|
|||||||
/**
|
/**
|
||||||
* The raw list of RemoteParticipants as reported by LiveKit
|
* The raw list of RemoteParticipants as reported by LiveKit
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private readonly rawRemoteParticipants: Observable<RemoteParticipant[]> =
|
private readonly rawRemoteParticipants: Observable<RemoteParticipant[]> =
|
||||||
connectedParticipantsObserver(this.livekitRoom).pipe(this.scope.state());
|
connectedParticipantsObserver(this.livekitRoom).pipe(this.scope.state());
|
||||||
|
|
||||||
@@ -573,42 +572,41 @@ export class CallViewModel extends ViewModel {
|
|||||||
this.scope.state(),
|
this.scope.state(),
|
||||||
);
|
);
|
||||||
|
|
||||||
private readonly spotlightSpeaker: Observable<
|
private readonly spotlightSpeaker: Observable<UserMediaViewModel | null> =
|
||||||
UserMediaViewModel | undefined
|
this.userMedia.pipe(
|
||||||
> = this.userMedia.pipe(
|
switchMap((mediaItems) =>
|
||||||
switchMap((mediaItems) =>
|
mediaItems.length === 0
|
||||||
mediaItems.length === 0
|
? of([])
|
||||||
? of([])
|
: combineLatest(
|
||||||
: combineLatest(
|
mediaItems.map((m) =>
|
||||||
mediaItems.map((m) =>
|
m.vm.speaking.pipe(map((s) => [m, s] as const)),
|
||||||
m.vm.speaking.pipe(map((s) => [m, s] as const)),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
scan<(readonly [UserMedia, boolean])[], UserMedia | undefined, null>(
|
||||||
scan<(readonly [UserMedia, boolean])[], UserMedia | undefined, null>(
|
(prev, mediaItems) => {
|
||||||
(prev, mediaItems) => {
|
// Only remote users that are still in the call should be sticky
|
||||||
// Only remote users that are still in the call should be sticky
|
const [stickyMedia, stickySpeaking] =
|
||||||
const [stickyMedia, stickySpeaking] =
|
(!prev?.vm.local && mediaItems.find(([m]) => m === prev)) || [];
|
||||||
(!prev?.vm.local && mediaItems.find(([m]) => m === prev)) || [];
|
// Decide who to spotlight:
|
||||||
// Decide who to spotlight:
|
// If the previous speaker is still speaking, stick with them rather
|
||||||
// If the previous speaker is still speaking, stick with them rather
|
// than switching eagerly to someone else
|
||||||
// than switching eagerly to someone else
|
return stickySpeaking
|
||||||
return stickySpeaking
|
? stickyMedia!
|
||||||
? stickyMedia!
|
: // Otherwise, select any remote user who is speaking
|
||||||
: // Otherwise, select any remote user who is speaking
|
(mediaItems.find(([m, s]) => !m.vm.local && s)?.[0] ??
|
||||||
(mediaItems.find(([m, s]) => !m.vm.local && s)?.[0] ??
|
// Otherwise, stick with the person who was last speaking
|
||||||
// Otherwise, stick with the person who was last speaking
|
stickyMedia ??
|
||||||
stickyMedia ??
|
// Otherwise, spotlight an arbitrary remote user
|
||||||
// Otherwise, spotlight an arbitrary remote user
|
mediaItems.find(([m]) => !m.vm.local)?.[0] ??
|
||||||
mediaItems.find(([m]) => !m.vm.local)?.[0] ??
|
// Otherwise, spotlight the local user
|
||||||
// Otherwise, spotlight the local user
|
mediaItems.find(([m]) => m.vm.local)?.[0]);
|
||||||
mediaItems.find(([m]) => m.vm.local)?.[0]);
|
},
|
||||||
},
|
null,
|
||||||
null,
|
),
|
||||||
),
|
map((speaker) => speaker?.vm ?? null),
|
||||||
map((speaker) => speaker?.vm),
|
this.scope.state(),
|
||||||
this.scope.state(),
|
);
|
||||||
);
|
|
||||||
|
|
||||||
private readonly grid: Observable<UserMediaViewModel[]> = this.userMedia.pipe(
|
private readonly grid: Observable<UserMediaViewModel[]> = this.userMedia.pipe(
|
||||||
switchMap((mediaItems) => {
|
switchMap((mediaItems) => {
|
||||||
@@ -647,7 +645,7 @@ export class CallViewModel extends ViewModel {
|
|||||||
);
|
);
|
||||||
|
|
||||||
private readonly spotlightAndPip: Observable<
|
private readonly spotlightAndPip: Observable<
|
||||||
[Observable<MediaViewModel[]>, Observable<UserMediaViewModel | undefined>]
|
[Observable<MediaViewModel[]>, Observable<UserMediaViewModel | null>]
|
||||||
> = this.screenShares.pipe(
|
> = this.screenShares.pipe(
|
||||||
map((screenShares) =>
|
map((screenShares) =>
|
||||||
screenShares.length > 0
|
screenShares.length > 0
|
||||||
@@ -660,7 +658,7 @@ export class CallViewModel extends ViewModel {
|
|||||||
switchMap((speaker) =>
|
switchMap((speaker) =>
|
||||||
speaker
|
speaker
|
||||||
? speaker.local
|
? speaker.local
|
||||||
? of(undefined)
|
? of(null)
|
||||||
: this.mediaItems.pipe(
|
: this.mediaItems.pipe(
|
||||||
switchMap((mediaItems) => {
|
switchMap((mediaItems) => {
|
||||||
const localUserMedia = mediaItems.find(
|
const localUserMedia = mediaItems.find(
|
||||||
@@ -671,11 +669,11 @@ export class CallViewModel extends ViewModel {
|
|||||||
map((alwaysShow) =>
|
map((alwaysShow) =>
|
||||||
alwaysShow ? localUserMedia : undefined,
|
alwaysShow ? localUserMedia : undefined,
|
||||||
),
|
),
|
||||||
) ?? of(undefined)
|
) ?? of(null)
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
: of(undefined),
|
: of(null),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
] as const),
|
] as const),
|
||||||
@@ -689,12 +687,14 @@ export class CallViewModel extends ViewModel {
|
|||||||
);
|
);
|
||||||
|
|
||||||
private readonly hasRemoteScreenShares: Observable<boolean> =
|
private readonly hasRemoteScreenShares: Observable<boolean> =
|
||||||
this.screenShares.pipe(
|
this.spotlight.pipe(
|
||||||
map((ms) => ms.some((m) => !m.vm.local)),
|
map((spotlight) =>
|
||||||
|
spotlight.some((vm) => !vm.local && vm instanceof ScreenShareViewModel),
|
||||||
|
),
|
||||||
distinctUntilChanged(),
|
distinctUntilChanged(),
|
||||||
);
|
);
|
||||||
|
|
||||||
private readonly pip: Observable<UserMediaViewModel | undefined> =
|
private readonly pip: Observable<UserMediaViewModel | null> =
|
||||||
this.spotlightAndPip.pipe(switchMap(([, pip]) => pip));
|
this.spotlightAndPip.pipe(switchMap(([, pip]) => pip));
|
||||||
|
|
||||||
private readonly pipEnabled: Observable<boolean> = setPipEnabled.pipe(
|
private readonly pipEnabled: Observable<boolean> = setPipEnabled.pipe(
|
||||||
@@ -780,8 +780,7 @@ export class CallViewModel extends ViewModel {
|
|||||||
type: "spotlight-landscape",
|
type: "spotlight-landscape",
|
||||||
spotlight,
|
spotlight,
|
||||||
grid,
|
grid,
|
||||||
}),
|
}));
|
||||||
);
|
|
||||||
|
|
||||||
private readonly spotlightPortraitLayoutMedia: Observable<SpotlightPortraitLayoutMedia> =
|
private readonly spotlightPortraitLayoutMedia: Observable<SpotlightPortraitLayoutMedia> =
|
||||||
combineLatest([this.grid, this.spotlight], (grid, spotlight) => ({
|
combineLatest([this.grid, this.spotlight], (grid, spotlight) => ({
|
||||||
|
|||||||
Reference in New Issue
Block a user