diff --git a/src/domain/session/RoomGridViewModel.js b/src/domain/session/RoomGridViewModel.js index d8dc38ab..40b7192c 100644 --- a/src/domain/session/RoomGridViewModel.js +++ b/src/domain/session/RoomGridViewModel.js @@ -25,15 +25,39 @@ export class RoomGridViewModel extends ViewModel { this._viewModels = []; } - roomViewModelAt(idx) { - return this._viewModels[idx]?.vm; + _posToIdx(x, y) { + return (y * this.width) + x; } - get focusedIndex() { - return this._selectedIndex; + _idxToX(idx) { + return idx % this.width; } - setFocusedIndex(idx) { + _idxToY(idx) { + return Math.floor(idx / this.width); + } + + roomViewModelAt(x, y) { + return this._viewModels[this._posToIdx(x, y)]?.vm; + } + + get focusX() { + return this._idxToX(this._selectedIndex); + } + + get focusY() { + return this._idxToY(this._selectedIndex); + } + + isFocusAt(x, y) { + return this._posToIdx(x, y) === this._selectedIndex; + } + + setFocusAt(x, y) { + this._setFocusedIndex(this._posToIdx(x, y)); + } + + _setFocusedIndex(idx) { if (idx === this._selectedIndex) { return; } @@ -72,8 +96,13 @@ export class RoomGridViewModel extends ViewModel { /** * @package */ - roomIndex(roomId) { - return this._viewModels.findIndex(vms => vms?.vm._room.id === roomId); + tryFocusRoom(roomId) { + const index = this._viewModels.findIndex(vms => vms?.vm._room.id === roomId); + if (index >= 0) { + this._setFocusedIndex(index); + return true; + } + return false; } /** diff --git a/src/domain/session/SessionViewModel.js b/src/domain/session/SessionViewModel.js index 082d738f..e6965c8c 100644 --- a/src/domain/session/SessionViewModel.js +++ b/src/domain/session/SessionViewModel.js @@ -109,14 +109,8 @@ export class SessionViewModel extends ViewModel { } _openRoom(room, roomTileVM) { - // for now, we don't support having the same room opened more than once, - // so bail out if we already have the room open - if (this._gridViewModel) { - const roomIndex = this._gridViewModel.roomIndex(room.id); - if (roomIndex >= 0) { - this._gridViewModel.setFocusedIndex(roomIndex); - return; - } + if (this._gridViewModel?.tryFocusRoom(room.id)) { + return; } else if (this._currentRoomViewModel?._room.id === room.id) { return; } diff --git a/src/ui/web/session/RoomGridView.js b/src/ui/web/session/RoomGridView.js index d87d1e9d..f954c4f1 100644 --- a/src/ui/web/session/RoomGridView.js +++ b/src/ui/web/session/RoomGridView.js @@ -20,24 +20,27 @@ import {TemplateView} from "../general/TemplateView.js"; export class RoomGridView extends TemplateView { render(t, vm) { - const roomViews = []; - const len = vm.width * vm.height; - for (let i = 0; i < len; i+=1) { - roomViews[i] = t.div({ - onClick: () => vm.setFocusedIndex(i), - onFocusin: () => vm.setFocusedIndex(i), - className: {focused: vm => vm.focusedIndex === i}, - },t.mapView(vm => vm.roomViewModelAt(i), roomVM => { - if (roomVM) { - return new RoomView(roomVM); - } else { - return new RoomPlaceholderView(); - } - })) + const children = []; + for (let y = 0; y < vm.height; y+=1) { + for (let x = 0; x < vm.width; x+=1) { + children.push(t.div({ + onClick: () => vm.setFocusAt(x, y), + onFocusin: () => vm.setFocusAt(x, y), + className: "container", + style: `--column: ${x + 1}; --row: ${y + 1}` + },t.mapView(vm => vm.roomViewModelAt(x, y), roomVM => { + if (roomVM) { + return new RoomView(roomVM); + } else { + return new RoomPlaceholderView(); + } + }))); + } } + children.push(t.div({className: "focus-ring", style: vm => `--column: ${vm.focusX + 1}; --row: ${vm.focusY + 1}`})); return t.div({ className: "RoomGridView", style: `--columns: ${vm.width}; --rows: ${vm.height}` - }, roomViews); + }, children); } }