From 88f25dec4dc03c1360f3964c74cd04ef53fd94f1 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 28 Jan 2019 17:52:46 +0100 Subject: [PATCH 1/3] don't over-constraint layout while resizing adapting the approach taken in the prototype --- src/resizer/distributors/roomsublist2.js | 29 +++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/resizer/distributors/roomsublist2.js b/src/resizer/distributors/roomsublist2.js index d6bf8d6c7a..57a07ecda3 100644 --- a/src/resizer/distributors/roomsublist2.js +++ b/src/resizer/distributors/roomsublist2.js @@ -41,6 +41,14 @@ export class Layout { this._sectionHeights = Object.assign({}, initialSizes); // in-progress heights, while dragging. Committed on mouse-up. this._heights = []; + // use while manually resizing to cancel + // the resize for a given mouse position + // when the previous resize made the layout + // constrained + this._clampedOffset = 0; + // used while manually resizing, to clear + // _clampedOffset when the direction of resizing changes + this._lastOffset = 0; } setAvailableHeight(newSize) { @@ -268,6 +276,22 @@ export class Layout { this._sectionHeights[section.id] = this._heights[i]; }); } + + _setUncommittedSectionHeight(sectionIndex, offset) { + if (Math.sign(offset) != Math.sign(this._lastOffset)) { + this._clampedOffset = undefined; + } + if (this._clampedOffset !== undefined) { + if (offset < 0 && offset < this._clampedOffset) { + return; + } + if (offset > 0 && offset > this._clampedOffset) { + return; + } + } + this._clampedOffset = this._relayout(sectionIndex, offset); + this._lastOffset = offset; + } } class Handle { @@ -278,7 +302,10 @@ class Handle { } setHeight(height) { - this._layout._relayout(this._sectionIndex, height - this._initialHeight); + this._layout._setUncommittedSectionHeight( + this._sectionIndex, + height - this._initialHeight, + ); return this; } From 8d1e105b503392764c7a989b530ab3f6705fc8c0 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 28 Jan 2019 18:02:36 +0100 Subject: [PATCH 2/3] add option for whitespace behaviour and handle height --- src/components/views/rooms/RoomList.js | 6 +++++- src/resizer/distributors/roomsublist2.js | 13 +++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index f79ca64869..8818c9026e 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -82,6 +82,10 @@ module.exports = React.createClass({ this.collapsedState = collapsedJson ? JSON.parse(collapsedJson) : {}; this._layoutSections = []; + const options = { + allowWhitespace: false, + handleHeight: 1, + }; this._layout = new Layout((key, size) => { const subList = this._subListRefs[key]; if (subList) { @@ -95,7 +99,7 @@ module.exports = React.createClass({ window.localStorage.setItem("mx_roomlist_sizes", JSON.stringify(this.subListSizes)); } - }, this.subListSizes, this.collapsedState); + }, this.subListSizes, this.collapsedState, options); return { isLoadingLeftRooms: false, diff --git a/src/resizer/distributors/roomsublist2.js b/src/resizer/distributors/roomsublist2.js index 57a07ecda3..6f607f2fe8 100644 --- a/src/resizer/distributors/roomsublist2.js +++ b/src/resizer/distributors/roomsublist2.js @@ -16,9 +16,6 @@ limitations under the License. import FixedDistributor from "./fixed"; -// const allowWhitespace = true; -const handleHeight = 1; - function clamp(height, min, max) { if (height > max) return max; if (height < min) return min; @@ -26,7 +23,7 @@ function clamp(height, min, max) { } export class Layout { - constructor(applyHeight, initialSizes, collapsedState) { + constructor(applyHeight, initialSizes, collapsedState, options) { // callback to set height of section this._applyHeight = applyHeight; // list of {id, count} objects, @@ -49,6 +46,9 @@ export class Layout { // used while manually resizing, to clear // _clampedOffset when the direction of resizing changes this._lastOffset = 0; + + this._allowWhitespace = options && options.allowWhitespace; + this._handleHeight = (options && options.handleHeight) || 0; } setAvailableHeight(newSize) { @@ -112,7 +112,7 @@ export class Layout { const collapsed = this._collapsedState[section.id]; return count + (collapsed ? 0 : 1); }, 0); - return this._availableHeight - ((nonCollapsedSectionCount - 1) * handleHeight); + return this._availableHeight - ((nonCollapsedSectionCount - 1) * this._handleHeight); } _applyNewSize() { @@ -138,9 +138,10 @@ export class Layout { if (collapsed) { return this._sectionHeight(0); + } else if (!this._allowWhitespace) { + return this._sectionHeight(section.count); } else { return 100000; - // return this._sectionHeight(section.count); } } From 529c48d1b0e478b690c5e83314c2c79a64ee975d Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Mon, 28 Jan 2019 18:28:04 +0100 Subject: [PATCH 3/3] avoid whitespace and expand all matching section when filtering --- src/components/structures/RoomSubList.js | 24 ++++++++------- src/components/views/rooms/RoomList.js | 37 ++++++++++++++++++------ src/resizer/distributors/roomsublist2.js | 4 +-- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/src/components/structures/RoomSubList.js b/src/components/structures/RoomSubList.js index 852dddd063..676e0e6976 100644 --- a/src/components/structures/RoomSubList.js +++ b/src/components/structures/RoomSubList.js @@ -84,7 +84,7 @@ const RoomSubList = React.createClass({ // The dataset elements are added in the RoomList _initAndPositionStickyHeaders method isCollapsableOnClick: function() { const stuck = this.refs.header.dataset.stuck; - if (this.state.hidden || stuck === undefined || stuck === "none") { + if (!this.props.forceExpand && (this.state.hidden || stuck === undefined || stuck === "none")) { return true; } else { return false; @@ -238,7 +238,7 @@ const RoomSubList = React.createClass({ } }, - _getHeaderJsx: function() { + _getHeaderJsx: function(isCollapsed) { const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const subListNotifications = this.roomNotificationCount(); const subListNotifCount = subListNotifications[0]; @@ -287,8 +287,8 @@ const RoomSubList = React.createClass({ if (len) { const chevronClasses = classNames({ 'mx_RoomSubList_chevron': true, - 'mx_RoomSubList_chevronRight': this.state.hidden, - 'mx_RoomSubList_chevronDown': !this.state.hidden, + 'mx_RoomSubList_chevronRight': isCollapsed, + 'mx_RoomSubList_chevronDown': !isCollapsed, }); chevron = (
); } @@ -321,21 +321,23 @@ const RoomSubList = React.createClass({ render: function() { const len = this.props.list.length + this.props.extraTiles.length; + const isCollapsed = this.state.hidden && !this.props.forceExpand; if (len) { const subListClasses = classNames({ "mx_RoomSubList": true, - "mx_RoomSubList_hidden": this.state.hidden, - "mx_RoomSubList_nonEmpty": len && !this.state.hidden, + "mx_RoomSubList_hidden": isCollapsed, + "mx_RoomSubList_nonEmpty": len && !isCollapsed, }); - if (this.state.hidden) { + + if (isCollapsed) { return
- {this._getHeaderJsx()} + {this._getHeaderJsx(isCollapsed)}
; } else { const tiles = this.makeRoomTiles(); tiles.push(...this.props.extraTiles); return
- {this._getHeaderJsx()} + {this._getHeaderJsx(isCollapsed)} { tiles } @@ -344,13 +346,13 @@ const RoomSubList = React.createClass({ } else { const Loader = sdk.getComponent("elements.Spinner"); let content; - if (this.props.showSpinner && !this.state.hidden) { + if (this.props.showSpinner && !isCollapsed) { content = ; } return (
- { this._getHeaderJsx() } + { this._getHeaderJsx(isCollapsed) } { content }
); diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 8818c9026e..03aa6766c4 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -82,11 +82,11 @@ module.exports = React.createClass({ this.collapsedState = collapsedJson ? JSON.parse(collapsedJson) : {}; this._layoutSections = []; - const options = { - allowWhitespace: false, + const unfilteredOptions = { + allowWhitespace: true, handleHeight: 1, }; - this._layout = new Layout((key, size) => { + this._unfilteredlayout = new Layout((key, size) => { const subList = this._subListRefs[key]; if (subList) { subList.setHeight(size); @@ -99,7 +99,19 @@ module.exports = React.createClass({ window.localStorage.setItem("mx_roomlist_sizes", JSON.stringify(this.subListSizes)); } - }, this.subListSizes, this.collapsedState, options); + }, this.subListSizes, this.collapsedState, unfilteredOptions); + + this._filteredLayout = new Layout((key, size) => { + const subList = this._subListRefs[key]; + if (subList) { + subList.setHeight(size); + } + }, null, null, { + allowWhitespace: false, + handleHeight: 0, + }); + + this._layout = this._unfilteredlayout; return { isLoadingLeftRooms: false, @@ -191,15 +203,21 @@ module.exports = React.createClass({ }, componentDidUpdate: function(prevProps) { + let forceLayoutUpdate = false; this._repositionIncomingCallBox(undefined, false); - // if (this.props.searchFilter !== prevProps.searchFilter) { - // this._checkSubListsOverflow(); - // } + if (!this.props.searchFilter && prevProps.searchFilter) { + this._layout = this._unfilteredlayout; + forceLayoutUpdate = true; + } else if (this.props.searchFilter && !prevProps.searchFilter) { + this._layout = this._filteredLayout; + forceLayoutUpdate = true; + } this._layout.update( this._layoutSections, this.resizeContainer && this.resizeContainer.clientHeight, + forceLayoutUpdate, ); - // TODO: call layout.setAvailableHeight, window height was changed when bannerShown prop was changed + this._checkSubListsOverflow(); }, onAction: function(payload) { @@ -621,7 +639,7 @@ module.exports = React.createClass({ onHeaderClick(collapsed); } }; - const startAsHidden = props.startAsHidden || this.collapsedState[chosenKey]; + let startAsHidden = props.startAsHidden || this.collapsedState[chosenKey]; this._layoutSections.push({ id: chosenKey, count: len, @@ -629,6 +647,7 @@ module.exports = React.createClass({ let subList = (