Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/web/src/LegacyCallHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import { Action } from "./dispatcher/actions";
import { addManagedHybridWidget, isManagedHybridWidgetEnabled } from "./widgets/ManagedHybrid";
import SdkConfig from "./SdkConfig";
import { ensureDMExists } from "./createRoom";
import { Container, WidgetLayoutStore } from "./stores/widgets/WidgetLayoutStore";
import { WidgetLayoutStore } from "./stores/widgets/WidgetLayoutStore";
import IncomingLegacyCallToast, { getIncomingLegacyCallToastKey } from "./toasts/IncomingLegacyCallToast";
import ToastStore from "./stores/ToastStore";
import { type ViewRoomPayload } from "./dispatcher/payloads/ViewRoomPayload";
Expand Down Expand Up @@ -1027,7 +1027,7 @@ export default class LegacyCallHandler extends TypedEventEmitter<LegacyCallHandl
// If there already is a Jitsi widget, pin it
const room = client.getRoom(roomId);
if (isNotNull(room)) {
WidgetLayoutStore.instance.moveToContainer(room, widget, Container.Top);
WidgetLayoutStore.instance.moveToContainer(room, widget, "top");
}
return;
}
Expand Down
14 changes: 11 additions & 3 deletions apps/web/src/components/structures/RoomView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ import { CallView } from "../views/voip/CallView";
import { UPDATE_EVENT } from "../../stores/AsyncStore";
import Notifier from "../../Notifier";
import { showToast as showNotificationsToast } from "../../toasts/DesktopNotificationsToast";
import { Container, WidgetLayoutStore } from "../../stores/widgets/WidgetLayoutStore";
import { WidgetLayoutStore } from "../../stores/widgets/WidgetLayoutStore";
import { getKeyBindingsManager } from "../../KeyBindingsManager";
import { objectHasDiff } from "../../utils/objects";
import SpaceRoomView from "./SpaceRoomView";
Expand Down Expand Up @@ -141,6 +141,7 @@ import { isRoomEncrypted } from "../../hooks/useIsEncrypted";
import { type RoomViewStore } from "../../stores/RoomViewStore.tsx";
import { RoomStatusBarViewModel } from "../../viewmodels/room/RoomStatusBar.ts";
import { EncryptionEventViewModel } from "../../viewmodels/event-tiles/EncryptionEventViewModel.ts";
import { ModuleApi } from "../../modules/Api.ts";

const DEBUG = false;
const PREVENT_MULTIPLE_JITSI_WITHIN = 30_000;
Expand Down Expand Up @@ -953,7 +954,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
// Otherwise (in case the user set hideWidgetDrawer by clicking the button) follow the parameter.
const isManuallyShown = hideWidgetDrawer ? hideWidgetDrawer === "false" : true;

const widgets = this.context.widgetLayoutStore.getContainerWidgets(room, Container.Top);
const widgets = this.context.widgetLayoutStore.getContainerWidgets(room, "top");
return isManuallyShown && widgets.length > 0;
}

Expand Down Expand Up @@ -2727,6 +2728,12 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
this.state.mainSplitContentType === MainSplitContentType.Call ? "video_room" : "maximised_widget";
}

const extraButtons: JSX.Element[] = [];
for (const cb of ModuleApi.instance.extras.roomHeaderButtonsCallbacks) {
const b = cb(this.state.room.roomId);
if (b) extraButtons.push(b);
}

