move show footer logic to callViewModel

Also remove header prop. This is accesible via urlParams.
This commit is contained in:
Timo K
2026-04-10 17:01:56 +02:00
parent 6be06de153
commit f75e91fc2b
9 changed files with 58 additions and 17 deletions

View File

@@ -1,3 +1,10 @@
/*
Copyright 2026 Element Creations Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import type { StorybookConfig } from "@storybook/react-vite"; import type { StorybookConfig } from "@storybook/react-vite";
const config: StorybookConfig = { const config: StorybookConfig = {

View File

@@ -1,3 +1,10 @@
/*
Copyright 2026 Element Creations Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { create } from "storybook/theming"; import { create } from "storybook/theming";
import { addons } from "storybook/manager-api"; import { addons } from "storybook/manager-api";

View File

@@ -1,3 +1,10 @@
/*
Copyright 2026 Element Creations Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import type { Preview } from "@storybook/react-vite"; import type { Preview } from "@storybook/react-vite";
import { TooltipProvider } from "@vector-im/compound-web"; import { TooltipProvider } from "@vector-im/compound-web";
import i18n from "i18next"; import i18n from "i18next";

View File

@@ -14,11 +14,13 @@ import {
type RTCNotificationType, type RTCNotificationType,
} from "matrix-js-sdk/lib/matrixrtc"; } from "matrix-js-sdk/lib/matrixrtc";
import { pickBy } from "lodash-es"; import { pickBy } from "lodash-es";
import { BehaviorSubject } from "rxjs";
import { Config } from "./config/Config"; import { Config } from "./config/Config";
import { type EncryptionSystem } from "./e2ee/sharedKeyManagement"; import { type EncryptionSystem } from "./e2ee/sharedKeyManagement";
import { E2eeType } from "./e2ee/e2eeType"; import { E2eeType } from "./e2ee/e2eeType";
import { platform } from "./Platform"; import { platform } from "./Platform";
import { type ObservableScope } from "./state/ObservableScope";
interface RoomIdentifier { interface RoomIdentifier {
roomAlias: string | null; roomAlias: string | null;
@@ -607,6 +609,24 @@ export const useRoomIdentifier = (): RoomIdentifier => {
); );
}; };
let urlParams$ = undefined as BehaviorSubject<UrlParams> | undefined;
export const observerUrlParams$ = (
scope: ObservableScope,
): BehaviorSubject<UrlParams> => {
if (urlParams$ !== undefined) return urlParams$;
function updateUrlParams(): void {
console.log("[observerUrlParams$] update urlParams$");
urlParams$!.next(getUrlParams());
}
urlParams$ = new BehaviorSubject(getUrlParams());
window.addEventListener("hashchange", updateUrlParams);
scope.onEnd(() => {
window.removeEventListener("hashchange", updateUrlParams);
});
return urlParams$;
};
export function generateUrlSearchParams( export function generateUrlSearchParams(
roomId: string, roomId: string,
encryptionSystem: EncryptionSystem, encryptionSystem: EncryptionSystem,

View File

@@ -93,7 +93,6 @@ interface Props {
confineToRoom: boolean; confineToRoom: boolean;
preload: UrlParams["preload"]; preload: UrlParams["preload"];
skipLobby: UrlParams["skipLobby"]; skipLobby: UrlParams["skipLobby"];
header: HeaderStyle;
rtcSession: MatrixRTCSession; rtcSession: MatrixRTCSession;
joined: boolean; joined: boolean;
setJoined: (value: boolean) => void; setJoined: (value: boolean) => void;
@@ -107,7 +106,6 @@ export const GroupCallView: FC<Props> = ({
confineToRoom, confineToRoom,
preload, preload,
skipLobby, skipLobby,
header,
rtcSession, rtcSession,
joined, joined,
setJoined, setJoined,
@@ -182,6 +180,7 @@ export const GroupCallView: FC<Props> = ({
perParticipantE2EE, perParticipantE2EE,
returnToLobby, returnToLobby,
password: passwordFromUrl, password: passwordFromUrl,
header,
} = useUrlParams(); } = useUrlParams();
const e2eeSystem = useRoomEncryptionSystem(room.roomId); const e2eeSystem = useRoomEncryptionSystem(room.roomId);
@@ -463,7 +462,6 @@ export const GroupCallView: FC<Props> = ({
rtcSession={rtcSession as MatrixRTCSession} rtcSession={rtcSession as MatrixRTCSession}
matrixRoom={room} matrixRoom={room}
onLeft={onLeft} onLeft={onLeft}
header={header}
muteStates={muteStates} muteStates={muteStates}
e2eeSystem={e2eeSystem} e2eeSystem={e2eeSystem}
//otelGroupCallMembership={otelGroupCallMembership} //otelGroupCallMembership={otelGroupCallMembership}

View File

@@ -39,7 +39,6 @@ import { ReactionsSenderProvider } from "../reactions/useReactionsSender";
import { useRoomEncryptionSystem } from "../e2ee/sharedKeyManagement"; import { useRoomEncryptionSystem } from "../e2ee/sharedKeyManagement";
import { LivekitRoomAudioRenderer } from "../livekit/MatrixAudioRenderer"; import { LivekitRoomAudioRenderer } from "../livekit/MatrixAudioRenderer";
import { MediaDevicesContext } from "../MediaDevicesContext"; import { MediaDevicesContext } from "../MediaDevicesContext";
import { HeaderStyle } from "../UrlParams";
import { type MediaDevices as ECMediaDevices } from "../state/MediaDevices"; import { type MediaDevices as ECMediaDevices } from "../state/MediaDevices";
import { initializeWidget } from "../widget"; import { initializeWidget } from "../widget";
@@ -131,7 +130,6 @@ function createInCallView(args: CreateInCallViewArgs = {}): RenderResult & {
<RoomContext value={livekitRoom}> <RoomContext value={livekitRoom}>
<InCallView <InCallView
client={client} client={client}
header={HeaderStyle.Standard}
rtcSession={rtcSession.asMockedSession()} rtcSession={rtcSession.asMockedSession()}
muteStates={muteState} muteStates={muteState}
vm={vm} vm={vm}

View File

@@ -171,7 +171,6 @@ export interface InCallViewProps {
rtcSession: MatrixRTCSession; rtcSession: MatrixRTCSession;
matrixRoom: MatrixRoom; matrixRoom: MatrixRoom;
muteStates: MuteStates; muteStates: MuteStates;
header: HeaderStyle;
onShareClick: (() => void) | null; onShareClick: (() => void) | null;
} }
@@ -181,8 +180,6 @@ export const InCallView: FC<InCallViewProps> = ({
matrixInfo, matrixInfo,
matrixRoom, matrixRoom,
muteStates, muteStates,
header: headerStyle,
onShareClick, onShareClick,
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -206,7 +203,7 @@ export const InCallView: FC<InCallViewProps> = ({
// Merge the refs so they can attach to the same element // Merge the refs so they can attach to the same element
const containerRef = useMergedRefs(containerRef1, containerRef2); const containerRef = useMergedRefs(containerRef1, containerRef2);
const { showControls } = useUrlParams(); const { showControls, header: headerStyle } = useUrlParams();
const muteAllAudio = useBehavior(muteAllAudio$); const muteAllAudio = useBehavior(muteAllAudio$);
@@ -565,14 +562,11 @@ export const InCallView: FC<InCallViewProps> = ({
<SettingsButton key="settings" onClick={openSettings} />, <SettingsButton key="settings" onClick={openSettings} />,
); );
const footerNotNeeded =
showControls === false && headerStyle === HeaderStyle.None;
const footer = ( const footer = (
<InCallFooter <InCallFooter
ref={footerRef} ref={footerRef}
asOverlay={windowMode === "flat"} asOverlay={windowMode === "flat"}
// TODO this should be computed in the view model! showFooter={showFooter}
showFooter={showFooter && !footerNotNeeded}
showControls={showControls} showControls={showControls}
showLogo={headerStyle !== HeaderStyle.None} showLogo={headerStyle !== HeaderStyle.None}
showSettingsButton={headerStyle !== HeaderStyle.AppBar} showSettingsButton={headerStyle !== HeaderStyle.AppBar}

View File

@@ -136,7 +136,6 @@ export const RoomPage: FC = () => {
confineToRoom={confineToRoom} confineToRoom={confineToRoom}
preload={preload} preload={preload}
skipLobby={skipLobby || wasInWaitForInviteState.current} skipLobby={skipLobby || wasInWaitForInviteState.current}
header={header}
muteStates={muteStates} muteStates={muteStates}
/> />
) )

View File

@@ -51,6 +51,7 @@ import { v4 as uuidv4 } from "uuid";
import { type IMembershipManager } from "matrix-js-sdk/lib/matrixrtc/IMembershipManager"; import { type IMembershipManager } from "matrix-js-sdk/lib/matrixrtc/IMembershipManager";
import { import {
and$,
createToggle$, createToggle$,
filterBehavior, filterBehavior,
generateItem, generateItem,
@@ -82,7 +83,7 @@ import { constant, type Behavior } from "../Behavior";
import { E2eeType } from "../../e2ee/e2eeType"; import { E2eeType } from "../../e2ee/e2eeType";
import { MatrixKeyProvider } from "../../e2ee/matrixKeyProvider"; import { MatrixKeyProvider } from "../../e2ee/matrixKeyProvider";
import { type MuteStates } from "../MuteStates"; import { type MuteStates } from "../MuteStates";
import { getUrlParams } from "../../UrlParams"; import { getUrlParams, HeaderStyle, observerUrlParams$ } from "../../UrlParams";
import { type ProcessorState } from "../../livekit/TrackProcessorContext"; import { type ProcessorState } from "../../livekit/TrackProcessorContext";
import { ElementWidgetActions, widget } from "../../widget"; import { ElementWidgetActions, widget } from "../../widget";
import { import {
@@ -1316,7 +1317,15 @@ export function createCallViewModel$(
windowMode$.pipe(map((mode) => mode !== "pip" && mode !== "flat")), windowMode$.pipe(map((mode) => mode !== "pip" && mode !== "flat")),
); );
const showFooter$ = scope.behavior<boolean>( const urlParams$ = observerUrlParams$(scope);
const showFooterUrlParams$ = urlParams$.pipe(
map(
({ header, showControls }) =>
// with no header and no controls we always set showFooter to false.
!(header === HeaderStyle.None && showControls === false),
),
);
const showFooterLayout$ = scope.behavior<boolean>(
windowMode$.pipe( windowMode$.pipe(
switchMap((mode) => { switchMap((mode) => {
switch (mode) { switch (mode) {
@@ -1370,7 +1379,9 @@ export function createCallViewModel$(
}), }),
), ),
); );
const showFooter$ = scope.behavior(
and$(showFooterLayout$, showFooterUrlParams$),
);
/** /**
* Whether audio is currently being output through the earpiece. * Whether audio is currently being output through the earpiece.
*/ */