add LeftPanelView(Model) with room filtering
This commit is contained in:
parent
c8125595a7
commit
cac3daca72
5 changed files with 164 additions and 15 deletions
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2020 Bruno Windels <bruno@windels.cloud>
|
Copyright 2020 Bruno Windels <bruno@windels.cloud>
|
||||||
|
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,7 +15,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {RoomTileViewModel} from "./roomlist/RoomTileViewModel.js";
|
import {LeftPanelViewModel} from "./leftpanel/LeftPanelViewModel.js";
|
||||||
import {RoomViewModel} from "./room/RoomViewModel.js";
|
import {RoomViewModel} from "./room/RoomViewModel.js";
|
||||||
import {SessionStatusViewModel} from "./SessionStatusViewModel.js";
|
import {SessionStatusViewModel} from "./SessionStatusViewModel.js";
|
||||||
import {ViewModel} from "../ViewModel.js";
|
import {ViewModel} from "../ViewModel.js";
|
||||||
|
@ -29,22 +30,22 @@ export class SessionViewModel extends ViewModel {
|
||||||
reconnector: sessionContainer.reconnector,
|
reconnector: sessionContainer.reconnector,
|
||||||
session: sessionContainer.session,
|
session: sessionContainer.session,
|
||||||
})));
|
})));
|
||||||
|
this._leftPanelViewModel = new LeftPanelViewModel(this.childOptions({
|
||||||
|
rooms: this._session.rooms,
|
||||||
|
openRoom: this._openRoom.bind(this)
|
||||||
|
}));
|
||||||
this._currentRoomTileViewModel = null;
|
this._currentRoomTileViewModel = null;
|
||||||
this._currentRoomViewModel = null;
|
this._currentRoomViewModel = null;
|
||||||
const roomTileVMs = this._session.rooms.mapValues((room, emitChange) => {
|
|
||||||
return new RoomTileViewModel({
|
|
||||||
room,
|
|
||||||
emitChange,
|
|
||||||
emitOpen: this._openRoom.bind(this)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
this._roomList = roomTileVMs.sortValues((a, b) => a.compare(b));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
this._sessionStatusViewModel.start();
|
this._sessionStatusViewModel.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get leftPanelViewModel() {
|
||||||
|
return this._leftPanelViewModel;
|
||||||
|
}
|
||||||
|
|
||||||
get sessionStatusViewModel() {
|
get sessionStatusViewModel() {
|
||||||
return this._sessionStatusViewModel;
|
return this._sessionStatusViewModel;
|
||||||
}
|
}
|
||||||
|
|
58
src/domain/session/leftpanel/LeftPanelViewModel.js
Normal file
58
src/domain/session/leftpanel/LeftPanelViewModel.js
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 Bruno Windels <bruno@windels.cloud>
|
||||||
|
Copyright 2020 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 {ViewModel} from "../../ViewModel.js";
|
||||||
|
import {RoomTileViewModel} from "./RoomTileViewModel.js";
|
||||||
|
import {RoomFilter} from "./RoomFilter.js";
|
||||||
|
import {ApplyMap} from "../../../observable/map/ApplyMap.js";
|
||||||
|
|
||||||
|
export class LeftPanelViewModel extends ViewModel {
|
||||||
|
constructor(options) {
|
||||||
|
super(options);
|
||||||
|
const {rooms, openRoom} = options;
|
||||||
|
const roomTileVMs = rooms.mapValues((room, emitChange) => {
|
||||||
|
return new RoomTileViewModel({
|
||||||
|
room,
|
||||||
|
emitChange,
|
||||||
|
emitOpen: openRoom
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this._roomListFilterMap = new ApplyMap(roomTileVMs);
|
||||||
|
this._roomList = this._roomListFilterMap.sortValues((a, b) => a.compare(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
get roomList() {
|
||||||
|
return this._roomList;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearFilter() {
|
||||||
|
this._roomListFilterMap.setApply(null);
|
||||||
|
this._roomListFilterMap.applyOnce((roomId, vm) => vm.hidden = false);
|
||||||
|
}
|
||||||
|
|
||||||
|
setFilter(query) {
|
||||||
|
query = query.trim();
|
||||||
|
if (query.length === 0) {
|
||||||
|
this.clearFilter();
|
||||||
|
} else {
|
||||||
|
const filter = new RoomFilter(query);
|
||||||
|
this._roomListFilterMap.setApply((roomId, vm) => {
|
||||||
|
vm.hidden = !filter.matches(vm);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
src/domain/session/leftpanel/RoomFilter.js
Normal file
26
src/domain/session/leftpanel/RoomFilter.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class RoomFilter {
|
||||||
|
constructor(query) {
|
||||||
|
this._parts = query.split(" ").map(s => s.toLowerCase().trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
matches(roomTileVM) {
|
||||||
|
const name = roomTileVM.name.toLowerCase();
|
||||||
|
return this._parts.every(p => name.includes(p));
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,10 +14,20 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
.LeftPanel {
|
.LeftPanel {
|
||||||
overflow-y: auto;
|
display: flex;
|
||||||
overscroll-behavior: contain;
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.LeftPanel .filter {
|
||||||
|
flex: 0;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.LeftPanel .filter input {
|
||||||
|
display: block;
|
||||||
|
flex: 1;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.LeftPanel ul {
|
.LeftPanel ul {
|
||||||
|
@ -26,19 +36,24 @@ limitations under the License.
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.LeftPanel li {
|
.RoomList {
|
||||||
|
overflow-y: auto;
|
||||||
|
overscroll-behavior: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RoomList li {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.LeftPanel div.description {
|
.RoomList .description {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
flex: 1 1 0;
|
flex: 1 1 0;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.LeftPanel .description > .name {
|
.RoomList .description > .name {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|
49
src/ui/web/session/leftpanel/LeftPanelView.js
Normal file
49
src/ui/web/session/leftpanel/LeftPanelView.js
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 Bruno Windels <bruno@windels.cloud>
|
||||||
|
|
||||||
|
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 {ListView} from "../../general/ListView.js";
|
||||||
|
import {TemplateView} from "../../general/TemplateView.js";
|
||||||
|
import {RoomTileView} from "./RoomTileView.js";
|
||||||
|
|
||||||
|
export class LeftPanelView extends TemplateView {
|
||||||
|
render(t, vm) {
|
||||||
|
const filterInput = t.input({
|
||||||
|
type: "text",
|
||||||
|
placeholder: vm.i18n`Filter rooms…`,
|
||||||
|
"aria-label": vm.i18n`Filter rooms by name`,
|
||||||
|
autocomplete: true,
|
||||||
|
name: "room-filter",
|
||||||
|
onInput: event => vm.setFilter(event.target.value),
|
||||||
|
});
|
||||||
|
return t.div({className: "LeftPanel"}, [
|
||||||
|
t.div({className: "filter"}, [
|
||||||
|
filterInput,
|
||||||
|
t.button({onClick: () => {
|
||||||
|
filterInput.value = "";
|
||||||
|
vm.clearFilter();
|
||||||
|
}}, vm.i18n`Clear`)
|
||||||
|
]),
|
||||||
|
t.view(new ListView(
|
||||||
|
{
|
||||||
|
className: "RoomList",
|
||||||
|
list: vm.roomList,
|
||||||
|
onItemClick: (roomTile, event) => roomTile.clicked(event)
|
||||||
|
},
|
||||||
|
roomTileVM => new RoomTileView(roomTileVM)
|
||||||
|
))
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
Reference in a new issue