2020-08-05 18:38:55 +02:00
|
|
|
/*
|
|
|
|
Copyright 2020 Bruno Windels <bruno@windels.cloud>
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2021-08-20 11:49:42 +02:00
|
|
|
import {LoadStatus} from "../matrix/SessionContainer.js";
|
2020-04-23 09:06:04 +02:00
|
|
|
import {SyncStatus} from "../matrix/Sync.js";
|
2020-05-04 19:23:11 +02:00
|
|
|
import {ViewModel} from "./ViewModel.js";
|
2020-04-23 09:06:04 +02:00
|
|
|
|
2020-05-04 19:23:11 +02:00
|
|
|
export class SessionLoadViewModel extends ViewModel {
|
2020-05-05 23:14:58 +02:00
|
|
|
constructor(options) {
|
|
|
|
super(options);
|
2021-08-20 11:49:42 +02:00
|
|
|
const {sessionContainer, ready, homeserver, deleteSessionOnCancel} = options;
|
|
|
|
this._sessionContainer = sessionContainer;
|
2020-10-09 16:59:34 +02:00
|
|
|
this._ready = ready;
|
2020-04-23 09:06:04 +02:00
|
|
|
this._homeserver = homeserver;
|
2020-04-29 10:10:20 +02:00
|
|
|
this._deleteSessionOnCancel = deleteSessionOnCancel;
|
2020-04-23 09:06:04 +02:00
|
|
|
this._loading = false;
|
|
|
|
this._error = null;
|
2021-05-18 15:27:31 +02:00
|
|
|
this.backUrl = this.urlCreator.urlForSegment("session", true);
|
2020-04-23 09:06:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async start() {
|
|
|
|
if (this._loading) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
this._loading = true;
|
2020-06-24 22:42:39 +02:00
|
|
|
this.emitChange("loading");
|
2020-04-23 09:06:04 +02:00
|
|
|
this._waitHandle = this._sessionContainer.loadStatus.waitFor(s => {
|
2020-06-24 22:42:39 +02:00
|
|
|
this.emitChange("loadLabel");
|
2020-04-23 09:06:04 +02:00
|
|
|
// wait for initial sync, but not catchup sync
|
|
|
|
const isCatchupSync = s === LoadStatus.FirstSync &&
|
2020-05-04 19:38:23 +02:00
|
|
|
this._sessionContainer.sync.status.get() === SyncStatus.CatchupSync;
|
2020-04-23 09:06:04 +02:00
|
|
|
return isCatchupSync ||
|
|
|
|
s === LoadStatus.LoginFailed ||
|
|
|
|
s === LoadStatus.Error ||
|
|
|
|
s === LoadStatus.Ready;
|
|
|
|
});
|
|
|
|
try {
|
|
|
|
await this._waitHandle.promise;
|
|
|
|
} catch (err) {
|
2020-04-29 10:10:20 +02:00
|
|
|
return; // aborted by goBack
|
2020-04-23 09:06:04 +02:00
|
|
|
}
|
|
|
|
// TODO: should we deal with no connection during initial sync
|
|
|
|
// and we're retrying as well here?
|
|
|
|
// e.g. show in the label what is going on wrt connectionstatus
|
|
|
|
// much like we will once you are in the app. Probably a good idea
|
|
|
|
|
|
|
|
// did it finish or get stuck at LoginFailed or Error?
|
|
|
|
const loadStatus = this._sessionContainer.loadStatus.get();
|
2020-10-09 16:59:34 +02:00
|
|
|
const loadError = this._sessionContainer.loadError;
|
2020-04-23 09:06:04 +02:00
|
|
|
if (loadStatus === LoadStatus.FirstSync || loadStatus === LoadStatus.Ready) {
|
2020-10-09 16:59:34 +02:00
|
|
|
const sessionContainer = this._sessionContainer;
|
|
|
|
// session container is ready,
|
|
|
|
// don't dispose it anymore when
|
|
|
|
// we get disposed
|
|
|
|
this._sessionContainer = null;
|
|
|
|
this._ready(sessionContainer);
|
2020-04-23 09:06:04 +02:00
|
|
|
}
|
2020-10-09 16:59:34 +02:00
|
|
|
if (loadError) {
|
|
|
|
console.error("session load error", loadError);
|
2020-09-02 14:54:57 +02:00
|
|
|
}
|
2020-04-23 09:06:04 +02:00
|
|
|
} catch (err) {
|
|
|
|
this._error = err;
|
2020-09-02 14:54:57 +02:00
|
|
|
console.error("error thrown during session load", err.stack);
|
2020-04-23 09:06:04 +02:00
|
|
|
} finally {
|
|
|
|
this._loading = false;
|
2020-06-26 23:26:24 +02:00
|
|
|
// loadLabel in case of sc.loadError also gets updated through this
|
2020-06-24 22:42:39 +02:00
|
|
|
this.emitChange("loading");
|
2020-04-23 09:06:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-09 16:59:34 +02:00
|
|
|
dispose() {
|
|
|
|
if (this._sessionContainer) {
|
|
|
|
this._sessionContainer.dispose();
|
|
|
|
this._sessionContainer = null;
|
|
|
|
}
|
|
|
|
if (this._waitHandle) {
|
|
|
|
// rejects with AbortError
|
|
|
|
this._waitHandle.dispose();
|
|
|
|
this._waitHandle = null;
|
2020-04-23 09:06:04 +02:00
|
|
|
}
|
2020-04-29 10:10:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// to show a spinner or not
|
|
|
|
get loading() {
|
|
|
|
return this._loading;
|
2020-04-23 09:06:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
get loadLabel() {
|
|
|
|
const sc = this._sessionContainer;
|
|
|
|
const error = this._error || (sc && sc.loadError);
|
|
|
|
|
|
|
|
if (error || (sc && sc.loadStatus.get() === LoadStatus.Error)) {
|
|
|
|
return `Something went wrong: ${error && error.message}.`;
|
|
|
|
}
|
|
|
|
|
2021-08-20 19:27:13 +02:00
|
|
|
// Statuses related to login are handled by respective login view models
|
2020-04-23 09:06:04 +02:00
|
|
|
if (sc) {
|
|
|
|
switch (sc.loadStatus.get()) {
|
2020-09-08 17:16:34 +02:00
|
|
|
case LoadStatus.SessionSetup:
|
|
|
|
return `Setting up your encryption keys…`;
|
2020-04-23 09:06:04 +02:00
|
|
|
case LoadStatus.Loading:
|
|
|
|
return `Loading your conversations…`;
|
|
|
|
case LoadStatus.FirstSync:
|
|
|
|
return `Getting your conversations from the server…`;
|
|
|
|
default:
|
|
|
|
return this._sessionContainer.loadStatus.get();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return `Preparing…`;
|
|
|
|
}
|
|
|
|
}
|