adjust LoginView(Model) further to showing loading status in place

This commit is contained in:
Bruno Windels 2020-04-22 20:52:28 +02:00
parent 96aa4f83b9
commit e37101210c
2 changed files with 74 additions and 24 deletions

View file

@ -1,5 +1,5 @@
import {EventEmitter} from "../utils/EventEmitter.js"; import {EventEmitter} from "../utils/EventEmitter.js";
import {LoadStatus} from "../matrix/SessionContainer.js"; import {LoadStatus, LoginFailure} from "../matrix/SessionContainer.js";
import {AbortError} from "../utils/error.js"; import {AbortError} from "../utils/error.js";
export class LoginViewModel extends EventEmitter { export class LoginViewModel extends EventEmitter {
@ -8,6 +8,7 @@ export class LoginViewModel extends EventEmitter {
this._createSessionContainer = createSessionContainer; this._createSessionContainer = createSessionContainer;
this._sessionCallback = sessionCallback; this._sessionCallback = sessionCallback;
this._defaultHomeServer = defaultHomeServer; this._defaultHomeServer = defaultHomeServer;
this._homeserver = null;
this._sessionContainer = null; this._sessionContainer = null;
this._loadWaitHandle = null; this._loadWaitHandle = null;
this._loading = false; this._loading = false;
@ -18,18 +19,24 @@ export class LoginViewModel extends EventEmitter {
get passwordPlaceholder() { return "Password"; } get passwordPlaceholder() { return "Password"; }
get hsPlaceholder() { return "Your matrix homeserver"; } get hsPlaceholder() { return "Your matrix homeserver"; }
get defaultHomeServer() { return this._defaultHomeServer; } get defaultHomeServer() { return this._defaultHomeServer; }
get error() { return this._error; } get loading() {return this._loading}
get loading() { return this._loading; }
get showLoadLabel() {
return this._loading || this._sessionContainer;
}
async login(username, password, homeserver) { async login(username, password, homeserver) {
try { try {
this._loading = true; this._loading = true;
this.emit("change", "loading"); this.emit("change", "loading");
this._homeserver = homeserver;
this._sessionContainer = this._createSessionContainer(); this._sessionContainer = this._createSessionContainer();
this._sessionContainer.startWithLogin(homeserver, username, password); this._sessionContainer.startWithLogin(homeserver, username, password);
this._loadWaitHandle = this._sessionContainer.loadStatus.waitFor(s => { this._loadWaitHandle = this._sessionContainer.loadStatus.waitFor(s => {
this.emit("change", "loadStatus"); this.emit("change", "loadLabel");
return s === LoadStatus.Ready; return s === LoadStatus.Ready ||
s === LoadStatus.LoginFailed ||
s === LoadStatus.Error;
}); });
try { try {
await this._loadWaitHandle.promise; await this._loadWaitHandle.promise;
@ -40,8 +47,17 @@ export class LoginViewModel extends EventEmitter {
} }
} }
this._loadWaitHandle = null; this._loadWaitHandle = null;
this._sessionCallback(this._sessionContainer); if (this._sessionContainer.loadStatus.get() === LoadStatus.Ready) {
// wait for parent view model to switch away here this._sessionCallback(this._sessionContainer);
// wait for parent view model to switch away here
} else {
this._loading = false;
this.emit("change", "loading");
if (this._sessionContainer.loadError) {
console.error(this._sessionContainer.loadError);
}
}
} catch (err) { } catch (err) {
this._error = err; this._error = err;
this._loading = false; this._loading = false;
@ -49,21 +65,43 @@ export class LoginViewModel extends EventEmitter {
} }
} }
get loadStatus() { get loadLabel() {
return this._sessionContainer && this._sessionContainer.loadStatus; if (this._error) {
} return `Something went wrong: ${this._error.message}.`;
}
get loadError() { if (this.showLoadLabel) {
if (this._sessionContainer) { if (this._sessionContainer) {
const error = this._sessionContainer.loadError; switch (this._sessionContainer.loadStatus.get()) {
if (error) { case LoadStatus.NotLoading:
return error.message; return `Preparing…`;
case LoadStatus.Login:
return `Checking your login and password…`;
case LoadStatus.LoginFailed:
switch (this._sessionContainer.loginFailure) {
case LoginFailure.LoginFailure:
return `Your username and/or password don't seem to be correct.`;
case LoginFailure.Connection:
return `Can't connect to ${this._homeserver}.`;
case LoginFailure.Unknown:
return `Something went wrong while checking your login and password.`;
}
break;
case LoadStatus.Loading:
return `Loading your conversations…`;
case LoadStatus.FirstSync:
return `Getting your conversations from the server…`;
case LoadStatus.Error:
return `Something went wrong: ${this._sessionContainer.loadError.message}.`;
default:
return this._sessionContainer.loadStatus.get();
}
} }
return `Preparing…`;
} }
return null; return null;
} }
async cancelLogin() { async cancel() {
if (!this._loading) { if (!this._loading) {
return; return;
} }
@ -81,7 +119,9 @@ export class LoginViewModel extends EventEmitter {
} }
} }
cancel() { goBack() {
this._sessionCallback(); if (!this._loading) {
this._sessionCallback();
}
} }
} }

View file

@ -7,9 +7,10 @@ export class LoginView extends TemplateView {
} }
render(t, vm) { render(t, vm) {
const username = t.input({type: "text", placeholder: vm.usernamePlaceholder}); const disabled = vm => vm.loading;
const password = t.input({type: "password", placeholder: vm.passwordPlaceholder}); const username = t.input({type: "text", placeholder: vm.usernamePlaceholder, disabled});
const homeserver = t.input({type: "text", placeholder: vm.hsPlaceholder, value: vm.defaultHomeServer}); const password = t.input({type: "password", placeholder: vm.passwordPlaceholder, disabled});
const homeserver = t.input({type: "text", placeholder: vm.hsPlaceholder, value: vm.defaultHomeServer, disabled});
return t.div({className: "LoginView form"}, [ return t.div({className: "LoginView form"}, [
t.h1(["Log in to your homeserver"]), t.h1(["Log in to your homeserver"]),
t.if(vm => vm.error, t => t.div({className: "error"}, vm => vm.error)), t.if(vm => vm.error, t => t.div({className: "error"}, vm => vm.error)),
@ -18,10 +19,19 @@ export class LoginView extends TemplateView {
t.div(homeserver), t.div(homeserver),
t.div(t.button({ t.div(t.button({
onClick: () => vm.login(username.value, password.value, homeserver.value), onClick: () => vm.login(username.value, password.value, homeserver.value),
disabled: vm => vm.loading disabled
}, "Log In")), }, "Log In")),
t.div(t.button({onClick: () => vm.cancel()}, ["Pick an existing session"])), t.div(t.button({onClick: () => vm.goBack(), disabled}, ["Pick an existing session"])),
t.if(vm => vm.showLoadLabel, renderLoadProgress),
t.p(brawlGithubLink(t)) t.p(brawlGithubLink(t))
]); ]);
} }
} }
function renderLoadProgress(t) {
return t.div({className: "loadProgress"}, [
t.div({className: "spinner"}),
t.p(vm => vm.loadLabel),
t.if(vm => vm.loading, t => t.button({onClick: vm => vm.cancel()}, "Cancel login"))
]);
}