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._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,

View file

@ -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);
}

View file

@ -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();
}

View file

@ -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"; }