Merge pull request #2546 from robintown/spotlight-duplication

Avoid duplicating the video of someone in the spotlight
This commit is contained in:
Robin
2024-08-09 09:11:13 -04:00
committed by GitHub
3 changed files with 33 additions and 3 deletions

View File

@@ -35,7 +35,7 @@ import {
import useMeasure from "react-use-measure"; import useMeasure from "react-use-measure";
import { MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession"; import { MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
import classNames from "classnames"; import classNames from "classnames";
import { BehaviorSubject } from "rxjs"; import { BehaviorSubject, of } from "rxjs";
import { useObservableEagerState } from "observable-hooks"; import { useObservableEagerState } from "observable-hooks";
import LogoMark from "../icons/LogoMark.svg?react"; import LogoMark from "../icons/LogoMark.svg?react";
@@ -298,6 +298,13 @@ export const InCallView: FC<InCallViewProps> = ({
const onToggleExpanded = useObservableEagerState( const onToggleExpanded = useObservableEagerState(
vm.toggleSpotlightExpanded, vm.toggleSpotlightExpanded,
); );
const showVideo = useObservableEagerState(
useMemo(
() =>
model.type === "grid" ? vm.showGridVideo(model.vm) : of(true),
[model],
),
);
const showSpeakingIndicatorsValue = useObservableEagerState( const showSpeakingIndicatorsValue = useObservableEagerState(
vm.showSpeakingIndicators, vm.showSpeakingIndicators,
); );
@@ -314,6 +321,7 @@ export const InCallView: FC<InCallViewProps> = ({
targetHeight={targetHeight} targetHeight={targetHeight}
className={classNames(className, styles.tile)} className={classNames(className, styles.tile)}
style={style} style={style}
showVideo={showVideo}
showSpeakingIndicators={showSpeakingIndicatorsValue} showSpeakingIndicators={showSpeakingIndicatorsValue}
/> />
) : ( ) : (

View File

@@ -694,8 +694,27 @@ export class CallViewModel extends ViewModel {
shareReplay(1), shareReplay(1),
); );
/**
* Determines whether video should be shown for a certain piece of media
* appearing in the grid.
*/
public showGridVideo(vm: MediaViewModel): Observable<boolean> {
return this.layout.pipe(
map(
(l) =>
!(
(l.type === "spotlight-landscape" ||
l.type === "spotlight-portrait") &&
// This media is already visible in the spotlight; avoid duplication
l.spotlight.some((spotlightVm) => spotlightVm === vm)
),
),
distinctUntilChanged(),
);
}
public showSpeakingIndicators: Observable<boolean> = this.layout.pipe( public showSpeakingIndicators: Observable<boolean> = this.layout.pipe(
map((l) => l.type !== "one-on-one" && l.type !== "spotlight-expanded"), map((l) => l.type !== "one-on-one" && !l.type.startsWith("spotlight-")),
distinctUntilChanged(), distinctUntilChanged(),
shareReplay(1), shareReplay(1),
); );

View File

@@ -60,6 +60,7 @@ interface TileProps {
targetWidth: number; targetWidth: number;
targetHeight: number; targetHeight: number;
displayName: string; displayName: string;
showVideo: boolean;
showSpeakingIndicators: boolean; showSpeakingIndicators: boolean;
} }
@@ -74,6 +75,7 @@ const UserMediaTile = forwardRef<HTMLDivElement, UserMediaTileProps>(
( (
{ {
vm, vm,
showVideo,
showSpeakingIndicators, showSpeakingIndicators,
menuStart, menuStart,
menuEnd, menuEnd,
@@ -120,7 +122,7 @@ const UserMediaTile = forwardRef<HTMLDivElement, UserMediaTileProps>(
video={video} video={video}
member={vm.member} member={vm.member}
unencryptedWarning={unencryptedWarning} unencryptedWarning={unencryptedWarning}
videoEnabled={videoEnabled} videoEnabled={videoEnabled && showVideo}
videoFit={cropVideo ? "cover" : "contain"} videoFit={cropVideo ? "cover" : "contain"}
className={classNames(className, styles.tile, { className={classNames(className, styles.tile, {
[styles.speaking]: showSpeakingIndicators && speaking, [styles.speaking]: showSpeakingIndicators && speaking,
@@ -279,6 +281,7 @@ interface GridTileProps {
targetHeight: number; targetHeight: number;
className?: string; className?: string;
style?: ComponentProps<typeof animated.div>["style"]; style?: ComponentProps<typeof animated.div>["style"];
showVideo: boolean;
showSpeakingIndicators: boolean; showSpeakingIndicators: boolean;
} }