fix: Allow switching back to grid when there is a screenshare

This commit is contained in:
Valere
2025-12-02 11:18:50 +01:00
parent 60bc6f1e93
commit b5d3f3c72a
2 changed files with 80 additions and 30 deletions

View File

@@ -82,7 +82,7 @@ test("Should switch to spotlight mode when there is a remote screen share", () =
}); });
}); });
test.fails("Can manually force grid when there is a screenshare", () => { test("Can manually force grid when there is a screenshare", () => {
withTestScheduler(({ cold, behavior, expectObservable, schedule }): void => { withTestScheduler(({ cold, behavior, expectObservable, schedule }): void => {
const { gridMode$, setGridMode } = createLayoutModeSwitch( const { gridMode$, setGridMode } = createLayoutModeSwitch(
scope, scope,
@@ -101,6 +101,29 @@ test.fails("Can manually force grid when there is a screenshare", () => {
}); });
}); });
test("Should not auto-switch after manually selected grid", () => {
withTestScheduler(({ cold, behavior, expectObservable, schedule }): void => {
const { gridMode$, setGridMode } = createLayoutModeSwitch(
scope,
behavior("n", { n: "normal" }),
cold("-ft-ft", { f: false, t: true }),
);
schedule("---g", {
g: () => setGridMode("grid"),
});
const expectation = "ggsg";
// If we did not respect manual selection, the expectation would be:
// const expectation = "ggsg-s";
expectObservable(gridMode$).toBe(expectation, {
g: "grid",
s: "spotlight",
});
});
});
test("Should switch back to grid mode when the remote screen share ends", () => { test("Should switch back to grid mode when the remote screen share ends", () => {
withTestScheduler(({ cold, behavior, expectObservable }): void => { withTestScheduler(({ cold, behavior, expectObservable }): void => {
const shareMarble = "f--t--f-"; const shareMarble = "f--t--f-";

View File

@@ -9,9 +9,8 @@ import {
BehaviorSubject, BehaviorSubject,
combineLatest, combineLatest,
map, map,
switchMap,
type Observable, type Observable,
of, scan,
} from "rxjs"; } from "rxjs";
import { logger } from "matrix-js-sdk/lib/logger"; import { logger } from "matrix-js-sdk/lib/logger";
@@ -51,33 +50,61 @@ export function createLayoutModeSwitch(
// If the user hasn't selected spotlight and somebody starts screen sharing, // If the user hasn't selected spotlight and somebody starts screen sharing,
// automatically switch to spotlight mode and reset when screen sharing ends // automatically switch to spotlight mode and reset when screen sharing ends
scope.behavior<GridMode>( scope.behavior<GridMode>(
gridModeUserSelection$.pipe( combineLatest([
switchMap((userSelection): Observable<GridMode> => { gridModeUserSelection$,
if (userSelection === "spotlight") { hasRemoteScreenShares$,
// If already in spotlight mode, stay there windowMode$,
return of("spotlight"); ]).pipe(
} else { // Scan to keep track if we have auto-switched already or not.
// Otherwise, check if there is a remote screen share active // To allow the user to override the auto-switch by selecting grid mode again.
// as this could force us into spotlight mode. scan<
return combineLatest([hasRemoteScreenShares$, windowMode$]).pipe( [GridMode, boolean, WindowMode],
map(([hasScreenShares, windowMode]): GridMode => { { mode: GridMode; hasAutoSwitched: boolean }
// TODO: strange that we do that for flat mode but not for other modes? >(
// TODO: Why is this not handled in layoutMedia$ like other window modes? (acc, [userSelection, hasScreenShares, windowMode]) => {
const isFlatMode = windowMode === "flat"; const isFlatMode = windowMode === "flat";
if (hasScreenShares || isFlatMode) {
logger.debug( // Always force spotlight in flat mode, grid layout is not supported
`Forcing spotlight mode, hasScreenShares=${hasScreenShares} windowMode=${windowMode}`, // in that mode.
); // TODO: strange that we do that for flat mode but not for other modes?
// override to spotlight mode // TODO: Why is this not handled in layoutMedia$ like other window modes?
return "spotlight"; if (isFlatMode) {
} else { logger.debug(`Forcing spotlight mode, windowMode=${windowMode}`);
// respect user choice return {
return "grid"; mode: "spotlight",
} hasAutoSwitched: acc.hasAutoSwitched,
}), };
); }
}
}), // User explicitly chose spotlight.
// Respect that choice.
if (userSelection === "spotlight") {
return {
mode: "spotlight",
hasAutoSwitched: acc.hasAutoSwitched,
};
}
// User has chosen grid mode. If a screen share starts, we will
// auto-switch to spotlight mode for better experience.
// But we only do it once, if the user switches back to grid mode,
// we respect that choice until they explicitly change it again.
if (hasScreenShares && !acc.hasAutoSwitched) {
logger.debug(
`Auto-switching to spotlight mode, hasScreenShares=${hasScreenShares}`,
);
return { mode: "spotlight", hasAutoSwitched: true };
}
// Respect user's grid choice
// XXX If we want to allow switching automatically again after we can
// return hasAutoSwitched: false here instead of keeping the previous value.
return { mode: "grid", hasAutoSwitched: acc.hasAutoSwitched };
},
// initial value
{ mode: "grid", hasAutoSwitched: false },
),
map(({ mode }) => mode),
), ),
"grid", "grid",
); );