Move sublist auto expand to out from layouts

Co-authored-by: Travis Ralston <travpc@gmail.com>
pull/21833/head
Jorik Schellekens 2020-07-09 18:32:28 +01:00
parent 096cd482f1
commit ade89ab4e9
3 changed files with 22 additions and 35 deletions

View File

@ -191,17 +191,6 @@ export default class RoomList2 extends React.Component<IProps, IState> {
show_room_tile: true, // to make sure the room gets scrolled into view show_room_tile: true, // to make sure the room gets scrolled into view
}); });
} }
} else if (payload.action === Action.StartRoomFilter) {
this.state.layouts.forEach(x => {
x.saveCollapsedState();
x.isCollapsed = false;
});
this.forceUpdate();
} else if (payload.action === Action.StopRoomFilter) {
this.state.layouts.forEach(x => {
x.restoreCollapsedState();
});
this.forceUpdate();
} }
}; };
@ -304,6 +293,7 @@ export default class RoomList2 extends React.Component<IProps, IState> {
isMinimized={this.props.isMinimized} isMinimized={this.props.isMinimized}
onResize={this.props.onResize} onResize={this.props.onResize}
extraBadTilesThatShouldntExist={extraTiles} extraBadTilesThatShouldntExist={extraTiles}
isFiltered={!!this.searchFilter.search}
/> />
); );
} }

View File

