Skip to content
This repository has been archived by the owner on Oct 22, 2024. It is now read-only.

Commit

Permalink
Tweak default right panel size to be 320px except for maximised widge…
Browse files Browse the repository at this point in the history
…ts at 420px (#110)

* Add extra buttons to room summary card

Signed-off-by: Michael Telatynski <[email protected]>

* Remove right panel tabs in favour of X button on each panel

Signed-off-by: Michael Telatynski <[email protected]>

* Update room summary card header to align close button correctly

Signed-off-by: Michael Telatynski <[email protected]>

* Fix typo in pinned messages heading

Signed-off-by: Michael Telatynski <[email protected]>

* Update snapshots

Signed-off-by: Michael Telatynski <[email protected]>

* Update tests

Signed-off-by: Michael Telatynski <[email protected]>

* Iterate

Signed-off-by: Michael Telatynski <[email protected]>

* Update snapshots

Signed-off-by: Michael Telatynski <[email protected]>

* Update screenshot

Signed-off-by: Michael Telatynski <[email protected]>

* Improve coverage

Signed-off-by: Michael Telatynski <[email protected]>

* Tweak default right panel size to be 320px except for video rooms/maximised widgets at 420px

Signed-off-by: Michael Telatynski <[email protected]>

* Iterate

Signed-off-by: Michael Telatynski <[email protected]>

* Update tests

Signed-off-by: Michael Telatynski <[email protected]>

* Update snapshots

Signed-off-by: Michael Telatynski <[email protected]>

* Track panel resizing in analytics

Signed-off-by: Michael Telatynski <[email protected]>

* Fix import cycle

Signed-off-by: Michael Telatynski <[email protected]>

* Update screenshots

Signed-off-by: Michael Telatynski <[email protected]>

* Improve coverage

Signed-off-by: Michael Telatynski <[email protected]>

* Fix tests

Signed-off-by: Michael Telatynski <[email protected]>

* Update snapshot

Signed-off-by: Michael Telatynski <[email protected]>

* Update test/components/structures/MainSplit-test.tsx

Co-authored-by: David Baker <[email protected]>

---------

Signed-off-by: Michael Telatynski <[email protected]>
Co-authored-by: David Baker <[email protected]>
  • Loading branch information
t3chguy and dbkr authored Oct 4, 2024
1 parent 70418f8 commit 0a9b4ae
Show file tree
Hide file tree
Showing 26 changed files with 435 additions and 56 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 15 additions & 6 deletions src/components/structures/MainSplit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 => {
Expand All @@ -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 } {
Expand Down
49 changes: 19 additions & 30 deletions src/components/structures/RoomView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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";
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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,
});
};

Expand Down Expand Up @@ -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}>
Expand All @@ -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}
Expand Down
2 changes: 1 addition & 1 deletion src/components/structures/SpaceRoomView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
7 changes: 6 additions & 1 deletion src/components/structures/UserView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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>
);
Expand Down
10 changes: 9 additions & 1 deletion src/contexts/RoomContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -35,7 +43,6 @@ const RoomContext = createContext<
showApps: false,
isPeeking: false,
showRightPanel: true,
threadRightPanel: false,
joining: false,
showTopUnreadMessagesBar: false,
statusBarVisible: false,
Expand All @@ -59,6 +66,7 @@ const RoomContext = createContext<
matrixClientIsReady: false,
showUrlPreview: false,
timelineRenderingType: TimelineRenderingType.Room,
mainSplitContentType: MainSplitContentType.Timeline,
threadId: undefined,
liveTimeline: undefined,
narrow: false,
Expand Down
54 changes: 49 additions & 5 deletions test/components/structures/MainSplit-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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
Expand All @@ -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,
});
});
});
6 changes: 6 additions & 0 deletions test/components/structures/RoomView-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit 0a9b4ae

Please sign in to comment.