diff --git a/src/components/structures/IndicatorScrollbar.js b/src/components/structures/IndicatorScrollbar.js index 76e6dfa96a..2470f9fa11 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 a45b8f257f..2f2df42a1b 100644 --- a/src/components/views/rooms/RoomBreadcrumbs.js +++ b/src/components/views/rooms/RoomBreadcrumbs.js @@ -33,7 +33,13 @@ const MAX_ROOMS = 20; export default class RoomBreadcrumbs extends React.Component { constructor(props) { super(props); - this.state = {rooms: []}; + + const tolerances = SettingsStore.getValue("breadcrumb_scroll_tolerances"); + this.state = {rooms: [], scrollTolerances: tolerances}; + + // Record this for debugging purposes + console.log("Breadcrumbs scroll tolerances:", tolerances); + this.onAction = this.onAction.bind(this); this._dispatcherRef = null; } @@ -334,7 +340,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 35baa718b9..dcd6f91aef 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.8, + }, + }, "analyticsOptIn": { supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, displayName: _td('Send analytics data'),