@ -47,6 +47,7 @@ import { Direction } from "re-resizable/lib/resizer";
import { polyfillTouchEvent } from "../../../@types/polyfill"; import { polyfillTouchEvent } from "../../../@types/polyfill";
import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore"; import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore";
import RoomListLayoutStore from "../../../stores/room-list/RoomListLayoutStore"; import RoomListLayoutStore from "../../../stores/room-list/RoomListLayoutStore";
import { Action } from "../../../dispatcher/actions";
// TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14231 // TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14231
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14231 // TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14231
@ -78,6 +79,7 @@ interface IProps {
isMinimized: boolean; isMinimized: boolean;
tagId: TagID; tagId: TagID;
onResize: () => void; onResize: () => void;
isFiltered: boolean;
// TODO: Don't use this. It's for community invites, and community invites shouldn't be here. // TODO: Don't use this. It's for community invites, and community invites shouldn't be here.
// You should feel bad if you use this. // You should feel bad if you use this.
@ -92,6 +94,7 @@ interface IState {
notificationState: ListNotificationState; notificationState: ListNotificationState;
contextMenuPosition: PartialDOMRect; contextMenuPosition: PartialDOMRect;
isResizing: boolean; isResizing: boolean;
isExpanded: boolean; // used for the for expand of the sublist when the room list is being filtered
} }
export default class RoomSublist2 extends React.Component<IProps, IState> { export default class RoomSublist2 extends React.Component<IProps, IState> {
@ -109,6 +112,7 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
notificationState: RoomNotificationStateStore.instance.getListState(this.props.tagId), notificationState: RoomNotificationStateStore.instance.getListState(this.props.tagId),
contextMenuPosition: null, contextMenuPosition: null,
isResizing: false, isResizing: false,
isExpanded: this.props.isFiltered ? this.props.isFiltered : !this.layout.isCollapsed
}; };
this.state.notificationState.setRooms(this.props.rooms); this.state.notificationState.setRooms(this.props.rooms);
this.dispatcherRef = defaultDispatcher.register(this.onAction); this.dispatcherRef = defaultDispatcher.register(this.onAction);
@ -123,8 +127,15 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
return Math.min(nVisible, this.numTiles); return Math.min(nVisible, this.numTiles);
} }
public componentDidUpdate() { public componentDidUpdate(prevProps: Readonly<IProps>) {
this.state.notificationState.setRooms(this.props.rooms); this.state.notificationState.setRooms(this.props.rooms);
if (prevProps.isFiltered !== this.props.isFiltered) {
if (this.props.isFiltered) {
this.setState({isExpanded: true});
} else {
this.setState({isExpanded: !this.layout.isCollapsed});
}
}
} }
public componentWillUnmount() { public componentWillUnmount() {
@ -137,10 +148,9 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
// XXX: we have to do this a tick later because we have incorrect intermediate props during a room change // XXX: we have to do this a tick later because we have incorrect intermediate props during a room change
// where we lose the room we are changing from temporarily and then it comes back in an update right after. // where we lose the room we are changing from temporarily and then it comes back in an update right after.
setImmediate(() => { setImmediate(() => {
const isCollapsed = this.layout.isCollapsed;
const roomIndex = this.props.rooms.findIndex((r) => r.roomId === payload.room_id); const roomIndex = this.props.rooms.findIndex((r) => r.roomId === payload.room_id);
if (isCollapsed && roomIndex > -1) { if (!this.state.isExpanded && roomIndex > -1) {
this.toggleCollapsed(); this.toggleCollapsed();
} }
// extend the visible section to include the room if it is entirely invisible // extend the visible section to include the room if it is entirely invisible
@ -295,24 +305,23 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
}; };
private toggleCollapsed = () => { private toggleCollapsed = () => {
this.layout.isCollapsed = !this.layout.isCollapsed; this.layout.isCollapsed = this.state.isExpanded;
this.forceUpdate(); // because the layout doesn't trigger an update this.setState({isExpanded: !this.layout.isCollapsed});
setImmediate(() => this.props.onResize()); // needs to happen when the DOM is updated setImmediate(() => this.props.onResize()); // needs to happen when the DOM is updated
}; };
private onHeaderKeyDown = (ev: React.KeyboardEvent) => { private onHeaderKeyDown = (ev: React.KeyboardEvent) => {
const isCollapsed = this.layout && this.layout.isCollapsed;
switch (ev.key) { switch (ev.key) {
case Key.ARROW_LEFT: case Key.ARROW_LEFT:
ev.stopPropagation(); ev.stopPropagation();
if (!isCollapsed) { if (this.state.isExpanded) {
// On ARROW_LEFT collapse the room sublist if it isn't already // On ARROW_LEFT collapse the room sublist if it isn't already
this.toggleCollapsed(); this.toggleCollapsed();
} }
break; break;
case Key.ARROW_RIGHT: { case Key.ARROW_RIGHT: {
ev.stopPropagation(); ev.stopPropagation();
if (isCollapsed) { if (!this.state.isExpanded) {
// On ARROW_RIGHT expand the room sublist if it isn't already // On ARROW_RIGHT expand the room sublist if it isn't already
this.toggleCollapsed(); this.toggleCollapsed();
} else if (this.sublistRef.current) { } else if (this.sublistRef.current) {
@ -341,7 +350,7 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
}; };
private renderVisibleTiles(): React.ReactElement[] { private renderVisibleTiles(): React.ReactElement[] {
if (this.layout && this.layout.isCollapsed) { if (!this.state.isExpanded) {
// don't waste time on rendering // don't waste time on rendering
return []; return [];
} }
@ -498,7 +507,7 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
const collapseClasses = classNames({ const collapseClasses = classNames({
'mx_RoomSublist2_collapseBtn': true, 'mx_RoomSublist2_collapseBtn': true,
'mx_RoomSublist2_collapseBtn_collapsed': this.layout && this.layout.isCollapsed, 'mx_RoomSublist2_collapseBtn_collapsed': !this.state.isExpanded,
}); });
const classes = classNames({ const classes = classNames({
@ -526,7 +535,7 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
tabIndex={tabIndex} tabIndex={tabIndex}
className="mx_RoomSublist2_headerText" className="mx_RoomSublist2_headerText"
role="treeitem" role="treeitem"
aria-expanded={!this.layout.isCollapsed} aria-expanded={this.state.isExpanded}
aria-level={1} aria-level={1}
onClick={this.onHeaderClick} onClick={this.onHeaderClick}
onContextMenu={this.onContextMenu} onContextMenu={this.onContextMenu}

View File

@ -26,14 +26,12 @@ interface ISerializedListLayout {
numTiles: number; numTiles: number;
showPreviews: boolean; showPreviews: boolean;
collapsed: boolean; collapsed: boolean;
savedCollapsed: boolean;
} }
export class ListLayout { export class ListLayout {
private _n = 0; private _n = 0;
private _previews = false; private _previews = false;
private _collapsed = false; private _collapsed = false;
private _savedCollapsed = false;
constructor(public readonly tagId: TagID) { constructor(public readonly tagId: TagID) {
const serialized = localStorage.getItem(this.key); const serialized = localStorage.getItem(this.key);
@ -43,7 +41,6 @@ export class ListLayout {
this._n = parsed.numTiles; this._n = parsed.numTiles;
this._previews = parsed.showPreviews; this._previews = parsed.showPreviews;
this._collapsed = parsed.collapsed; this._collapsed = parsed.collapsed;
this._savedCollapsed = parsed.savedCollapsed;
} }
} }
@ -136,20 +133,11 @@ export class ListLayout {
localStorage.setItem(this.key, JSON.stringify(this.serialize())); localStorage.setItem(this.key, JSON.stringify(this.serialize()));
} }
public saveCollapsedState() {
this._savedCollapsed = this.isCollapsed;
}
public restoreCollapsedState() {
this.isCollapsed = this._savedCollapsed;
}
private serialize(): ISerializedListLayout { private serialize(): ISerializedListLayout {
return { return {
numTiles: this.visibleTiles, numTiles: this.visibleTiles,
showPreviews: this.showPreviews, showPreviews: this.showPreviews,
collapsed: this.isCollapsed, collapsed: this.isCollapsed,
savedCollapsed: this._savedCollapsed,
}; };
} }
} }