return (
<ScopedRoomContextProvider {...this.state} roomViewStore={this.roomViewStore}>
<div
Expand Down Expand Up @@ -2754,7 +2761,8 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
{!this.props.hideHeader && (
<RoomHeader
room={this.state.room}
additionalButtons={this.state.viewRoomOpts.buttons}
legacyAdditionalButtons={this.state.viewRoomOpts.buttons}
extraButtons={<>{extraButtons}</>}
/>
)}
{mainSplitBody}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import QuestionDialog from "../dialogs/QuestionDialog";
import ErrorDialog from "../dialogs/ErrorDialog";
import { WidgetType } from "../../../widgets/WidgetType";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import { Container, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
import { WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
import { getConfigLivestreamUrl, startJitsiAudioLivestream } from "../../../Livestream";
import { ModuleRunner } from "../../../modules/ModuleRunner";
import { ElementWidget, type WidgetMessaging } from "../../../stores/widgets/WidgetMessaging";
Expand Down Expand Up @@ -79,7 +79,7 @@ const showSnapshotButton = (widgetMessaging: WidgetMessaging | undefined): boole
const showMoveButtons = (app: IWidget, room: Room | undefined, showUnpin: boolean | undefined): [boolean, boolean] => {
if (!showUnpin) return [false, false];

const pinnedWidgets = room ? WidgetLayoutStore.instance.getContainerWidgets(room, Container.Top) : [];
const pinnedWidgets = room ? WidgetLayoutStore.instance.getContainerWidgets(room, "top") : [];
const widgetIndex = pinnedWidgets.findIndex((widget) => widget.id === app.id);
return [widgetIndex > 0, widgetIndex < pinnedWidgets.length - 1];
};
Expand Down Expand Up @@ -221,7 +221,7 @@ export const WidgetContextMenu: React.FC<IProps> = ({
if (showMoveLeftButton) {
const onClick = (): void => {
if (!room) throw new Error("room must be defined");
WidgetLayoutStore.instance.moveWithinContainer(room, Container.Top, app, -1);
WidgetLayoutStore.instance.moveWithinContainer(room, "top", app, -1);
onFinished();
};

Expand All @@ -232,7 +232,7 @@ export const WidgetContextMenu: React.FC<IProps> = ({
if (showMoveRightButton) {
const onClick = (): void => {
if (!room) throw new Error("room must be defined");
WidgetLayoutStore.instance.moveWithinContainer(room, Container.Top, app, 1);
WidgetLayoutStore.instance.moveWithinContainer(room, "top", app, 1);
onFinished();
};

Expand Down
19 changes: 7 additions & 12 deletions apps/web/src/components/views/elements/AppTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import { ElementWidget, WidgetMessaging, WidgetMessagingEvent } from "../../../s
import WidgetAvatar from "../avatars/WidgetAvatar";
import LegacyCallHandler from "../../../LegacyCallHandler";
import { type IApp, isAppWidget } from "../../../stores/WidgetStore";
import { Container, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
import { WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
import { OwnProfileStore } from "../../../stores/OwnProfileStore";
import { UPDATE_EVENT } from "../../../stores/AsyncStore";
import WidgetUtils from "../../../utils/WidgetUtils";
Expand Down Expand Up @@ -682,21 +682,17 @@ export default class AppTile extends React.Component<IProps, IState> {

private onToggleMaximisedClick = (): void => {
if (!this.props.room) return; // ignore action - it shouldn't even be visible
const targetContainer = WidgetLayoutStore.instance.isInContainer(
this.props.room,
this.props.app,
Container.Center,
)
? Container.Top
: Container.Center;
const targetContainer = WidgetLayoutStore.instance.isInContainer(this.props.room, this.props.app, "center")
? "top"
: "center";
WidgetLayoutStore.instance.moveToContainer(this.props.room, this.props.app, targetContainer);

if (targetContainer === Container.Top) this.closeChatCardIfNeeded();
if (targetContainer === "top") this.closeChatCardIfNeeded();
};

private onMinimiseClicked = (): void => {
if (!this.props.room) return; // ignore action - it shouldn't even be visible
WidgetLayoutStore.instance.moveToContainer(this.props.room, this.props.app, Container.Right);
WidgetLayoutStore.instance.moveToContainer(this.props.room, this.props.app, "right");
this.closeChatCardIfNeeded();
};

Expand Down Expand Up @@ -822,8 +818,7 @@ export default class AppTile extends React.Component<IProps, IState> {
const layoutButtons: ReactNode[] = [];
if (this.props.showLayoutButtons) {
const isMaximised =
this.props.room &&
WidgetLayoutStore.instance.isInContainer(this.props.room, this.props.app, Container.Center);
this.props.room && WidgetLayoutStore.instance.isInContainer(this.props.room, this.props.app, "center");

layoutButtons.push(
<AccessibleButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { EventTileBubble } from "@element-hq/web-shared-components";
import { _t } from "../../../languageHandler";
import WidgetStore from "../../../stores/WidgetStore";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import { Container, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
import { WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";

interface IProps {
mxEvent: MatrixEvent;
Expand All @@ -32,7 +32,7 @@ export default class MJitsiWidgetEvent extends React.PureComponent<IProps> {
const widget = WidgetStore.instance.getRoom(room.roomId, true).widgets.find((w) => w.id === widgetId);

let joinCopy: string | null = _t("timeline|m.widget|jitsi_join_top_prompt");
if (widget && WidgetLayoutStore.instance.isInContainer(room, widget, Container.Right)) {
if (widget && WidgetLayoutStore.instance.isInContainer(room, widget, "right")) {
joinCopy = _t("timeline|m.widget|jitsi_join_right_prompt");
} else if (!widget) {
joinCopy = null;
Expand Down
12 changes: 6 additions & 6 deletions apps/web/src/components/views/right_panel/ExtensionsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { useContextMenu } from "../../structures/ContextMenu";
import RightPanelStore from "../../../stores/right-panel/RightPanelStore";
import { type IApp } from "../../../stores/WidgetStore";
import { RightPanelPhases } from "../../../stores/right-panel/RightPanelStorePhases";
import { Container, MAX_PINNED, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
import { MAX_PINNED, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
import AccessibleButton from "../elements/AccessibleButton";
import WidgetAvatar from "../avatars/WidgetAvatar";
import { IntegrationManagers } from "../../../integrations/IntegrationManagers";
Expand Down Expand Up @@ -58,18 +58,18 @@ const AppRow: React.FC<IAppRowProps> = ({ app, room }) => {
});
};

const isPinned = WidgetLayoutStore.instance.isInContainer(room, app, Container.Top);
const isPinned = WidgetLayoutStore.instance.isInContainer(room, app, "top");
const togglePin = isPinned
? () => {
WidgetLayoutStore.instance.moveToContainer(room, app, Container.Right);
WidgetLayoutStore.instance.moveToContainer(room, app, "right");
}
: () => {
WidgetLayoutStore.instance.moveToContainer(room, app, Container.Top);
WidgetLayoutStore.instance.moveToContainer(room, app, "top");
};

const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu<HTMLDivElement>();

const cannotPin = !isPinned && !WidgetLayoutStore.instance.canAddToContainer(room, Container.Top);
const cannotPin = !isPinned && !WidgetLayoutStore.instance.canAddToContainer(room, "top");

let pinTitle: string;
if (cannotPin) {
Expand All @@ -78,7 +78,7 @@ const AppRow: React.FC<IAppRowProps> = ({ app, room }) => {
pinTitle = isPinned ? _t("action|unpin") : _t("action|pin");
}

const isMaximised = WidgetLayoutStore.instance.isInContainer(room, app, Container.Center);
const isMaximised = WidgetLayoutStore.instance.isInContainer(room, app, "center");

let openTitle = "";
if (isPinned) {
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/components/views/right_panel/WidgetCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import WidgetUtils, { useWidgets } from "../../../utils/WidgetUtils";
import AppTile from "../elements/AppTile";
import { _t } from "../../../languageHandler";
import { ContextMenuButton, useContextMenu } from "../../structures/ContextMenu";
import { Container, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
import { WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
import RightPanelStore from "../../../stores/right-panel/RightPanelStore";
import Heading from "../typography/Heading";
import { WidgetContextMenu } from "../../../viewmodels/right-panel/WidgetContextMenuViewModel";
Expand All @@ -31,7 +31,7 @@ const WidgetCard: React.FC<IProps> = ({ room, widgetId, onClose }) => {

const apps = useWidgets(room);
const app = apps.find((a) => a.id === widgetId);
const isRight = app && WidgetLayoutStore.instance.isInContainer(room, app, Container.Right);
const isRight = app && WidgetLayoutStore.instance.isInContainer(room, app, "right");

const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu();

Expand Down
26 changes: 13 additions & 13 deletions apps/web/src/components/views/rooms/AppsDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import type ResizeNotifier from "../../../utils/ResizeNotifier";
import ResizeHandle from "../elements/ResizeHandle";
import Resizer, { type IConfig } from "../../../resizer/resizer";
import PercentageDistributor from "../../../resizer/distributors/percentage";
import { Container, WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
import { WidgetLayoutStore } from "../../../stores/widgets/WidgetLayoutStore";
import UIStore from "../../../stores/UIStore";
import { type ActionPayload } from "../../../dispatcher/payloads";
import Spinner from "../elements/Spinner";
Expand All @@ -39,9 +39,9 @@ interface IProps {

interface IState {
apps: {
[Container.Top]: IWidget[];
[Container.Center]: IWidget[];
[Container.Right]?: IWidget[];
["top"]: IWidget[];
["center"]: IWidget[];
["right"]?: IWidget[];
};
resizingVertical: boolean; // true when changing the height of the apps drawer
resizingHorizontal: boolean; // true when changing the distribution of the width between widgets
Expand Down Expand Up @@ -119,7 +119,7 @@ export default class AppsDrawer extends React.Component<IProps, IState> {
this.resizeContainer?.classList.remove("mx_AppsDrawer--resizing");
WidgetLayoutStore.instance.setResizerDistributions(
this.props.room,
Container.Top,
"top",
this.topApps()
.slice(1)
.map((_, i) => this.resizer.forHandleAt(i)!.size),
Expand Down Expand Up @@ -152,7 +152,7 @@ export default class AppsDrawer extends React.Component<IProps, IState> {
if (prevProps.userId !== this.props.userId || prevProps.room !== this.props.room) {
// Room has changed, update apps
this.updateApps();
} else if (this.getAppsHash(this.topApps()) !== this.getAppsHash(prevState.apps[Container.Top])) {
} else if (this.getAppsHash(this.topApps()) !== this.getAppsHash(prevState.apps["top"])) {
this.loadResizerPreferences();
}
}
Expand All @@ -166,7 +166,7 @@ export default class AppsDrawer extends React.Component<IProps, IState> {
};

private loadResizerPreferences = (): void => {
const distributions = WidgetLayoutStore.instance.getResizerDistributions(this.props.room, Container.Top);
const distributions = WidgetLayoutStore.instance.getResizerDistributions(this.props.room, "top");
if (this.state.apps && this.topApps().length - 1 === distributions.length) {
distributions.forEach((size, i) => {
const distributor = this.resizer.forHandleAt(i);
Expand Down Expand Up @@ -206,11 +206,11 @@ export default class AppsDrawer extends React.Component<IProps, IState> {
};

private getApps = (): IState["apps"] => ({
[Container.Top]: WidgetLayoutStore.instance.getContainerWidgets(this.props.room, Container.Top),
[Container.Center]: WidgetLayoutStore.instance.getContainerWidgets(this.props.room, Container.Center),
["top"]: WidgetLayoutStore.instance.getContainerWidgets(this.props.room, "top"),
["center"]: WidgetLayoutStore.instance.getContainerWidgets(this.props.room, "center"),
});
private topApps = (): IWidget[] => this.state.apps[Container.Top];
private centerApps = (): IWidget[] => this.state.apps[Container.Center];
private topApps = (): IWidget[] => this.state.apps["top"];
private centerApps = (): IWidget[] => this.state.apps["center"];

private updateApps = (): void => {
if (this.unmounted) return;
Expand Down Expand Up @@ -321,7 +321,7 @@ const PersistentVResizer: React.FC<IPersistentResizerProps> = ({
resizeNotifier,
children,
}) => {
let defaultHeight = WidgetLayoutStore.instance.getContainerHeight(room, Container.Top);
let defaultHeight = WidgetLayoutStore.instance.getContainerHeight(room, "top");

// Arbitrary defaults to avoid NaN problems. 100 px or 3/4 of the visible window.
if (!minHeight) minHeight = 100;
Expand Down Expand Up @@ -352,7 +352,7 @@ const PersistentVResizer: React.FC<IPersistentResizerProps> = ({
let newHeight = defaultHeight! + d.height;
newHeight = percentageOf(newHeight, minHeight, maxHeight) * 100;

WidgetLayoutStore.instance.setContainerHeight(room, Container.Top, newHeight);
WidgetLayoutStore.instance.setContainerHeight(room, "top", newHeight);

resizeNotifier.stopResizing();
}}
Expand Down
24 changes: 18 additions & 6 deletions apps/web/src/components/views/rooms/RoomHeader/RoomHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,12 @@ import { useIsEncrypted } from "../../../../hooks/useIsEncrypted.ts";

function RoomHeaderButtons({
room,
additionalButtons,
legacyAdditionalButtons,
extraButtons,
}: {
room: Room;
additionalButtons?: ViewRoomOpts["buttons"];
legacyAdditionalButtons?: ViewRoomOpts["buttons"];
extraButtons?: JSX.Element;
}): JSX.Element {
const members = useRoomMembers(room, 2500);
const memberCount = useRoomMemberCount(room, { throttleWait: 2500, includeInvited: true });
Expand Down Expand Up @@ -297,7 +299,9 @@ function RoomHeaderButtons({
roomContext.mainSplitContentType === MainSplitContentType.Call;
return (
<>
{additionalButtons?.map((props) => {
{extraButtons}

{legacyAdditionalButtons?.map((props) => {
const label = props.label();

return (
Expand Down Expand Up @@ -427,11 +431,15 @@ function historyVisibilityIcon(historyVisibility: HistoryVisibility): JSX.Elemen

export default function RoomHeader({
room,
additionalButtons,
extraButtons,
legacyAdditionalButtons,
oobData,
}: {
room: Room | LocalRoom;
additionalButtons?: ViewRoomOpts["buttons"];
// Extra buttons added by a new element web module API module
extraButtons?: JSX.Element;
// DEPRECATED: Buttons added by a legacy react-sdk module API module.
legacyAdditionalButtons?: ViewRoomOpts["buttons"];
oobData?: IOOBData;
}): JSX.Element {
const client = useMatrixClientContext();
Expand Down Expand Up @@ -530,7 +538,11 @@ export default function RoomHeader({
</button>
{/* If the room is local-only then we don't want to show any additional buttons, as it won't work */}
{room instanceof LocalRoom === false && (
<RoomHeaderButtons room={room} additionalButtons={additionalButtons} />
<RoomHeaderButtons
room={room}
legacyAdditionalButtons={legacyAdditionalButtons}
extraButtons={extraButtons}
/>
)}
</Flex>
{askToJoinEnabled && <RoomKnocksBar room={room} />}
Expand Down
Loading
Loading