extract loading into a sub viewmodel

to show the loading in a separate view
This commit is contained in:
Bruno Windels 2020-04-22 21:53:55 +02:00
parent b2954fd774
commit acc511e69f

View File

@ -2,6 +2,7 @@ import {SortedArray} from "../observable/index.js";
import {EventEmitter} from "../utils/EventEmitter.js"; import {EventEmitter} from "../utils/EventEmitter.js";
import {LoadStatus} from "../matrix/SessionContainer.js"; import {LoadStatus} from "../matrix/SessionContainer.js";
import {SyncStatus} from "../matrix/Sync.js"; import {SyncStatus} from "../matrix/Sync.js";
import {loadLabel} from "./common.js";
class SessionItemViewModel extends EventEmitter { class SessionItemViewModel extends EventEmitter {
constructor(sessionInfo, pickerVM) { constructor(sessionInfo, pickerVM) {
@ -99,14 +100,79 @@ class SessionItemViewModel extends EventEmitter {
} }
} }
export class SessionPickerViewModel { class LoadViewModel extends EventEmitter {
constructor({createSessionContainer, sessionCallback, sessionId}) {
super();
this._createSessionContainer = createSessionContainer;
this._sessionCallback = sessionCallback;
this._sessionId = sessionId;
this._loading = false;
}
async _start() {
try {
this._loading = true;
this.emit("change", "loading");
this._sessionContainer = this._createSessionContainer();
this._sessionContainer.startWithExistingSession(this._sessionId);
this._waitHandle = this._sessionContainer.loadStatus.waitFor(s => {
this.emit("change", "loadStatus");
// wait for initial sync, but not catchup sync
const isCatchupSync = s === LoadStatus.FirstSync &&
this._sessionContainer.sync.status === SyncStatus.CatchupSync;
return isCatchupSync ||
s === LoadStatus.Error ||
s === LoadStatus.Ready;
});
try {
await this._waitHandle.promise;
} catch (err) {
// swallow AbortError
}
if (this._sessionContainer.loadStatus.get() !== LoadStatus.Error) {
this._sessionCallback(this._sessionContainer);
}
} catch (err) {
this._error = err;
} finally {
this._loading = false;
this.emit("change", "loading");
}
}
get loading() {
return this._loading;
}
goBack() {
if (this._sessionContainer) {
this._sessionContainer.stop();
this._sessionContainer = null;
if (this._waitHandle) {
this._waitHandle.dispose();
}
}
this._sessionCallback();
}
get loadLabel() {
const sc = this._sessionContainer;
return loadLabel(
sc && sc.loadStatus,
sc && sc.loadError || this._error);
}
}
export class SessionPickerViewModel extends EventEmitter {
constructor({storageFactory, sessionInfoStorage, sessionCallback, createSessionContainer}) { constructor({storageFactory, sessionInfoStorage, sessionCallback, createSessionContainer}) {
super();
this._storageFactory = storageFactory; this._storageFactory = storageFactory;
this._sessionInfoStorage = sessionInfoStorage; this._sessionInfoStorage = sessionInfoStorage;
this._sessionCallback = sessionCallback; this._sessionCallback = sessionCallback;
this._createSessionContainer = createSessionContainer; this._createSessionContainer = createSessionContainer;
this._sessions = new SortedArray((s1, s2) => s1.id.localeCompare(s2.id)); this._sessions = new SortedArray((s1, s2) => s1.id.localeCompare(s2.id));
this._loading = false; this._loadViewModel = null;
this._error = null;
} }
// this loads all the sessions // this loads all the sessions
@ -115,43 +181,33 @@ export class SessionPickerViewModel {
this._sessions.setManyUnsorted(sessions.map(s => new SessionItemViewModel(s, this))); this._sessions.setManyUnsorted(sessions.map(s => new SessionItemViewModel(s, this)));
} }
// this is the loading of a single picked session // for the loading of 1 picked session
get loading() { get loadViewModel() {
return this._loading; return this._loadViewModel;
}
get loadStatus() {
return this._sessionContainer && this._sessionContainer.loadStatus;
}
get loadError() {
if (this._sessionContainer) {
const error = this._sessionContainer.loadError;
if (error) {
return error.message;
}
}
return null;
} }
async pick(id) { async pick(id) {
if (this._loadViewModel) {
return;
}
const sessionVM = this._sessions.array.find(s => s.id === id); const sessionVM = this._sessions.array.find(s => s.id === id);
if (sessionVM) { if (sessionVM) {
this._loading = true; this._loadViewModel = new LoadViewModel({
this.emit("change", "loading"); createSessionContainer: this._createSessionContainer,
this._sessionContainer = this._createSessionContainer(); sessionCallback: sessionContainer => {
this._sessionContainer.startWithExistingSession(sessionVM.sessionInfo.id); if (sessionContainer) {
// TODO: allow to cancel here // make parent view model move away
const waitHandle = this._sessionContainer.loadStatus.waitFor(s => { this._sessionCallback(sessionContainer);
this.emit("change", "loadStatus"); } else {
// wait for initial sync, but not catchup sync // show list of session again
return ( this._loadViewModel = null;
s === LoadStatus.FirstSync && this.emit("change", "loadViewModel");
this._sessionContainer.sync.status === SyncStatus.CatchupSync }
) || s === LoadStatus.Ready; },
sessionId: sessionVM.id,
}); });
await waitHandle.promise; this._loadViewModel.start();
this._sessionCallback(this._sessionContainer); this.emit("change", "loadViewModel");
} }
} }