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

Commit 32ba47b

Browse files
committed
WIP on new room list
1 parent cdb0c24 commit 32ba47b

21 files changed

+798
-51
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@
118118
"@babel/register": "^7.7.4",
119119
"@peculiar/webcrypto": "^1.0.22",
120120
"@types/classnames": "^2.2.10",
121+
"@types/flux": "^3.1.9",
121122
"@types/modernizr": "^3.5.3",
122123
"@types/react": "16.9",
123124
"babel-eslint": "^10.0.3",

src/actions/RoomListActions.js

+9-8
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ limitations under the License.
1515
*/
1616

1717
import { asyncAction } from './actionCreators';
18-
import RoomListStore, {TAG_DM} from '../stores/RoomListStore';
1918
import Modal from '../Modal';
2019
import * as Rooms from '../Rooms';
2120
import { _t } from '../languageHandler';
2221
import * as sdk from '../index';
22+
import {RoomListStoreTempProxy} from "../stores/room-list/RoomListStoreTempProxy";
23+
import {DefaultTagID} from "../stores/room-list/models";
2324

2425
const RoomListActions = {};
2526

@@ -44,7 +45,7 @@ RoomListActions.tagRoom = function(matrixClient, room, oldTag, newTag, oldIndex,
4445

4546
// Is the tag ordered manually?
4647
if (newTag && !newTag.match(/^(m\.lowpriority|im\.vector\.fake\.(invite|recent|direct|archived))$/)) {
47-
const lists = RoomListStore.getRoomLists();
48+
const lists = RoomListStoreTempProxy.getRoomLists();
4849
const newList = [...lists[newTag]];
4950

5051
newList.sort((a, b) => a.tags[newTag].order - b.tags[newTag].order);
@@ -73,11 +74,11 @@ RoomListActions.tagRoom = function(matrixClient, room, oldTag, newTag, oldIndex,
7374
const roomId = room.roomId;
7475

7576
// Evil hack to get DMs behaving
76-
if ((oldTag === undefined && newTag === TAG_DM) ||
77-
(oldTag === TAG_DM && newTag === undefined)
77+
if ((oldTag === undefined && newTag === DefaultTagID.DM) ||
78+
(oldTag === DefaultTagID.DM && newTag === undefined)
7879
) {
7980
return Rooms.guessAndSetDMRoom(
80-
room, newTag === TAG_DM,
81+
room, newTag === DefaultTagID.DM,
8182
).catch((err) => {
8283
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
8384
console.error("Failed to set direct chat tag " + err);
@@ -91,10 +92,10 @@ RoomListActions.tagRoom = function(matrixClient, room, oldTag, newTag, oldIndex,
9192
const hasChangedSubLists = oldTag !== newTag;
9293

9394
// More evilness: We will still be dealing with moving to favourites/low prio,
94-
// but we avoid ever doing a request with TAG_DM.
95+
// but we avoid ever doing a request with DefaultTagID.DM.
9596
//
9697
// if we moved lists, remove the old tag
97-
if (oldTag && oldTag !== TAG_DM &&
98+
if (oldTag && oldTag !== DefaultTagID.DM &&
9899
hasChangedSubLists
99100
) {
100101
const promiseToDelete = matrixClient.deleteRoomTag(
@@ -112,7 +113,7 @@ RoomListActions.tagRoom = function(matrixClient, room, oldTag, newTag, oldIndex,
112113
}
113114

114115
// if we moved lists or the ordering changed, add the new tag
115-
if (newTag && newTag !== TAG_DM &&
116+
if (newTag && newTag !== DefaultTagID.DM &&
116117
(hasChangedSubLists || metaData)
117118
) {
118119
// metaData is the body of the PUT to set the tag, so it must

src/components/structures/LeftPanel.js

+25-9
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import * as VectorConferenceHandler from '../../VectorConferenceHandler';
2626
import SettingsStore from '../../settings/SettingsStore';
2727
import {_t} from "../../languageHandler";
2828
import Analytics from "../../Analytics";
29+
import RoomList2 from "../views/rooms/RoomList2";
2930

3031

3132
const LeftPanel = createReactClass({
@@ -273,6 +274,29 @@ const LeftPanel = createReactClass({
273274
breadcrumbs = (<RoomBreadcrumbs collapsed={this.props.collapsed} />);
274275
}
275276

277+
let roomList = null;
278+
if (SettingsStore.isFeatureEnabled("feature_new_room_list")) {
279+
roomList = <RoomList2
280+
onKeyDown={this._onKeyDown}
281+
resizeNotifier={this.props.resizeNotifier}
282+
collapsed={this.props.collapsed}
283+
searchFilter={this.state.searchFilter}
284+
ref={this.collectRoomList}
285+
onFocus={this._onFocus}
286+
onBlur={this._onBlur}
287+
/>;
288+
} else {
289+
roomList = <RoomList
290+
onKeyDown={this._onKeyDown}
291+
onFocus={this._onFocus}
292+
onBlur={this._onBlur}
293+
ref={this.collectRoomList}
294+
resizeNotifier={this.props.resizeNotifier}
295+
collapsed={this.props.collapsed}
296+
searchFilter={this.state.searchFilter}
297+
ConferenceHandler={VectorConferenceHandler} />;
298+
}
299+
276300
return (
277301
<div className={containerClasses}>
278302
{ tagPanelContainer }
@@ -284,15 +308,7 @@ const LeftPanel = createReactClass({
284308
{ exploreButton }
285309
{ searchBox }
286310
</div>
287-
<RoomList
288-
onKeyDown={this._onKeyDown}
289-
onFocus={this._onFocus}
290-
onBlur={this._onBlur}
291-
ref={this.collectRoomList}
292-
resizeNotifier={this.props.resizeNotifier}
293-
collapsed={this.props.collapsed}
294-
searchFilter={this.state.searchFilter}
295-
ConferenceHandler={VectorConferenceHandler} />
311+
{roomList}
296312
</aside>
297313
</div>
298314
);

src/components/structures/LoggedInView.tsx

+7-6
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import dis from '../../dispatcher';
3131
import sessionStore from '../../stores/SessionStore';
3232
import {MatrixClientPeg, MatrixClientCreds} from '../../MatrixClientPeg';
3333
import SettingsStore from "../../settings/SettingsStore";
34-
import RoomListStore from "../../stores/RoomListStore";
3534

3635
import TagOrderActions from '../../actions/TagOrderActions';
3736
import RoomListActions from '../../actions/RoomListActions';
@@ -42,6 +41,8 @@ import * as KeyboardShortcuts from "../../accessibility/KeyboardShortcuts";
4241
import HomePage from "./HomePage";
4342
import ResizeNotifier from "../../utils/ResizeNotifier";
4443
import PlatformPeg from "../../PlatformPeg";
44+
import { RoomListStoreTempProxy } from "../../stores/room-list/RoomListStoreTempProxy";
45+
import { DefaultTagID } from "../../stores/room-list/models";
4546
// We need to fetch each pinned message individually (if we don't already have it)
4647
// so each pinned message may trigger a request. Limit the number per room for sanity.
4748
// NB. this is just for server notices rather than pinned messages in general.
@@ -297,18 +298,18 @@ class LoggedInView extends React.PureComponent<IProps, IState> {
297298
};
298299

299300
onRoomStateEvents = (ev, state) => {
300-
const roomLists = RoomListStore.getRoomLists();
301-
if (roomLists['m.server_notice'] && roomLists['m.server_notice'].some(r => r.roomId === ev.getRoomId())) {
301+
const roomLists = RoomListStoreTempProxy.getRoomLists();
302+
if (roomLists[DefaultTagID.ServerNotice] && roomLists[DefaultTagID.ServerNotice].some(r => r.roomId === ev.getRoomId())) {
302303
this._updateServerNoticeEvents();
303304
}
304305
};
305306

306307
_updateServerNoticeEvents = async () => {
307-
const roomLists = RoomListStore.getRoomLists();
308-
if (!roomLists['m.server_notice']) return [];
308+
const roomLists = RoomListStoreTempProxy.getRoomLists();
309+
if (!roomLists[DefaultTagID.ServerNotice]) return [];
309310

310311
const pinnedEvents = [];
311-
for (const room of roomLists['m.server_notice']) {
312+
for (const room of roomLists[DefaultTagID.ServerNotice]) {
312313
const pinStateEvent = room.currentState.getStateEvents("m.room.pinned_events", "");
313314

314315
if (!pinStateEvent || !pinStateEvent.getContent().pinned) continue;

src/components/views/dialogs/InviteDialog.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ import {humanizeTime} from "../../../utils/humanize";
3434
import createRoom, {canEncryptToAllUsers} from "../../../createRoom";
3535
import {inviteMultipleToRoom} from "../../../RoomInvite";
3636
import SettingsStore from '../../../settings/SettingsStore';
37-
import RoomListStore, {TAG_DM} from "../../../stores/RoomListStore";
3837
import {Key} from "../../../Keyboard";
38+
import {RoomListStoreTempProxy} from "../../../stores/room-list/RoomListStoreTempProxy";
39+
import {DefaultTagID} from "../../../stores/room-list/models";
3940

4041
export const KIND_DM = "dm";
4142
export const KIND_INVITE = "invite";
@@ -343,10 +344,10 @@ export default class InviteDialog extends React.PureComponent {
343344
_buildRecents(excludedTargetIds: Set<string>): {userId: string, user: RoomMember, lastActive: number} {
344345
const rooms = DMRoomMap.shared().getUniqueRoomsWithIndividuals(); // map of userId => js-sdk Room
345346

346-
// Also pull in all the rooms tagged as TAG_DM so we don't miss anything. Sometimes the
347+
// Also pull in all the rooms tagged as DefaultTagID.DM so we don't miss anything. Sometimes the
347348
// room list doesn't tag the room for the DMRoomMap, but does for the room list.
348-
const taggedRooms = RoomListStore.getRoomLists();
349-
const dmTaggedRooms = taggedRooms[TAG_DM];
349+
const taggedRooms = RoomListStoreTempProxy.getRoomLists();
350+
const dmTaggedRooms = taggedRooms[DefaultTagID.DM];
350351
const myUserId = MatrixClientPeg.get().getUserId();
351352
for (const dmRoom of dmTaggedRooms) {
352353
const otherMembers = dmRoom.getJoinedMembers().filter(u => u.userId !== myUserId);

src/components/views/rooms/RoomList.js

+8-7
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import rate_limited_func from "../../../ratelimitedfunc";
2929
import * as Rooms from '../../../Rooms';
3030
import DMRoomMap from '../../../utils/DMRoomMap';
3131
import TagOrderStore from '../../../stores/TagOrderStore';
32-
import RoomListStore, {TAG_DM} from '../../../stores/RoomListStore';
3332
import CustomRoomTagStore from '../../../stores/CustomRoomTagStore';
3433
import GroupStore from '../../../stores/GroupStore';
3534
import RoomSubList from '../../structures/RoomSubList';
@@ -41,6 +40,8 @@ import * as Receipt from "../../../utils/Receipt";
4140
import {Resizer} from '../../../resizer';
4241
import {Layout, Distributor} from '../../../resizer/distributors/roomsublist2';
4342
import {RovingTabIndexProvider} from "../../../accessibility/RovingTabIndex";
43+
import {RoomListStoreTempProxy} from "../../../stores/room-list/RoomListStoreTempProxy";
44+
import {DefaultTagID} from "../../../stores/room-list/models";
4445
import * as Unread from "../../../Unread";
4546
import RoomViewStore from "../../../stores/RoomViewStore";
4647

@@ -161,7 +162,7 @@ export default createReactClass({
161162
this.updateVisibleRooms();
162163
});
163164

164-
this._roomListStoreToken = RoomListStore.addListener(() => {
165+
this._roomListStoreToken = RoomListStoreTempProxy.addListener(() => {
165166
this._delayedRefreshRoomList();
166167
});
167168

@@ -521,7 +522,7 @@ export default createReactClass({
521522
},
522523

523524
getTagNameForRoomId: function(roomId) {
524-
const lists = RoomListStore.getRoomLists();
525+
const lists = RoomListStoreTempProxy.getRoomLists();
525526
for (const tagName of Object.keys(lists)) {
526527
for (const room of lists[tagName]) {
527528
// Should be impossible, but guard anyways.
@@ -541,7 +542,7 @@ export default createReactClass({
541542
},
542543

543544
getRoomLists: function() {
544-
const lists = RoomListStore.getRoomLists();
545+
const lists = RoomListStoreTempProxy.getRoomLists();
545546

546547
const filteredLists = {};
547548

@@ -773,10 +774,10 @@ export default createReactClass({
773774
incomingCall: incomingCallIfTaggedAs('m.favourite'),
774775
},
775776
{
776-
list: this.state.lists[TAG_DM],
777+
list: this.state.lists[DefaultTagID.DM],
777778
label: _t('Direct Messages'),
778-
tagName: TAG_DM,
779-
incomingCall: incomingCallIfTaggedAs(TAG_DM),
779+
tagName: DefaultTagID.DM,
780+
incomingCall: incomingCallIfTaggedAs(DefaultTagID.DM),
780781
onAddRoom: () => {dis.dispatch({action: 'view_create_chat'});},
781782
addRoomLabel: _t("Start chat"),
782783
},
+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
Copyright 2015, 2016 OpenMarket Ltd
3+
Copyright 2017, 2018 Vector Creations Ltd
4+
Copyright 2020 The Matrix.org Foundation C.I.C.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
import * as React from "react";
20+
import { _t } from "../../../languageHandler";
21+
import { Layout } from '../../../resizer/distributors/roomsublist2';
22+
import { RovingTabIndexProvider } from "../../../accessibility/RovingTabIndex";
23+
import { ResizeNotifier } from "../../../utils/ResizeNotifier";
24+
import RoomListStore from "../../../stores/room-list/RoomListStore2";
25+
26+
interface IProps {
27+
onKeyDown: (ev: React.KeyboardEvent) => void;
28+
onFocus: (ev: React.FocusEvent) => void;
29+
onBlur: (ev: React.FocusEvent) => void;
30+
resizeNotifier: ResizeNotifier;
31+
collapsed: boolean;
32+
searchFilter: string;
33+
}
34+
35+
interface IState {
36+
}
37+
38+
// TODO: Actually write stub
39+
export class RoomSublist2 extends React.Component<any, any> {
40+
public setHeight(size: number) {
41+
}
42+
}
43+
44+
export default class RoomList2 extends React.Component<IProps, IState> {
45+
private sublistRefs: { [tagId: string]: React.RefObject<RoomSublist2> } = {};
46+
private sublistSizes: { [tagId: string]: number } = {};
47+
private sublistCollapseStates: { [tagId: string]: boolean } = {};
48+
private unfilteredLayout: Layout;
49+
private filteredLayout: Layout;
50+
51+
constructor(props: IProps) {
52+
super(props);
53+
54+
this.loadSublistSizes();
55+
this.prepareLayouts();
56+
}
57+
58+
public componentDidMount(): void {
59+
RoomListStore.instance.addListener(() => {
60+
console.log(RoomListStore.instance.orderedLists);
61+
});
62+
}
63+
64+
private loadSublistSizes() {
65+
const sizesJson = window.localStorage.getItem("mx_roomlist_sizes");
66+
if (sizesJson) this.sublistSizes = JSON.parse(sizesJson);
67+
68+
const collapsedJson = window.localStorage.getItem("mx_roomlist_collapsed");
69+
if (collapsedJson) this.sublistCollapseStates = JSON.parse(collapsedJson);
70+
}
71+
72+
private saveSublistSizes() {
73+
window.localStorage.setItem("mx_roomlist_sizes", JSON.stringify(this.sublistSizes));
74+
window.localStorage.setItem("mx_roomlist_collapsed", JSON.stringify(this.sublistCollapseStates));
75+
}
76+
77+
private prepareLayouts() {
78+
this.unfilteredLayout = new Layout((tagId: string, height: number) => {
79+
const sublist = this.sublistRefs[tagId];
80+
if (sublist) sublist.current.setHeight(height);
81+
82+
// TODO: Check overflow
83+
84+
// Don't store a height for collapsed sublists
85+
if (!this.sublistCollapseStates[tagId]) {
86+
this.sublistSizes[tagId] = height;
87+
this.saveSublistSizes();
88+
}
89+
}, this.sublistSizes, this.sublistCollapseStates, {
90+
allowWhitespace: false,
91+
handleHeight: 1,
92+
});
93+
94+
this.filteredLayout = new Layout((tagId: string, height: number) => {
95+
const sublist = this.sublistRefs[tagId];
96+
if (sublist) sublist.current.setHeight(height);
97+
}, null, null, {
98+
allowWhitespace: false,
99+
handleHeight: 0,
100+
});
101+
}
102+
103+
private collectSublistRef(tagId: string, ref: React.RefObject<RoomSublist2>) {
104+
if (!ref) {
105+
delete this.sublistRefs[tagId];
106+
} else {
107+
this.sublistRefs[tagId] = ref;
108+
}
109+
}
110+
111+
public render() {
112+
return (
113+
<RovingTabIndexProvider handleHomeEnd={true} onKeyDown={this.props.onKeyDown}>
114+
{({onKeyDownHandler}) => (
115+
<div
116+
onFocus={this.props.onFocus}
117+
onBlur={this.props.onBlur}
118+
onKeyDown={onKeyDownHandler}
119+
className="mx_RoomList"
120+
role="tree"
121+
aria-label={_t("Rooms")}
122+
// Firefox sometimes makes this element focusable due to
123+
// overflow:scroll;, so force it out of tab order.
124+
tabIndex={-1}
125+
>{_t("TODO")}</div>
126+
)}
127+
</RovingTabIndexProvider>
128+
);
129+
}
130+
}

0 commit comments

Comments
 (0)