diff --git a/spec.js b/spec.js index a488e5e..600af14 100644 --- a/spec.js +++ b/spec.js @@ -84,11 +84,6 @@ module.exports = [ source: "/js/functions.js", target: "/static/functions.js", }, - { - type: "js", - source: "/js/login.js", - target: "/static/login.js", - }, { type: "file", source: "/assets/fonts/whitney-500.woff", diff --git a/src/js/login.js b/src/js/login.js deleted file mode 100644 index de32932..0000000 --- a/src/js/login.js +++ /dev/null @@ -1,148 +0,0 @@ -import {q, ElemJS, ejs} from $to_relative "/js/basic.js" - -const password = q("#password") -const homeserver = q("#homeserver") - -class Username extends ElemJS { - constructor() { - super(q("#username")) - - this.on("change", this.updateServer.bind(this)) - } - - isValid() { - return !!this.element.value.match(/^@?[a-z0-9._=\/-]+(?::[a-zA-Z0-9.:\[\]-]+)?$/) - } - - getUsername() { - return this.element.value.match(/^@?([a-z0-9._=\/-]+)/)[1] - } - - getServer() { - const server = this.element.value.match(/^@?[a-z0-9._=\?-]+:([a-zA-Z0-9.:\[\]-]+)$/) - if (server && server[1]) return server[1] - else return null - } - - updateServer() { - if (!this.isValid()) return - if (this.getServer()) homeserver.value = this.getServer() - } -} - -const username = new Username() - -class Feedback extends ElemJS { - constructor() { - super(q("#feedback")) - this.loading = false - this.loadingIcon = ejs("span").class("loading-icon") - this.messageSpan = ejs("span") - this.child(this.messageSpan) - } - - setLoading(state) { - if (this.loading && !state) { - this.loadingIcon.remove() - } else if (!this.loading && state) { - this.childAt(0, this.loadingIcon) - } - this.loading = state - } - - message(content) { - if (content) { - this.class("form-feedback") - } else { - this.removeClass("form-feedback") - } - this.messageSpan.text(content) - } -} - -const feedback = new Feedback() - -class Form extends ElemJS { - constructor() { - super(q("#form")) - - this.processing = false - - this.on("submit", this.submit.bind(this)) - } - - async submit() { - if (this.processing) return - this.processing = true - if (!username.isValid()) return this.cancel("Username is not valid.") - - // Resolve homeserver address - let currentAddress = homeserver.value - let ok = false - while (!ok) { - if (!currentAddress.match(/^https?:\/\//)) currentAddress = "https://" + currentAddress - currentAddress = currentAddress.replace(/\/*$/, "") - this.status(`Looking up homeserver... trying ${currentAddress}`) - try { - // check if we found the actual matrix server - try { - const versions = await fetch(`${currentAddress}/_matrix/client/versions`).then(res => res.json()) - if (Array.isArray(versions.versions)) { - ok = true - break - } - } catch (e) {} - // find the next matrix server in the chain - const root = await fetch(`${currentAddress}/.well-known/matrix/client`).then(res => res.json()) - let nextAddress = root["m.homeserver"].base_url - nextAddress = nextAddress.replace(/\/*$/, "") - if (currentAddress === nextAddress) { - ok = true - } - currentAddress = nextAddress - } catch (e) { - return this.cancel(`Failed to look up server ${currentAddress}`) - } - } - - // Request access token - this.status("Logging in...") - const root = await fetch(`${currentAddress}/_matrix/client/r0/login`, { - method: "POST", - body: JSON.stringify({ - type: "m.login.password", - user: username.getUsername(), - password: password.value - }) - }).then(res => res.json()) - - if (!root.access_token) { - if (root.error) { - this.cancel(`Server said: ${root.error}`) - } else { - this.cancel("Login mysteriously failed.") - console.error(root) - } - return - } - - localStorage.setItem("mx_user_id", root.user_id) - localStorage.setItem("domain", currentAddress) - localStorage.setItem("access_token", root.access_token) - - location.assign("./") - } - - status(message) { - feedback.setLoading(true) - feedback.message(message) - } - - cancel(message) { - this.processing = false - feedback.setLoading(false) - feedback.message(message) - } -} - -const form = new Form() diff --git a/src/js/room-picker.js b/src/js/room-picker.js index 9fbbece..8e696de 100644 --- a/src/js/room-picker.js +++ b/src/js/room-picker.js @@ -108,12 +108,10 @@ class Room extends ElemJS { getIcon() { const avatar = this.data.state.events.find(e => e.type === "m.room.avatar") if (avatar) { - const url = avatar.content.url || avatar.content.avatar_url - if (url) { - return resolveMxc(url, 32, "crop") - } + return resolveMxc(avatar.content.url || avatar.content.avatar_url, 32, "crop") + } else { + return null } - return null } isDirect() { diff --git a/src/login.pug b/src/login.pug index 85d4485..13acefd 100644 --- a/src/login.pug +++ b/src/login.pug @@ -2,20 +2,19 @@ doctype html html head meta(charset="utf-8") + link(rel="stylesheet" type="text/css" href=getStatic("/sass/login.sass")) title Carbon meta(name="viewport" content="width=device-width, initial-scale=1") - link(rel="stylesheet" type="text/css" href=getStatic("/sass/login.sass")) - script(type="module" src=getStatic("/js/login.js")) body main.main .center-login-container h1 Welcome to the Matrix! - form.login-form(method="post" onsubmit="return false")#form + form.login-form .data-input .form-input-container - label(for="username") Username - input(type="text" name="username" autocomplete="username" placeholder="@username:server.tld" pattern="^@?[a-z0-9._=/-]+(?::[a-zA-Z0-9.:\\[\\]-]+)?$" required)#username + label(for="login") Username + input(type="text" name="login" autocomplete="username" required)#login .form-input-container label(for="password") Password @@ -23,10 +22,7 @@ html .form-input-container label(for="homeserver") Homeserver - input(type="text" name="homeserver" value="matrix.org" placeholder="matrix.org" required)#homeserver - - #feedback + input(type="text" name="homeserver" value="matrix.org" required)#homeserver .form-input-container - input(type="submit" value="Log in")#submit - + input(type="submit" value="Login") diff --git a/src/sass/login.sass b/src/sass/login.sass index e4820ee..92f443f 100644 --- a/src/sass/login.sass +++ b/src/sass/login.sass @@ -10,10 +10,10 @@ flex-flow: column justify-content: center align-items: center - width: min(100vw, 450px) + width: min(100vw, 30rem) padding: max(1rem,3vw) 2rem - margin: 8px - box-shadow: 0px 2px 10px c.$darkest + height: 27rem + box-shadow: -2px 2px 10px c.$darkest background-color: c.$darker border-radius: 5px @@ -34,48 +34,23 @@ flex-direction: column margin: 1em 0 -.form-feedback - width: 100% - margin: -0.5em 0 -0.8em - -@keyframes spin - 0% - transform: rotate(0deg) - 100% - transform: rotate(180deg) - -.loading-icon - display: inline-block - background-color: #ccc - width: 12px - height: 12px - margin-right: 6px - animation: spin 0.7s infinite - -input, button - font-family: inherit - font-size: 17px - background-color: c.$mild - color: #eee +input width: 100% + height: 2.4rem border-radius: 5px box-sizing: border-box - transition: background-color 0.15s ease-out, border-color 0.15s ease-out - padding: 4px 9px + transition: background-color 1s, border-color 1s + padding: 0px 1ch border: 0px input[type="text"],input[type="password"] border: 3px solid transparent margin: 0.4em 0px - - &:hover, &:focus - border-color: c.$milder - -button, input[type="submit"] - padding: 7px - &:hover - background-color: c.$milder + border-color: c.$mild + +input[type="submit"]:hover + background-color: c.$mild label - font-size: 18px + font-size: 1.2em