more tweaking to server consent flow and changing servers on preview

This commit is contained in:
Bruno Windels 2020-12-04 13:59:52 +01:00
parent 4d57b3c5da
commit aa62f1fedc
11 changed files with 88 additions and 32 deletions

View file

@ -179,6 +179,11 @@ input[type='text'].large {
box-sizing: border-box;
}
.OpenLinkView .previewSource {
color: var(--grey);
font-size: 12px;
}
.ServerConsentView .actions {
margin-top: 24px;
display: flex;

View file

@ -15,6 +15,7 @@ limitations under the License.
*/
import {createEnum} from "./utils/enum.js";
import {orderedUnique} from "./utils/unique.js";
const ROOMALIAS_PATTERN = /^#([^:]*):(.+)$/;
const ROOMID_PATTERN = /^!([^:]*):(.+)$/;
@ -56,16 +57,6 @@ export const LinkKind = createEnum(
"Event"
)
function orderedUnique(array) {
const copy = [];
for (let i = 0; i < array.length; ++i) {
if (i === 0 || array.lastIndexOf(array[i], i - 1) === -1) {
copy.push(array[i]);
}
}
return copy;
}
export class Link {
static parse(fragment) {
if (!fragment) {

View file

@ -15,9 +15,11 @@ limitations under the License.
*/
import {Platform} from "./Platform.js";
import {EventEmitter} from "./utils/ViewModel.js";
export class Preferences {
export class Preferences extends EventEmitter {
constructor(localStorage) {
super();
this._localStorage = localStorage;
this.clientId = null;
// used to differentiate web from native if a client supports both
@ -41,11 +43,15 @@ export class Preferences {
platform = Platform[platform];
this.platform = platform;
this._localStorage.setItem("preferred_client", JSON.stringify({id, platform}));
this.emit("canClear")
}
setHomeservers(homeservers) {
setHomeservers(homeservers, persist) {
this.homeservers = homeservers;
this._localStorage.setItem("consented_servers", JSON.stringify(homeservers));
if (persist) {
this._localStorage.setItem("consented_servers", JSON.stringify(homeservers));
this.emit("canClear");
}
}
clear() {

View file

@ -29,6 +29,9 @@ export class RootViewModel extends ViewModel {
this.openLinkViewModel = null;
this.createLinkViewModel = null;
this.loadServerPolicyViewModel = null;
this.preferences.on("canClear", () => {
this.emitChange();
});
}
_updateChildVMs(oldLink) {
@ -37,7 +40,7 @@ export class RootViewModel extends ViewModel {
if (!oldLink || !oldLink.equals(this.link)) {
this.openLinkViewModel = new OpenLinkViewModel(this.childOptions({
link: this.link,
clients: createClients()
clients: createClients(),
}));
}
} else {

View file

@ -39,7 +39,11 @@ class ShowLinkView extends TemplateView {
onClick: () => vm.showClients()
}, vm => vm.showClientsLabel)),
t.mapView(vm => vm.clientsViewModel, childVM => childVM ? new ClientListView(childVM) : null),
t.p({className: {hidden: vm => !vm.previewDomain}}, ["Preview provided by ", vm => vm.previewDomain]),
t.p({className: {previewSource: true, hidden: vm => !vm.previewDomain}}, [
vm => vm.previewFailed ? `${vm.previewDomain} did not return a preview.` : `Preview provided by ${vm.previewDomain}.`,
" ",
t.button({className: "text", onClick: () => vm.changeServer()}, "Change"),
]),
]);
}
}

View file

@ -32,18 +32,22 @@ export class OpenLinkViewModel extends ViewModel {
this.clientsViewModel = null;
this.previewLoading = false;
if (this.preferences.homeservers === null) {
this.serverConsentViewModel = new ServerConsentViewModel(this.childOptions({
servers: this._link.servers,
done: () => {
this.serverConsentViewModel = null;
this._showLink();
}
}));
this._showServerConsent();
} else {
this._showLink();
}
}
_showServerConsent() {
this.serverConsentViewModel = new ServerConsentViewModel(this.childOptions({
servers: this._link.servers,
done: () => {
this.serverConsentViewModel = null;
this._showLink();
}
}));
}
async _showLink() {
const preferredClient = this.preferences.clientId ? this._clients.find(c => c.id === this.preferences.clientId) : null;
this.clientsViewModel = preferredClient ? new ClientListViewModel(this.childOptions({
@ -63,13 +67,24 @@ export class OpenLinkViewModel extends ViewModel {
}
get previewDomain() {
return this.previewViewModel.previewDomain;
return this.previewViewModel?.domain;
}
get previewFailed() {
return this.previewViewModel?.failed;
}
get showClientsLabel() {
return getLabelForLinkKind(this._link.kind);
}
changeServer() {
this.previewViewModel = null;
this.clientsViewModel = null;
this._showServerConsent();
this.emitChange();
}
showClients() {
if (!this.clientsViewModel) {
this.clientsViewModel = new ClientListViewModel(this.childOptions({

View file

@ -50,7 +50,7 @@ export class ServerConsentView extends TemplateView {
t.form({action: "#", onSubmit: evt => this._onSubmit(evt)}, [
t.mapView(vm => vm.showSelectServer, show => show ? new ServerOptions(vm) : null),
t.div({className: "actions"}, [
t.label([t.input({type: "checkbox", name: "persist"}), "Ask every time"]),
t.label([t.input({type: "checkbox", name: "askEveryTime"}), "Ask every time"]),
t.input({type: "submit", value: "Continue", className: "primary fullwidth"})
])
])
@ -59,7 +59,8 @@ export class ServerConsentView extends TemplateView {
_onSubmit(evt) {
evt.preventDefault();
this.value.continueWithSelection();
const {askEveryTime} = evt.target.elements;
this.value.continueWithSelection(askEveryTime.checked);
}
}

View file

@ -19,6 +19,7 @@ import {ClientListViewModel} from "./ClientListViewModel.js";
import {ClientViewModel} from "./ClientViewModel.js";
import {PreviewViewModel} from "../preview/PreviewViewModel.js";
import {getLabelForLinkKind} from "../Link.js";
import {orderedUnique} from "../utils/unique.js";
export class ServerConsentViewModel extends ViewModel {
constructor(options) {
@ -47,7 +48,7 @@ export class ServerConsentViewModel extends ViewModel {
try {
const domain = new URL(urlStr).hostname;
if (/((?:[0-9a-zA-Z][0-9a-zA-Z-]{1,61}\.)+)(xn--[a-z0-9]+|[a-z]+)/.test(domain) || domain === "localhost") {
this.selectServer(urlStr);
this.selectServer(domainOrUrl);
return true;
}
} catch (err) {}
@ -55,11 +56,11 @@ export class ServerConsentViewModel extends ViewModel {
return false;
}
continueWithSelection() {
continueWithSelection(askEveryTime) {
// keep previously consented servers
const homeservers = this.preferences.homeservers || [];
homeservers.unshift(this.selectedServer);
this.preferences.setHomeservers(homeservers);
this.preferences.setHomeservers(orderedUnique(homeservers), !askEveryTime);
this.done();
}

View file

@ -32,13 +32,13 @@ export class PreviewViewModel extends ViewModel {
this.identifier = null;
this.memberCount = null;
this.topic = null;
this.previewDomain = null;
this.domain = null;
this.failed = false;
}
async load() {
this.loading = true;
this.emitChange();
// await new Promise(r => setTimeout(r, 5000));
for (const server of this._consentedServers) {
try {
const homeserver = await resolveServer(this.request, server);
@ -51,7 +51,7 @@ export class PreviewViewModel extends ViewModel {
break;
}
// assume we're done if nothing threw
this.previewDomain = server;
this.domain = server;
this.loading = false;
this.emitChange();
return;
@ -59,8 +59,13 @@ export class PreviewViewModel extends ViewModel {
continue;
}
}
this._setNoPreview(this._link);
this.loading = false;
if (this._consentedServers.length) {
this.domain = this._consentedServers[this._consentedServers.length - 1];
this.failed = true;
}
this.emitChange();
}

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
class EventEmitter {
export class EventEmitter {
constructor() {
this._handlersByName = {};
}

25
src/utils/unique.js Normal file
View file

@ -0,0 +1,25 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
export function orderedUnique(array) {
const copy = [];
for (let i = 0; i < array.length; ++i) {
if (i === 0 || array.lastIndexOf(array[i], i - 1) === -1) {
copy.push(array[i]);
}
}
return copy;
}