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

Commit

Permalink
Merge pull request #2507 from matrix-org/bwindels/roomlistjslayout
Browse files Browse the repository at this point in the history
Redesign: new layout algorithm for room sublists.
  • Loading branch information
bwindels authored Jan 28, 2019
2 parents eb7112c + eaf212d commit 55e0838
Show file tree
Hide file tree
Showing 7 changed files with 379 additions and 73 deletions.
25 changes: 2 additions & 23 deletions res/css/structures/_RoomSubList.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,34 +32,13 @@ limitations under the License.
*/

.mx_RoomSubList {
min-height: 31px;
flex: 0 10000 auto;
display: flex;
flex-direction: column;
}

.mx_RoomSubList.resized-sized {
/*
flex-basis to 0 so sublists
are not shrinking/growing relative
to their content (as would be the case with auto),
as this intervenes with sizing an item exactly
when not available space is available
in the flex container
*/
flex: 1 1 0;
}

.mx_RoomSubList_nonEmpty {
min-height: 74px;

.mx_AutoHideScrollbar_offset {
padding-bottom: 4px;
}
}

.mx_RoomSubList_hidden {
flex: none !important;
.mx_RoomSubList_nonEmpty .mx_AutoHideScrollbar_offset {
padding-bottom: 4px;
}

.mx_RoomSubList_labelContainer {
Expand Down
9 changes: 5 additions & 4 deletions res/css/views/rooms/_RoomList.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ limitations under the License.

.mx_RoomList {
/* take up remaining space below TopLeftMenu */
flex: 1 1 auto;
/* use flexbox to layout sublists */
display: flex;
flex-direction: column;
flex: 1;
min-height: 0;
}

.mx_RoomList .mx_ResizeHandle {
position: relative;
}

.mx_SearchBox {
flex: none;
}
Expand Down
1 change: 1 addition & 0 deletions src/components/structures/LeftPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ const LeftPanel = React.createClass({
<CallPreview ConferenceHandler={VectorConferenceHandler} />
<RoomList
ref={this.collectRoomList}
toolbarShown={this.props.toolbarShown}
collapsed={this.props.collapsed}
searchFilter={this.state.searchFilter}
ConferenceHandler={VectorConferenceHandler} />
Expand Down
1 change: 1 addition & 0 deletions src/components/structures/LoggedInView.js
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,7 @@ const LoggedInView = React.createClass({
<DragDropContext onDragEnd={this._onDragEnd}>
<div ref={this._setResizeContainerRef} className={bodyClasses}>
<LeftPanel
toolbarShown={!!topBar}
collapsed={this.props.collapseLhs || this.state.collapseLhs || false}
disabled={this.props.leftDisabled}
/>
Expand Down
12 changes: 9 additions & 3 deletions src/components/structures/RoomSubList.js
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,12 @@ const RoomSubList = React.createClass({
}
},

setHeight: function(height) {
if (this.refs.subList) {
this.refs.subList.style.height = `${height}px`;
}
},

render: function() {
const len = this.props.list.length + this.props.extraTiles.length;
if (len) {
Expand All @@ -322,13 +328,13 @@ const RoomSubList = React.createClass({
"mx_RoomSubList_nonEmpty": len && !this.state.hidden,
});
if (this.state.hidden) {
return <div className={subListClasses}>
return <div ref="subList" className={subListClasses}>
{this._getHeaderJsx()}
</div>;
} else {
const tiles = this.makeRoomTiles();
tiles.push(...this.props.extraTiles);
return <div className={subListClasses}>
return <div ref="subList" className={subListClasses}>
{this._getHeaderJsx()}
<IndicatorScrollbar ref="scroller" className="mx_RoomSubList_scroll">
{ tiles }
Expand All @@ -343,7 +349,7 @@ const RoomSubList = React.createClass({
}

return (
<div className="mx_RoomSubList">
<div ref="subList" className="mx_RoomSubList">
{ this._getHeaderJsx() }
{ content }
</div>
Expand Down
99 changes: 56 additions & 43 deletions src/components/views/rooms/RoomList.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ import GroupStore from '../../../stores/GroupStore';
import RoomSubList from '../../structures/RoomSubList';
import ResizeHandle from '../elements/ResizeHandle';

import {Resizer, RoomSubListDistributor} from '../../../resizer'
import {Resizer} from '../../../resizer'
import {Layout, Distributor} from '../../../resizer/distributors/roomsublist2';
const HIDE_CONFERENCE_CHANS = true;
const STANDARD_TAGS_REGEX = /^(m\.(favourite|lowpriority|server_notice)|im\.vector\.fake\.(invite|recent|direct|archived))$/;

Expand Down Expand Up @@ -79,6 +80,23 @@ module.exports = React.createClass({
const collapsedJson = window.localStorage.getItem("mx_roomlist_collapsed");
this.subListSizes = sizesJson ? JSON.parse(sizesJson) : {};
this.collapsedState = collapsedJson ? JSON.parse(collapsedJson) : {};
this._layoutSections = [];

this._layout = new Layout((key, size) => {
const subList = this._subListRefs[key];
if (subList) {
subList.setHeight(size);
}
// update overflow indicators
this._checkSubListsOverflow();
// don't store height for collapsed sublists
if(!this.collapsedState[key]) {
this.subListSizes[key] = size;
window.localStorage.setItem("mx_roomlist_sizes",
JSON.stringify(this.subListSizes));
}
}, this.subListSizes, this.collapsedState);

return {
isLoadingLeftRooms: false,
totalRoomCount: null,
Expand Down Expand Up @@ -146,54 +164,38 @@ module.exports = React.createClass({
this._delayedRefreshRoomListLoopCount = 0;
},

_onSubListResize: function(newSize, id) {
if (!id) {
return;
}
if (typeof newSize === "string") {
newSize = Number.MAX_SAFE_INTEGER;
}
if (newSize === null) {
delete this.subListSizes[id];
} else {
this.subListSizes[id] = newSize;
}
window.localStorage.setItem("mx_roomlist_sizes", JSON.stringify(this.subListSizes));
// update overflow indicators
this._checkSubListsOverflow();
},

componentDidMount: function() {
this.dispatcherRef = dis.register(this.onAction);
const cfg = {
onResized: this._onSubListResize,
layout: this._layout,
};
this.resizer = new Resizer(this.resizeContainer, RoomSubListDistributor, cfg);
this.resizer = new Resizer(this.resizeContainer, Distributor, cfg);
this.resizer.setClassNames({
handle: "mx_ResizeHandle",
vertical: "mx_ResizeHandle_vertical",
reverse: "mx_ResizeHandle_reverse"
});

// load stored sizes
Object.keys(this.subListSizes).forEach((key) => {
this._restoreSubListSize(key);
});
this._layout.update(
this._layoutSections,
this.resizeContainer && this.resizeContainer.offsetHeight,
);
this._checkSubListsOverflow();

this.resizer.attach();
window.addEventListener("resize", this.onWindowResize);
this.mounted = true;
},

componentDidUpdate: function(prevProps) {
this._repositionIncomingCallBox(undefined, false);
if (this.props.searchFilter !== prevProps.searchFilter) {
// restore sizes
Object.keys(this.subListSizes).forEach((key) => {
this._restoreSubListSize(key);
});
this._checkSubListsOverflow();
}
// if (this.props.searchFilter !== prevProps.searchFilter) {
// this._checkSubListsOverflow();
// }
this._layout.update(
this._layoutSections,
this.resizeContainer && this.resizeContainer.clientHeight,
);
// TODO: call layout.setAvailableHeight, window height was changed when bannerShown prop was changed
},

onAction: function(payload) {
Expand Down Expand Up @@ -222,6 +224,7 @@ module.exports = React.createClass({
componentWillUnmount: function() {
this.mounted = false;

window.removeEventListener("resize", this.onWindowResize);
dis.unregister(this.dispatcherRef);
if (MatrixClientPeg.get()) {
MatrixClientPeg.get().removeListener("Room", this.onRoom);
Expand Down Expand Up @@ -251,6 +254,17 @@ module.exports = React.createClass({
this._delayedRefreshRoomList.cancelPendingCall();
},

onWindowResize: function() {
if (this.mounted && this._layout && this.resizeContainer &&
Array.isArray(this._layoutSections)
) {
this._layout.update(
this._layoutSections,
this.resizeContainer.offsetHeight
);
}
},

onRoom: function(room) {
this.updateVisibleRooms();
},
Expand Down Expand Up @@ -551,22 +565,16 @@ module.exports = React.createClass({
this.collapsedState[key] = collapsed;
window.localStorage.setItem("mx_roomlist_collapsed", JSON.stringify(this.collapsedState));
// load the persisted size configuration of the expanded sub list
if (!collapsed) {
this._restoreSubListSize(key);
if (collapsed) {
this._layout.collapseSection(key);
} else {
this._layout.expandSection(key, this.subListSizes[key]);
}
// check overflow, as sub lists sizes have changed
// important this happens after calling resize above
this._checkSubListsOverflow();
},

_restoreSubListSize(key) {
const size = this.subListSizes[key];
const handle = this.resizer.forHandleWithId(key);
if (handle) {
handle.resize(size);
}
},

// check overflow for scroll indicator gradient
_checkSubListsOverflow() {
Object.values(this._subListRefs).forEach(l => l.checkOverflow());
Expand All @@ -581,6 +589,7 @@ module.exports = React.createClass({
},

_mapSubListProps: function(subListsProps) {
this._layoutSections = [];
const defaultProps = {
collapsed: this.props.collapsed,
isFiltered: !!this.props.searchFilter,
Expand All @@ -599,6 +608,7 @@ module.exports = React.createClass({
return subListsProps.reduce((components, props, i) => {
props = Object.assign({}, defaultProps, props);
const isLast = i === subListsProps.length - 1;
const len = props.list.length + (props.extraTiles ? props.extraTiles.length : 0);
const {key, label, onHeaderClick, ... otherProps} = props;
const chosenKey = key || label;
const onSubListHeaderClick = (collapsed) => {
Expand All @@ -608,7 +618,10 @@ module.exports = React.createClass({
}
};
const startAsHidden = props.startAsHidden || this.collapsedState[chosenKey];

this._layoutSections.push({
id: chosenKey,
count: len,
});
let subList = (<RoomSubList
ref={this._subListRef.bind(this, chosenKey)}
startAsHidden={startAsHidden}
Expand Down
Loading

0 comments on commit 55e0838

Please sign in to comment.