167 lines
5 KiB
JavaScript
167 lines
5 KiB
JavaScript
/*
|
|
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";
|
|
|
|
export class RoomGridViewModel extends ViewModel {
|
|
constructor(options) {
|
|
super(options);
|
|
|
|
this._width = options.width;
|
|
this._height = options.height;
|
|
this._createRoomViewModel = options.createRoomViewModel;
|
|
|
|
this._selectedIndex = 0;
|
|
this._viewModels = (options.roomIds || []).map(roomId => {
|
|
if (roomId) {
|
|
const vm = this._createRoomViewModel(roomId);
|
|
if (vm) {
|
|
return this.track(vm);
|
|
}
|
|
}
|
|
});
|
|
this._setupNavigation();
|
|
}
|
|
|
|
_setupNavigation() {
|
|
const focusTileIndex = this.navigation.observe("empty-grid-tile");
|
|
this.track(focusTileIndex.subscribe(index => {
|
|
if (typeof index === "number") {
|
|
this._setFocusIndex(index);
|
|
}
|
|
}));
|
|
if (typeof focusTileIndex.get() === "number") {
|
|
this._selectedIndex = focusTileIndex.get();
|
|
}
|
|
|
|
const focusedRoom = this.navigation.observe("room");
|
|
this.track(focusedRoom.subscribe(roomId => {
|
|
if (roomId) {
|
|
this._openRoom(roomId);
|
|
}
|
|
}));
|
|
if (focusedRoom.get()) {
|
|
const index = this._viewModels.findIndex(vm => vm && vm.id === focusedRoom.get());
|
|
if (index >= 0) {
|
|
this._selectedIndex = index;
|
|
}
|
|
}
|
|
}
|
|
|
|
roomViewModelAt(i) {
|
|
return this._viewModels[i];
|
|
}
|
|
|
|
get focusIndex() {
|
|
return this._selectedIndex;
|
|
}
|
|
|
|
get width() {
|
|
return this._width;
|
|
}
|
|
|
|
get height() {
|
|
return this._height;
|
|
}
|
|
|
|
focusTile(index) {
|
|
if (index === this._selectedIndex) {
|
|
return;
|
|
}
|
|
let path = this.navigation.path;
|
|
const vm = this._viewModels[index];
|
|
if (vm) {
|
|
path = path.with(this.navigation.segment("room", vm.id));
|
|
} else {
|
|
path = path.with(this.navigation.segment("empty-grid-tile", index));
|
|
}
|
|
let url = this.urlRouter.urlForPath(path);
|
|
url = this.urlRouter.applyUrl(url);
|
|
this.urlRouter.history.pushUrl(url);
|
|
}
|
|
|
|
/** called from SessionViewModel */
|
|
setRoomIds(roomIds) {
|
|
let changed = false;
|
|
const len = this._height * this._width;
|
|
for (let i = 0; i < len; i += 1) {
|
|
const newId = roomIds[i];
|
|
const vm = this._viewModels[i];
|
|
if (newId && !vm) {
|
|
this._viewModels[i] = this.track(this._createRoomViewModel(newId));
|
|
changed = true;
|
|
} else if (newId !== vm?.id) {
|
|
this._viewModels[i] = this.disposeTracked(this._viewModels[i]);
|
|
if (newId) {
|
|
this._viewModels[i] = this.track(this._createRoomViewModel(newId));
|
|
}
|
|
changed = true;
|
|
}
|
|
}
|
|
if (changed) {
|
|
this.emitChange();
|
|
}
|
|
}
|
|
|
|
/** called from SessionViewModel */
|
|
transferRoomViewModel(index, roomVM) {
|
|
const oldVM = this._viewModels[index];
|
|
this.disposeTracked(oldVM);
|
|
this._viewModels[index] = this.track(roomVM);
|
|
}
|
|
|
|
/** called from SessionViewModel */
|
|
releaseRoomViewModel(roomId) {
|
|
const index = this._viewModels.findIndex(vm => vm.id === roomId);
|
|
if (index !== -1) {
|
|
const vm = this._viewModels[index];
|
|
this.untrack(vm);
|
|
this._viewModels[index] = null;
|
|
return vm;
|
|
}
|
|
}
|
|
|
|
_setFocusIndex(idx) {
|
|
if (idx === this._selectedIndex || idx >= (this._width * this._height)) {
|
|
return;
|
|
}
|
|
this._selectedIndex = idx;
|
|
const vm = this._viewModels[this._selectedIndex];
|
|
vm?.focus();
|
|
this.emitChange("focusedIndex");
|
|
}
|
|
|
|
_setFocusRoom(roomId) {
|
|
const index = this._viewModels.findIndex(vm => vm.id === roomId);
|
|
if (index >= 0) {
|
|
this._setFocusIndex(index);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
_openRoom(roomId) {
|
|
if (!this._setFocusRoom(roomId)) {
|
|
// replace vm at focused index
|
|
const vm = this._viewModels[this._selectedIndex];
|
|
if (vm) {
|
|
this.disposeTracked(vm);
|
|
}
|
|
this._viewModels[this._selectedIndex] = this.track(this._createRoomViewModel(roomId));
|
|
this.emitChange();
|
|
}
|
|
}
|
|
}
|