show invites at the top of the room list

This commit is contained in:
Bruno Windels 2021-04-21 17:26:34 +02:00
parent 16df40331b
commit 1cf49688d6
4 changed files with 86 additions and 27 deletions

View file

@ -36,6 +36,7 @@ export class SessionViewModel extends ViewModel {
session: sessionContainer.session,
})));
this._leftPanelViewModel = this.track(new LeftPanelViewModel(this.childOptions({
invites: this._sessionContainer.session.invites,
rooms: this._sessionContainer.session.rooms
})));
this._settingsViewModel = null;

View file

@ -17,37 +17,51 @@ limitations under the License.
import {ViewModel} from "../../ViewModel.js";
import {RoomTileViewModel} from "./RoomTileViewModel.js";
import {InviteTileViewModel} from "./InviteTileViewModel.js";
import {RoomFilter} from "./RoomFilter.js";
import {ApplyMap} from "../../../observable/map/ApplyMap.js";
export class LeftPanelViewModel extends ViewModel {
constructor(options) {
super(options);
const {rooms} = options;
this._roomTileViewModels = rooms.mapValues((room, emitChange) => {
const isOpen = this.navigation.path.get("room")?.value === room.id;
const vm = new RoomTileViewModel(this.childOptions({
isOpen,
room,
emitChange
}));
// need to also update the current vm here as
// we can't call `_open` from the ctor as the map
// is only populated when the view subscribes.
if (isOpen) {
this._currentTileVM?.close();
this._currentTileVM = vm;
}
return vm;
});
this._roomListFilterMap = new ApplyMap(this._roomTileViewModels);
this._roomList = this._roomListFilterMap.sortValues((a, b) => a.compare(b));
const {rooms, invites} = options;
this._tileViewModelsMap = this._mapTileViewModels(rooms, invites);
this._tileViewModelsFilterMap = new ApplyMap(this._tileViewModelsMap);
this._tileViewModels = this._tileViewModelsFilterMap.sortValues((a, b) => a.compare(b));
this._currentTileVM = null;
this._setupNavigation();
this._closeUrl = this.urlCreator.urlForSegment("session");
this._settingsUrl = this.urlCreator.urlForSegment("settings");
}
_mapTileViewModels(rooms, invites) {
const roomTileViewModels = rooms.mapValues((room, emitChange) => {
const isOpen = this.navigation.path.get("room")?.value === room.id;
const vm = new RoomTileViewModel(this.childOptions({isOpen, room, emitChange}));
if (isOpen) {
this._updateCurrentVM(vm);
}
return vm;
});
const inviteTileViewModels = invites.mapValues((invite, emitChange) => {
const isOpen = this.navigation.path.get("room")?.value === invite.id;
const vm = new InviteTileViewModel(this.childOptions({isOpen, invite, emitChange}));
if (isOpen) {
this._updateCurrentVM(vm);
}
return vm;
});
return roomTileViewModels.join(inviteTileViewModels);
}
_updateCurrentVM(vm) {
// need to also update the current vm here as
// we can't call `_open` from the ctor as the map
// is only populated when the view subscribes.
this._currentTileVM?.close();
this._currentTileVM = vm;
}
get closeUrl() {
return this._closeUrl;
}
@ -75,7 +89,7 @@ export class LeftPanelViewModel extends ViewModel {
this._currentTileVM?.close();
this._currentTileVM = null;
if (roomId) {
this._currentTileVM = this._roomTileViewModels.get(roomId);
this._currentTileVM = this._tileViewModelsMap.get(roomId);
this._currentTileVM?.open();
}
}
@ -102,13 +116,13 @@ export class LeftPanelViewModel extends ViewModel {
}
}
get roomList() {
return this._roomList;
get tileViewModels() {
return this._tileViewModels;
}
clearFilter() {
this._roomListFilterMap.setApply(null);
this._roomListFilterMap.applyOnce((roomId, vm) => vm.hidden = false);
this._tileViewModelsFilterMap.setApply(null);
this._tileViewModelsFilterMap.applyOnce((roomId, vm) => vm.hidden = false);
}
setFilter(query) {
@ -117,7 +131,7 @@ export class LeftPanelViewModel extends ViewModel {
this.clearFilter();
} else {
const filter = new RoomFilter(query);
this._roomListFilterMap.setApply((roomId, vm) => {
this._tileViewModelsFilterMap.setApply((roomId, vm) => {
vm.hidden = !filter.matches(vm);
});
}

View file

@ -0,0 +1,37 @@
/*
Copyright 2020 Bruno Windels <bruno@windels.cloud>
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import {TemplateView} from "../../general/TemplateView.js";
import {renderStaticAvatar} from "../../avatar.js";
export class InviteTileView extends TemplateView {
render(t, vm) {
const classes = {
"active": vm => vm.isOpen,
"hidden": vm => vm.hidden
};
return t.li({"className": classes}, [
t.a({href: vm.url}, [
renderStaticAvatar(vm, 32),
t.div({className: "description"}, [
t.div({className: "name"}, vm.name),
t.div({className: "badge highlighted"}, "!"),
])
])
]);
}
}

View file

@ -17,6 +17,7 @@ limitations under the License.
import {ListView} from "../../general/ListView.js";
import {TemplateView} from "../../general/TemplateView.js";
import {RoomTileView} from "./RoomTileView.js";
import {InviteTileView} from "./InviteTileView.js";
class FilterField extends TemplateView {
render(t, options) {
@ -84,9 +85,15 @@ export class LeftPanelView extends TemplateView {
t.view(new ListView(
{
className: "RoomList",
list: vm.roomList,
list: vm.tileViewModels,
},
roomTileVM => new RoomTileView(roomTileVM)
tileVM => {
if (tileVM.kind === "invite") {
return new InviteTileView(tileVM);
} else {
return new RoomTileView(tileVM);
}
}
))
]);
}