hydrogen-web/src/domain/BrawlViewModel.js

174 lines
5.9 KiB
JavaScript
Raw Normal View History

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";
2019-12-14 22:59:35 +05:30
export function createNewSessionId() {
return (Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)).toString();
}
export default class BrawlViewModel extends EventEmitter {
2019-10-13 00:46:48 +05:30
constructor({storageFactory, sessionStore, createHsApi, clock}) {
super();
2019-10-13 00:46:48 +05:30
this._storageFactory = storageFactory;
this._sessionStore = sessionStore;
this._createHsApi = createHsApi;
this._clock = clock;
this._loading = false;
this._error = null;
this._sessionViewModel = null;
this._loginViewModel = null;
this._sessionPickerViewModel = null;
}
async load() {
if (await this._sessionStore.hasAnySession()) {
this._showPicker();
} else {
this._showLogin();
}
}
async _showPicker() {
this._clearSections();
this._sessionPickerViewModel = new SessionPickerViewModel({
sessionStore: this._sessionStore,
2019-10-13 00:46:48 +05:30
storageFactory: this._storageFactory,
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 13:14:39 +05:30
defaultHomeServer: "https://matrix.org",
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
2019-12-14 22:59:35 +05:30
const sessionId = createNewSessionId();
const sessionInfo = {
id: sessionId,
deviceId: loginData.device_id,
userId: loginData.user_id,
2019-09-28 13:14:39 +05:30
homeServer: loginData.homeServerUrl,
accessToken: loginData.access_token,
lastUsed: this._clock.now()
};
await this._sessionStore.add(sessionInfo);
this._loadSession(sessionInfo);
} else {
this._showPicker();
}
}
_onSessionPicked(sessionInfo) {
if (sessionInfo) {
this._loadSession(sessionInfo);
this._sessionStore.updateLastUsed(sessionInfo.id, this._clock.now());
} else {
this._showLogin();
}
}
async _loadSession(sessionInfo) {
try {
this._loading = true;
this._loadingText = "Loading your conversations…";
2020-04-05 18:41:15 +05:30
const reconnector = new Reconnector(
new ExponentialRetryDelay(2000, this._clock.createTimeout),
this._clock.createMeasure
);
const hsApi = this._createHsApi(sessionInfo.homeServer, sessionInfo.accessToken, reconnector);
2019-10-13 00:46:48 +05:30
const storage = await this._storageFactory.create(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();
2020-04-05 18:41:15 +05:30
const sync = new Sync({hsApi, storage, session});
reconnector.on("state", state => {
if (state === ConnectionState.Online) {
sync.start();
session.notifyNetworkAvailable(reconnector.lastVersionsResponse);
}
});
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) {
console.error(err);
this._error = err;
}
this.emit("change", "activeSection");
}
}