Implement the new spotlight layout
This commit is contained in:
@@ -28,12 +28,13 @@ import {
|
||||
import { Room as MatrixRoom, RoomMember } from "matrix-js-sdk/src/matrix";
|
||||
import { useEffect, useRef } from "react";
|
||||
import {
|
||||
BehaviorSubject,
|
||||
EMPTY,
|
||||
Observable,
|
||||
Subject,
|
||||
audit,
|
||||
combineLatest,
|
||||
concat,
|
||||
concatMap,
|
||||
distinctUntilChanged,
|
||||
filter,
|
||||
map,
|
||||
@@ -48,6 +49,7 @@ import {
|
||||
switchMap,
|
||||
throttleTime,
|
||||
timer,
|
||||
withLatestFrom,
|
||||
zip,
|
||||
} from "rxjs";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
@@ -371,6 +373,13 @@ export class CallViewModel extends ViewModel {
|
||||
private readonly screenShares: Observable<ScreenShare[]> =
|
||||
this.mediaItems.pipe(
|
||||
map((ms) => ms.filter((m): m is ScreenShare => m instanceof ScreenShare)),
|
||||
shareReplay(1),
|
||||
);
|
||||
|
||||
private readonly hasScreenShares: Observable<boolean> =
|
||||
this.screenShares.pipe(
|
||||
map((ms) => ms.length > 0),
|
||||
distinctUntilChanged(),
|
||||
);
|
||||
|
||||
private readonly spotlightSpeaker: Observable<UserMedia | null> =
|
||||
@@ -385,11 +394,13 @@ export class CallViewModel extends ViewModel {
|
||||
scan<(readonly [UserMedia, boolean])[], UserMedia | null, null>(
|
||||
(prev, ms) =>
|
||||
// Decide who to spotlight:
|
||||
// If the previous speaker is still speaking, stick with them rather
|
||||
// than switching eagerly to someone else
|
||||
ms.find(([m, s]) => m === prev && s)?.[0] ??
|
||||
// Otherwise, select anyone who is speaking
|
||||
ms.find(([, s]) => s)?.[0] ??
|
||||
// If the previous speaker (not the local user) is still speaking,
|
||||
// stick with them rather than switching eagerly to someone else
|
||||
(prev === null || prev.vm.local
|
||||
? null
|
||||
: ms.find(([m, s]) => m === prev && s)?.[0]) ??
|
||||
// Otherwise, select any remote user who is speaking
|
||||
ms.find(([m, s]) => !m.vm.local && s)?.[0] ??
|
||||
// Otherwise, stick with the person who was last speaking
|
||||
prev ??
|
||||
// Otherwise, spotlight the local user
|
||||
@@ -398,7 +409,8 @@ export class CallViewModel extends ViewModel {
|
||||
null,
|
||||
),
|
||||
distinctUntilChanged(),
|
||||
throttleTime(800, undefined, { leading: true, trailing: true }),
|
||||
shareReplay(1),
|
||||
throttleTime(1600, undefined, { leading: true, trailing: true }),
|
||||
);
|
||||
|
||||
private readonly grid: Observable<UserMediaViewModel[]> = this.userMedia.pipe(
|
||||
@@ -453,18 +465,31 @@ export class CallViewModel extends ViewModel {
|
||||
// orientation
|
||||
private readonly windowMode = of<WindowMode>("normal");
|
||||
|
||||
private readonly _gridMode = new BehaviorSubject<GridMode>("grid");
|
||||
private readonly gridModeUserSelection = new Subject<GridMode>();
|
||||
/**
|
||||
* The layout mode of the media tile grid.
|
||||
*/
|
||||
public readonly gridMode: Observable<GridMode> = this._gridMode;
|
||||
public readonly gridMode: Observable<GridMode> = merge(
|
||||
// Always honor a manual user selection
|
||||
this.gridModeUserSelection,
|
||||
// If the user hasn't selected spotlight and somebody starts screen sharing,
|
||||
// automatically switch to spotlight mode and reset when screen sharing ends
|
||||
this.hasScreenShares.pipe(
|
||||
withLatestFrom(this.gridModeUserSelection.pipe(startWith(null))),
|
||||
concatMap(([hasScreenShares, userSelection]) =>
|
||||
userSelection === "spotlight"
|
||||
? EMPTY
|
||||
: of<GridMode>(hasScreenShares ? "spotlight" : "grid"),
|
||||
),
|
||||
),
|
||||
).pipe(distinctUntilChanged(), shareReplay(1));
|
||||
|
||||
public setGridMode(value: GridMode): void {
|
||||
this._gridMode.next(value);
|
||||
this.gridModeUserSelection.next(value);
|
||||
}
|
||||
|
||||
public readonly layout: Observable<Layout> = combineLatest(
|
||||
[this._gridMode, this.windowMode],
|
||||
[this.gridMode, this.windowMode],
|
||||
(gridMode, windowMode) => {
|
||||
switch (windowMode) {
|
||||
case "full screen":
|
||||
|
||||
Reference in New Issue
Block a user