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

Commit 0a9b4ae

Browse files
t3chguydbkr
andauthored
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>
1 parent 70418f8 commit 0a9b4ae

26 files changed

+435
-56
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
},
7373
"dependencies": {
7474
"@babel/runtime": "^7.12.5",
75-
"@matrix-org/analytics-events": "^0.25.0",
75+
"@matrix-org/analytics-events": "^0.26.0",
7676
"@matrix-org/emojibase-bindings": "^1.1.2",
7777
"@matrix-org/matrix-wysiwyg": "2.37.9",
7878
"@matrix-org/react-sdk-module-api": "^2.4.0",
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading

src/components/structures/MainSplit.tsx

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ Please see LICENSE files in the repository root for full details.
1010
import React, { ReactNode } from "react";
1111
import { NumberSize, Resizable } from "re-resizable";
1212
import { Direction } from "re-resizable/lib/resizer";
13+
import { WebPanelResize } from "@matrix-org/analytics-events/types/typescript/WebPanelResize";
1314

1415
import ResizeNotifier from "../../utils/ResizeNotifier";
16+
import { PosthogAnalytics } from "../../PosthogAnalytics.ts";
1517

1618
interface IProps {
1719
resizeNotifier: ResizeNotifier;
@@ -26,14 +28,16 @@ interface IProps {
2628
*/
2729
sizeKey?: string;
2830
/**
29-
* The size to use for the panel component if one isn't persisted in storage. Defaults to 350.
31+
* The size to use for the panel component if one isn't persisted in storage. Defaults to 320.
3032
*/
3133
defaultSize: number;
34+
35+
analyticsRoomType: WebPanelResize["roomType"];
3236
}
3337

3438
export default class MainSplit extends React.Component<IProps> {
3539
public static defaultProps = {
36-
defaultSize: 350,
40+
defaultSize: 320,
3741
};
3842

3943
private onResizeStart = (): void => {
@@ -58,11 +62,16 @@ export default class MainSplit extends React.Component<IProps> {
5862
elementRef: HTMLElement,
5963
delta: NumberSize,
6064
): void => {
65+
const newSize = this.loadSidePanelSize().width + delta.width;
6166
this.props.resizeNotifier.stopResizing();
62-
window.localStorage.setItem(
63-
this.sizeSettingStorageKey,
64-
(this.loadSidePanelSize().width + delta.width).toString(),
65-
);
67+
window.localStorage.setItem(this.sizeSettingStorageKey, newSize.toString());
68+
69+
PosthogAnalytics.instance.trackEvent<WebPanelResize>({
70+
eventName: "WebPanelResize",
71+
panel: "right",
72+
roomType: this.props.analyticsRoomType,
73+
size: newSize,
74+
});
6675
};
6776

6877
private loadSidePanelSize(): { height: string | number; width: number } {

src/components/structures/RoomView.tsx

Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
99
Please see LICENSE files in the repository root for full details.
1010
*/
1111

12-
import React, { ChangeEvent, createRef, ReactElement, ReactNode, RefObject, useContext } from "react";
12+
import React, { ChangeEvent, ComponentProps, createRef, ReactElement, ReactNode, RefObject, useContext } from "react";
1313
import classNames from "classnames";
1414
import {
1515
IRecommendedVersion,
@@ -54,7 +54,7 @@ import WidgetEchoStore from "../../stores/WidgetEchoStore";
5454
import SettingsStore from "../../settings/SettingsStore";
5555
import { Layout } from "../../settings/enums/Layout";
5656
import AccessibleButton, { ButtonEvent } from "../views/elements/AccessibleButton";
57-
import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext";
57+
import RoomContext, { TimelineRenderingType, MainSplitContentType } from "../../contexts/RoomContext";
5858
import { E2EStatus, shieldStatusForRoom } from "../../utils/ShieldUtils";
5959
import { Action } from "../../dispatcher/actions";
6060
import { IMatrixClientCreds } from "../../MatrixClientPeg";
@@ -152,13 +152,8 @@ interface IRoomProps {
152152
onRegistered?(credentials: IMatrixClientCreds): void;
153153
}
154154

155-
// This defines the content of the mainSplit.
156-
// If the mainSplit does not contain the Timeline, the chat is shown in the right panel.
157-
export enum MainSplitContentType {
158-
Timeline,
159-
MaximisedWidget,
160-
Call,
161-
}
155+
export { MainSplitContentType };
156+
162157
export interface IRoomState {
163158
room?: Room;
164159
virtualRoom?: Room;
@@ -191,11 +186,6 @@ export interface IRoomState {
191186
showApps: boolean;
192187
isPeeking: boolean;
193188
showRightPanel: boolean;
194-
/**
195-
* Whether the right panel shown is either of ThreadPanel or ThreadView.
196-
* Always false when `showRightPanel` is false.
197-
*/
198-
threadRightPanel: boolean;
199189
// error object, as from the matrix client/server API
200190
// If we failed to load information about the room,
201191
// store the error here.
@@ -234,7 +224,7 @@ export interface IRoomState {
234224
e2eStatus?: E2EStatus;
235225
rejecting?: boolean;
236226
hasPinnedWidgets?: boolean;
237-
mainSplitContentType?: MainSplitContentType;
227+
mainSplitContentType: MainSplitContentType;
238228
// whether or not a spaces context switch brought us here,
239229
// if it did we don't want the room to be marked as read as soon as it is loaded.
240230
wasContextSwitch?: boolean;
@@ -399,7 +389,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
399389
showApps: false,
400390
isPeeking: false,
401391
showRightPanel: false,
402-
threadRightPanel: false,
403392
joining: false,
404393
showTopUnreadMessagesBar: false,
405394
statusBarVisible: false,
@@ -626,11 +615,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
626615
mainSplitContentType: room ? this.getMainSplitContentType(room) : undefined,
627616
initialEventId: undefined, // default to clearing this, will get set later in the method if needed
628617
showRightPanel: roomId ? this.context.rightPanelStore.isOpenForRoom(roomId) : false,
629-
threadRightPanel: roomId
630-
? [RightPanelPhases.ThreadView, RightPanelPhases.ThreadPanel].includes(
631-
this.context.rightPanelStore.currentCardForRoom(roomId).phase!,
632-
)
633-
: false,
634618
activeCall: roomId ? CallStore.instance.getActiveCall(roomId) : null,
635619
promptAskToJoin: this.context.roomViewStore.promptAskToJoin(),
636620
viewRoomOpts: this.context.roomViewStore.getViewRoomOpts(),
@@ -1033,11 +1017,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
10331017
const { roomId } = this.state;
10341018
this.setState({
10351019
showRightPanel: roomId ? this.context.rightPanelStore.isOpenForRoom(roomId) : false,
1036-
threadRightPanel: roomId
1037-
? [RightPanelPhases.ThreadView, RightPanelPhases.ThreadPanel].includes(
1038-
this.context.rightPanelStore.currentCardForRoom(roomId).phase!,
1039-
)
1040-
: false,
10411020
});
10421021
};
10431022

@@ -2531,6 +2510,17 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
25312510
}
25322511
const mainSplitContentClasses = classNames("mx_RoomView_body", mainSplitContentClassName);
25332512

2513+
let sizeKey: string | undefined;
2514+
let defaultSize: number | undefined;
2515+
let analyticsRoomType: ComponentProps<typeof MainSplit>["analyticsRoomType"] = "other_room";
2516+
if (this.state.mainSplitContentType !== MainSplitContentType.Timeline) {
2517+
// Override defaults for video rooms where more space is needed for the chat timeline
2518+
sizeKey = "wide";
2519+
defaultSize = 420;
2520+
analyticsRoomType =
2521+
this.state.mainSplitContentType === MainSplitContentType.Call ? "video_room" : "maximised_widget";
2522+
}
2523+
25342524
return (
25352525
<RoomContext.Provider value={this.state}>
25362526
<div className={mainClasses} ref={this.roomView} onKeyDown={this.onReactKeyDown}>
@@ -2541,10 +2531,9 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
25412531
<MainSplit
25422532
panel={rightPanel}
25432533
resizeNotifier={this.props.resizeNotifier}
2544-
// Override defaults when a thread is being shown to allow persisting a separate
2545-
// right panel width for thread panels as they tend to want to be wider.
2546-
sizeKey={this.state.threadRightPanel ? "thread" : undefined}
2547-
defaultSize={this.state.threadRightPanel ? 500 : undefined}
2534+
sizeKey={sizeKey}
2535+
defaultSize={defaultSize}
2536+
analyticsRoomType={analyticsRoomType}
25482537
>
25492538
<div
25502539
className={mainSplitContentClasses}

src/components/structures/SpaceRoomView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,7 @@ export default class SpaceRoomView extends React.PureComponent<IProps, IState> {
764764
return (
765765
<main className="mx_SpaceRoomView">
766766
<ErrorBoundary>
767-
<MainSplit panel={rightPanel} resizeNotifier={this.props.resizeNotifier}>
767+
<MainSplit panel={rightPanel} resizeNotifier={this.props.resizeNotifier} analyticsRoomType="space">
768768
{this.renderBody()}
769769
</MainSplit>
770770
</ErrorBoundary>

src/components/structures/UserView.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,12 @@ export default class UserView extends React.Component<IProps, IState> {
8787
/>
8888
);
8989
return (
90-
<MainSplit panel={panel} resizeNotifier={this.props.resizeNotifier}>
90+
<MainSplit
91+
panel={panel}
92+
resizeNotifier={this.props.resizeNotifier}
93+
defaultSize={420}
94+
analyticsRoomType="user_profile"
95+
>
9196
<UserOnboardingPage />
9297
</MainSplit>
9398
);

src/contexts/RoomContext.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ export enum TimelineRenderingType {
2121
Pinned = "Pinned",
2222
}
2323

24+
// This defines the content of the mainSplit.
25+
// If the mainSplit does not contain the Timeline, the chat is shown in the right panel.
26+
export enum MainSplitContentType {
27+
Timeline,
28+
MaximisedWidget,
29+
Call,
30+
}
31+
2432
const RoomContext = createContext<
2533
IRoomState & {
2634
threadId?: string;
@@ -35,7 +43,6 @@ const RoomContext = createContext<
3543
showApps: false,
3644
isPeeking: false,
3745
showRightPanel: true,
38-
threadRightPanel: false,
3946
joining: false,
4047
showTopUnreadMessagesBar: false,
4148
statusBarVisible: false,
@@ -59,6 +66,7 @@ const RoomContext = createContext<
5966
matrixClientIsReady: false,
6067
showUrlPreview: false,
6168
timelineRenderingType: TimelineRenderingType.Room,
69+
mainSplitContentType: MainSplitContentType.Timeline,
6270
threadId: undefined,
6371
liveTimeline: undefined,
6472
narrow: false,

test/components/structures/MainSplit-test.tsx

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ Please see LICENSE files in the repository root for full details.
77
*/
88

99
import React from "react";
10-
import { render } from "@testing-library/react";
10+
import { fireEvent, render } from "@testing-library/react";
1111

1212
import MainSplit from "../../../src/components/structures/MainSplit";
1313
import ResizeNotifier from "../../../src/utils/ResizeNotifier";
14+
import { PosthogAnalytics } from "../../../src/PosthogAnalytics.ts";
1415

1516
describe("<MainSplit/>", () => {
1617
const resizeNotifier = new ResizeNotifier();
@@ -21,18 +22,33 @@ describe("<MainSplit/>", () => {
2122
);
2223
const panel = <div>Right panel</div>;
2324

25+
beforeEach(() => {
26+
localStorage.clear();
27+
});
28+
2429
it("renders", () => {
2530
const { asFragment, container } = render(
26-
<MainSplit resizeNotifier={resizeNotifier} children={children} panel={panel} />,
31+
<MainSplit
32+
resizeNotifier={resizeNotifier}
33+
children={children}
34+
panel={panel}
35+
analyticsRoomType="other_room"
36+
/>,
2737
);
2838
expect(asFragment()).toMatchSnapshot();
29-
// Assert it matches the default width of 350
30-
expect(container.querySelector<HTMLElement>(".mx_RightPanel_ResizeWrapper")!.style.width).toBe("350px");
39+
// Assert it matches the default width of 320
40+
expect(container.querySelector<HTMLElement>(".mx_RightPanel_ResizeWrapper")!.style.width).toBe("320px");
3141
});
3242

3343
it("respects defaultSize prop", () => {
3444
const { asFragment, container } = render(
35-
<MainSplit resizeNotifier={resizeNotifier} children={children} panel={panel} defaultSize={500} />,
45+
<MainSplit
46+
resizeNotifier={resizeNotifier}
47+
children={children}
48+
panel={panel}
49+
defaultSize={500}
50+
analyticsRoomType="other_room"
51+
/>,
3652
);
3753
expect(asFragment()).toMatchSnapshot();
3854
// Assert it matches the default width of 350
@@ -48,8 +64,36 @@ describe("<MainSplit/>", () => {
4864
panel={panel}
4965
sizeKey="thread"
5066
defaultSize={400}
67+
analyticsRoomType="other_room"
5168
/>,
5269
);
5370
expect(container.querySelector<HTMLElement>(".mx_RightPanel_ResizeWrapper")!.style.width).toBe("333px");
5471
});
72+
73+
it("should report to analytics on resize stop", () => {
74+
const { container } = render(
75+
<MainSplit
76+
resizeNotifier={resizeNotifier}
77+
children={children}
78+
panel={panel}
79+
sizeKey="thread"
80+
defaultSize={400}
81+
analyticsRoomType="other_room"
82+
/>,
83+
);
84+
85+
const spy = jest.spyOn(PosthogAnalytics.instance, "trackEvent");
86+
87+
const handle = container.querySelector(".mx_ResizeHandle--horizontal")!;
88+
fireEvent.mouseDown(handle);
89+
fireEvent.mouseMove(handle, { clientX: 0 });
90+
fireEvent.mouseUp(handle);
91+
92+
expect(spy).toHaveBeenCalledWith({
93+
eventName: "WebPanelResize",
94+
panel: "right",
95+
roomType: "other_room",
96+
size: 400,
97+
});
98+
});
5599
});

test/components/structures/RoomView-test.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,12 @@ describe("RoomView", () => {
311311
expect(stores.rightPanelStore.isOpen).toEqual(true);
312312
expect(stores.rightPanelStore.currentCard.phase).toEqual(RightPanelPhases.Timeline);
313313
});
314+
315+
it("should render joined video room view", async () => {
316+
jest.spyOn(room, "getMyMembership").mockReturnValue(KnownMembership.Join);
317+
const { asFragment } = await mountRoomView();
318+
expect(asFragment()).toMatchSnapshot();
319+
});
314320
});
315321

316322
describe("for a local room", () => {

test/components/structures/__snapshots__/MainSplit-test.tsx.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ exports[`<MainSplit/> renders 1`] = `
1414
</div>
1515
<div
1616
class="mx_RightPanel_ResizeWrapper"
17-
style="position: relative; user-select: auto; width: 350px; height: 100%; max-width: 50%; min-width: 264px; box-sizing: border-box; flex-shrink: 0;"
17+
style="position: relative; user-select: auto; width: 320px; height: 100%; max-width: 50%; min-width: 264px; box-sizing: border-box; flex-shrink: 0;"
1818
>
1919
<div>
2020
Right panel

0 commit comments

Comments
 (0)