From f2d7f5e4dad8751141e14fc63a66f4945840ca49 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 23 Apr 2021 18:06:38 +0200 Subject: [PATCH] refresh vm when left room receives invite clean up room vm switching in the process --- src/domain/session/RoomGridViewModel.js | 27 +++--- src/domain/session/SessionViewModel.js | 98 ++++++++++------------ src/domain/session/room/InviteViewModel.js | 6 +- src/domain/session/room/RoomViewModel.js | 13 ++- 4 files changed, 70 insertions(+), 74 deletions(-) diff --git a/src/domain/session/RoomGridViewModel.js b/src/domain/session/RoomGridViewModel.js index 535d454a..05c55041 100644 --- a/src/domain/session/RoomGridViewModel.js +++ b/src/domain/session/RoomGridViewModel.js @@ -32,11 +32,10 @@ export class RoomGridViewModel extends ViewModel { this._width = options.width; this._height = options.height; - this._createRoomOrInviteViewModel = options.createRoomOrInviteViewModel; - + this._createRoomViewModel = options.createRoomViewModel; this._selectedIndex = 0; this._viewModels = []; - this._replaceInviteWithRoom = this._replaceInviteWithRoom.bind(this); + this._refreshRoomViewModel = this._refreshRoomViewModel.bind(this); this._setupNavigation(); } @@ -64,7 +63,7 @@ export class RoomGridViewModel extends ViewModel { // initial focus for a room is set by initializeRoomIdsAndTransferVM } - _replaceInviteWithRoom(roomId) { + _refreshRoomViewModel(roomId) { const index = this._viewModels.findIndex(vm => vm?.id === roomId); if (index === -1) { return; @@ -72,7 +71,7 @@ export class RoomGridViewModel extends ViewModel { this._viewModels[index] = this.disposeTracked(this._viewModels[index]); // this will create a RoomViewModel because the invite is already // removed from the collection (see Invite.afterSync) - const roomVM = this._createRoomOrInviteViewModel(roomId, this._replaceInviteWithRoom); + const roomVM = this._createRoomViewModel(roomId, this._refreshRoomViewModel); if (roomVM) { this._viewModels[index] = this.track(roomVM); if (this.focusIndex === index) { @@ -147,7 +146,7 @@ export class RoomGridViewModel extends ViewModel { this._viewModels[i] = this.disposeTracked(vm); } if (newId) { - const newVM = this._createRoomOrInviteViewModel(newId, this._replaceInviteWithRoom); + const newVM = this._createRoomViewModel(newId, this._refreshRoomViewModel); if (newVM) { this._viewModels[i] = this.track(newVM); } @@ -230,7 +229,7 @@ export function tests() { "initialize with duplicate set of rooms": assert => { const navigation = createNavigationForRoom(["c", "a", "b", undefined, "a"], "a"); const gridVM = new RoomGridViewModel({ - createRoomOrInviteViewModel: id => new RoomVMMock(id), + createRoomViewModel: id => new RoomVMMock(id), navigation, width: 3, height: 2, @@ -247,7 +246,7 @@ export function tests() { "transfer room view model": assert => { const navigation = createNavigationForRoom(["a"], "a"); const gridVM = new RoomGridViewModel({ - createRoomOrInviteViewModel: () => assert.fail("no vms should be created"), + createRoomViewModel: () => assert.fail("no vms should be created"), navigation, width: 3, height: 2, @@ -261,7 +260,7 @@ export function tests() { "reject transfer for non-matching room view model": assert => { const navigation = createNavigationForRoom(["a"], "a"); const gridVM = new RoomGridViewModel({ - createRoomOrInviteViewModel: id => new RoomVMMock(id), + createRoomViewModel: id => new RoomVMMock(id), navigation, width: 3, height: 2, @@ -275,7 +274,7 @@ export function tests() { "created & released room view model is not disposed": assert => { const navigation = createNavigationForRoom(["a"], "a"); const gridVM = new RoomGridViewModel({ - createRoomOrInviteViewModel: id => new RoomVMMock(id), + createRoomViewModel: id => new RoomVMMock(id), navigation, width: 3, height: 2, @@ -289,7 +288,7 @@ export function tests() { "transfered & released room view model is not disposed": assert => { const navigation = createNavigationForRoom([undefined, "a"], "a"); const gridVM = new RoomGridViewModel({ - createRoomOrInviteViewModel: () => assert.fail("no vms should be created"), + createRoomViewModel: () => assert.fail("no vms should be created"), navigation, width: 3, height: 2, @@ -304,7 +303,7 @@ export function tests() { "try release non-existing room view model is": assert => { const navigation = createNavigationForEmptyTile([undefined, "b"], 3); const gridVM = new RoomGridViewModel({ - createRoomOrInviteViewModel: id => new RoomVMMock(id), + createRoomViewModel: id => new RoomVMMock(id), navigation, width: 3, height: 2, @@ -316,7 +315,7 @@ export function tests() { "initial focus is set to empty tile": assert => { const navigation = createNavigationForEmptyTile(["a"], 1); const gridVM = new RoomGridViewModel({ - createRoomOrInviteViewModel: id => new RoomVMMock(id), + createRoomViewModel: id => new RoomVMMock(id), navigation, width: 3, height: 2, @@ -328,7 +327,7 @@ export function tests() { "change room ids after creation": assert => { const navigation = createNavigationForRoom(["a", "b"], "a"); const gridVM = new RoomGridViewModel({ - createRoomOrInviteViewModel: id => new RoomVMMock(id), + createRoomViewModel: id => new RoomVMMock(id), navigation, width: 3, height: 2, diff --git a/src/domain/session/SessionViewModel.js b/src/domain/session/SessionViewModel.js index 45b97c3e..6bf334b5 100644 --- a/src/domain/session/SessionViewModel.js +++ b/src/domain/session/SessionViewModel.js @@ -42,8 +42,8 @@ export class SessionViewModel extends ViewModel { this._settingsViewModel = null; this._currentRoomViewModel = null; this._gridViewModel = null; - this._replaceInviteWithRoom = this._replaceInviteWithRoom.bind(this); - this._createRoomOrInviteViewModel = this._createRoomOrInviteViewModel.bind(this); + this._refreshRoomViewModel = this._refreshRoomViewModel.bind(this); + this._createRoomViewModel = this._createRoomViewModel.bind(this); this._setupNavigation(); } @@ -121,7 +121,7 @@ export class SessionViewModel extends ViewModel { this._gridViewModel = this.track(new RoomGridViewModel(this.childOptions({ width: 3, height: 2, - createRoomOrInviteViewModel: this._createRoomOrInviteViewModel, + createRoomViewModel: this._createRoomViewModel, }))); if (this._gridViewModel.initializeRoomIdsAndTransferVM(roomIds, this._currentRoomViewModel)) { this._currentRoomViewModel = this.untrack(this._currentRoomViewModel); @@ -138,7 +138,7 @@ export class SessionViewModel extends ViewModel { if (vm) { this._currentRoomViewModel = this.track(vm); } else { - const newVM = this._createRoomViewModel(currentRoomId.value); + const newVM = this._createRoomViewModel(currentRoomId.value, this._refreshRoomViewModel); if (newVM) { this._currentRoomViewModel = this.track(newVM); } @@ -151,72 +151,62 @@ export class SessionViewModel extends ViewModel { } } - _createRoomViewModel(roomId) { - const room = this._sessionContainer.session.rooms.get(roomId); - if (!room) { - return null; - } - const roomVM = new RoomViewModel(this.childOptions({ - room, - ownUserId: this._sessionContainer.session.user.id, - })); - roomVM.load(); - return roomVM; - } - - _createInviteViewModel(roomId, replaceInviteWithRoom) { + /** + * @param {string} roomId + * @param {function} refreshRoomViewModel passed in as an argument, because the grid needs a different impl of this + * @return {RoomViewModel | InviteViewModel} + */ + _createRoomViewModel(roomId, refreshRoomViewModel) { const invite = this._sessionContainer.session.invites.get(roomId); - if (!invite) { - return null; - } - return new InviteViewModel(this.childOptions({ - invite, - mediaRepository: this._sessionContainer.session.mediaRepository, - closeCallback: accepted => this._closeInvite(roomId, accepted, replaceInviteWithRoom), - })); - } - - _createRoomOrInviteViewModel(roomId, replaceInviteWithRoom) { - const inviteVM = this._createInviteViewModel(roomId, replaceInviteWithRoom); - if (inviteVM) { - return inviteVM; - } - return this._createRoomViewModel(roomId); - } - - _closeInvite(roomId, accepted, replaceInviteWithRoom) { - if (accepted) { - replaceInviteWithRoom(roomId); + if (invite) { + console.log("got invite"); + return new InviteViewModel(this.childOptions({ + invite, + mediaRepository: this._sessionContainer.session.mediaRepository, + refreshRoomViewModel, + })); } else { - // close invite - this.navigation.applyPath(removeRoomFromPath(this.navigation.path, roomId)); + const room = this._sessionContainer.session.rooms.get(roomId); + if (room) { + console.log("got room"); + const roomVM = new RoomViewModel(this.childOptions({ + room, + ownUserId: this._sessionContainer.session.user.id, + refreshRoomViewModel + })); + roomVM.load(); + return roomVM; + } } + return null; } - _replaceInviteWithRoom(roomId) { + /** refresh the room view model after an internal change that needs + to change between invite, room or none state */ + _refreshRoomViewModel(roomId) { this._currentRoomViewModel = this.disposeTracked(this._currentRoomViewModel); - const roomVM = this._createRoomViewModel(roomId); + const roomVM = this._createRoomViewModel(roomId, this._refreshRoomViewModel); if (roomVM) { this._currentRoomViewModel = this.track(roomVM); + } else { + // close room id + this.navigation.applyPath(removeRoomFromPath(this.navigation.path, roomId)); } this.emitChange("activeMiddleViewModel"); } _updateRoom(roomId) { - if (!roomId) { - // closing invite or room view? - if (this._currentRoomViewModel) { - this._currentRoomViewModel = this.disposeTracked(this._currentRoomViewModel); - this.emitChange("activeMiddleViewModel"); - } - return; - } - // already open? + // opening a room and already open? if (this._currentRoomViewModel?.id === roomId) { + console.log("bailing out"); return; } - this._currentRoomViewModel = this.disposeTracked(this._currentRoomViewModel); - const roomVM = this._createRoomOrInviteViewModel(roomId, this._replaceInviteWithRoom); + // close if needed + if (this._currentRoomViewModel) { + this._currentRoomViewModel = this.disposeTracked(this._currentRoomViewModel); + } + // and try opening again + const roomVM = this._createRoomViewModel(roomId, this._refreshRoomViewModel); if (roomVM) { this._currentRoomViewModel = this.track(roomVM); } diff --git a/src/domain/session/room/InviteViewModel.js b/src/domain/session/room/InviteViewModel.js index 2b43feb0..31171b88 100644 --- a/src/domain/session/room/InviteViewModel.js +++ b/src/domain/session/room/InviteViewModel.js @@ -21,10 +21,10 @@ import {ViewModel} from "../../ViewModel.js"; export class InviteViewModel extends ViewModel { constructor(options) { super(options); - const {invite, mediaRepository, closeCallback} = options; + const {invite, mediaRepository, refreshRoomViewModel} = options; this._invite = invite; this._mediaRepository = mediaRepository; - this._closeCallback = closeCallback; + this._refreshRoomViewModel = refreshRoomViewModel; this._onInviteChange = this._onInviteChange.bind(this); this._error = null; this._closeUrl = this.urlCreator.urlUntilSegment("session"); @@ -99,7 +99,7 @@ export class InviteViewModel extends ViewModel { // we're in a grid view, and opening the room doesn't change // the nav path because the url is the same for an // invite and the room. - this._closeCallback(this._invite.accepted); + this._refreshRoomViewModel(this.id); } else { this.emitChange(); } diff --git a/src/domain/session/room/RoomViewModel.js b/src/domain/session/room/RoomViewModel.js index 6a48f9d9..e3e40c2a 100644 --- a/src/domain/session/room/RoomViewModel.js +++ b/src/domain/session/room/RoomViewModel.js @@ -22,9 +22,10 @@ import {ViewModel} from "../../ViewModel.js"; export class RoomViewModel extends ViewModel { constructor(options) { super(options); - const {room, ownUserId} = options; + const {room, ownUserId, refreshRoomViewModel} = options; this._room = room; this._ownUserId = ownUserId; + this._refreshRoomViewModel = refreshRoomViewModel; this._timelineVM = null; this._onRoomChange = this._onRoomChange.bind(this); this._timelineError = null; @@ -65,7 +66,7 @@ export class RoomViewModel extends ViewModel { } catch (err) { if (err.name !== "AbortError") { throw err; - } + } } } @@ -85,7 +86,13 @@ export class RoomViewModel extends ViewModel { // room doesn't tell us yet which fields changed, // so emit all fields originating from summary _onRoomChange() { - this.emitChange("name"); + // if there is now an invite on this (left) room, + // show the invite view by refreshing the view model + if (this._room.invite) { + this._refreshRoomViewModel(this.id); + } else { + this.emitChange("name"); + } } get kind() { return "room"; }