Allow maintaining a different right panel width for thread panels (#11064)

* Move Room context threadId our of RoomView state

* Allow maintaining a different right panel width for thread panels

* Fix types

* Fix types

* Add tests

* Increase coverage

* Increase coverage

* Add comments

* Update src/components/structures/MainSplit.tsx

Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>

---------

Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>
This commit is contained in:
Michael Telatynski 2023-06-15 12:57:58 +01:00 committed by GitHub
parent cb2b1718ff
commit 7236e48765
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 190 additions and 7 deletions

View file

@ -26,9 +26,24 @@ interface IProps {
collapsedRhs?: boolean;
panel?: JSX.Element;
children: ReactNode;
/**
* A unique identifier for this panel split.
*
* This is appended to the key used to store the panel size in localStorage, allowing the widths of different
* panels to be stored.
*/
sizeKey?: string;
/**
* The size to use for the panel component if one isn't persisted in storage. Defaults to 350.
*/
defaultSize: number;
}
export default class MainSplit extends React.Component<IProps> {
public static defaultProps = {
defaultSize: 350,
};
private onResizeStart = (): void => {
this.props.resizeNotifier.startResizing();
};
@ -37,6 +52,14 @@ export default class MainSplit extends React.Component<IProps> {
this.props.resizeNotifier.notifyRightHandleResized();
};
private get sizeSettingStorageKey(): string {
let key = "mx_rhs_size";
if (!!this.props.sizeKey) {
key += `_${this.props.sizeKey}`;
}
return key;
}
private onResizeStop = (
event: MouseEvent | TouchEvent,
direction: Direction,
@ -44,14 +67,17 @@ export default class MainSplit extends React.Component<IProps> {
delta: NumberSize,
): void => {
this.props.resizeNotifier.stopResizing();
window.localStorage.setItem("mx_rhs_size", (this.loadSidePanelSize().width + delta.width).toString());
window.localStorage.setItem(
this.sizeSettingStorageKey,
(this.loadSidePanelSize().width + delta.width).toString(),
);
};
private loadSidePanelSize(): { height: string | number; width: number } {
let rhsSize = parseInt(window.localStorage.getItem("mx_rhs_size")!, 10);
let rhsSize = parseInt(window.localStorage.getItem(this.sizeSettingStorageKey)!, 10);
if (isNaN(rhsSize)) {
rhsSize = 350;
rhsSize = this.props.defaultSize;
}
return {
@ -70,6 +96,7 @@ export default class MainSplit extends React.Component<IProps> {
if (hasResizer) {
children = (
<Resizable
key={this.props.sizeKey}
defaultSize={this.loadSidePanelSize()}
minWidth={264}
maxWidth="50%"

View file

@ -179,6 +179,11 @@ 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.
@ -223,7 +228,6 @@ export interface IRoomState {
wasContextSwitch?: boolean;
editState?: EditorStateTransfer;
timelineRenderingType: TimelineRenderingType;
threadId?: string;
liveTimeline?: EventTimeline;
narrow: boolean;
msc3946ProcessDynamicPredecessor: boolean;
@ -402,6 +406,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
showApps: false,
isPeeking: false,
showRightPanel: false,
threadRightPanel: false,
joining: false,
showTopUnreadMessagesBar: false,
statusBarVisible: false,
@ -623,6 +628,11 @@ 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,
};
@ -1011,8 +1021,14 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
}
private onRightPanelStoreUpdate = (): void => {
const { roomId } = this.state;
this.setState({
showRightPanel: this.state.roomId ? this.context.rightPanelStore.isOpenForRoom(this.state.roomId) : false,
showRightPanel: roomId ? this.context.rightPanelStore.isOpenForRoom(roomId) : false,
threadRightPanel: roomId
? [RightPanelPhases.ThreadView, RightPanelPhases.ThreadPanel].includes(
this.context.rightPanelStore.currentCardForRoom(roomId).phase!,
)
: false,
});
};
@ -2439,7 +2455,14 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
viewingCall={viewingCall}
activeCall={this.state.activeCall}
/>
<MainSplit panel={rightPanel} resizeNotifier={this.props.resizeNotifier}>
<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}
>
<div
className={mainSplitContentClasses}
ref={this.roomViewBody}

View file

@ -29,7 +29,11 @@ export enum TimelineRenderingType {
Pinned = "Pinned",
}
const RoomContext = createContext<IRoomState>({
const RoomContext = createContext<
IRoomState & {
threadId?: string;
}
>({
roomLoading: true,
peekLoading: false,
shouldPeek: true,
@ -39,6 +43,7 @@ const RoomContext = createContext<IRoomState>({
showApps: false,
isPeeking: false,
showRightPanel: true,
threadRightPanel: false,
joining: false,
showTopUnreadMessagesBar: false,
statusBarVisible: false,