From 1cf49688d65d91c52def50e253956e285bd220b7 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Wed, 21 Apr 2021 17:26:34 +0200 Subject: [PATCH] show invites at the top of the room list --- src/domain/session/SessionViewModel.js | 1 + .../session/leftpanel/LeftPanelViewModel.js | 64 +++++++++++-------- .../ui/session/leftpanel/InviteTileView.js | 37 +++++++++++ .../web/ui/session/leftpanel/LeftPanelView.js | 11 +++- 4 files changed, 86 insertions(+), 27 deletions(-) create mode 100644 src/platform/web/ui/session/leftpanel/InviteTileView.js diff --git a/src/domain/session/SessionViewModel.js b/src/domain/session/SessionViewModel.js index 25e13162..45b97c3e 100644 --- a/src/domain/session/SessionViewModel.js +++ b/src/domain/session/SessionViewModel.js @@ -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; diff --git a/src/domain/session/leftpanel/LeftPanelViewModel.js b/src/domain/session/leftpanel/LeftPanelViewModel.js index de70245a..c9a8b436 100644 --- a/src/domain/session/leftpanel/LeftPanelViewModel.js +++ b/src/domain/session/leftpanel/LeftPanelViewModel.js @@ -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); }); } diff --git a/src/platform/web/ui/session/leftpanel/InviteTileView.js b/src/platform/web/ui/session/leftpanel/InviteTileView.js new file mode 100644 index 00000000..1ac8b40e --- /dev/null +++ b/src/platform/web/ui/session/leftpanel/InviteTileView.js @@ -0,0 +1,37 @@ +/* +Copyright 2020 Bruno Windels +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"}, "!"), + ]) + ]) + ]); + } +} diff --git a/src/platform/web/ui/session/leftpanel/LeftPanelView.js b/src/platform/web/ui/session/leftpanel/LeftPanelView.js index a681b326..5b56fa4a 100644 --- a/src/platform/web/ui/session/leftpanel/LeftPanelView.js +++ b/src/platform/web/ui/session/leftpanel/LeftPanelView.js @@ -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); + } + } )) ]); }