Merge pull request #6113 from matrix-org/gsouquet/improve-layout-rendering
commit
9d126c51e4
|
@ -280,6 +280,7 @@ $left-gutter: 64px;
|
||||||
height: $font-14px;
|
height: $font-14px;
|
||||||
width: $font-14px;
|
width: $font-14px;
|
||||||
|
|
||||||
|
will-change: left, top;
|
||||||
transition:
|
transition:
|
||||||
left var(--transition-short) ease-out,
|
left var(--transition-short) ease-out,
|
||||||
top var(--transition-standard) ease-out;
|
top var(--transition-standard) ease-out;
|
||||||
|
|
|
@ -816,7 +816,9 @@ export default class CountlyAnalytics {
|
||||||
window.addEventListener("mousemove", this.onUserActivity);
|
window.addEventListener("mousemove", this.onUserActivity);
|
||||||
window.addEventListener("click", this.onUserActivity);
|
window.addEventListener("click", this.onUserActivity);
|
||||||
window.addEventListener("keydown", this.onUserActivity);
|
window.addEventListener("keydown", this.onUserActivity);
|
||||||
window.addEventListener("scroll", this.onUserActivity);
|
// Using the passive option to not block the main thread
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners
|
||||||
|
window.addEventListener("scroll", this.onUserActivity, { passive: true });
|
||||||
|
|
||||||
this.activityIntervalId = setInterval(() => {
|
this.activityIntervalId = setInterval(() => {
|
||||||
this.inactivityCounter++;
|
this.inactivityCounter++;
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2018 New Vector Ltd
|
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
export default class AutoHideScrollbar extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this._collectContainerRef = this._collectContainerRef.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
_collectContainerRef(ref) {
|
|
||||||
if (ref && !this.containerRef) {
|
|
||||||
this.containerRef = ref;
|
|
||||||
}
|
|
||||||
if (this.props.wrappedRef) {
|
|
||||||
this.props.wrappedRef(ref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getScrollTop() {
|
|
||||||
return this.containerRef.scrollTop;
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (<div
|
|
||||||
ref={this._collectContainerRef}
|
|
||||||
style={this.props.style}
|
|
||||||
className={["mx_AutoHideScrollbar", this.props.className].join(" ")}
|
|
||||||
onScroll={this.props.onScroll}
|
|
||||||
onWheel={this.props.onWheel}
|
|
||||||
tabIndex={this.props.tabIndex}
|
|
||||||
>
|
|
||||||
{ this.props.children }
|
|
||||||
</div>);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 New Vector Ltd
|
||||||
|
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
className?: string;
|
||||||
|
onScroll?: () => void;
|
||||||
|
onWheel?: () => void;
|
||||||
|
style?: React.CSSProperties
|
||||||
|
tabIndex?: number,
|
||||||
|
wrappedRef?: (ref: HTMLDivElement) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class AutoHideScrollbar extends React.Component<IProps> {
|
||||||
|
private containerRef: React.RefObject<HTMLDivElement> = React.createRef();
|
||||||
|
|
||||||
|
public componentDidMount() {
|
||||||
|
if (this.containerRef.current && this.props.onScroll) {
|
||||||
|
// Using the passive option to not block the main thread
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners
|
||||||
|
this.containerRef.current.addEventListener("scroll", this.props.onScroll, { passive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.props.wrappedRef) {
|
||||||
|
this.props.wrappedRef(this.containerRef.current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentWillUnmount() {
|
||||||
|
if (this.containerRef.current && this.props.onScroll) {
|
||||||
|
this.containerRef.current.removeEventListener("scroll", this.props.onScroll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getScrollTop(): number {
|
||||||
|
return this.containerRef.current.scrollTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
return (<div
|
||||||
|
ref={this.containerRef}
|
||||||
|
style={this.props.style}
|
||||||
|
className={["mx_AutoHideScrollbar", this.props.className].join(" ")}
|
||||||
|
onWheel={this.props.onWheel}
|
||||||
|
tabIndex={this.props.tabIndex}
|
||||||
|
>
|
||||||
|
{ this.props.children }
|
||||||
|
</div>);
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,7 +59,9 @@ export default class IndicatorScrollbar extends React.Component {
|
||||||
_collectScroller(scroller) {
|
_collectScroller(scroller) {
|
||||||
if (scroller && !this._scrollElement) {
|
if (scroller && !this._scrollElement) {
|
||||||
this._scrollElement = scroller;
|
this._scrollElement = scroller;
|
||||||
this._scrollElement.addEventListener("scroll", this.checkOverflow);
|
// Using the passive option to not block the main thread
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners
|
||||||
|
this._scrollElement.addEventListener("scroll", this.checkOverflow, { passive: true });
|
||||||
this.checkOverflow();
|
this.checkOverflow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,9 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
||||||
public componentDidMount() {
|
public componentDidMount() {
|
||||||
UIStore.instance.trackElementDimensions("ListContainer", this.listContainerRef.current);
|
UIStore.instance.trackElementDimensions("ListContainer", this.listContainerRef.current);
|
||||||
UIStore.instance.on("ListContainer", this.refreshStickyHeaders);
|
UIStore.instance.on("ListContainer", this.refreshStickyHeaders);
|
||||||
|
// Using the passive option to not block the main thread
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners
|
||||||
|
this.listContainerRef.current?.addEventListener("scroll", this.onScroll, { passive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentWillUnmount() {
|
public componentWillUnmount() {
|
||||||
|
@ -108,6 +111,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
||||||
SpaceStore.instance.off(UPDATE_SELECTED_SPACE, this.updateActiveSpace);
|
SpaceStore.instance.off(UPDATE_SELECTED_SPACE, this.updateActiveSpace);
|
||||||
UIStore.instance.stopTrackingElementDimensions("ListContainer");
|
UIStore.instance.stopTrackingElementDimensions("ListContainer");
|
||||||
UIStore.instance.removeListener("ListContainer", this.refreshStickyHeaders);
|
UIStore.instance.removeListener("ListContainer", this.refreshStickyHeaders);
|
||||||
|
this.listContainerRef.current?.removeEventListener("scroll", this.onScroll);
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentDidUpdate(prevProps: IProps, prevState: IState): void {
|
public componentDidUpdate(prevProps: IProps, prevState: IState): void {
|
||||||
|
@ -295,7 +299,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onScroll = (ev: React.MouseEvent<HTMLDivElement>) => {
|
private onScroll = (ev: Event) => {
|
||||||
const list = ev.target as HTMLDivElement;
|
const list = ev.target as HTMLDivElement;
|
||||||
this.handleStickyHeaders(list);
|
this.handleStickyHeaders(list);
|
||||||
};
|
};
|
||||||
|
@ -459,7 +463,6 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
||||||
<div className="mx_LeftPanel_roomListWrapper">
|
<div className="mx_LeftPanel_roomListWrapper">
|
||||||
<div
|
<div
|
||||||
className={roomListClasses}
|
className={roomListClasses}
|
||||||
onScroll={this.onScroll}
|
|
||||||
ref={this.listContainerRef}
|
ref={this.listContainerRef}
|
||||||
// Firefox sometimes makes this element focusable due to
|
// Firefox sometimes makes this element focusable due to
|
||||||
// overflow:scroll;, so force it out of tab order.
|
// overflow:scroll;, so force it out of tab order.
|
||||||
|
|
|
@ -212,7 +212,7 @@ export const AddExistingToSpace: React.FC<IAddExistingToSpaceProps> = ({
|
||||||
autoComplete={true}
|
autoComplete={true}
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
/>
|
/>
|
||||||
<AutoHideScrollbar className="mx_AddExistingToSpace_content" id="mx_AddExistingToSpace">
|
<AutoHideScrollbar className="mx_AddExistingToSpace_content">
|
||||||
{ rooms.length > 0 ? (
|
{ rooms.length > 0 ? (
|
||||||
<div className="mx_AddExistingToSpace_section">
|
<div className="mx_AddExistingToSpace_section">
|
||||||
<h3>{ _t("Rooms") }</h3>
|
<h3>{ _t("Rooms") }</h3>
|
||||||
|
|
|
@ -70,7 +70,10 @@ export default class Tooltip extends React.Component<IProps> {
|
||||||
this.tooltipContainer = document.createElement("div");
|
this.tooltipContainer = document.createElement("div");
|
||||||
this.tooltipContainer.className = "mx_Tooltip_wrapper";
|
this.tooltipContainer.className = "mx_Tooltip_wrapper";
|
||||||
document.body.appendChild(this.tooltipContainer);
|
document.body.appendChild(this.tooltipContainer);
|
||||||
window.addEventListener('scroll', this.renderTooltip, true);
|
window.addEventListener('scroll', this.renderTooltip, {
|
||||||
|
passive: true,
|
||||||
|
capture: true,
|
||||||
|
});
|
||||||
|
|
||||||
this.parent = ReactDOM.findDOMNode(this).parentNode as Element;
|
this.parent = ReactDOM.findDOMNode(this).parentNode as Element;
|
||||||
|
|
||||||
|
@ -85,7 +88,9 @@ export default class Tooltip extends React.Component<IProps> {
|
||||||
public componentWillUnmount() {
|
public componentWillUnmount() {
|
||||||
ReactDOM.unmountComponentAtNode(this.tooltipContainer);
|
ReactDOM.unmountComponentAtNode(this.tooltipContainer);
|
||||||
document.body.removeChild(this.tooltipContainer);
|
document.body.removeChild(this.tooltipContainer);
|
||||||
window.removeEventListener('scroll', this.renderTooltip, true);
|
window.removeEventListener('scroll', this.renderTooltip, {
|
||||||
|
capture: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private updatePosition(style: CSSProperties) {
|
private updatePosition(style: CSSProperties) {
|
||||||
|
|
|
@ -105,6 +105,7 @@ interface IState {
|
||||||
export default class RoomSublist extends React.Component<IProps, IState> {
|
export default class RoomSublist extends React.Component<IProps, IState> {
|
||||||
private headerButton = createRef<HTMLDivElement>();
|
private headerButton = createRef<HTMLDivElement>();
|
||||||
private sublistRef = createRef<HTMLDivElement>();
|
private sublistRef = createRef<HTMLDivElement>();
|
||||||
|
private tilesRef = createRef<HTMLDivElement>();
|
||||||
private dispatcherRef: string;
|
private dispatcherRef: string;
|
||||||
private layout: ListLayout;
|
private layout: ListLayout;
|
||||||
private heightAtStart: number;
|
private heightAtStart: number;
|
||||||
|
@ -246,11 +247,15 @@ export default class RoomSublist extends React.Component<IProps, IState> {
|
||||||
public componentDidMount() {
|
public componentDidMount() {
|
||||||
this.dispatcherRef = defaultDispatcher.register(this.onAction);
|
this.dispatcherRef = defaultDispatcher.register(this.onAction);
|
||||||
RoomListStore.instance.on(LISTS_UPDATE_EVENT, this.onListsUpdated);
|
RoomListStore.instance.on(LISTS_UPDATE_EVENT, this.onListsUpdated);
|
||||||
|
// Using the passive option to not block the main thread
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners
|
||||||
|
this.tilesRef.current?.addEventListener("scroll", this.onScrollPrevent, { passive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentWillUnmount() {
|
public componentWillUnmount() {
|
||||||
defaultDispatcher.unregister(this.dispatcherRef);
|
defaultDispatcher.unregister(this.dispatcherRef);
|
||||||
RoomListStore.instance.off(LISTS_UPDATE_EVENT, this.onListsUpdated);
|
RoomListStore.instance.off(LISTS_UPDATE_EVENT, this.onListsUpdated);
|
||||||
|
this.tilesRef.current?.removeEventListener("scroll", this.onScrollPrevent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onListsUpdated = () => {
|
private onListsUpdated = () => {
|
||||||
|
@ -755,7 +760,7 @@ export default class RoomSublist extends React.Component<IProps, IState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onScrollPrevent(e: React.UIEvent<HTMLDivElement>) {
|
private onScrollPrevent(e: Event) {
|
||||||
// the RoomTile calls scrollIntoView and the browser may scroll a div we do not wish to be scrollable
|
// the RoomTile calls scrollIntoView and the browser may scroll a div we do not wish to be scrollable
|
||||||
// this fixes https://github.com/vector-im/element-web/issues/14413
|
// this fixes https://github.com/vector-im/element-web/issues/14413
|
||||||
(e.target as HTMLDivElement).scrollTop = 0;
|
(e.target as HTMLDivElement).scrollTop = 0;
|
||||||
|
@ -884,7 +889,7 @@ export default class RoomSublist extends React.Component<IProps, IState> {
|
||||||
className="mx_RoomSublist_resizeBox"
|
className="mx_RoomSublist_resizeBox"
|
||||||
enable={handles}
|
enable={handles}
|
||||||
>
|
>
|
||||||
<div className="mx_RoomSublist_tiles" onScroll={this.onScrollPrevent}>
|
<div className="mx_RoomSublist_tiles" ref={this.tilesRef}>
|
||||||
{visibleTiles}
|
{visibleTiles}
|
||||||
</div>
|
</div>
|
||||||
{showNButton}
|
{showNButton}
|
||||||
|
|
Loading…
Reference in New Issue