From ead94695f144fe6f808cc67b07480c0e66b4a33f Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 27 Nov 2020 21:28:54 +0100 Subject: [PATCH] preview view model --- src/Link.js | 7 +++- src/RootViewModel.js | 36 +++++++++++++++++ src/main.js | 20 ++++----- src/{matrix => preview}/HomeServer.js | 2 +- src/preview/PreviewViewModel.js | 58 +++++++++++++++++++++++++++ src/{ => utils}/TemplateView.js | 0 src/{ => utils}/html.js | 0 7 files changed, 107 insertions(+), 16 deletions(-) create mode 100644 src/RootViewModel.js rename src/{matrix => preview}/HomeServer.js (97%) create mode 100644 src/preview/PreviewViewModel.js rename src/{ => utils}/TemplateView.js (100%) rename src/{ => utils}/html.js (100%) diff --git a/src/Link.js b/src/Link.js index a9fd0b7..5b60048 100644 --- a/src/Link.js +++ b/src/Link.js @@ -24,7 +24,7 @@ const EVENT_WITH_ROOMALIAS_PATTERN = /^[#]([^:]*):(.+)\/\$([^:]+):(.+)$/; const USERID_PATTERN = /^@([^:]+):(.+)$/; const GROUPID_PATTERN = /^\+([^:]+):(.+)$/; -export const IdentifierKind = createEnum( +const IdentifierKind = createEnum( "RoomId", "RoomAlias", "UserId", @@ -60,6 +60,9 @@ function orderedUnique(array) { export class Link { static parseFragment(fragment) { + if (!fragment) { + return null; + } let [identifier, queryParams] = fragment.split("?"); let viaServers = []; @@ -117,7 +120,7 @@ export class Link { const localPart = matches[1]; return new Link(viaServers, IdentifierKind.GroupId, localPart, server); } - return; + return null; } constructor(viaServers, identifierKind, localPart, server, messageLocalPart = null, messageServer = null) { diff --git a/src/RootViewModel.js b/src/RootViewModel.js new file mode 100644 index 0000000..ea4a9bf --- /dev/null +++ b/src/RootViewModel.js @@ -0,0 +1,36 @@ +/* +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 {Link} from "./Link.js"; +import {ViewModel} from "./ViewModel.js"; +import {PreviewViewModel} from "./preview/PreviewViewModel.js"; + +export class RootViewModel extends ViewModel { + constructor(request, hash) { + super(); + this._request = request; + this.link = Link.parseFragment(hash); + this.previewViewModel = null; + } + + load() { + if (this.link) { + this.previewViewModel = new PreviewViewModel(this._request, this.link); + this.emitChange(); + this.previewViewModel.load(); + } + } +} \ No newline at end of file diff --git a/src/main.js b/src/main.js index b1433ab..901eb55 100644 --- a/src/main.js +++ b/src/main.js @@ -1,16 +1,10 @@ import {xhrRequest} from "./utils/xhr.js"; -import {validateHomeServer} from "./matrix/HomeServer.js"; -import {Link, LinkKind} from "./Link.js"; +import {RootViewModel} from "./RootViewModel.js"; -export async function main() { - const link = Link.parseFragment(location.hash); - if (!link) { - throw new Error("bad link"); - } - const hs = await validateHomeServer(xhrRequest, link.servers[0]); - if (link.kind === LinkKind.User) { - const profile = await hs.getUserProfile(link.identifier); - const imageURL = hs.mxcUrlThumbnail(profile.avatar_url, 64, 64, "crop"); - console.log(imageURL); - } +export async function main(container) { + const vm = new RootViewModel(xhrRequest, location.hash); + vm.load(); + window.__rootvm = vm; + // const view = new RootView(vm); + // container.appendChild(view.mount()); } \ No newline at end of file diff --git a/src/matrix/HomeServer.js b/src/preview/HomeServer.js similarity index 97% rename from src/matrix/HomeServer.js rename to src/preview/HomeServer.js index 016825b..ac9a597 100644 --- a/src/matrix/HomeServer.js +++ b/src/preview/HomeServer.js @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -export async function validateHomeServer(request, baseURL) { +export async function resolveServer(request, baseURL) { if (!baseURL.startsWith("http://") && !baseURL.startsWith("https://")) { baseURL = `https://${baseURL}`; } diff --git a/src/preview/PreviewViewModel.js b/src/preview/PreviewViewModel.js new file mode 100644 index 0000000..e6fd7e8 --- /dev/null +++ b/src/preview/PreviewViewModel.js @@ -0,0 +1,58 @@ +/* +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 {LinkKind} from "../Link.js"; +import {ViewModel} from "../ViewModel.js"; +import {resolveServer} from "./HomeServer.js"; + +export class PreviewViewModel extends ViewModel { + constructor(request, link) { + super(); + this._link = link; + this._request = request; + this.loading = false; + this.name = null; + this.avatarURL = null; + } + + async load() { + this.loading = true; + this.emitChange(); + for (const server of this._link.servers) { + try { + const homeserver = await resolveServer(this._request, server); + switch (this._link.kind) { + case LinkKind.User: + await this._loadUserPreview(homeserver, this._link.identifier); + } + // assume we're done if nothing threw + break; + } catch (err) { + continue; + } + } + this.loading = false; + this.emitChange(); + } + + async _loadUserPreview(homeserver, userId) { + const profile = await homeserver.getUserProfile(userId); + this.name = profile.displayname || userId; + this.avatarURL = profile.avatar_url ? + homeserver.mxcUrlThumbnail(profile.avatar_url, 64, 64, "crop") : + null; + } +} \ No newline at end of file diff --git a/src/TemplateView.js b/src/utils/TemplateView.js similarity index 100% rename from src/TemplateView.js rename to src/utils/TemplateView.js diff --git a/src/html.js b/src/utils/html.js similarity index 100% rename from src/html.js rename to src/utils/html.js