diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss
index 5d1dd043835..5d477d63c92 100644
--- a/res/css/views/rooms/_EventTile.scss
+++ b/res/css/views/rooms/_EventTile.scss
@@ -280,6 +280,7 @@ $left-gutter: 64px;
height: $font-14px;
width: $font-14px;
+ will-change: left, top;
transition:
left var(--transition-short) ease-out,
top var(--transition-standard) ease-out;
diff --git a/src/CountlyAnalytics.ts b/src/CountlyAnalytics.ts
index aac53b188b1..5545ed84837 100644
--- a/src/CountlyAnalytics.ts
+++ b/src/CountlyAnalytics.ts
@@ -816,7 +816,9 @@ export default class CountlyAnalytics {
window.addEventListener("mousemove", this.onUserActivity);
window.addEventListener("click", 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.inactivityCounter++;
diff --git a/src/components/structures/AutoHideScrollbar.js b/src/components/structures/AutoHideScrollbar.js
deleted file mode 100644
index 14f7c9ca838..00000000000
--- a/src/components/structures/AutoHideScrollbar.js
+++ /dev/null
@@ -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 (
- { this.props.children }
-
);
- }
-}
diff --git a/src/components/structures/AutoHideScrollbar.tsx b/src/components/structures/AutoHideScrollbar.tsx
new file mode 100644
index 00000000000..66f998b6162
--- /dev/null
+++ b/src/components/structures/AutoHideScrollbar.tsx
@@ -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 {
+ private containerRef: React.RefObject = 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 (
+ { this.props.children }
+
);
+ }
+}
diff --git a/src/components/structures/IndicatorScrollbar.js b/src/components/structures/IndicatorScrollbar.js
index 341ab2df719..51a3b287f01 100644
--- a/src/components/structures/IndicatorScrollbar.js
+++ b/src/components/structures/IndicatorScrollbar.js
@@ -59,7 +59,9 @@ export default class IndicatorScrollbar extends React.Component {
_collectScroller(scroller) {
if (scroller && !this._scrollElement) {
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();
}
}
diff --git a/src/components/structures/LeftPanel.tsx b/src/components/structures/LeftPanel.tsx
index 7df4bcadf3a..5b6b9c37175 100644
--- a/src/components/structures/LeftPanel.tsx
+++ b/src/components/structures/LeftPanel.tsx
@@ -97,6 +97,9 @@ export default class LeftPanel extends React.Component {
public componentDidMount() {
UIStore.instance.trackElementDimensions("ListContainer", this.listContainerRef.current);
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() {
@@ -108,6 +111,7 @@ export default class LeftPanel extends React.Component {
SpaceStore.instance.off(UPDATE_SELECTED_SPACE, this.updateActiveSpace);
UIStore.instance.stopTrackingElementDimensions("ListContainer");
UIStore.instance.removeListener("ListContainer", this.refreshStickyHeaders);
+ this.listContainerRef.current?.removeEventListener("scroll", this.onScroll);
}
public componentDidUpdate(prevProps: IProps, prevState: IState): void {
@@ -295,7 +299,7 @@ export default class LeftPanel extends React.Component {
}
}
- private onScroll = (ev: React.MouseEvent) => {
+ private onScroll = (ev: Event) => {
const list = ev.target as HTMLDivElement;
this.handleStickyHeaders(list);
};
@@ -459,7 +463,6 @@ export default class LeftPanel extends React.Component {
= ({
autoComplete={true}
autoFocus={true}
/>
-
+
{ rooms.length > 0 ? (
{ _t("Rooms") }
diff --git a/src/components/views/elements/Tooltip.tsx b/src/components/views/elements/Tooltip.tsx
index 7e9ce9745cf..0202c6b02f7 100644
--- a/src/components/views/elements/Tooltip.tsx
+++ b/src/components/views/elements/Tooltip.tsx
@@ -70,7 +70,10 @@ export default class Tooltip extends React.Component
{
this.tooltipContainer = document.createElement("div");
this.tooltipContainer.className = "mx_Tooltip_wrapper";
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;
@@ -85,7 +88,9 @@ export default class Tooltip extends React.Component {
public componentWillUnmount() {
ReactDOM.unmountComponentAtNode(this.tooltipContainer);
document.body.removeChild(this.tooltipContainer);
- window.removeEventListener('scroll', this.renderTooltip, true);
+ window.removeEventListener('scroll', this.renderTooltip, {
+ capture: true,
+ });
}
private updatePosition(style: CSSProperties) {
diff --git a/src/components/views/rooms/RoomSublist.tsx b/src/components/views/rooms/RoomSublist.tsx
index df00524b3be..0bb7381dbc1 100644
--- a/src/components/views/rooms/RoomSublist.tsx
+++ b/src/components/views/rooms/RoomSublist.tsx
@@ -105,6 +105,7 @@ interface IState {
export default class RoomSublist extends React.Component {
private headerButton = createRef();
private sublistRef = createRef();
+ private tilesRef = createRef();
private dispatcherRef: string;
private layout: ListLayout;
private heightAtStart: number;
@@ -246,11 +247,15 @@ export default class RoomSublist extends React.Component {
public componentDidMount() {
this.dispatcherRef = defaultDispatcher.register(this.onAction);
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() {
defaultDispatcher.unregister(this.dispatcherRef);
RoomListStore.instance.off(LISTS_UPDATE_EVENT, this.onListsUpdated);
+ this.tilesRef.current?.removeEventListener("scroll", this.onScrollPrevent);
}
private onListsUpdated = () => {
@@ -755,7 +760,7 @@ export default class RoomSublist extends React.Component {
);
}
- private onScrollPrevent(e: React.UIEvent) {
+ private onScrollPrevent(e: Event) {
// 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
(e.target as HTMLDivElement).scrollTop = 0;
@@ -884,7 +889,7 @@ export default class RoomSublist extends React.Component {
className="mx_RoomSublist_resizeBox"
enable={handles}
>
-
+
{visibleTiles}
{showNButton}