Merge pull request #4809 from matrix-org/travis/room-list/headers-resize

Fix sticky headers over/under extending themselves in the new room list
pull/21833/head
Travis Ralston 2020-06-22 13:51:24 -06:00 committed by GitHub
commit 6dd20d80a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 12 deletions

View File

@ -19,7 +19,6 @@ import TagPanel from "./TagPanel";
import classNames from "classnames"; import classNames from "classnames";
import dis from "../../dispatcher/dispatcher"; import dis from "../../dispatcher/dispatcher";
import { _t } from "../../languageHandler"; import { _t } from "../../languageHandler";
import SearchBox from "./SearchBox";
import RoomList2 from "../views/rooms/RoomList2"; import RoomList2 from "../views/rooms/RoomList2";
import { Action } from "../../dispatcher/actions"; import { Action } from "../../dispatcher/actions";
import { MatrixClientPeg } from "../../MatrixClientPeg"; import { MatrixClientPeg } from "../../MatrixClientPeg";
@ -30,6 +29,8 @@ import AccessibleButton from "../views/elements/AccessibleButton";
import RoomBreadcrumbs2 from "../views/rooms/RoomBreadcrumbs2"; import RoomBreadcrumbs2 from "../views/rooms/RoomBreadcrumbs2";
import { BreadcrumbsStore } from "../../stores/BreadcrumbsStore"; import { BreadcrumbsStore } from "../../stores/BreadcrumbsStore";
import { UPDATE_EVENT } from "../../stores/AsyncStore"; import { UPDATE_EVENT } from "../../stores/AsyncStore";
import ResizeNotifier from "../../utils/ResizeNotifier";
import { createRef } from "react";
/******************************************************************* /*******************************************************************
* CAUTION * * CAUTION *
@ -41,6 +42,7 @@ import { UPDATE_EVENT } from "../../stores/AsyncStore";
interface IProps { interface IProps {
isMinimized: boolean; isMinimized: boolean;
resizeNotifier: ResizeNotifier;
} }
interface IState { interface IState {
@ -49,6 +51,8 @@ interface IState {
} }
export default class LeftPanel2 extends React.Component<IProps, IState> { export default class LeftPanel2 extends React.Component<IProps, IState> {
private listContainerRef: React.RefObject<HTMLDivElement> = createRef();
// TODO: Properly support TagPanel // TODO: Properly support TagPanel
// TODO: Properly support searching/filtering // TODO: Properly support searching/filtering
// TODO: Properly support breadcrumbs // TODO: Properly support breadcrumbs
@ -65,10 +69,15 @@ export default class LeftPanel2 extends React.Component<IProps, IState> {
}; };
BreadcrumbsStore.instance.on(UPDATE_EVENT, this.onBreadcrumbsUpdate); BreadcrumbsStore.instance.on(UPDATE_EVENT, this.onBreadcrumbsUpdate);
// We watch the middle panel because we don't actually get resized, the middle panel does.
// We listen to the noisy channel to avoid choppy reaction times.
this.props.resizeNotifier.on("middlePanelResizedNoisy", this.onResize);
} }
public componentWillUnmount() { public componentWillUnmount() {
BreadcrumbsStore.instance.off(UPDATE_EVENT, this.onBreadcrumbsUpdate); BreadcrumbsStore.instance.off(UPDATE_EVENT, this.onBreadcrumbsUpdate);
this.props.resizeNotifier.off("middlePanelResizedNoisy", this.onResize);
} }
private onSearch = (term: string): void => { private onSearch = (term: string): void => {
@ -86,9 +95,7 @@ export default class LeftPanel2 extends React.Component<IProps, IState> {
} }
}; };
// TODO: Apply this on resize, init, etc for reliability private handleStickyHeaders(list: HTMLDivElement) {
private onScroll = (ev: React.MouseEvent<HTMLDivElement>) => {
const list = ev.target as HTMLDivElement;
const rlRect = list.getBoundingClientRect(); const rlRect = list.getBoundingClientRect();
const bottom = rlRect.bottom; const bottom = rlRect.bottom;
const top = rlRect.top; const top = rlRect.top;
@ -123,6 +130,18 @@ export default class LeftPanel2 extends React.Component<IProps, IState> {
header.style.top = `unset`; header.style.top = `unset`;
} }
} }
}
// TODO: Apply this on resize, init, etc for reliability
private onScroll = (ev: React.MouseEvent<HTMLDivElement>) => {
const list = ev.target as HTMLDivElement;
this.handleStickyHeaders(list);
};
private onResize = () => {
console.log("Resize width");
if (!this.listContainerRef.current) return; // ignore: no headers to sticky
this.handleStickyHeaders(this.listContainerRef.current);
}; };
private renderHeader(): React.ReactNode { private renderHeader(): React.ReactNode {
@ -230,9 +249,11 @@ export default class LeftPanel2 extends React.Component<IProps, IState> {
<aside className="mx_LeftPanel2_roomListContainer"> <aside className="mx_LeftPanel2_roomListContainer">
{this.renderHeader()} {this.renderHeader()}
{this.renderSearchExplore()} {this.renderSearchExplore()}
<div className="mx_LeftPanel2_actualRoomListContainer" onScroll={this.onScroll}> <div
{roomList} className="mx_LeftPanel2_actualRoomListContainer"
</div> onScroll={this.onScroll}
ref={this.listContainerRef}
>{roomList}</div>
</aside> </aside>
</div> </div>
); );

View File

@ -677,7 +677,10 @@ class LoggedInView extends React.PureComponent<IProps, IState> {
if (SettingsStore.isFeatureEnabled("feature_new_room_list")) { if (SettingsStore.isFeatureEnabled("feature_new_room_list")) {
// TODO: Supply props like collapsed and disabled to LeftPanel2 // TODO: Supply props like collapsed and disabled to LeftPanel2
leftPanel = ( leftPanel = (
<LeftPanel2 isMinimized={this.props.collapseLhs || false} /> <LeftPanel2
isMinimized={this.props.collapseLhs || false}
resizeNotifier={this.props.resizeNotifier}
/>
); );
} }

View File

@ -15,9 +15,13 @@ limitations under the License.
*/ */
/** /**
* Fires when the middle panel has been resized. * Fires when the middle panel has been resized (throttled).
* @event module:utils~ResizeNotifier#"middlePanelResized" * @event module:utils~ResizeNotifier#"middlePanelResized"
*/ */
/**
* Fires when the middle panel has been resized by a pixel.
* @event module:utils~ResizeNotifier#"middlePanelResizedNoisy"
*/
import { EventEmitter } from "events"; import { EventEmitter } from "events";
import { throttle } from "lodash"; import { throttle } from "lodash";
@ -29,15 +33,24 @@ export default class ResizeNotifier extends EventEmitter {
this._throttledMiddlePanel = throttle(() => this.emit("middlePanelResized"), 200); this._throttledMiddlePanel = throttle(() => this.emit("middlePanelResized"), 200);
} }
_noisyMiddlePanel() {
this.emit("middlePanelResizedNoisy");
}
_updateMiddlePanel() {
this._throttledMiddlePanel();
this._noisyMiddlePanel();
}
// can be called in quick succession // can be called in quick succession
notifyLeftHandleResized() { notifyLeftHandleResized() {
// don't emit event for own region // don't emit event for own region
this._throttledMiddlePanel(); this._updateMiddlePanel();
} }
// can be called in quick succession // can be called in quick succession
notifyRightHandleResized() { notifyRightHandleResized() {
this._throttledMiddlePanel(); this._updateMiddlePanel();
} }
// can be called in quick succession // can be called in quick succession
@ -48,7 +61,7 @@ export default class ResizeNotifier extends EventEmitter {
// taller than the available space // taller than the available space
this.emit("leftPanelResized"); this.emit("leftPanelResized");
this._throttledMiddlePanel(); this._updateMiddlePanel();
} }
} }