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";
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 { 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 { TooltipProvider } from "@vector-im/compound-web";
import i18n from "i18next";

View File

@@ -14,11 +14,13 @@ import {
type RTCNotificationType,
} from "matrix-js-sdk/lib/matrixrtc";
import { pickBy } from "lodash-es";
import { BehaviorSubject } from "rxjs";
import { Config } from "./config/Config";
import { type EncryptionSystem } from "./e2ee/sharedKeyManagement";
import { E2eeType } from "./e2ee/e2eeType";
import { platform } from "./Platform";
import { type ObservableScope } from "./state/ObservableScope";
interface RoomIdentifier {
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(
roomId: string,
encryptionSystem: EncryptionSystem,

View File

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

View File

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

View File

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

View File

@@ -136,7 +136,6 @@ export const RoomPage: FC = () => {
confineToRoom={confineToRoom}
preload={preload}
skipLobby={skipLobby || wasInWaitForInviteState.current}
header={header}
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 {
and$,
createToggle$,
filterBehavior,
generateItem,
@@ -82,7 +83,7 @@ import { constant, type Behavior } from "../Behavior";
import { E2eeType } from "../../e2ee/e2eeType";
import { MatrixKeyProvider } from "../../e2ee/matrixKeyProvider";
import { type MuteStates } from "../MuteStates";
import { getUrlParams } from "../../UrlParams";
import { getUrlParams, HeaderStyle, observerUrlParams$ } from "../../UrlParams";
import { type ProcessorState } from "../../livekit/TrackProcessorContext";
import { ElementWidgetActions, widget } from "../../widget";
import {
@@ -1316,7 +1317,15 @@ export function createCallViewModel$(
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(
switchMap((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.
*/