refresh vm when left room receives invite

clean up room vm switching in the process
This commit is contained in:
Bruno Windels 2021-04-23 18:06:38 +02:00
parent 827075bc37
commit f2d7f5e4da
4 changed files with 70 additions and 74 deletions

View file

@ -32,11 +32,10 @@ export class RoomGridViewModel extends ViewModel {
this._width = options.width; this._width = options.width;
this._height = options.height; this._height = options.height;
this._createRoomOrInviteViewModel = options.createRoomOrInviteViewModel; this._createRoomViewModel = options.createRoomViewModel;
this._selectedIndex = 0; this._selectedIndex = 0;
this._viewModels = []; this._viewModels = [];
this._replaceInviteWithRoom = this._replaceInviteWithRoom.bind(this); this._refreshRoomViewModel = this._refreshRoomViewModel.bind(this);
this._setupNavigation(); this._setupNavigation();
} }
@ -64,7 +63,7 @@ export class RoomGridViewModel extends ViewModel {
// initial focus for a room is set by initializeRoomIdsAndTransferVM // initial focus for a room is set by initializeRoomIdsAndTransferVM
} }
_replaceInviteWithRoom(roomId) { _refreshRoomViewModel(roomId) {
const index = this._viewModels.findIndex(vm => vm?.id === roomId); const index = this._viewModels.findIndex(vm => vm?.id === roomId);
if (index === -1) { if (index === -1) {
return; return;
@ -72,7 +71,7 @@ export class RoomGridViewModel extends ViewModel {
this._viewModels[index] = this.disposeTracked(this._viewModels[index]); this._viewModels[index] = this.disposeTracked(this._viewModels[index]);
// this will create a RoomViewModel because the invite is already // this will create a RoomViewModel because the invite is already
// removed from the collection (see Invite.afterSync) // removed from the collection (see Invite.afterSync)
const roomVM = this._createRoomOrInviteViewModel(roomId, this._replaceInviteWithRoom); const roomVM = this._createRoomViewModel(roomId, this._refreshRoomViewModel);
if (roomVM) { if (roomVM) {
this._viewModels[index] = this.track(roomVM); this._viewModels[index] = this.track(roomVM);
if (this.focusIndex === index) { if (this.focusIndex === index) {
@ -147,7 +146,7 @@ export class RoomGridViewModel extends ViewModel {
this._viewModels[i] = this.disposeTracked(vm); this._viewModels[i] = this.disposeTracked(vm);
} }
if (newId) { if (newId) {
const newVM = this._createRoomOrInviteViewModel(newId, this._replaceInviteWithRoom); const newVM = this._createRoomViewModel(newId, this._refreshRoomViewModel);
if (newVM) { if (newVM) {
this._viewModels[i] = this.track(newVM); this._viewModels[i] = this.track(newVM);
} }
@ -230,7 +229,7 @@ export function tests() {
"initialize with duplicate set of rooms": assert => { "initialize with duplicate set of rooms": assert => {
const navigation = createNavigationForRoom(["c", "a", "b", undefined, "a"], "a"); const navigation = createNavigationForRoom(["c", "a", "b", undefined, "a"], "a");
const gridVM = new RoomGridViewModel({ const gridVM = new RoomGridViewModel({
createRoomOrInviteViewModel: id => new RoomVMMock(id), createRoomViewModel: id => new RoomVMMock(id),
navigation, navigation,
width: 3, width: 3,
height: 2, height: 2,
@ -247,7 +246,7 @@ export function tests() {
"transfer room view model": assert => { "transfer room view model": assert => {
const navigation = createNavigationForRoom(["a"], "a"); const navigation = createNavigationForRoom(["a"], "a");
const gridVM = new RoomGridViewModel({ const gridVM = new RoomGridViewModel({
createRoomOrInviteViewModel: () => assert.fail("no vms should be created"), createRoomViewModel: () => assert.fail("no vms should be created"),
navigation, navigation,
width: 3, width: 3,
height: 2, height: 2,
@ -261,7 +260,7 @@ export function tests() {
"reject transfer for non-matching room view model": assert => { "reject transfer for non-matching room view model": assert => {
const navigation = createNavigationForRoom(["a"], "a"); const navigation = createNavigationForRoom(["a"], "a");
const gridVM = new RoomGridViewModel({ const gridVM = new RoomGridViewModel({
createRoomOrInviteViewModel: id => new RoomVMMock(id), createRoomViewModel: id => new RoomVMMock(id),
navigation, navigation,
width: 3, width: 3,
height: 2, height: 2,
@ -275,7 +274,7 @@ export function tests() {
"created & released room view model is not disposed": assert => { "created & released room view model is not disposed": assert => {
const navigation = createNavigationForRoom(["a"], "a"); const navigation = createNavigationForRoom(["a"], "a");
const gridVM = new RoomGridViewModel({ const gridVM = new RoomGridViewModel({
createRoomOrInviteViewModel: id => new RoomVMMock(id), createRoomViewModel: id => new RoomVMMock(id),
navigation, navigation,
width: 3, width: 3,
height: 2, height: 2,
@ -289,7 +288,7 @@ export function tests() {
"transfered & released room view model is not disposed": assert => { "transfered & released room view model is not disposed": assert => {
const navigation = createNavigationForRoom([undefined, "a"], "a"); const navigation = createNavigationForRoom([undefined, "a"], "a");
const gridVM = new RoomGridViewModel({ const gridVM = new RoomGridViewModel({
createRoomOrInviteViewModel: () => assert.fail("no vms should be created"), createRoomViewModel: () => assert.fail("no vms should be created"),
navigation, navigation,
width: 3, width: 3,
height: 2, height: 2,
@ -304,7 +303,7 @@ export function tests() {
"try release non-existing room view model is": assert => { "try release non-existing room view model is": assert => {
const navigation = createNavigationForEmptyTile([undefined, "b"], 3); const navigation = createNavigationForEmptyTile([undefined, "b"], 3);
const gridVM = new RoomGridViewModel({ const gridVM = new RoomGridViewModel({
createRoomOrInviteViewModel: id => new RoomVMMock(id), createRoomViewModel: id => new RoomVMMock(id),
navigation, navigation,
width: 3, width: 3,
height: 2, height: 2,
@ -316,7 +315,7 @@ export function tests() {
"initial focus is set to empty tile": assert => { "initial focus is set to empty tile": assert => {
const navigation = createNavigationForEmptyTile(["a"], 1); const navigation = createNavigationForEmptyTile(["a"], 1);
const gridVM = new RoomGridViewModel({ const gridVM = new RoomGridViewModel({
createRoomOrInviteViewModel: id => new RoomVMMock(id), createRoomViewModel: id => new RoomVMMock(id),
navigation, navigation,
width: 3, width: 3,
height: 2, height: 2,
@ -328,7 +327,7 @@ export function tests() {
"change room ids after creation": assert => { "change room ids after creation": assert => {
const navigation = createNavigationForRoom(["a", "b"], "a"); const navigation = createNavigationForRoom(["a", "b"], "a");
const gridVM = new RoomGridViewModel({ const gridVM = new RoomGridViewModel({
createRoomOrInviteViewModel: id => new RoomVMMock(id), createRoomViewModel: id => new RoomVMMock(id),
navigation, navigation,
width: 3, width: 3,
height: 2, height: 2,

View file

@ -42,8 +42,8 @@ export class SessionViewModel extends ViewModel {
this._settingsViewModel = null; this._settingsViewModel = null;
this._currentRoomViewModel = null; this._currentRoomViewModel = null;
this._gridViewModel = null; this._gridViewModel = null;
this._replaceInviteWithRoom = this._replaceInviteWithRoom.bind(this); this._refreshRoomViewModel = this._refreshRoomViewModel.bind(this);
this._createRoomOrInviteViewModel = this._createRoomOrInviteViewModel.bind(this); this._createRoomViewModel = this._createRoomViewModel.bind(this);
this._setupNavigation(); this._setupNavigation();
} }
@ -121,7 +121,7 @@ export class SessionViewModel extends ViewModel {
this._gridViewModel = this.track(new RoomGridViewModel(this.childOptions({ this._gridViewModel = this.track(new RoomGridViewModel(this.childOptions({
width: 3, width: 3,
height: 2, height: 2,
createRoomOrInviteViewModel: this._createRoomOrInviteViewModel, createRoomViewModel: this._createRoomViewModel,
}))); })));
if (this._gridViewModel.initializeRoomIdsAndTransferVM(roomIds, this._currentRoomViewModel)) { if (this._gridViewModel.initializeRoomIdsAndTransferVM(roomIds, this._currentRoomViewModel)) {
this._currentRoomViewModel = this.untrack(this._currentRoomViewModel); this._currentRoomViewModel = this.untrack(this._currentRoomViewModel);
@ -138,7 +138,7 @@ export class SessionViewModel extends ViewModel {
if (vm) { if (vm) {
this._currentRoomViewModel = this.track(vm); this._currentRoomViewModel = this.track(vm);
} else { } else {
const newVM = this._createRoomViewModel(currentRoomId.value); const newVM = this._createRoomViewModel(currentRoomId.value, this._refreshRoomViewModel);
if (newVM) { if (newVM) {
this._currentRoomViewModel = this.track(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); * @param {string} roomId
if (!room) { * @param {function} refreshRoomViewModel passed in as an argument, because the grid needs a different impl of this
return null; * @return {RoomViewModel | InviteViewModel}
} */
const roomVM = new RoomViewModel(this.childOptions({ _createRoomViewModel(roomId, refreshRoomViewModel) {
room,
ownUserId: this._sessionContainer.session.user.id,
}));
roomVM.load();
return roomVM;
}
_createInviteViewModel(roomId, replaceInviteWithRoom) {
const invite = this._sessionContainer.session.invites.get(roomId); const invite = this._sessionContainer.session.invites.get(roomId);
if (!invite) { if (invite) {
return null; console.log("got invite");
} return new InviteViewModel(this.childOptions({
return new InviteViewModel(this.childOptions({ invite,
invite, mediaRepository: this._sessionContainer.session.mediaRepository,
mediaRepository: this._sessionContainer.session.mediaRepository, refreshRoomViewModel,
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);
} else { } else {
// close invite const room = this._sessionContainer.session.rooms.get(roomId);
this.navigation.applyPath(removeRoomFromPath(this.navigation.path, 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); this._currentRoomViewModel = this.disposeTracked(this._currentRoomViewModel);
const roomVM = this._createRoomViewModel(roomId); const roomVM = this._createRoomViewModel(roomId, this._refreshRoomViewModel);
if (roomVM) { if (roomVM) {
this._currentRoomViewModel = this.track(roomVM); this._currentRoomViewModel = this.track(roomVM);
} else {
// close room id
this.navigation.applyPath(removeRoomFromPath(this.navigation.path, roomId));
} }
this.emitChange("activeMiddleViewModel"); this.emitChange("activeMiddleViewModel");
} }
_updateRoom(roomId) { _updateRoom(roomId) {
if (!roomId) { // opening a room and already open?
// closing invite or room view?
if (this._currentRoomViewModel) {
this._currentRoomViewModel = this.disposeTracked(this._currentRoomViewModel);
this.emitChange("activeMiddleViewModel");
}
return;
}
// already open?
if (this._currentRoomViewModel?.id === roomId) { if (this._currentRoomViewModel?.id === roomId) {
console.log("bailing out");
return; return;
} }
this._currentRoomViewModel = this.disposeTracked(this._currentRoomViewModel); // close if needed
const roomVM = this._createRoomOrInviteViewModel(roomId, this._replaceInviteWithRoom); if (this._currentRoomViewModel) {
this._currentRoomViewModel = this.disposeTracked(this._currentRoomViewModel);
}
// and try opening again
const roomVM = this._createRoomViewModel(roomId, this._refreshRoomViewModel);
if (roomVM) { if (roomVM) {
this._currentRoomViewModel = this.track(roomVM); this._currentRoomViewModel = this.track(roomVM);
} }

View file

@ -21,10 +21,10 @@ import {ViewModel} from "../../ViewModel.js";
export class InviteViewModel extends ViewModel { export class InviteViewModel extends ViewModel {
constructor(options) { constructor(options) {
super(options); super(options);
const {invite, mediaRepository, closeCallback} = options; const {invite, mediaRepository, refreshRoomViewModel} = options;
this._invite = invite; this._invite = invite;
this._mediaRepository = mediaRepository; this._mediaRepository = mediaRepository;
this._closeCallback = closeCallback; this._refreshRoomViewModel = refreshRoomViewModel;
this._onInviteChange = this._onInviteChange.bind(this); this._onInviteChange = this._onInviteChange.bind(this);
this._error = null; this._error = null;
this._closeUrl = this.urlCreator.urlUntilSegment("session"); 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 // we're in a grid view, and opening the room doesn't change
// the nav path because the url is the same for an // the nav path because the url is the same for an
// invite and the room. // invite and the room.
this._closeCallback(this._invite.accepted); this._refreshRoomViewModel(this.id);
} else { } else {
this.emitChange(); this.emitChange();
} }

View file

@ -22,9 +22,10 @@ import {ViewModel} from "../../ViewModel.js";
export class RoomViewModel extends ViewModel { export class RoomViewModel extends ViewModel {
constructor(options) { constructor(options) {
super(options); super(options);
const {room, ownUserId} = options; const {room, ownUserId, refreshRoomViewModel} = options;
this._room = room; this._room = room;
this._ownUserId = ownUserId; this._ownUserId = ownUserId;
this._refreshRoomViewModel = refreshRoomViewModel;
this._timelineVM = null; this._timelineVM = null;
this._onRoomChange = this._onRoomChange.bind(this); this._onRoomChange = this._onRoomChange.bind(this);
this._timelineError = null; this._timelineError = null;
@ -65,7 +66,7 @@ export class RoomViewModel extends ViewModel {
} catch (err) { } catch (err) {
if (err.name !== "AbortError") { if (err.name !== "AbortError") {
throw err; throw err;
} }
} }
} }
@ -85,7 +86,13 @@ export class RoomViewModel extends ViewModel {
// room doesn't tell us yet which fields changed, // room doesn't tell us yet which fields changed,
// so emit all fields originating from summary // so emit all fields originating from summary
_onRoomChange() { _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"; } get kind() { return "room"; }