Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

BACAT Scrolling #2842

Merged
merged 55 commits into from
Mar 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
8cf2607
use AutoHideScrollbar in ScrollPanel
bwindels Mar 12, 2019
27070b3
remove onChildResize in RoomView as it's unused
bwindels Mar 12, 2019
735b4f6
create ResizeNotifier to derive which areas of the app resize and emit
bwindels Mar 12, 2019
56aeb51
emit timeline_resize in MatrixChat based on ResizeNotifier
bwindels Mar 12, 2019
c8123ec
use AutoHideScrollbar in memberlist
bwindels Mar 12, 2019
d3af992
use AutoHideScrollbar in member info panel
bwindels Mar 12, 2019
58f26ee
emit resize event when banners are shown/hidden to restore scroll pos
bwindels Mar 12, 2019
9541cc1
use ResizeNotifier as well to relayout room list
bwindels Mar 12, 2019
955ec14
chrome apparently anchors the scroll position, which fights against o…
bwindels Mar 14, 2019
0b81963
fix some tests
bwindels Mar 15, 2019
30d848b
use AutoHideScrollbar in ScrollPanel
bwindels Mar 12, 2019
f71a9f1
remove onChildResize in RoomView as it's unused
bwindels Mar 12, 2019
891e343
create ResizeNotifier to derive which areas of the app resize and emit
bwindels Mar 12, 2019
1bdbf30
emit timeline_resize in MatrixChat based on ResizeNotifier
bwindels Mar 12, 2019
dad382a
use AutoHideScrollbar in memberlist
bwindels Mar 12, 2019
af0a51d
use AutoHideScrollbar in member info panel
bwindels Mar 12, 2019
4795625
emit resize event when banners are shown/hidden to restore scroll pos
bwindels Mar 12, 2019
bab2730
use ResizeNotifier as well to relayout room list
bwindels Mar 12, 2019
987a1a0
chrome apparently anchors the scroll position, which fights against o…
bwindels Mar 14, 2019
95e61a5
fix some tests
bwindels Mar 15, 2019
d84003a
dont break room directory and search
bwindels Mar 18, 2019
b26f733
Merge branch 'bwindels/timeline-nativescrollbars' of github.com:matri…
bwindels Mar 18, 2019
71f6b08
first impl of new scrolling, still a bit broken
bwindels Mar 19, 2019
469511a
correctly calculate last node in viewport
bwindels Mar 19, 2019
2bcced7
take (potentially clipped) content height into account for filling
bwindels Mar 19, 2019
88f039f
keep track of current updateHeight request outside of method
bwindels Mar 19, 2019
c306181
take into account that node might not be in DOM while updating height
bwindels Mar 20, 2019
1e372aa
only log when node was found
bwindels Mar 20, 2019
f164a78
reimplement typing notif timeline shrinking prevention
bwindels Mar 20, 2019
460f9a5
comment typo
bwindels Mar 20, 2019
a8b149c
cleanup scrollpanel logging
bwindels Mar 20, 2019
9da13fe
small cleanup
bwindels Mar 20, 2019
02a5aa3
more logging cleanup
bwindels Mar 20, 2019
85d3054
no need for forceUpdate here
bwindels Mar 20, 2019
3e13a11
restore scroll position after hiding typing notifs with checkScroll
bwindels Mar 20, 2019
4947793
Merge branch 'develop' into bwindels/bacat-scrolling
bwindels Mar 21, 2019
680afc5
fix scrollToToken alignment
bwindels Mar 21, 2019
ab49bc4
fix comment typo
bwindels Mar 21, 2019
4bfdbe3
fix jumping when unfilling the top while scrolling down
bwindels Mar 22, 2019
c9c2519
log scroll events
bwindels Mar 22, 2019
8f7170a
add timeline profiling markers when updateheight and onscroll run
bwindels Mar 25, 2019
18b5041
try filling async instead of sync in scroll handler
bwindels Mar 26, 2019
82a9b34
add some comments and initialization for async filling
bwindels Mar 26, 2019
805539f
remove timestamp logging in profiler
bwindels Mar 26, 2019
46f5f87
implement scrolling to a token (best effort)
bwindels Mar 26, 2019
7e56a9a
prevent resize handle hit area overlapping with (native) scrollbar
bwindels Mar 26, 2019
f2f3661
more debug logging
bwindels Mar 26, 2019
5d53913
fix filling conditions
bwindels Mar 27, 2019
adf263c
Merge branch 'develop' into bwindels/bacat-scrolling-merged-develop
bwindels Mar 27, 2019
82e4424
make resizeNotifier optional in MainSplit for GroupView
bwindels Mar 27, 2019
41c5582
make resizeNotifier optional so tests don't fail
bwindels Mar 28, 2019
30dc6a9
remove tests relying on scrollpanel behaviour
bwindels Mar 28, 2019
0a4ef44
fix lint
bwindels Mar 28, 2019
1a26400
turn off debug logging
bwindels Mar 28, 2019
f157838
dispatch supports async dispatching on its own
bwindels Mar 29, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions res/css/_components.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
@import "./structures/_RoomStatusBar.scss";
@import "./structures/_RoomSubList.scss";
@import "./structures/_RoomView.scss";
@import "./structures/_ScrollPanel.scss";
@import "./structures/_SearchBox.scss";
@import "./structures/_TabbedView.scss";
@import "./structures/_TagPanel.scss";
Expand Down
6 changes: 6 additions & 0 deletions res/css/structures/_MainSplit.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,9 @@ limitations under the License.
flex-direction: row;
min-width: 0;
}

