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 = (
- {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 4f92d0cad6..44fb14476a 100644
--- a/src/components/views/rooms/RoomList.js
+++ b/src/components/views/rooms/RoomList.js
@@ -82,7 +82,11 @@ module.exports = React.createClass({
this.collapsedState = collapsedJson ? JSON.parse(collapsedJson) : {};
this._layoutSections = [];
- this._layout = new Layout((key, size) => {
+ const unfilteredOptions = {
+ allowWhitespace: true,
+ handleHeight: 1,
+ };
+ this._unfilteredlayout = new Layout((key, size) => {
const subList = this._subListRefs[key];
if (subList) {
subList.setHeight(size);
@@ -95,7 +99,19 @@ module.exports = React.createClass({
window.localStorage.setItem("mx_roomlist_sizes",
JSON.stringify(this.subListSizes));
}
- }, this.subListSizes, this.collapsedState);
+ }, 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,
@@ -187,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) {
@@ -617,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,
@@ -625,6 +647,7 @@ module.exports = React.createClass({
let subList = (
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,
@@ -41,6 +38,17 @@ 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;
+
+ this._allowWhitespace = options && options.allowWhitespace;
+ this._handleHeight = (options && options.handleHeight) || 0;
}
setAvailableHeight(newSize) {
@@ -60,7 +68,7 @@ export class Layout {
this._applyNewSize();
}
- update(sections, availableHeight) {
+ update(sections, availableHeight, force = false) {
let heightChanged = false;
if (Number.isFinite(availableHeight) && availableHeight !== this._availableHeight) {
@@ -75,7 +83,7 @@ export class Layout {
return a.id !== b.id || a.count !== b.count;
});
- if (!heightChanged && !sectionsChanged) {
+ if (!heightChanged && !sectionsChanged && !force) {
return;
}
@@ -104,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() {
@@ -130,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);
}
}
@@ -268,6 +277,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 +303,10 @@ class Handle {
}
setHeight(height) {
- this._layout._relayout(this._sectionIndex, height - this._initialHeight);
+ this._layout._setUncommittedSectionHeight(
+ this._sectionIndex,
+ height - this._initialHeight,
+ );
return this;
}