diff --git a/css/main.css b/css/main.css index 7bcf364..fc89f50 100644 --- a/css/main.css +++ b/css/main.css @@ -173,3 +173,17 @@ input[type='text'].large { width: 100%; box-sizing: border-box; } + +.LoadServerPolicyView { + display: flex; +} + +.LoadServerPolicyView .spinner { + width: 32px; + height: 32px; + margin-right: 12px; +} + +.LoadServerPolicyView h2 { + margin-top: 0; +} diff --git a/src/RootView.js b/src/RootView.js index 303deb9..183724d 100644 --- a/src/RootView.js +++ b/src/RootView.js @@ -17,12 +17,14 @@ limitations under the License. import {TemplateView} from "./utils/TemplateView.js"; import {OpenLinkView} from "./open/OpenLinkView.js"; import {CreateLinkView} from "./create/CreateLinkView.js"; +import {LoadServerPolicyView} from "./policy/LoadServerPolicyView.js"; export class RootView extends TemplateView { render(t, vm) { return t.div({className: "RootView"}, [ t.mapView(vm => vm.openLinkViewModel, vm => vm ? new OpenLinkView(vm) : null), t.mapView(vm => vm.createLinkViewModel, vm => vm ? new CreateLinkView(vm) : null), + t.mapView(vm => vm.loadServerPolicyViewModel, vm => vm ? new LoadServerPolicyView(vm) : null), t.div({className: "footer"}, [ t.p(t.img({src: "images/matrix-logo.svg"})), t.p(["This invite uses ", externalLink(t, "https://matrix.org", "Matrix"), ", an open network for secure, decentralized communication."]), diff --git a/src/RootViewModel.js b/src/RootViewModel.js index 1387702..fba00ab 100644 --- a/src/RootViewModel.js +++ b/src/RootViewModel.js @@ -19,6 +19,7 @@ import {ViewModel} from "./utils/ViewModel.js"; import {OpenLinkViewModel} from "./open/OpenLinkViewModel.js"; import {createClients} from "./open/clients/index.js"; import {CreateLinkViewModel} from "./create/CreateLinkViewModel.js"; +import {LoadServerPolicyViewModel} from "./policy/LoadServerPolicyViewModel.js"; import {Platform} from "./Platform.js"; export class RootViewModel extends ViewModel { @@ -27,6 +28,7 @@ export class RootViewModel extends ViewModel { this.link = null; this.openLinkViewModel = null; this.createLinkViewModel = null; + this.loadServerPolicyViewModel = null; } _updateChildVMs(oldLink) { @@ -48,9 +50,15 @@ export class RootViewModel extends ViewModel { } updateHash(hash) { - const oldLink = this.link; - this.link = Link.parse(hash); - this._updateChildVMs(oldLink); + if (hash.startsWith("#/policy/")) { + const server = hash.substr(9); + this.loadServerPolicyViewModel = new LoadServerPolicyViewModel(this.childOptions({server})); + this.loadServerPolicyViewModel.load(); + } else { + const oldLink = this.link; + this.link = Link.parse(hash); + this._updateChildVMs(oldLink); + } } clearPreferences() { diff --git a/src/policy/LoadServerPolicyView.js b/src/policy/LoadServerPolicyView.js new file mode 100644 index 0000000..b6d2f08 --- /dev/null +++ b/src/policy/LoadServerPolicyView.js @@ -0,0 +1,26 @@ +/* +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. +*/ + +import {TemplateView} from "../utils/TemplateView.js"; + +export class LoadServerPolicyView extends TemplateView { + render(t, vm) { + return t.div({className: "LoadServerPolicyView card"}, [ + t.div({className: {spinner: true, hidden: vm => !vm.loading}}), + t.h2(vm => vm.message) + ]); + } +} diff --git a/src/policy/LoadServerPolicyViewModel.js b/src/policy/LoadServerPolicyViewModel.js new file mode 100644 index 0000000..4e6a119 --- /dev/null +++ b/src/policy/LoadServerPolicyViewModel.js @@ -0,0 +1,52 @@ +/* +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. +*/ + +import {ViewModel} from "../utils/ViewModel.js"; +import {resolveServer} from "../preview/HomeServer.js"; + +export class LoadServerPolicyViewModel extends ViewModel { + constructor(options) { + super(options); + this.server = options.server; + this.message = `Looking up ${this.server} privacy policy…`; + this.loading = false; + } + + async load() { + this.loading = true; + this.emitChange(); + try { + const homeserver = await resolveServer(this.request, this.server); + if (homeserver) { + const url = await homeserver.getPrivacyPolicyUrl(); + if (url) { + this.message = `Loading ${this.server} privacy policy now…`; + this.openLink(url); + } else { + this.loading = false; + this.message = `${this.server} does not declare a privacy policy.`; + } + } else { + this.loading = false; + this.message = `${this.server} does not look like a matrix homeserver.`; + } + } catch (err) { + this.loading = false; + this.message = `Failed to get the privacy policy for ${this.server}`; + } + this.emitChange(); + } +}