// move hit area 5px to the right so it doesn't overlap with the timeline scrollbar
.mx_MainSplit > .mx_ResizeHandle.mx_ResizeHandle_horizontal {
margin: 0 -10px 0 0;
padding: 0 10px 0 0;
}
3 changes: 3 additions & 0 deletions res/css/structures/_RoomView.scss
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ limitations under the License.
display: flex;
flex-direction: column;
flex: 1;
min-width: 0;
}

.mx_RoomView_body .mx_RoomView_timeline {
Expand Down Expand Up @@ -111,6 +112,8 @@ limitations under the License.
.mx_RoomView_messagePanel {
width: 100%;
overflow-y: auto;
flex: 1 1 0;
overflow-anchor: none;
}

.mx_RoomView_messagePanelSearchSpinner {
Expand Down
26 changes: 26 additions & 0 deletions res/css/structures/_ScrollPanel.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
Copyright 2019 New Vector Ltd

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.
*/

.mx_ScrollPanel {

.mx_RoomView_MessageList {
position: relative;
display: flex;
flex-direction: column;
justify-content: flex-end;
overflow-y: hidden;
}
}
5 changes: 5 additions & 0 deletions res/css/views/rooms/_MemberList.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ limitations under the License.
flex: 1;
display: flex;
flex-direction: column;
min-height: 0;

.mx_Spinner {
flex: 1 0 auto;
Expand All @@ -35,6 +36,10 @@ limitations under the License.
margin-top: 8px;
margin-bottom: 4px;
}

.mx_AutoHideScrollbar {
flex: 1 1 0;
}
}

.mx_MemberList_chevron {
Expand Down
12 changes: 11 additions & 1 deletion src/Notifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,17 @@ const Notifier = {
}
},

isToolbarHidden: function() {
shouldShowToolbar: function() {
const client = MatrixClientPeg.get();
if (!client) {
return false;
}
const isGuest = client.isGuest();
return !isGuest && Notifier.supportsDesktopNotifications() &&
!Notifier.isEnabled() && !Notifier._isToolbarHidden();
},

_isToolbarHidden: function() {
// Check localStorage for any such meta data
if (global.localStorage) {
return global.localStorage.getItem("notifications_hidden") === "true";
Expand Down
1 change: 1 addition & 0 deletions src/components/structures/AutoHideScrollbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ export default class AutoHideScrollbar extends React.Component {
render() {
return (<div
ref={this._collectContainerRef}
style={this.props.style}
className={["mx_AutoHideScrollbar", this.props.className].join(" ")}
onScroll={this.props.onScroll}
>
Expand Down
1 change: 1 addition & 0 deletions src/components/structures/FilePanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ const FilePanel = React.createClass({
timelineSet={this.state.timelineSet}
showUrlPreview = {false}
tileShape="file_grid"
resizeNotifier={this.props.resizeNotifier}
empty={_t('There are no visible files in this room')}
/>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/structures/LeftPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ const LeftPanel = React.createClass({
<CallPreview ConferenceHandler={VectorConferenceHandler} />
<RoomList
ref={this.collectRoomList}
toolbarShown={this.props.toolbarShown}
resizeNotifier={this.props.resizeNotifier}
collapsed={this.props.collapsed}
searchFilter={this.state.searchFilter}
ConferenceHandler={VectorConferenceHandler} />
Expand Down
23 changes: 16 additions & 7 deletions src/components/structures/LoggedInView.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import PropTypes from 'prop-types';
import { DragDropContext } from 'react-beautiful-dnd';

import { KeyCode, isOnlyCtrlOrCmdKeyEvent } from '../../Keyboard';
import Notifier from '../../Notifier';
import PageTypes from '../../PageTypes';
import CallMediaHandler from '../../CallMediaHandler';
import sdk from '../../index';
Expand Down Expand Up @@ -121,6 +120,18 @@ const LoggedInView = React.createClass({
this._matrixClient.on("RoomState.events", this.onRoomStateEvents);
},

componentDidUpdate(prevProps) {
// attempt to guess when a banner was opened or closed
if (
(prevProps.showCookieBar !== this.props.showCookieBar) ||
(prevProps.hasNewVersion !== this.props.hasNewVersion) ||
(prevProps.userHasGeneratedPassword !== this.props.userHasGeneratedPassword) ||
(prevProps.showNotifierToolbar !== this.props.showNotifierToolbar)
) {
this.props.resizeNotifier.notifyBannersChanged();
}
},

componentWillUnmount: function() {
document.removeEventListener('keydown', this._onKeyDown);
this._matrixClient.removeListener("accountData", this.onAccountData);
Expand Down Expand Up @@ -173,6 +184,7 @@ const LoggedInView = React.createClass({
},
onResized: (size) => {
window.localStorage.setItem("mx_lhs_size", '' + size);
this.props.resizeNotifier.notifyLeftHandleResized();
},
};
const resizer = new Resizer(
Expand Down Expand Up @@ -448,6 +460,7 @@ const LoggedInView = React.createClass({
disabled={this.props.middleDisabled}
collapsedRhs={this.props.collapsedRhs}
ConferenceHandler={this.props.ConferenceHandler}
resizeNotifier={this.props.resizeNotifier}
/>;
break;

Expand Down Expand Up @@ -489,7 +502,6 @@ const LoggedInView = React.createClass({
});

let topBar;
const isGuest = this.props.matrixClient.isGuest();
if (this.state.syncErrorData && this.state.syncErrorData.error.errcode === 'M_RESOURCE_LIMIT_EXCEEDED') {
topBar = <ServerLimitBar kind='hard'
adminContact={this.state.syncErrorData.error.data.admin_contact}
Expand All @@ -513,10 +525,7 @@ const LoggedInView = React.createClass({
topBar = <UpdateCheckBar {...this.props.checkingForUpdate} />;
} else if (this.state.userHasGeneratedPassword) {
topBar = <PasswordNagBar />;
} else if (
!isGuest && Notifier.supportsDesktopNotifications() &&
!Notifier.isEnabled() && !Notifier.isToolbarHidden()
) {
} else if (this.props.showNotifierToolbar) {
topBar = <MatrixToolbar />;
}

Expand All @@ -534,7 +543,7 @@ const LoggedInView = React.createClass({
<DragDropContext onDragEnd={this._onDragEnd}>
<div ref={this._setResizeContainerRef} className={bodyClasses}>
<LeftPanel
toolbarShown={!!topBar}
resizeNotifier={this.props.resizeNotifier}
collapsed={this.props.collapseLhs || false}
disabled={this.props.leftDisabled}
/>
Expand Down
3 changes: 3 additions & 0 deletions src/components/structures/MainSplit.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ export default class MainSplit extends React.Component {

_onResized(size) {
window.localStorage.setItem("mx_rhs_size", size);
if (this.props.resizeNotifier) {
this.props.resizeNotifier.notifyRightHandleResized();
}
}

_createResizer() {
Expand Down
19 changes: 17 additions & 2 deletions src/components/structures/MatrixChat.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import PlatformPeg from "../../PlatformPeg";
import SdkConfig from "../../SdkConfig";
import * as RoomListSorter from "../../RoomListSorter";
import dis from "../../dispatcher";
import Notifier from '../../Notifier';

import Modal from "../../Modal";
import Tinter from "../../Tinter";
Expand All @@ -48,6 +49,7 @@ import { _t, getCurrentLanguage } from '../../languageHandler';
import SettingsStore, {SettingLevel} from "../../settings/SettingsStore";
import { startAnyRegistrationFlow } from "../../Registration.js";
import { messageForSyncError } from '../../utils/ErrorUtils';
import ResizeNotifier from "../../utils/ResizeNotifier";
import TimelineExplosionDialog from "../views/dialogs/TimelineExplosionDialog";

const AutoDiscovery = Matrix.AutoDiscovery;
Expand Down Expand Up @@ -195,6 +197,8 @@ export default React.createClass({
hideToSRUsers: false,

syncError: null, // If the current syncing status is ERROR, the error object, otherwise null.
resizeNotifier: new ResizeNotifier(),
showNotifierToolbar: Notifier.shouldShowToolbar(),
};
return s;
},
Expand Down Expand Up @@ -317,6 +321,9 @@ export default React.createClass({
// N.B. we don't call the whole of setTheme() here as we may be
// racing with the theme CSS download finishing from index.js
Tinter.tint();

// For PersistentElement
this.state.resizeNotifier.on("middlePanelResized", this._dispatchTimelineResize);
},

componentDidMount: function() {
Expand Down Expand Up @@ -399,6 +406,7 @@ export default React.createClass({
dis.unregister(this.dispatcherRef);
window.removeEventListener("focus", this.onFocus);
window.removeEventListener('resize', this.handleResize);
this.state.resizeNotifier.removeListener("middlePanelResized", this._dispatchTimelineResize);
},

componentWillUpdate: function(props, state) {
Expand Down Expand Up @@ -639,8 +647,9 @@ export default React.createClass({
case 'view_invite':
showRoomInviteDialog(payload.roomId);
break;
case 'notifier_enabled':
this.forceUpdate();
case 'notifier_enabled': {
this.setState({showNotifierToolbar: Notifier.shouldShowToolbar()});
}
break;
case 'hide_left_panel':
this.setState({
Expand Down Expand Up @@ -1189,6 +1198,7 @@ export default React.createClass({
*/
_onLoggedIn: async function() {
this.setStateForNewView({view: VIEWS.LOGGED_IN});
this.setState({showNotifierToolbar: Notifier.shouldShowToolbar()});
if (this._is_registered) {
this._is_registered = false;

Expand Down Expand Up @@ -1687,9 +1697,14 @@ export default React.createClass({
dis.dispatch({ action: 'show_right_panel' });
}

this.state.resizeNotifier.notifyWindowResized();
this._windowWidth = window.innerWidth;
},

_dispatchTimelineResize() {
dis.dispatch({ action: 'timeline_resize' });
},

onRoomCreated: function(roomId) {
dis.dispatch({
action: "view_room",
Expand Down
42 changes: 28 additions & 14 deletions src/components/structures/MessagePanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import PropTypes from 'prop-types';
import classNames from 'classnames';
import shouldHideEvent from '../../shouldHideEvent';
import {wantsDateSeparator} from '../../DateUtils';
import dis from "../../dispatcher";
import sdk from '../../index';

import MatrixClientPeg from '../../MatrixClientPeg';
Expand Down Expand Up @@ -628,16 +627,29 @@ module.exports = React.createClass({
_onHeightChanged: function() {
const scrollPanel = this.refs.scrollPanel;
if (scrollPanel) {
scrollPanel.forceUpdate();
scrollPanel.checkScroll();
}
},

_onTypingVisible: function() {
_onTypingShown: function() {
const scrollPanel = this.refs.scrollPanel;
// this will make the timeline grow, so checkScroll
scrollPanel.checkScroll();
if (scrollPanel && scrollPanel.getScrollState().stuckAtBottom) {
// scroll down if at bottom
scrollPanel.preventShrinking();
}
},

_onTypingHidden: function() {
const scrollPanel = this.refs.scrollPanel;
if (scrollPanel) {
// as hiding the typing notifications doesn't
// update the scrollPanel, we tell it to apply
// the shrinking prevention once the typing notifs are hidden
scrollPanel.updatePreventShrinking();
// order is important here as checkScroll will scroll down to
// reveal added padding to balance the notifs disappearing.
scrollPanel.checkScroll();
scrollPanel.blockShrinking();
}
},

Expand All @@ -653,22 +665,18 @@ module.exports = React.createClass({
// update the min-height, so once the last
// person stops typing, no jumping occurs
if (isAtBottom && isTypingVisible) {
scrollPanel.blockShrinking();
scrollPanel.preventShrinking();
}
}
},

clearTimelineHeight: function() {
onTimelineReset: function() {
const scrollPanel = this.refs.scrollPanel;
if (scrollPanel) {
scrollPanel.clearBlockShrinking();
scrollPanel.clearPreventShrinking();
}
},

onResize: function() {
dis.dispatch({ action: 'timeline_resize' }, true);
},

render: function() {
const ScrollPanel = sdk.getComponent("structures.ScrollPanel");
const WhoIsTypingTile = sdk.getComponent("rooms.WhoIsTypingTile");
Expand All @@ -693,7 +701,12 @@ module.exports = React.createClass({

let whoIsTyping;
if (this.props.room) {
whoIsTyping = (<WhoIsTypingTile room={this.props.room} onVisible={this._onTypingVisible} ref="whoIsTyping" />);
whoIsTyping = (<WhoIsTypingTile
room={this.props.room}
onShown={this._onTypingShown}
onHidden={this._onTypingHidden}
ref="whoIsTyping" />
);
}

return (
Expand All @@ -703,7 +716,8 @@ module.exports = React.createClass({
onFillRequest={this.props.onFillRequest}
onUnfillRequest={this.props.onUnfillRequest}
style={style}
stickyBottom={this.props.stickyBottom}>
stickyBottom={this.props.stickyBottom}
resizeNotifier={this.props.resizeNotifier}>
{ topSpinner }
{ this._getEventTiles() }
{ whoIsTyping }
Expand Down
2 changes: 1 addition & 1 deletion src/components/structures/RightPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ export default class RightPanel extends React.Component {
} else if (this.state.phase === RightPanel.Phase.NotificationPanel) {
panel = <NotificationPanel />;
} else if (this.state.phase === RightPanel.Phase.FilePanel) {
panel = <FilePanel roomId={this.props.roomId} />;
panel = <FilePanel roomId={this.props.roomId} resizeNotifier={this.props.resizeNotifier} />;
}

const classes = classNames("mx_RightPanel", "mx_fadable", {
Expand Down
1 change: 0 additions & 1 deletion src/components/structures/RoomDirectory.js
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,6 @@ module.exports = React.createClass({
onFillRequest={ this.onFillRequest }
stickyBottom={false}
startAtBottom={false}
onResize={function() {}}
>
{ scrollpanel_content }
</ScrollPanel>;
Expand Down
Loading