2019-07-29 22:39:56 +02:00
|
|
|
import Session from "../matrix/session.js";
|
|
|
|
import Sync from "../matrix/sync.js";
|
|
|
|
import SessionViewModel from "./session/SessionViewModel.js";
|
|
|
|
import LoginViewModel from "./LoginViewModel.js";
|
|
|
|
import SessionPickerViewModel from "./SessionPickerViewModel.js";
|
|
|
|
import EventEmitter from "../EventEmitter.js";
|
|
|
|
|
|
|
|
export default class BrawlViewModel extends EventEmitter {
|
2019-09-08 10:19:16 +02:00
|
|
|
constructor({createStorage, sessionStore, createHsApi, clock}) {
|
2019-07-29 22:39:56 +02:00
|
|
|
super();
|
|
|
|
this._createStorage = createStorage;
|
2019-09-08 10:19:16 +02:00
|
|
|
this._sessionStore = sessionStore;
|
2019-07-29 22:39:56 +02:00
|
|
|
this._createHsApi = createHsApi;
|
|
|
|
this._clock = clock;
|
|
|
|
|
|
|
|
this._loading = false;
|
|
|
|
this._error = null;
|
|
|
|
this._sessionViewModel = null;
|
|
|
|
this._loginViewModel = null;
|
|
|
|
this._sessionPickerViewModel = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
async load() {
|
2019-09-08 10:19:16 +02:00
|
|
|
if (await this._sessionStore.hasAnySession()) {
|
2019-07-29 22:39:56 +02:00
|
|
|
this._showPicker();
|
|
|
|
} else {
|
|
|
|
this._showLogin();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async _showPicker() {
|
|
|
|
this._clearSections();
|
|
|
|
this._sessionPickerViewModel = new SessionPickerViewModel({
|
2019-09-08 10:19:16 +02:00
|
|
|
sessionStore: this._sessionStore,
|
2019-07-29 22:39:56 +02:00
|
|
|
sessionCallback: sessionInfo => this._onSessionPicked(sessionInfo)
|
|
|
|
});
|
|
|
|
this.emit("change", "activeSection");
|
|
|
|
try {
|
|
|
|
await this._sessionPickerViewModel.load();
|
|
|
|
} catch (err) {
|
|
|
|
this._clearSections();
|
|
|
|
this._error = err;
|
|
|
|
this.emit("change", "activeSection");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_showLogin() {
|
|
|
|
this._clearSections();
|
|
|
|
this._loginViewModel = new LoginViewModel({
|
|
|
|
createHsApi: this._createHsApi,
|
2019-09-28 09:44:39 +02:00
|
|
|
defaultHomeServer: "https://matrix.org",
|
2019-07-29 22:39:56 +02:00
|
|
|
loginCallback: loginData => this._onLoginFinished(loginData)
|
|
|
|
});
|
|
|
|
this.emit("change", "activeSection");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
_showSession(session, sync) {
|
|
|
|
this._clearSections();
|
|
|
|
this._sessionViewModel = new SessionViewModel({session, sync});
|
|
|
|
this.emit("change", "activeSection");
|
|
|
|
}
|
|
|
|
|
|
|
|
_clearSections() {
|
|
|
|
this._error = null;
|
|
|
|
this._loading = false;
|
|
|
|
this._sessionViewModel = null;
|
|
|
|
this._loginViewModel = null;
|
|
|
|
this._sessionPickerViewModel = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
get activeSection() {
|
|
|
|
if (this._error) {
|
|
|
|
return "error";
|
|
|
|
} else if(this._loading) {
|
|
|
|
return "loading";
|
|
|
|
} else if (this._sessionViewModel) {
|
|
|
|
return "session";
|
|
|
|
} else if (this._loginViewModel) {
|
|
|
|
return "login";
|
|
|
|
} else {
|
|
|
|
return "picker";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
get loadingText() { return this._loadingText; }
|
|
|
|
get sessionViewModel() { return this._sessionViewModel; }
|
|
|
|
get loginViewModel() { return this._loginViewModel; }
|
|
|
|
get sessionPickerViewModel() { return this._sessionPickerViewModel; }
|
|
|
|
get errorText() { return this._error && this._error.message; }
|
|
|
|
|
|
|
|
async _onLoginFinished(loginData) {
|
|
|
|
if (loginData) {
|
|
|
|
// TODO: extract random() as it is a source of non-determinism
|
|
|
|
const sessionId = (Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)).toString();
|
|
|
|
const sessionInfo = {
|
|
|
|
id: sessionId,
|
|
|
|
deviceId: loginData.device_id,
|
|
|
|
userId: loginData.user_id,
|
2019-09-28 09:44:39 +02:00
|
|
|
homeServer: loginData.homeServerUrl,
|
2019-07-29 22:39:56 +02:00
|
|
|
accessToken: loginData.access_token,
|
|
|
|
lastUsed: this._clock.now()
|
|
|
|
};
|
2019-09-08 10:19:16 +02:00
|
|
|
await this._sessionStore.add(sessionInfo);
|
2019-07-29 22:39:56 +02:00
|
|
|
this._loadSession(sessionInfo);
|
|
|
|
} else {
|
|
|
|
this._showPicker();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_onSessionPicked(sessionInfo) {
|
|
|
|
if (sessionInfo) {
|
|
|
|
this._loadSession(sessionInfo);
|
2019-09-08 10:19:16 +02:00
|
|
|
this._sessionStore.updateLastUsed(sessionInfo.id, this._clock.now());
|
2019-07-29 22:39:56 +02:00
|
|
|
} else {
|
|
|
|
this._showLogin();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async _loadSession(sessionInfo) {
|
|
|
|
try {
|
|
|
|
this._loading = true;
|
|
|
|
this._loadingText = "Loading your conversations…";
|
2019-09-08 10:19:16 +02:00
|
|
|
const hsApi = this._createHsApi(sessionInfo.homeServer, sessionInfo.accessToken);
|
2019-07-29 22:39:56 +02:00
|
|
|
const storage = await this._createStorage(sessionInfo.id);
|
|
|
|
// no need to pass access token to session
|
|
|
|
const filteredSessionInfo = {
|
|
|
|
deviceId: sessionInfo.deviceId,
|
|
|
|
userId: sessionInfo.userId,
|
|
|
|
homeServer: sessionInfo.homeServer,
|
|
|
|
};
|
|
|
|
const session = new Session({storage, sessionInfo: filteredSessionInfo, hsApi});
|
|
|
|
// show spinner now, with title loading stored data?
|
|
|
|
|
|
|
|
this.emit("change", "activeSection");
|
|
|
|
await session.load();
|
|
|
|
const sync = new Sync({hsApi, storage, session});
|
|
|
|
|
|
|
|
const needsInitialSync = !session.syncToken;
|
|
|
|
if (!needsInitialSync) {
|
|
|
|
this._showSession(session, sync);
|
|
|
|
}
|
|
|
|
this._loadingText = "Getting your conversations from the server…";
|
|
|
|
this.emit("change", "loadingText");
|
|
|
|
// update spinner title to initial sync
|
|
|
|
await sync.start();
|
|
|
|
if (needsInitialSync) {
|
|
|
|
this._showSession(session, sync);
|
|
|
|
}
|
|
|
|
// start sending pending messages
|
|
|
|
session.notifyNetworkAvailable();
|
|
|
|
} catch (err) {
|
2019-09-08 10:19:16 +02:00
|
|
|
console.error(err);
|
2019-07-29 22:39:56 +02:00
|
|
|
this._error = err;
|
|
|
|
}
|
|
|
|
this.emit("change", "activeSection");
|
|
|
|
}
|
|
|
|
}
|