Move homeserver input into LoginView

Signed-off-by: RMidhunSuresh <rmidhunsuresh@gmail.com>
This commit is contained in:
RMidhunSuresh 2021-08-18 13:05:05 +05:30
parent 13cb8979ac
commit 10a6aca477
6 changed files with 81 additions and 57 deletions

View file

@ -32,39 +32,51 @@ export class LoginViewModel extends ViewModel {
this._passwordLoginViewModel = null;
this._startSSOLoginViewModel = null;
this._completeSSOLoginViewModel = null;
this._start();
this._homeserver = null;
this._errorMessage = "";
this._start(this._defaultHomeServer);
}
get passwordLoginViewModel() { return this._passwordLoginViewModel; }
get startSSOLoginViewModel() { return this._startSSOLoginViewModel; }
get completeSSOLoginViewModel(){ return this._completeSSOLoginViewModel; }
get defaultHomeServer() { return this._defaultHomeServer; }
get errorMessage() { return this._errorMessage; }
async _start() {
async _start(homeserver) {
if (this._loginToken) {
this._completeSSOLoginViewModel = this.track(new CompleteSSOLoginViewModel(this.childOptions({loginToken: this._loginToken})));
this.emitChange("completeSSOLoginViewModel");
}
else {
await this.queryLogin(this._defaultHomeServer);
this._showPasswordLogin();
this._showSSOLogin(this._defaultHomeServer);
this._errorMessage = "";
await this.queryLogin(homeserver);
if (this._loginOptions) {
if (this._loginOptions.sso) { this._showSSOLogin(); }
if (this._loginOptions.password) { this._showPasswordLogin(); }
if (!this._loginOptions.sso && !this._loginOptions.password) {
this._showError("This homeserver neither supports SSO nor Password based login flows");
}
}
else {
this._showError("Could not query login methods supported by the homeserver");
}
}
}
_showPasswordLogin() {
this._passwordLoginViewModel = new PasswordLoginViewModel(this.childOptions({defaultHomeServer: this._defaultHomeServer}));
const observable = this._passwordLoginViewModel.homeserverObservable;
this.track(observable.subscribe(newHomeServer => this._onHomeServerChange(newHomeServer)));
this._passwordLoginViewModel = this.track(new PasswordLoginViewModel(this.childOptions()));
this.emitChange("passwordLoginViewModel");
}
_showSSOLogin(homeserver) {
this._startSSOLoginViewModel = this.disposeTracked(this._ssoLoginViewModel);
_showSSOLogin() {
this._startSSOLoginViewModel = this.track(new StartSSOLoginViewModel(this.childOptions()));
this.emitChange("startSSOLoginViewModel");
if (this._loginOptions?.sso && !this._loginToken) {
this._startSSOLoginViewModel = this.track(new StartSSOLoginViewModel(this.childOptions({homeserver})));
this.emitChange("startSSOLoginViewModel");
}
}
_showError(message) {
this._errorMessage = message;
this.emitChange("errorMessage");
}
async queryLogin(homeserver) {
@ -73,16 +85,22 @@ export class LoginViewModel extends ViewModel {
}
catch (e) {
this._loginOptions = null;
console.error("Could not query login methods supported by the homeserver");
}
}
async _onHomeServerChange(homeserver) {
await this.queryLogin(homeserver);
this._showSSOLogin(homeserver);
_disposeViewModels() {
this._startSSOLoginViewModel = this.disposeTracked(this._ssoLoginViewModel);
this._passwordLoginViewModel = this.disposeTracked(this._passwordLoginViewModel);
this.emitChange("disposeViewModels");
}
childOptions(options) {
updateHomeServer(newHomeserver) {
this._homeserver = newHomeserver;
this._disposeViewModels();
this._start(newHomeserver);
}
childOptions(options = {}) {
return {
...super.childOptions(options),
ready: sessionContainer => {
@ -91,7 +109,8 @@ export class LoginViewModel extends ViewModel {
this._ready(sessionContainer);
},
sessionContainer: this._sessionContainer,
loginOptions: this._loginOptions
loginOptions: this._loginOptions,
homeserver: this._homeserver ?? this._defaultHomeServer
}
}

View file

@ -16,30 +16,22 @@ limitations under the License.
import {ViewModel} from "../ViewModel.js";
import {SessionLoadViewModel} from "../SessionLoadViewModel.js";
import {ObservableValue} from "../../observable/ObservableValue.js";
export class PasswordLoginViewModel extends ViewModel {
constructor(options) {
super(options);
const {ready, defaultHomeServer, loginOptions, sessionContainer} = options;
const {ready, loginOptions, sessionContainer, homeserver} = options;
this._ready = ready;
this._defaultHomeServer = defaultHomeServer;
this._sessionContainer = sessionContainer;
this._loadViewModel = null;
this._loadViewModelSubscription = null;
this._loginOptions = loginOptions;
this._homeserverObservable = new ObservableValue(this._defaultHomeServer);
this._homeserver = homeserver;
}
get defaultHomeServer() { return this._defaultHomeServer; }
get loadViewModel() {return this._loadViewModel; }
get homeserverObservable() { return this._homeserverObservable; }
get cancelUrl() { return this.urlCreator.urlForSegment("session"); }
updateHomeServer(homeserver) {
this._homeserverObservable.set(homeserver);
}
get isBusy() {
if (!this._loadViewModel) {
return false;
@ -48,7 +40,8 @@ export class PasswordLoginViewModel extends ViewModel {
}
}
async login(username, password, homeserver) {
async login(username, password) {
const homeserver = this._homeserver;
if (!this._loginOptions.password) {
const path = this.navigation.pathFrom([this.navigation.segment("session")]);
this.navigation.applyPath(path);

View file

@ -50,8 +50,8 @@ limitations under the License.
margin: 0 20px;
}
.LoginView {
padding: 0.4em;
.PasswordLoginView {
padding: 0 0.4em 0.4em;
}
.SessionLoadStatusView {
@ -81,7 +81,7 @@ limitations under the License.
margin-top: 10px;
}
.StartSSOLoginView_separator {
.LoginView_separator {
justify-content: center;
display: flex;
margin: 8px;
@ -91,3 +91,11 @@ limitations under the License.
display: flex;
justify-content: center;
}
.LoginView_sso {
padding: 0.4em 0.4em 0;
}
.LoginView_error {
padding: 0.4em
}

View file

@ -228,7 +228,7 @@ a.button-action {
border-radius: 8px;
}
.StartSSOLoginView_separator {
.LoginView_separator {
font-weight: 500;
font-size: 1.5rem;
}

View file

@ -20,12 +20,25 @@ import {PasswordLoginView} from "./PasswordLoginView.js";
import {CompleteSSOView} from "./CompleteSSOView.js";
export class LoginView extends TemplateView {
render(t) {
return t.div({ className: "PreSessionScreen" }, [
t.div({ className: "logo" }),
t.mapView(vm => vm.completeSSOLoginViewModel, vm => vm? new CompleteSSOView(vm): null),
t.mapView(vm => vm.passwordLoginViewModel, vm => vm? new PasswordLoginView(vm): null),
t.mapView(vm => vm.startSSOLoginViewModel, vm => vm? new StartSSOLoginView(vm): null),
render(t, vm) {
const homeserver = t.input({
id: "homeserver",
type: "text",
placeholder: vm.i18n`Your matrix homeserver`,
value: vm.defaultHomeServer,
onChange: () => vm.updateHomeServer(homeserver.value),
});
return t.div({className: "PreSessionScreen"}, [
t.div({className: "logo"}),
t.h1([vm.i18n`Sign In`]),
t.mapView(vm => vm.completeSSOLoginViewModel, vm => vm ? new CompleteSSOView(vm) : null),
t.if(vm => !vm.completeSSOLoginViewModel,
(t, vm) => t.div({ className: "LoginView_sso form form-row" }, [t.label({ for: "homeserver" }, vm.i18n`Homeserver`), homeserver])),
t.mapView(vm => vm.passwordLoginViewModel, vm => vm ? new PasswordLoginView(vm): null),
t.if(vm => vm.passwordLoginViewModel && vm.startSSOLoginViewModel, t => t.p({className: "LoginView_separator"}, vm.i18n`or`)),
t.mapView(vm => vm.startSSOLoginViewModel, vm => vm ? new StartSSOLoginView(vm) : null),
t.if(vm => vm.errorMessage, (t, vm) => t.h5({className: "LoginView_error"}, vm.i18n(vm.errorMessage))),
// use t.mapView rather than t.if to create a new view when the view model changes too
t.p(hydrogenGithubLink(t))
]);
@ -35,10 +48,11 @@ export class LoginView extends TemplateView {
class StartSSOLoginView extends TemplateView {
render(t, vm) {
return t.div({ className: "StartSSOLoginView" },
[
t.p({ className: "StartSSOLoginView_separator" }, "or"),
t.button({ className: "StartSSOLoginView_button button-action secondary", type: "button", onClick: () => vm.startSSOLogin() }, "Log in with SSO")
]
t.button({
className: "StartSSOLoginView_button button-action secondary",
type: "button",
onClick: () => vm.startSSOLogin()
}, vm.i18n`Log in with SSO`)
);
}
}

View file

@ -32,27 +32,17 @@ export class PasswordLoginView extends TemplateView {
placeholder: vm.i18n`Password`,
disabled
});
const homeserver = t.input({
id: "homeserver",
type: "text",
placeholder: vm.i18n`Your matrix homeserver`,
value: vm.defaultHomeServer,
onChange: () => vm.updateHomeServer(homeserver.value),
disabled
});
return t.div({className: "LoginView form"}, [
t.h1([vm.i18n`Sign In`]),
return t.div({className: "PasswordLoginView form"}, [
t.if(vm => vm.error, t => t.div({ className: "error" }, vm => vm.error)),
t.form({
onSubmit: evnt => {
evnt.preventDefault();
vm.login(username.value, password.value, homeserver.value);
vm.login(username.value, password.value);
}
}, [
t.div({ className: "form-row" }, [t.label({ for: "username" }, vm.i18n`Username`), username]),
t.div({ className: "form-row" }, [t.label({ for: "password" }, vm.i18n`Password`), password]),
t.div({ className: "form-row" }, [t.label({ for: "homeserver" }, vm.i18n`Homeserver`), homeserver]),
t.mapView(vm => vm.loadViewModel, loadViewModel => loadViewModel ? new SessionLoadStatusView(loadViewModel) : null),
t.div({ className: "button-row" }, [
t.a({