From 46f9d681136d259e38f180203a7b73fc3d2605fe Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 8 Apr 2019 10:53:09 -0600 Subject: [PATCH] Add some tolerances to breadcrumb scrolling See https://github.com/vector-im/riot-web/issues/9400 See https://github.com/vector-im/riot-web/issues/9394 Tolerances are defined as a device-only setting to give advanced users an option to override the values. No UI is exposed for this. The default values are picked for assumptions on comfort, however as people change the tolerances themselves the defaults may need to change. --- .../structures/IndicatorScrollbar.js | 21 ++++++++++++++++++- src/components/views/rooms/RoomBreadcrumbs.js | 8 +++++-- src/settings/Settings.js | 7 +++++++ 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/components/structures/IndicatorScrollbar.js b/src/components/structures/IndicatorScrollbar.js index 76e6dfa96a78..2470f9fa117f 100644 --- a/src/components/structures/IndicatorScrollbar.js +++ b/src/components/structures/IndicatorScrollbar.js @@ -29,6 +29,13 @@ export default class IndicatorScrollbar extends React.Component { // scroll horizontally rather than vertically. This should only be used on components // with no vertical scroll opportunity. verticalScrollsHorizontally: PropTypes.bool, + + // An object containing 2 numbers: xyThreshold and yReduction. xyThreshold is the amount + // of horizontal movement required in order to ignore any vertical changes in scroll, and + // only applies when verticalScrollsHorizontally is true. yReduction is the factor to + // multiply the vertical delta by when verticalScrollsHorizontally is true. The default + // behaviour is to have an xyThreshold of infinity and a yReduction of 0.8 + scrollTolerances: PropTypes.object, }; constructor(props) { @@ -120,8 +127,20 @@ export default class IndicatorScrollbar extends React.Component { onMouseWheel = (e) => { if (this.props.verticalScrollsHorizontally && this._scrollElement) { + const xyThreshold = this.props.scrollTolerances + ? this.props.scrollTolerances.xyThreshold + : Number.MAX_SAFE_INTEGER; + + const yReduction = this.props.scrollTolerances + ? this.props.scrollTolerances.yReduction + : 0.8; + + // Don't apply vertical motion to horizontal scrolls. This is meant to eliminate + // trackpads causing excessive scroll motion. + if (e.deltaX >= xyThreshold) return; + // noinspection JSSuspiciousNameCombination - this._scrollElement.scrollLeft += e.deltaY / 2; // divide by 2 to reduce harshness + this._scrollElement.scrollLeft += e.deltaY * yReduction; } }; diff --git a/src/components/views/rooms/RoomBreadcrumbs.js b/src/components/views/rooms/RoomBreadcrumbs.js index a45b8f257fb5..334aac756f73 100644 --- a/src/components/views/rooms/RoomBreadcrumbs.js +++ b/src/components/views/rooms/RoomBreadcrumbs.js @@ -33,7 +33,10 @@ const MAX_ROOMS = 20; export default class RoomBreadcrumbs extends React.Component { constructor(props) { super(props); - this.state = {rooms: []}; + this.state = { + rooms: [], + scrollTolerances: SettingsStore.getValue("breadcrumb_scroll_tolerances"), + }; this.onAction = this.onAction.bind(this); this._dispatcherRef = null; } @@ -334,7 +337,8 @@ export default class RoomBreadcrumbs extends React.Component { }); return ( + trackHorizontalOverflow={true} verticalScrollsHorizontally={true} + scrollTolerances={this.state.scrollTolerances}> { avatars } ); diff --git a/src/settings/Settings.js b/src/settings/Settings.js index 35baa718b926..aad459e15f92 100644 --- a/src/settings/Settings.js +++ b/src/settings/Settings.js @@ -262,6 +262,13 @@ export const SETTINGS = { supportedLevels: ['account'], default: [], }, + "breadcrumb_scroll_tolerances": { + supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS, + default: { + xyThreshold: 10, + yReduction: 0.2, + }, + }, "analyticsOptIn": { supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, displayName: _td('Send analytics data'),