Tweak default right panel size to be 320px except for maximised widgets at 420px (#110)
* Add extra buttons to room summary card Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Remove right panel tabs in favour of X button on each panel Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update room summary card header to align close button correctly Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix typo in pinned messages heading Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update snapshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update tests Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update snapshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update screenshot Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Improve coverage Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Tweak default right panel size to be 320px except for video rooms/maximised widgets at 420px Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update tests Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update snapshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Track panel resizing in analytics Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix import cycle Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update screenshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Improve coverage Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix tests Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update snapshot Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update test/components/structures/MainSplit-test.tsx Co-authored-by: David Baker <dbkr@users.noreply.github.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: David Baker <dbkr@users.noreply.github.com>
|
@ -72,7 +72,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@matrix-org/analytics-events": "^0.25.0",
|
||||
"@matrix-org/analytics-events": "^0.26.0",
|
||||
"@matrix-org/emojibase-bindings": "^1.1.2",
|
||||
"@matrix-org/matrix-wysiwyg": "2.37.9",
|
||||
"@matrix-org/react-sdk-module-api": "^2.4.0",
|
||||
|
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 73 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
@ -10,8 +10,10 @@ Please see LICENSE files in the repository root for full details.
|
|||
import React, { ReactNode } from "react";
|
||||
import { NumberSize, Resizable } from "re-resizable";
|
||||
import { Direction } from "re-resizable/lib/resizer";
|
||||
import { WebPanelResize } from "@matrix-org/analytics-events/types/typescript/WebPanelResize";
|
||||
|
||||
import ResizeNotifier from "../../utils/ResizeNotifier";
|
||||
import { PosthogAnalytics } from "../../PosthogAnalytics.ts";
|
||||
|
||||
interface IProps {
|
||||
resizeNotifier: ResizeNotifier;
|
||||
|
@ -26,14 +28,16 @@ interface IProps {
|
|||
*/
|
||||
sizeKey?: string;
|
||||
/**
|
||||
* The size to use for the panel component if one isn't persisted in storage. Defaults to 350.
|
||||
* The size to use for the panel component if one isn't persisted in storage. Defaults to 320.
|
||||
*/
|
||||
defaultSize: number;
|
||||
|
||||
analyticsRoomType: WebPanelResize["roomType"];
|
||||
}
|
||||
|
||||
export default class MainSplit extends React.Component<IProps> {
|
||||
public static defaultProps = {
|
||||
defaultSize: 350,
|
||||
defaultSize: 320,
|
||||
};
|
||||
|
||||
private onResizeStart = (): void => {
|
||||
|
@ -58,11 +62,16 @@ export default class MainSplit extends React.Component<IProps> {
|
|||
elementRef: HTMLElement,
|
||||
delta: NumberSize,
|
||||
): void => {
|
||||
const newSize = this.loadSidePanelSize().width + delta.width;
|
||||
this.props.resizeNotifier.stopResizing();
|
||||
window.localStorage.setItem(
|
||||
this.sizeSettingStorageKey,
|
||||
(this.loadSidePanelSize().width + delta.width).toString(),
|
||||
);
|
||||
window.localStorage.setItem(this.sizeSettingStorageKey, newSize.toString());
|
||||
|
||||
PosthogAnalytics.instance.trackEvent<WebPanelResize>({
|
||||
eventName: "WebPanelResize",
|
||||
panel: "right",
|
||||
roomType: this.props.analyticsRoomType,
|
||||
size: newSize,
|
||||
});
|
||||
};
|
||||
|
||||
private loadSidePanelSize(): { height: string | number; width: number } {
|
||||
|
|
|
@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
|||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React, { ChangeEvent, createRef, ReactElement, ReactNode, RefObject, useContext } from "react";
|
||||
import React, { ChangeEvent, ComponentProps, createRef, ReactElement, ReactNode, RefObject, useContext } from "react";
|
||||
import classNames from "classnames";
|
||||
import {
|
||||
IRecommendedVersion,
|
||||
|
@ -54,7 +54,7 @@ import WidgetEchoStore from "../../stores/WidgetEchoStore";
|
|||
import SettingsStore from "../../settings/SettingsStore";
|
||||
import { Layout } from "../../settings/enums/Layout";
|
||||
import AccessibleButton, { ButtonEvent } from "../views/elements/AccessibleButton";
|
||||
import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext";
|
||||
import RoomContext, { TimelineRenderingType, MainSplitContentType } from "../../contexts/RoomContext";
|
||||
import { E2EStatus, shieldStatusForRoom } from "../../utils/ShieldUtils";
|
||||
import { Action } from "../../dispatcher/actions";
|
||||
import { IMatrixClientCreds } from "../../MatrixClientPeg";
|
||||
|
@ -152,13 +152,8 @@ interface IRoomProps {
|
|||
onRegistered?(credentials: IMatrixClientCreds): void;
|
||||
}
|
||||
|
||||
// This defines the content of the mainSplit.
|
||||
// If the mainSplit does not contain the Timeline, the chat is shown in the right panel.
|
||||
export enum MainSplitContentType {
|
||||
Timeline,
|
||||
MaximisedWidget,
|
||||
Call,
|
||||
}
|
||||
export { MainSplitContentType };
|
||||
|
||||
export interface IRoomState {
|
||||
room?: Room;
|
||||
virtualRoom?: Room;
|
||||
|
@ -191,11 +186,6 @@ export interface IRoomState {
|
|||
showApps: boolean;
|
||||
isPeeking: boolean;
|
||||
showRightPanel: boolean;
|
||||
/**
|
||||
* Whether the right panel shown is either of ThreadPanel or ThreadView.
|
||||
* Always false when `showRightPanel` is false.
|
||||
*/
|
||||
threadRightPanel: boolean;
|
||||
// error object, as from the matrix client/server API
|
||||
// If we failed to load information about the room,
|
||||
// store the error here.
|
||||
|
@ -234,7 +224,7 @@ export interface IRoomState {
|
|||
e2eStatus?: E2EStatus;
|
||||
rejecting?: boolean;
|
||||
hasPinnedWidgets?: boolean;
|
||||
mainSplitContentType?: MainSplitContentType;
|
||||
mainSplitContentType: MainSplitContentType;
|
||||
// whether or not a spaces context switch brought us here,
|
||||
// if it did we don't want the room to be marked as read as soon as it is loaded.
|
||||
wasContextSwitch?: boolean;
|
||||
|
@ -399,7 +389,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
showApps: false,
|
||||
isPeeking: false,
|
||||
showRightPanel: false,
|
||||
threadRightPanel: false,
|
||||
joining: false,
|
||||
showTopUnreadMessagesBar: false,
|
||||
statusBarVisible: false,
|
||||
|
@ -626,11 +615,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
mainSplitContentType: room ? this.getMainSplitContentType(room) : undefined,
|
||||
initialEventId: undefined, // default to clearing this, will get set later in the method if needed
|
||||
showRightPanel: roomId ? this.context.rightPanelStore.isOpenForRoom(roomId) : false,
|
||||
threadRightPanel: roomId
|
||||
? [RightPanelPhases.ThreadView, RightPanelPhases.ThreadPanel].includes(
|
||||
this.context.rightPanelStore.currentCardForRoom(roomId).phase!,
|
||||
)
|
||||
: false,
|
||||
activeCall: roomId ? CallStore.instance.getActiveCall(roomId) : null,
|
||||
promptAskToJoin: this.context.roomViewStore.promptAskToJoin(),
|
||||
viewRoomOpts: this.context.roomViewStore.getViewRoomOpts(),
|
||||
|
@ -1033,11 +1017,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
const { roomId } = this.state;
|
||||
this.setState({
|
||||
showRightPanel: roomId ? this.context.rightPanelStore.isOpenForRoom(roomId) : false,
|
||||
threadRightPanel: roomId
|
||||
? [RightPanelPhases.ThreadView, RightPanelPhases.ThreadPanel].includes(
|
||||
this.context.rightPanelStore.currentCardForRoom(roomId).phase!,
|
||||
)
|
||||
: false,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -2531,6 +2510,17 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
}
|
||||
const mainSplitContentClasses = classNames("mx_RoomView_body", mainSplitContentClassName);
|
||||
|
||||
let sizeKey: string | undefined;
|
||||
let defaultSize: number | undefined;
|
||||
let analyticsRoomType: ComponentProps<typeof MainSplit>["analyticsRoomType"] = "other_room";
|
||||
if (this.state.mainSplitContentType !== MainSplitContentType.Timeline) {
|
||||
// Override defaults for video rooms where more space is needed for the chat timeline
|
||||
sizeKey = "wide";
|
||||
defaultSize = 420;
|
||||
analyticsRoomType =
|
||||
this.state.mainSplitContentType === MainSplitContentType.Call ? "video_room" : "maximised_widget";
|
||||
}
|
||||
|
||||
return (
|
||||
<RoomContext.Provider value={this.state}>
|
||||
<div className={mainClasses} ref={this.roomView} onKeyDown={this.onReactKeyDown}>
|
||||
|
@ -2541,10 +2531,9 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
<MainSplit
|
||||
panel={rightPanel}
|
||||
resizeNotifier={this.props.resizeNotifier}
|
||||
// Override defaults when a thread is being shown to allow persisting a separate
|
||||
// right panel width for thread panels as they tend to want to be wider.
|
||||
sizeKey={this.state.threadRightPanel ? "thread" : undefined}
|
||||
defaultSize={this.state.threadRightPanel ? 500 : undefined}
|
||||
sizeKey={sizeKey}
|
||||
defaultSize={defaultSize}
|
||||
analyticsRoomType={analyticsRoomType}
|
||||
>
|
||||
<div
|
||||
className={mainSplitContentClasses}
|
||||
|
|
|
@ -764,7 +764,7 @@ export default class SpaceRoomView extends React.PureComponent<IProps, IState> {
|
|||
return (
|
||||
<main className="mx_SpaceRoomView">
|
||||
<ErrorBoundary>
|
||||
<MainSplit panel={rightPanel} resizeNotifier={this.props.resizeNotifier}>
|
||||
<MainSplit panel={rightPanel} resizeNotifier={this.props.resizeNotifier} analyticsRoomType="space">
|
||||
{this.renderBody()}
|
||||
</MainSplit>
|
||||
</ErrorBoundary>
|
||||
|
|
|
@ -87,7 +87,12 @@ export default class UserView extends React.Component<IProps, IState> {
|
|||
/>
|
||||
);
|
||||
return (
|
||||
<MainSplit panel={panel} resizeNotifier={this.props.resizeNotifier}>
|
||||
<MainSplit
|
||||
panel={panel}
|
||||
resizeNotifier={this.props.resizeNotifier}
|
||||
defaultSize={420}
|
||||
analyticsRoomType="user_profile"
|
||||
>
|
||||
<UserOnboardingPage />
|
||||
</MainSplit>
|
||||
);
|
||||
|
|
|
@ -21,6 +21,14 @@ export enum TimelineRenderingType {
|
|||
Pinned = "Pinned",
|
||||
}
|
||||
|
||||
// This defines the content of the mainSplit.
|
||||
// If the mainSplit does not contain the Timeline, the chat is shown in the right panel.
|
||||
export enum MainSplitContentType {
|
||||
Timeline,
|
||||
MaximisedWidget,
|
||||
Call,
|
||||
}
|
||||
|
||||
const RoomContext = createContext<
|
||||
IRoomState & {
|
||||
threadId?: string;
|
||||
|
@ -35,7 +43,6 @@ const RoomContext = createContext<
|
|||
showApps: false,
|
||||
isPeeking: false,
|
||||
showRightPanel: true,
|
||||
threadRightPanel: false,
|
||||
joining: false,
|
||||
showTopUnreadMessagesBar: false,
|
||||
statusBarVisible: false,
|
||||
|
@ -59,6 +66,7 @@ const RoomContext = createContext<
|
|||
matrixClientIsReady: false,
|
||||
showUrlPreview: false,
|
||||
timelineRenderingType: TimelineRenderingType.Room,
|
||||
mainSplitContentType: MainSplitContentType.Timeline,
|
||||
threadId: undefined,
|
||||
liveTimeline: undefined,
|
||||
narrow: false,
|
||||
|
|
|
@ -7,10 +7,11 @@ Please see LICENSE files in the repository root for full details.
|
|||
*/
|
||||
|
||||
import React from "react";
|
||||
import { render } from "@testing-library/react";
|
||||
import { fireEvent, render } from "@testing-library/react";
|
||||
|
||||
import MainSplit from "../../../src/components/structures/MainSplit";
|
||||
import ResizeNotifier from "../../../src/utils/ResizeNotifier";
|
||||
import { PosthogAnalytics } from "../../../src/PosthogAnalytics.ts";
|
||||
|
||||
describe("<MainSplit/>", () => {
|
||||
const resizeNotifier = new ResizeNotifier();
|
||||
|
@ -21,18 +22,33 @@ describe("<MainSplit/>", () => {
|
|||
);
|
||||
const panel = <div>Right panel</div>;
|
||||
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
const { asFragment, container } = render(
|
||||
<MainSplit resizeNotifier={resizeNotifier} children={children} panel={panel} />,
|
||||
<MainSplit
|
||||
resizeNotifier={resizeNotifier}
|
||||
children={children}
|
||||
panel={panel}
|
||||
analyticsRoomType="other_room"
|
||||
/>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
// Assert it matches the default width of 350
|
||||
expect(container.querySelector<HTMLElement>(".mx_RightPanel_ResizeWrapper")!.style.width).toBe("350px");
|
||||
// Assert it matches the default width of 320
|
||||
expect(container.querySelector<HTMLElement>(".mx_RightPanel_ResizeWrapper")!.style.width).toBe("320px");
|
||||
});
|
||||
|
||||
it("respects defaultSize prop", () => {
|
||||
const { asFragment, container } = render(
|
||||
<MainSplit resizeNotifier={resizeNotifier} children={children} panel={panel} defaultSize={500} />,
|
||||
<MainSplit
|
||||
resizeNotifier={resizeNotifier}
|
||||
children={children}
|
||||
panel={panel}
|
||||
defaultSize={500}
|
||||
analyticsRoomType="other_room"
|
||||
/>,
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
// Assert it matches the default width of 350
|
||||
|
@ -48,8 +64,36 @@ describe("<MainSplit/>", () => {
|
|||
panel={panel}
|
||||
sizeKey="thread"
|
||||
defaultSize={400}
|
||||
analyticsRoomType="other_room"
|
||||
/>,
|
||||
);
|
||||
expect(container.querySelector<HTMLElement>(".mx_RightPanel_ResizeWrapper")!.style.width).toBe("333px");
|
||||
});
|
||||
|
||||
it("should report to analytics on resize stop", () => {
|
||||
const { container } = render(
|
||||
<MainSplit
|
||||
resizeNotifier={resizeNotifier}
|
||||
children={children}
|
||||
panel={panel}
|
||||
sizeKey="thread"
|
||||
defaultSize={400}
|
||||
analyticsRoomType="other_room"
|
||||
/>,
|
||||
);
|
||||
|
||||
const spy = jest.spyOn(PosthogAnalytics.instance, "trackEvent");
|
||||
|
||||
const handle = container.querySelector(".mx_ResizeHandle--horizontal")!;
|
||||
fireEvent.mouseDown(handle);
|
||||
fireEvent.mouseMove(handle, { clientX: 0 });
|
||||
fireEvent.mouseUp(handle);
|
||||
|
||||
expect(spy).toHaveBeenCalledWith({
|
||||
eventName: "WebPanelResize",
|
||||
panel: "right",
|
||||
roomType: "other_room",
|
||||
size: 400,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -311,6 +311,12 @@ describe("RoomView", () => {
|
|||
expect(stores.rightPanelStore.isOpen).toEqual(true);
|
||||
expect(stores.rightPanelStore.currentCard.phase).toEqual(RightPanelPhases.Timeline);
|
||||
});
|
||||
|
||||
it("should render joined video room view", async () => {
|
||||
jest.spyOn(room, "getMyMembership").mockReturnValue(KnownMembership.Join);
|
||||
const { asFragment } = await mountRoomView();
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe("for a local room", () => {
|
||||
|
|
|
@ -14,7 +14,7 @@ exports[`<MainSplit/> renders 1`] = `
|
|||
</div>
|
||||
<div
|
||||
class="mx_RightPanel_ResizeWrapper"
|
||||
style="position: relative; user-select: auto; width: 350px; height: 100%; max-width: 50%; min-width: 264px; box-sizing: border-box; flex-shrink: 0;"
|
||||
style="position: relative; user-select: auto; width: 320px; height: 100%; max-width: 50%; min-width: 264px; box-sizing: border-box; flex-shrink: 0;"
|
||||
>
|
||||
<div>
|
||||
Right panel
|
||||
|
|
|
@ -1125,3 +1125,322 @@ exports[`RoomView should show error view if failed to look up room alias 1`] = `
|
|||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`RoomView video rooms should render joined video room view 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_RoomView mx_RoomView_immersive"
|
||||
>
|
||||
<canvas
|
||||
aria-hidden="true"
|
||||
height="768"
|
||||
style="display: block; z-index: 999999; pointer-events: none; position: fixed; top: 0px; right: 0px;"
|
||||
width="0"
|
||||
/>
|
||||
<div
|
||||
class="mx_MainSplit"
|
||||
>
|
||||
<div
|
||||
class="mx_RoomView_body mx_MainSplit_call"
|
||||
data-layout="group"
|
||||
>
|
||||
<header
|
||||
class="mx_Flex mx_RoomHeader light-panel"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-3x);"
|
||||
>
|
||||
<button
|
||||
aria-label="Open room settings"
|
||||
aria-live="off"
|
||||
class="_avatar_mcap2_17 mx_BaseAvatar _avatar-imageless_mcap2_61"
|
||||
data-color="3"
|
||||
data-testid="avatar-img"
|
||||
data-type="round"
|
||||
role="button"
|
||||
style="--cpd-avatar-size: 40px;"
|
||||
tabindex="-1"
|
||||
>
|
||||
!
|
||||
</button>
|
||||
<button
|
||||
aria-label="Room info"
|
||||
class="mx_RoomHeader_infoWrapper"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="mx_Box mx_RoomHeader_info mx_Box--flex"
|
||||
style="--mx-box-flex: 1;"
|
||||
>
|
||||
<div
|
||||
aria-level="1"
|
||||
class="_typography_yh5dq_162 _font-body-lg-semibold_yh5dq_83 mx_RoomHeader_heading"
|
||||
dir="auto"
|
||||
role="heading"
|
||||
>
|
||||
<span
|
||||
class="mx_RoomHeader_truncated mx_lineClamp"
|
||||
>
|
||||
!10:example.org
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
<div
|
||||
class="mx_Flex"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-2x);"
|
||||
>
|
||||
<button
|
||||
aria-label="Room info"
|
||||
class="_icon-button_bh2qc_17"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_133tf_26"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<div />
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Chat"
|
||||
class="_icon-button_bh2qc_17"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_133tf_26"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<div />
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Threads"
|
||||
class="_icon-button_bh2qc_17"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 32px;"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_133tf_26"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<div />
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="_typography_yh5dq_162 _font-body-sm-medium_yh5dq_50"
|
||||
>
|
||||
<div
|
||||
aria-label="0 members"
|
||||
class="mx_AccessibleButton mx_FacePile"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="_stacked-avatars_mcap2_111"
|
||||
/>
|
||||
0
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
<div
|
||||
class="mx_RightPanel_ResizeWrapper"
|
||||
style="position: relative; user-select: auto; width: 420px; height: 100%; max-width: 50%; min-width: 264px; box-sizing: border-box; flex-shrink: 0;"
|
||||
>
|
||||
<aside
|
||||
class="mx_RightPanel"
|
||||
id="mx_RightPanel"
|
||||
>
|
||||
<div
|
||||
class="mx_BaseCard mx_ThreadPanel mx_TimelineCard"
|
||||
>
|
||||
<div
|
||||
class="mx_BaseCard_header"
|
||||
>
|
||||
<div
|
||||
class="mx_BaseCard_header_title"
|
||||
>
|
||||
<p
|
||||
class="_typography_yh5dq_162 _font-body-md-medium_yh5dq_69 mx_BaseCard_header_title_heading"
|
||||
role="heading"
|
||||
>
|
||||
Chat
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
class="_icon-button_bh2qc_17 _subtle-bg_bh2qc_38"
|
||||
data-testid="base-card-close-button"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 28px;"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_133tf_26"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6.293 6.293a1 1 0 0 1 1.414 0L12 10.586l4.293-4.293a1 1 0 1 1 1.414 1.414L13.414 12l4.293 4.293a1 1 0 0 1-1.414 1.414L12 13.414l-4.293 4.293a1 1 0 0 1-1.414-1.414L10.586 12 6.293 7.707a1 1 0 0 1 0-1.414Z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="mx_TimelineCard_timeline"
|
||||
>
|
||||
<div
|
||||
class="mx_AutoHideScrollbar mx_ScrollPanel mx_RoomView_messagePanel"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_RoomView_messageListWrapper"
|
||||
>
|
||||
<ol
|
||||
aria-live="polite"
|
||||
class="mx_RoomView_MessageList"
|
||||
style="height: 400px;"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Message composer"
|
||||
class="mx_MessageComposer mx_MessageComposer--compact"
|
||||
role="region"
|
||||
>
|
||||
<div
|
||||
class="mx_MessageComposer_wrapper"
|
||||
>
|
||||
<div
|
||||
class="mx_MessageComposer_row"
|
||||
>
|
||||
<div
|
||||
class="mx_SendMessageComposer"
|
||||
>
|
||||
<div
|
||||
class="mx_BasicMessageComposer"
|
||||
>
|
||||
<div
|
||||
aria-label="Formatting"
|
||||
class="mx_MessageComposerFormatBar"
|
||||
role="toolbar"
|
||||
>
|
||||
<button
|
||||
aria-label="Bold"
|
||||
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconBold"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
/>
|
||||
<button
|
||||
aria-label="Italics"
|
||||
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconItalic"
|
||||
role="button"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
/>
|
||||
<button
|
||||
aria-label="Strikethrough"
|
||||
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconStrikethrough"
|
||||
role="button"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
/>
|
||||
<button
|
||||
aria-label="Code block"
|
||||
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconCode"
|
||||
role="button"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
/>
|
||||
<button
|
||||
aria-label="Quote"
|
||||
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconQuote"
|
||||
role="button"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
/>
|
||||
<button
|
||||
aria-label="Insert link"
|
||||
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconInsertLink"
|
||||
role="button"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
aria-autocomplete="list"
|
||||
aria-disabled="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-label="Send a message…"
|
||||
aria-multiline="true"
|
||||
class="mx_BasicMessageComposer_input mx_BasicMessageComposer_input_shouldShowPillAvatar mx_BasicMessageComposer_inputEmpty"
|
||||
contenteditable="true"
|
||||
data-testid="basicmessagecomposer"
|
||||
dir="auto"
|
||||
role="textbox"
|
||||
style="--placeholder: 'Send\\ a\\ message…';"
|
||||
tabindex="0"
|
||||
translate="no"
|
||||
>
|
||||
<div>
|
||||
<br />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_MessageComposer_actions"
|
||||
>
|
||||
<div
|
||||
aria-label="Emoji"
|
||||
class="mx_AccessibleButton mx_EmojiButton mx_MessageComposer_button mx_EmojiButton_icon"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
/>
|
||||
<div
|
||||
aria-label="Attachment"
|
||||
class="mx_AccessibleButton mx_MessageComposer_button mx_MessageComposer_upload"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
/>
|
||||
<div
|
||||
aria-label="More options"
|
||||
class="mx_AccessibleButton mx_MessageComposer_button mx_MessageComposer_buttonMenu"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
/>
|
||||
<input
|
||||
multiple=""
|
||||
style="display: none;"
|
||||
type="file"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<div>
|
||||
<div
|
||||
class="mx_ResizeHandle--horizontal"
|
||||
style="position: absolute; user-select: none; width: 10px; height: 100%; top: 0px; left: -5px; cursor: col-resize;"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
|
|
@ -26,7 +26,7 @@ import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
|||
import defaultDispatcher from "../../../../src/dispatcher/dispatcher";
|
||||
import DocumentOffset from "../../../../src/editor/offset";
|
||||
import { Layout } from "../../../../src/settings/enums/Layout";
|
||||
import { IRoomState } from "../../../../src/components/structures/RoomView";
|
||||
import { IRoomState, MainSplitContentType } from "../../../../src/components/structures/RoomView";
|
||||
import { RoomPermalinkCreator } from "../../../../src/utils/permalinks/Permalinks";
|
||||
import { mockPlatformPeg } from "../../../test-utils/platform";
|
||||
import { doMaybeLocalRoomAction } from "../../../../src/utils/local-room";
|
||||
|
@ -47,7 +47,6 @@ describe("<SendMessageComposer/>", () => {
|
|||
showApps: false,
|
||||
isPeeking: false,
|
||||
showRightPanel: true,
|
||||
threadRightPanel: false,
|
||||
joining: false,
|
||||
atEndOfLiveTimeline: true,
|
||||
showTopUnreadMessagesBar: false,
|
||||
|
@ -69,6 +68,7 @@ describe("<SendMessageComposer/>", () => {
|
|||
showDisplaynameChanges: true,
|
||||
matrixClientIsReady: false,
|
||||
timelineRenderingType: TimelineRenderingType.Room,
|
||||
mainSplitContentType: MainSplitContentType.Timeline,
|
||||
liveTimeline: undefined,
|
||||
canSelfRedact: false,
|
||||
resizing: false,
|
||||
|
|
|
@ -7,10 +7,10 @@ Please see LICENSE files in the repository root for full details.
|
|||
*/
|
||||
|
||||
import { MockedObject } from "jest-mock";
|
||||
import { MatrixClient, MatrixEvent, EventType, Room, EventTimeline } from "matrix-js-sdk/src/matrix";
|
||||
import { EventTimeline, EventType, MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix";
|
||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||
|
||||
import { IRoomState } from "../../src/components/structures/RoomView";
|
||||
import { IRoomState, MainSplitContentType } from "../../src/components/structures/RoomView";
|
||||
import { TimelineRenderingType } from "../../src/contexts/RoomContext";
|
||||
import { Layout } from "../../src/settings/enums/Layout";
|
||||
import { mkEvent } from "./test-utils";
|
||||
|
@ -54,7 +54,6 @@ export function getRoomContext(room: Room, override: Partial<IRoomState>): IRoom
|
|||
showApps: false,
|
||||
isPeeking: false,
|
||||
showRightPanel: true,
|
||||
threadRightPanel: false,
|
||||
joining: false,
|
||||
atEndOfLiveTimeline: true,
|
||||
showTopUnreadMessagesBar: false,
|
||||
|
@ -76,6 +75,7 @@ export function getRoomContext(room: Room, override: Partial<IRoomState>): IRoom
|
|||
showDisplaynameChanges: true,
|
||||
matrixClientIsReady: false,
|
||||
timelineRenderingType: TimelineRenderingType.Room,
|
||||
mainSplitContentType: MainSplitContentType.Timeline,
|
||||
liveTimeline: undefined,
|
||||
canSelfRedact: false,
|
||||
resizing: false,
|
||||
|
|
|
@ -1893,10 +1893,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe"
|
||||
integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==
|
||||
|
||||
"@matrix-org/analytics-events@^0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@matrix-org/analytics-events/-/analytics-events-0.25.0.tgz#b0b85297dc05a67feaf89cc5d70b80283c988141"
|
||||
integrity sha512-UCTuMjlJGArMqG9qXGfeNz/XtZDFldwuO+dkqP6Wo1nVdWasoWAOlcimDWQ2JnNFCg+UDZU+HLBdS5juTd6xTg==
|
||||
"@matrix-org/analytics-events@^0.26.0":
|
||||
version "0.26.0"
|
||||
resolved "https://registry.yarnpkg.com/@matrix-org/analytics-events/-/analytics-events-0.26.0.tgz#7c8f8f924d8313c87951a0e941640ef8ff78f3d6"
|
||||
integrity sha512-cjKZBejajUG8wPhVygMkBTwTLdEn74luUP6g6RjCUqPR3RYIl3NVi58Zil8CWfRTILb4wVLCPpAvehgXJn1HnQ==
|
||||
|
||||
"@matrix-org/emojibase-bindings@^1.1.2":
|
||||
version "1.1.3"
|
||||
|
@ -9599,7 +9599,6 @@ which@^2.0.1:
|
|||
isexe "^2.0.0"
|
||||
|
||||
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
|
||||
name wrap-ansi-cjs
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||
|
|