Allow adding extra icons to the room header (#11799)
* Allow adding extra icons to the room header Signed-off-by: Charly Nguyen <charly.nguyen@nordeck.net> * Apply PR feedback Signed-off-by: Charly Nguyen <charly.nguyen@nordeck.net> * Apply PR feedback Signed-off-by: Charly Nguyen <charly.nguyen@nordeck.net> * Apply PR feedback Signed-off-by: Charly Nguyen <charly.nguyen@nordeck.net> * Apply PR feedback Signed-off-by: Charly Nguyen <charly.nguyen@nordeck.net> * Apply PR feedback Signed-off-by: Charly Nguyen <charly.nguyen@nordeck.net> --------- Signed-off-by: Charly Nguyen <charly.nguyen@nordeck.net>
This commit is contained in:
parent
9496097143
commit
01e7e01153
14 changed files with 210 additions and 7 deletions
|
@ -64,7 +64,7 @@
|
||||||
"@matrix-org/analytics-events": "^0.8.0",
|
"@matrix-org/analytics-events": "^0.8.0",
|
||||||
"@matrix-org/emojibase-bindings": "^1.1.2",
|
"@matrix-org/emojibase-bindings": "^1.1.2",
|
||||||
"@matrix-org/matrix-wysiwyg": "2.4.1",
|
"@matrix-org/matrix-wysiwyg": "2.4.1",
|
||||||
"@matrix-org/react-sdk-module-api": "^2.1.1",
|
"@matrix-org/react-sdk-module-api": "^2.2.0",
|
||||||
"@matrix-org/spec": "^1.7.0",
|
"@matrix-org/spec": "^1.7.0",
|
||||||
"@sentry/browser": "^7.0.0",
|
"@sentry/browser": "^7.0.0",
|
||||||
"@sentry/tracing": "^7.0.0",
|
"@sentry/tracing": "^7.0.0",
|
||||||
|
|
|
@ -42,6 +42,7 @@ import { logger } from "matrix-js-sdk/src/logger";
|
||||||
import { CallState, MatrixCall } from "matrix-js-sdk/src/webrtc/call";
|
import { CallState, MatrixCall } from "matrix-js-sdk/src/webrtc/call";
|
||||||
import { throttle } from "lodash";
|
import { throttle } from "lodash";
|
||||||
import { CryptoEvent } from "matrix-js-sdk/src/crypto";
|
import { CryptoEvent } from "matrix-js-sdk/src/crypto";
|
||||||
|
import { ViewRoomOpts } from "@matrix-org/react-sdk-module-api/lib/lifecycles/RoomViewLifecycle";
|
||||||
|
|
||||||
import shouldHideEvent from "../../shouldHideEvent";
|
import shouldHideEvent from "../../shouldHideEvent";
|
||||||
import { _t } from "../../languageHandler";
|
import { _t } from "../../languageHandler";
|
||||||
|
@ -246,6 +247,8 @@ export interface IRoomState {
|
||||||
|
|
||||||
canAskToJoin: boolean;
|
canAskToJoin: boolean;
|
||||||
promptAskToJoin: boolean;
|
promptAskToJoin: boolean;
|
||||||
|
|
||||||
|
viewRoomOpts: ViewRoomOpts;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LocalRoomViewProps {
|
interface LocalRoomViewProps {
|
||||||
|
@ -458,6 +461,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
||||||
msc3946ProcessDynamicPredecessor: SettingsStore.getValue("feature_dynamic_room_predecessors"),
|
msc3946ProcessDynamicPredecessor: SettingsStore.getValue("feature_dynamic_room_predecessors"),
|
||||||
canAskToJoin: this.askToJoinEnabled,
|
canAskToJoin: this.askToJoinEnabled,
|
||||||
promptAskToJoin: false,
|
promptAskToJoin: false,
|
||||||
|
viewRoomOpts: { buttons: [] },
|
||||||
};
|
};
|
||||||
|
|
||||||
this.dispatcherRef = dis.register(this.onAction);
|
this.dispatcherRef = dis.register(this.onAction);
|
||||||
|
@ -663,6 +667,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
||||||
: false,
|
: false,
|
||||||
activeCall: roomId ? CallStore.instance.getActiveCall(roomId) : null,
|
activeCall: roomId ? CallStore.instance.getActiveCall(roomId) : null,
|
||||||
promptAskToJoin: this.context.roomViewStore.promptAskToJoin(),
|
promptAskToJoin: this.context.roomViewStore.promptAskToJoin(),
|
||||||
|
viewRoomOpts: this.context.roomViewStore.getViewRoomOpts(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -1407,6 +1412,8 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
||||||
tombstone: this.getRoomTombstone(room),
|
tombstone: this.getRoomTombstone(room),
|
||||||
liveTimeline: room.getLiveTimeline(),
|
liveTimeline: room.getLiveTimeline(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
dis.dispatch<ActionPayload>({ action: Action.RoomLoaded });
|
||||||
};
|
};
|
||||||
|
|
||||||
private onRoomTimelineReset = (room?: Room): void => {
|
private onRoomTimelineReset = (room?: Room): void => {
|
||||||
|
@ -2601,7 +2608,10 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
||||||
data-layout={this.state.layout}
|
data-layout={this.state.layout}
|
||||||
>
|
>
|
||||||
{SettingsStore.getValue("feature_new_room_decoration_ui") ? (
|
{SettingsStore.getValue("feature_new_room_decoration_ui") ? (
|
||||||
<RoomHeader room={this.state.room} />
|
<RoomHeader
|
||||||
|
room={this.state.room}
|
||||||
|
additionalButtons={this.state.viewRoomOpts.buttons}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<LegacyRoomHeader
|
<LegacyRoomHeader
|
||||||
room={this.state.room}
|
room={this.state.room}
|
||||||
|
@ -2619,6 +2629,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
||||||
enableRoomOptionsMenu={!this.viewsLocalRoom}
|
enableRoomOptionsMenu={!this.viewsLocalRoom}
|
||||||
viewingCall={viewingCall}
|
viewingCall={viewingCall}
|
||||||
activeCall={this.state.activeCall}
|
activeCall={this.state.activeCall}
|
||||||
|
additionalButtons={this.state.viewRoomOpts.buttons}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{mainSplitBody}
|
{mainSplitBody}
|
||||||
|
|
|
@ -20,6 +20,8 @@ import classNames from "classnames";
|
||||||
import { throttle } from "lodash";
|
import { throttle } from "lodash";
|
||||||
import { RoomStateEvent, ISearchResults } from "matrix-js-sdk/src/matrix";
|
import { RoomStateEvent, ISearchResults } from "matrix-js-sdk/src/matrix";
|
||||||
import { CallType } from "matrix-js-sdk/src/webrtc/call";
|
import { CallType } from "matrix-js-sdk/src/webrtc/call";
|
||||||
|
import { IconButton, Tooltip } from "@vector-im/compound-web";
|
||||||
|
import { ViewRoomOpts } from "@matrix-org/react-sdk-module-api/lib/lifecycles/RoomViewLifecycle";
|
||||||
|
|
||||||
import type { MatrixEvent, Room } from "matrix-js-sdk/src/matrix";
|
import type { MatrixEvent, Room } from "matrix-js-sdk/src/matrix";
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
|
@ -476,6 +478,7 @@ export interface IProps {
|
||||||
enableRoomOptionsMenu?: boolean;
|
enableRoomOptionsMenu?: boolean;
|
||||||
viewingCall: boolean;
|
viewingCall: boolean;
|
||||||
activeCall: Call | null;
|
activeCall: Call | null;
|
||||||
|
additionalButtons?: ViewRoomOpts["buttons"];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
|
@ -669,6 +672,23 @@ export default class RoomHeader extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{this.props.additionalButtons?.map((props) => {
|
||||||
|
const label = props.label();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip label={label} key={props.id}>
|
||||||
|
<IconButton
|
||||||
|
onClick={() => {
|
||||||
|
props.onClick();
|
||||||
|
this.forceUpdate();
|
||||||
|
}}
|
||||||
|
title={label}
|
||||||
|
>
|
||||||
|
{props.icon}
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
})}
|
||||||
{startButtons}
|
{startButtons}
|
||||||
<RoomHeaderButtons
|
<RoomHeaderButtons
|
||||||
room={this.props.room}
|
room={this.props.room}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import { Icon as VerifiedIcon } from "@vector-im/compound-design-tokens/icons/ve
|
||||||
import { Icon as ErrorIcon } from "@vector-im/compound-design-tokens/icons/error.svg";
|
import { Icon as ErrorIcon } from "@vector-im/compound-design-tokens/icons/error.svg";
|
||||||
import { Icon as PublicIcon } from "@vector-im/compound-design-tokens/icons/public.svg";
|
import { Icon as PublicIcon } from "@vector-im/compound-design-tokens/icons/public.svg";
|
||||||
import { EventType, JoinRule, type Room } from "matrix-js-sdk/src/matrix";
|
import { EventType, JoinRule, type Room } from "matrix-js-sdk/src/matrix";
|
||||||
|
import { ViewRoomOpts } from "@matrix-org/react-sdk-module-api/lib/lifecycles/RoomViewLifecycle";
|
||||||
|
|
||||||
import { useRoomName } from "../../../hooks/useRoomName";
|
import { useRoomName } from "../../../hooks/useRoomName";
|
||||||
import { RightPanelPhases } from "../../../stores/right-panel/RightPanelStorePhases";
|
import { RightPanelPhases } from "../../../stores/right-panel/RightPanelStorePhases";
|
||||||
|
@ -63,7 +64,13 @@ function notificationColorToIndicator(color: NotificationColor): React.Component
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function RoomHeader({ room }: { room: Room }): JSX.Element {
|
export default function RoomHeader({
|
||||||
|
room,
|
||||||
|
additionalButtons,
|
||||||
|
}: {
|
||||||
|
room: Room;
|
||||||
|
additionalButtons?: ViewRoomOpts["buttons"];
|
||||||
|
}): JSX.Element {
|
||||||
const client = useMatrixClientContext();
|
const client = useMatrixClientContext();
|
||||||
|
|
||||||
const roomName = useRoomName(room);
|
const roomName = useRoomName(room);
|
||||||
|
@ -169,6 +176,23 @@ export default function RoomHeader({ room }: { room: Room }): JSX.Element {
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<Flex as="nav" align="center" gap="var(--cpd-space-2x)">
|
<Flex as="nav" align="center" gap="var(--cpd-space-2x)">
|
||||||
|
{additionalButtons?.map((props) => {
|
||||||
|
const label = props.label();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip label={label} key={props.id}>
|
||||||
|
<IconButton
|
||||||
|
aria-label={label}
|
||||||
|
onClick={(event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
props.onClick();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{props.icon}
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
})}
|
||||||
{!useElementCallExclusively && (
|
{!useElementCallExclusively && (
|
||||||
<Tooltip label={!voiceCallDisabledReason ? _t("voip|voice_call") : voiceCallDisabledReason!}>
|
<Tooltip label={!voiceCallDisabledReason ? _t("voip|voice_call") : voiceCallDisabledReason!}>
|
||||||
<IconButton
|
<IconButton
|
||||||
|
|
|
@ -73,6 +73,7 @@ const RoomContext = createContext<
|
||||||
msc3946ProcessDynamicPredecessor: false,
|
msc3946ProcessDynamicPredecessor: false,
|
||||||
canAskToJoin: false,
|
canAskToJoin: false,
|
||||||
promptAskToJoin: false,
|
promptAskToJoin: false,
|
||||||
|
viewRoomOpts: { buttons: [] },
|
||||||
});
|
});
|
||||||
RoomContext.displayName = "RoomContext";
|
RoomContext.displayName = "RoomContext";
|
||||||
export default RoomContext;
|
export default RoomContext;
|
||||||
|
|
|
@ -371,4 +371,9 @@ export enum Action {
|
||||||
* Fired when we want to open spotlight search. Use with a OpenSpotlightPayload.
|
* Fired when we want to open spotlight search. Use with a OpenSpotlightPayload.
|
||||||
*/
|
*/
|
||||||
OpenSpotlight = "open_spotlight",
|
OpenSpotlight = "open_spotlight",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fired when the room loaded.
|
||||||
|
*/
|
||||||
|
RoomLoaded = "room_loaded",
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import { ViewRoom as ViewRoomEvent } from "@matrix-org/analytics-events/types/ty
|
||||||
import { JoinedRoom as JoinedRoomEvent } from "@matrix-org/analytics-events/types/typescript/JoinedRoom";
|
import { JoinedRoom as JoinedRoomEvent } from "@matrix-org/analytics-events/types/typescript/JoinedRoom";
|
||||||
import { Optional } from "matrix-events-sdk";
|
import { Optional } from "matrix-events-sdk";
|
||||||
import EventEmitter from "events";
|
import EventEmitter from "events";
|
||||||
|
import { RoomViewLifecycle, ViewRoomOpts } from "@matrix-org/react-sdk-module-api/lib/lifecycles/RoomViewLifecycle";
|
||||||
|
|
||||||
import { MatrixDispatcher } from "../dispatcher/dispatcher";
|
import { MatrixDispatcher } from "../dispatcher/dispatcher";
|
||||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
import { MatrixClientPeg } from "../MatrixClientPeg";
|
||||||
|
@ -60,6 +61,7 @@ import { pauseNonLiveBroadcastFromOtherRoom } from "../voice-broadcast/utils/pau
|
||||||
import { ActionPayload } from "../dispatcher/payloads";
|
import { ActionPayload } from "../dispatcher/payloads";
|
||||||
import { CancelAskToJoinPayload } from "../dispatcher/payloads/CancelAskToJoinPayload";
|
import { CancelAskToJoinPayload } from "../dispatcher/payloads/CancelAskToJoinPayload";
|
||||||
import { SubmitAskToJoinPayload } from "../dispatcher/payloads/SubmitAskToJoinPayload";
|
import { SubmitAskToJoinPayload } from "../dispatcher/payloads/SubmitAskToJoinPayload";
|
||||||
|
import { ModuleRunner } from "../modules/ModuleRunner";
|
||||||
|
|
||||||
const NUM_JOIN_RETRY = 5;
|
const NUM_JOIN_RETRY = 5;
|
||||||
|
|
||||||
|
@ -119,6 +121,8 @@ interface State {
|
||||||
viewingCall: boolean;
|
viewingCall: boolean;
|
||||||
|
|
||||||
promptAskToJoin: boolean;
|
promptAskToJoin: boolean;
|
||||||
|
|
||||||
|
viewRoomOpts: ViewRoomOpts;
|
||||||
}
|
}
|
||||||
|
|
||||||
const INITIAL_STATE: State = {
|
const INITIAL_STATE: State = {
|
||||||
|
@ -140,6 +144,7 @@ const INITIAL_STATE: State = {
|
||||||
wasContextSwitch: false,
|
wasContextSwitch: false,
|
||||||
viewingCall: false,
|
viewingCall: false,
|
||||||
promptAskToJoin: false,
|
promptAskToJoin: false,
|
||||||
|
viewRoomOpts: { buttons: [] },
|
||||||
};
|
};
|
||||||
|
|
||||||
type Listener = (isActive: boolean) => void;
|
type Listener = (isActive: boolean) => void;
|
||||||
|
@ -370,6 +375,10 @@ export class RoomViewStore extends EventEmitter {
|
||||||
this.cancelAskToJoin(payload as CancelAskToJoinPayload);
|
this.cancelAskToJoin(payload as CancelAskToJoinPayload);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Action.RoomLoaded: {
|
||||||
|
this.setViewRoomOpts();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -805,4 +814,24 @@ export class RoomViewStore extends EventEmitter {
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current state of the 'viewRoomOpts' property.
|
||||||
|
*
|
||||||
|
* @returns {ViewRoomOpts} The value of the 'viewRoomOpts' property.
|
||||||
|
*/
|
||||||
|
public getViewRoomOpts(): ViewRoomOpts {
|
||||||
|
return this.state.viewRoomOpts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes the view room lifecycle to set the view room options.
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
private setViewRoomOpts(): void {
|
||||||
|
const viewRoomOpts: ViewRoomOpts = { buttons: [] };
|
||||||
|
ModuleRunner.instance.invoke(RoomViewLifecycle.ViewRoom, viewRoomOpts, this.getRoomId());
|
||||||
|
this.setState({ viewRoomOpts });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -585,4 +585,10 @@ describe("RoomView", () => {
|
||||||
expect(dis.dispatch).toHaveBeenCalledWith({ action: "cancel_ask_to_join", roomId: room.roomId });
|
expect(dis.dispatch).toHaveBeenCalledWith({ action: "cancel_ask_to_join", roomId: room.roomId });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("fires Action.RoomLoaded", async () => {
|
||||||
|
jest.spyOn(dis, "dispatch");
|
||||||
|
await mountRoomView();
|
||||||
|
expect(dis.dispatch).toHaveBeenCalledWith({ action: Action.RoomLoaded });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -29,6 +29,7 @@ import { CallType } from "matrix-js-sdk/src/webrtc/call";
|
||||||
import { ClientWidgetApi, Widget } from "matrix-widget-api";
|
import { ClientWidgetApi, Widget } from "matrix-widget-api";
|
||||||
import EventEmitter from "events";
|
import EventEmitter from "events";
|
||||||
import { setupJestCanvasMock } from "jest-canvas-mock";
|
import { setupJestCanvasMock } from "jest-canvas-mock";
|
||||||
|
import { ViewRoomOpts } from "@matrix-org/react-sdk-module-api/lib/lifecycles/RoomViewLifecycle";
|
||||||
|
|
||||||
import type { MatrixClient, MatrixEvent, RoomMember } from "matrix-js-sdk/src/matrix";
|
import type { MatrixClient, MatrixEvent, RoomMember } from "matrix-js-sdk/src/matrix";
|
||||||
import type { MatrixCall } from "matrix-js-sdk/src/webrtc/call";
|
import type { MatrixCall } from "matrix-js-sdk/src/webrtc/call";
|
||||||
|
@ -738,6 +739,34 @@ describe("LegacyRoomHeader", () => {
|
||||||
expect(wrapper.container.querySelector(".mx_LegacyRoomHeader_name.mx_AccessibleButton")).toBeFalsy();
|
expect(wrapper.container.querySelector(".mx_LegacyRoomHeader_name.mx_AccessibleButton")).toBeFalsy();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
it("renders additionalButtons", async () => {
|
||||||
|
const additionalButtons: ViewRoomOpts["buttons"] = [
|
||||||
|
{
|
||||||
|
icon: <>test-icon</>,
|
||||||
|
id: "test-id",
|
||||||
|
label: () => "test-label",
|
||||||
|
onClick: () => {},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
renderHeader({ additionalButtons });
|
||||||
|
expect(screen.getByRole("button", { name: "test-icon" })).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls onClick-callback on additionalButtons", () => {
|
||||||
|
const callback = jest.fn();
|
||||||
|
const additionalButtons: ViewRoomOpts["buttons"] = [
|
||||||
|
{
|
||||||
|
icon: <>test-icon</>,
|
||||||
|
id: "test-id",
|
||||||
|
label: () => "test-label",
|
||||||
|
onClick: callback,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
renderHeader({ additionalButtons });
|
||||||
|
fireEvent.click(screen.getByRole("button", { name: "test-icon" }));
|
||||||
|
expect(callback).toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IRoomCreationInfo {
|
interface IRoomCreationInfo {
|
||||||
|
|
|
@ -18,6 +18,7 @@ import React from "react";
|
||||||
import { CallType, MatrixCall } from "matrix-js-sdk/src/webrtc/call";
|
import { CallType, MatrixCall } from "matrix-js-sdk/src/webrtc/call";
|
||||||
import { EventType, JoinRule, MatrixClient, MatrixEvent, PendingEventOrdering, Room } from "matrix-js-sdk/src/matrix";
|
import { EventType, JoinRule, MatrixClient, MatrixEvent, PendingEventOrdering, Room } from "matrix-js-sdk/src/matrix";
|
||||||
import {
|
import {
|
||||||
|
createEvent,
|
||||||
fireEvent,
|
fireEvent,
|
||||||
getAllByLabelText,
|
getAllByLabelText,
|
||||||
getByLabelText,
|
getByLabelText,
|
||||||
|
@ -27,6 +28,7 @@ import {
|
||||||
screen,
|
screen,
|
||||||
waitFor,
|
waitFor,
|
||||||
} from "@testing-library/react";
|
} from "@testing-library/react";
|
||||||
|
import { ViewRoomOpts } from "@matrix-org/react-sdk-module-api/lib/lifecycles/RoomViewLifecycle";
|
||||||
|
|
||||||
import { filterConsole, mkEvent, stubClient, withClientContextRenderOptions } from "../../../test-utils";
|
import { filterConsole, mkEvent, stubClient, withClientContextRenderOptions } from "../../../test-utils";
|
||||||
import RoomHeader from "../../../../src/components/views/rooms/RoomHeader";
|
import RoomHeader from "../../../../src/components/views/rooms/RoomHeader";
|
||||||
|
@ -516,6 +518,47 @@ describe("RoomHeader", () => {
|
||||||
await waitFor(() => expect(getByLabelText(container, expectedLabel)).toBeInTheDocument());
|
await waitFor(() => expect(getByLabelText(container, expectedLabel)).toBeInTheDocument());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("renders additionalButtons", async () => {
|
||||||
|
const additionalButtons: ViewRoomOpts["buttons"] = [
|
||||||
|
{
|
||||||
|
icon: <>test-icon</>,
|
||||||
|
id: "test-id",
|
||||||
|
label: () => "test-label",
|
||||||
|
onClick: () => {},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
render(
|
||||||
|
<RoomHeader room={room} additionalButtons={additionalButtons} />,
|
||||||
|
withClientContextRenderOptions(MatrixClientPeg.get()!),
|
||||||
|
);
|
||||||
|
expect(screen.getByRole("button", { name: "test-label" })).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls onClick-callback on additionalButtons", () => {
|
||||||
|
const callback = jest.fn();
|
||||||
|
const additionalButtons: ViewRoomOpts["buttons"] = [
|
||||||
|
{
|
||||||
|
icon: <>test-icon</>,
|
||||||
|
id: "test-id",
|
||||||
|
label: () => "test-label",
|
||||||
|
onClick: callback,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
render(
|
||||||
|
<RoomHeader room={room} additionalButtons={additionalButtons} />,
|
||||||
|
withClientContextRenderOptions(MatrixClientPeg.get()!),
|
||||||
|
);
|
||||||
|
|
||||||
|
const button = screen.getByRole("button", { name: "test-label" });
|
||||||
|
const event = createEvent.click(button);
|
||||||
|
event.stopPropagation = jest.fn();
|
||||||
|
fireEvent(button, event);
|
||||||
|
|
||||||
|
expect(callback).toHaveBeenCalled();
|
||||||
|
expect(event.stopPropagation).toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -84,6 +84,7 @@ describe("<SendMessageComposer/>", () => {
|
||||||
msc3946ProcessDynamicPredecessor: false,
|
msc3946ProcessDynamicPredecessor: false,
|
||||||
canAskToJoin: false,
|
canAskToJoin: false,
|
||||||
promptAskToJoin: false,
|
promptAskToJoin: false,
|
||||||
|
viewRoomOpts: { buttons: [] },
|
||||||
};
|
};
|
||||||
describe("createMessageContent", () => {
|
describe("createMessageContent", () => {
|
||||||
const permalinkCreator = jest.fn() as any;
|
const permalinkCreator = jest.fn() as any;
|
||||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
import { mocked } from "jest-mock";
|
import { mocked } from "jest-mock";
|
||||||
import { MatrixError, Room } from "matrix-js-sdk/src/matrix";
|
import { MatrixError, Room } from "matrix-js-sdk/src/matrix";
|
||||||
import { sleep } from "matrix-js-sdk/src/utils";
|
import { sleep } from "matrix-js-sdk/src/utils";
|
||||||
|
import { RoomViewLifecycle, ViewRoomOpts } from "@matrix-org/react-sdk-module-api/lib/lifecycles/RoomViewLifecycle";
|
||||||
|
|
||||||
import { RoomViewStore } from "../../src/stores/RoomViewStore";
|
import { RoomViewStore } from "../../src/stores/RoomViewStore";
|
||||||
import { Action } from "../../src/dispatcher/actions";
|
import { Action } from "../../src/dispatcher/actions";
|
||||||
|
@ -43,6 +44,7 @@ import ErrorDialog from "../../src/components/views/dialogs/ErrorDialog";
|
||||||
import { CancelAskToJoinPayload } from "../../src/dispatcher/payloads/CancelAskToJoinPayload";
|
import { CancelAskToJoinPayload } from "../../src/dispatcher/payloads/CancelAskToJoinPayload";
|
||||||
import { JoinRoomErrorPayload } from "../../src/dispatcher/payloads/JoinRoomErrorPayload";
|
import { JoinRoomErrorPayload } from "../../src/dispatcher/payloads/JoinRoomErrorPayload";
|
||||||
import { SubmitAskToJoinPayload } from "../../src/dispatcher/payloads/SubmitAskToJoinPayload";
|
import { SubmitAskToJoinPayload } from "../../src/dispatcher/payloads/SubmitAskToJoinPayload";
|
||||||
|
import { ModuleRunner } from "../../src/modules/ModuleRunner";
|
||||||
|
|
||||||
jest.mock("../../src/Modal");
|
jest.mock("../../src/Modal");
|
||||||
|
|
||||||
|
@ -132,6 +134,11 @@ describe("RoomViewStore", function () {
|
||||||
await untilDispatch(Action.CancelAskToJoin, dis);
|
await untilDispatch(Action.CancelAskToJoin, dis);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const dispatchRoomLoaded = async () => {
|
||||||
|
dis.dispatch({ action: Action.RoomLoaded });
|
||||||
|
await untilDispatch(Action.RoomLoaded, dis);
|
||||||
|
};
|
||||||
|
|
||||||
let roomViewStore: RoomViewStore;
|
let roomViewStore: RoomViewStore;
|
||||||
let slidingSyncManager: SlidingSyncManager;
|
let slidingSyncManager: SlidingSyncManager;
|
||||||
let dis: MatrixDispatcher;
|
let dis: MatrixDispatcher;
|
||||||
|
@ -569,4 +576,30 @@ describe("RoomViewStore", function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("getViewRoomOpts", () => {
|
||||||
|
it("returns viewRoomOpts", () => {
|
||||||
|
expect(roomViewStore.getViewRoomOpts()).toEqual({ buttons: [] });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Action.RoomLoaded", () => {
|
||||||
|
it("updates viewRoomOpts", async () => {
|
||||||
|
const buttons: ViewRoomOpts["buttons"] = [
|
||||||
|
{
|
||||||
|
icon: "test-icon",
|
||||||
|
id: "test-id",
|
||||||
|
label: () => "test-label",
|
||||||
|
onClick: () => {},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
jest.spyOn(ModuleRunner.instance, "invoke").mockImplementation((lifecycleEvent, opts) => {
|
||||||
|
if (lifecycleEvent === RoomViewLifecycle.ViewRoom) {
|
||||||
|
opts.buttons = buttons;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await dispatchRoomLoaded();
|
||||||
|
expect(roomViewStore.getViewRoomOpts()).toEqual({ buttons });
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -90,6 +90,7 @@ export function getRoomContext(room: Room, override: Partial<IRoomState>): IRoom
|
||||||
msc3946ProcessDynamicPredecessor: false,
|
msc3946ProcessDynamicPredecessor: false,
|
||||||
canAskToJoin: false,
|
canAskToJoin: false,
|
||||||
promptAskToJoin: false,
|
promptAskToJoin: false,
|
||||||
|
viewRoomOpts: { buttons: [] },
|
||||||
|
|
||||||
...override,
|
...override,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1833,10 +1833,10 @@
|
||||||
resolved "https://registry.yarnpkg.com/@matrix-org/olm/-/olm-3.2.15.tgz#55f3c1b70a21bbee3f9195cecd6846b1083451ec"
|
resolved "https://registry.yarnpkg.com/@matrix-org/olm/-/olm-3.2.15.tgz#55f3c1b70a21bbee3f9195cecd6846b1083451ec"
|
||||||
integrity sha512-S7lOrndAK9/8qOtaTq/WhttJC/o4GAzdfK0MUPpo8ApzsJEC0QjtwrkC3KBXdFP1cD1MXi/mlKR7aaoVMKgs6Q==
|
integrity sha512-S7lOrndAK9/8qOtaTq/WhttJC/o4GAzdfK0MUPpo8ApzsJEC0QjtwrkC3KBXdFP1cD1MXi/mlKR7aaoVMKgs6Q==
|
||||||
|
|
||||||
"@matrix-org/react-sdk-module-api@^2.1.1":
|
"@matrix-org/react-sdk-module-api@^2.2.0":
|
||||||
version "2.1.1"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@matrix-org/react-sdk-module-api/-/react-sdk-module-api-2.1.1.tgz#54e8617c15185010d608c0325ecaec8d1574d12b"
|
resolved "https://registry.yarnpkg.com/@matrix-org/react-sdk-module-api/-/react-sdk-module-api-2.2.0.tgz#cb284601a82448dc23fac31949c466eb34ec64b4"
|
||||||
integrity sha512-dYPY3aXtNwPrg2aEmFeWddMdohus/Ha17XES2QH+WMCawt+hH+uq28jH1EmW1RUOOzxVcdY36lRGOwqRtAJbhA==
|
integrity sha512-HSicxLdagZRbQp35d3t2SeDFTiT4GmEQDQGih8dWSKRHXK4krVQjb6Kf1NkwweiFDAeU0qgbz2pP4RZqbv0XIg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.17.9"
|
"@babel/runtime" "^7.17.9"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue