Skip to content

Commit b5d3f3c

Browse files
committed
fix: Allow switching back to grid when there is a screenshare
1 parent 60bc6f1 commit b5d3f3c

File tree

2 files changed

+80
-30
lines changed

2 files changed

+80
-30
lines changed

src/state/CallViewModel/Layout.switch.test.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ test("Should switch to spotlight mode when there is a remote screen share", () =
8282
});
8383
});
8484

85-
test.fails("Can manually force grid when there is a screenshare", () => {
85+
test("Can manually force grid when there is a screenshare", () => {
8686
withTestScheduler(({ cold, behavior, expectObservable, schedule }): void => {
8787
const { gridMode$, setGridMode } = createLayoutModeSwitch(
8888
scope,
@@ -101,6 +101,29 @@ test.fails("Can manually force grid when there is a screenshare", () => {
101101
});
102102
});
103103

104+
test("Should not auto-switch after manually selected grid", () => {
105+
withTestScheduler(({ cold, behavior, expectObservable, schedule }): void => {
106+
const { gridMode$, setGridMode } = createLayoutModeSwitch(
107+
scope,
108+
behavior("n", { n: "normal" }),
109+
cold("-ft-ft", { f: false, t: true }),
110+
);
111+
112+
schedule("---g", {
113+
g: () => setGridMode("grid"),
114+
});
115+
116+
const expectation = "ggsg";
117+
// If we did not respect manual selection, the expectation would be:
118+
// const expectation = "ggsg-s";
119+
120+
expectObservable(gridMode$).toBe(expectation, {
121+
g: "grid",
122+
s: "spotlight",
123+
});
124+
});
125+
});
126+
104127
test("Should switch back to grid mode when the remote screen share ends", () => {
105128
withTestScheduler(({ cold, behavior, expectObservable }): void => {
106129
const shareMarble = "f--t--f-";

src/state/CallViewModel/LayoutSwitch.ts

Lines changed: 56 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ import {
99
BehaviorSubject,
1010
combineLatest,
1111
map,
12-
switchMap,
1312
type Observable,
14-
of,
13+
scan,
1514
} from "rxjs";
1615
import { logger } from "matrix-js-sdk/lib/logger";
1716

@@ -51,33 +50,61 @@ export function createLayoutModeSwitch(
5150
// If the user hasn't selected spotlight and somebody starts screen sharing,
5251
// automatically switch to spotlight mode and reset when screen sharing ends
5352
scope.behavior<GridMode>(
54-
gridModeUserSelection$.pipe(
55-
switchMap((userSelection): Observable<GridMode> => {
56-
if (userSelection === "spotlight") {
57-
// If already in spotlight mode, stay there
58-
return of("spotlight");
59-
} else {
60-
// Otherwise, check if there is a remote screen share active
61-
// as this could force us into spotlight mode.
62-
return combineLatest([hasRemoteScreenShares$, windowMode$]).pipe(
63-
map(([hasScreenShares, windowMode]): GridMode => {
64-
// TODO: strange that we do that for flat mode but not for other modes?
65-
// TODO: Why is this not handled in layoutMedia$ like other window modes?
66-
const isFlatMode = windowMode === "flat";
67-
if (hasScreenShares || isFlatMode) {
68-
logger.debug(
69-
`Forcing spotlight mode, hasScreenShares=${hasScreenShares} windowMode=${windowMode}`,
70-
);
71-
// override to spotlight mode
72-
return "spotlight";
73-
} else {
74-
// respect user choice
75-
return "grid";
76-
}
77-
}),
78-
);
79-
}
80-
}),
53+
combineLatest([
54+
gridModeUserSelection$,
55+
hasRemoteScreenShares$,
56+
windowMode$,
57+
]).pipe(
58+
// Scan to keep track if we have auto-switched already or not.
59+
// To allow the user to override the auto-switch by selecting grid mode again.
60+
scan<
61+
[GridMode, boolean, WindowMode],
62+
{ mode: GridMode; hasAutoSwitched: boolean }
63+
>(
64+
(acc, [userSelection, hasScreenShares, windowMode]) => {
65+
const isFlatMode = windowMode === "flat";
66+
67+
// Always force spotlight in flat mode, grid layout is not supported
68+
// in that mode.
69+
// TODO: strange that we do that for flat mode but not for other modes?
70+
// TODO: Why is this not handled in layoutMedia$ like other window modes?
71+
if (isFlatMode) {
72+
logger.debug(`Forcing spotlight mode, windowMode=${windowMode}`);
73+
return {
74+
mode: "spotlight",
75+
hasAutoSwitched: acc.hasAutoSwitched,
76+
};
77+
}
78+
79+
// User explicitly chose spotlight.
80+
// Respect that choice.
81+
if (userSelection === "spotlight") {
82+
return {
83+
mode: "spotlight",
84+
hasAutoSwitched: acc.hasAutoSwitched,
85+
};
86+
}
87+
88+
// User has chosen grid mode. If a screen share starts, we will
89+
// auto-switch to spotlight mode for better experience.
90+
// But we only do it once, if the user switches back to grid mode,
91+
// we respect that choice until they explicitly change it again.
92+
if (hasScreenShares && !acc.hasAutoSwitched) {
93+
logger.debug(
94+
`Auto-switching to spotlight mode, hasScreenShares=${hasScreenShares}`,
95+
);
96+
return { mode: "spotlight", hasAutoSwitched: true };
97+
}
98+
99+
// Respect user's grid choice
100+
// XXX If we want to allow switching automatically again after we can
101+
// return hasAutoSwitched: false here instead of keeping the previous value.
102+
return { mode: "grid", hasAutoSwitched: acc.hasAutoSwitched };
103+
},
104+
// initial value
105+
{ mode: "grid", hasAutoSwitched: false },
106+
),
107+
map(({ mode }) => mode),
81108
),
82109
"grid",
83110
);

0 commit comments

Comments
 (0)