From 9c39e306fd4ea771f82f989cc925228fc8685cd4 Mon Sep 17 00:00:00 2001 From: Germain Date: Mon, 28 Nov 2022 10:13:16 +0000 Subject: [PATCH] Copy deep link when using Element client Copying the link helps clients to retrieve the room the user originally tried to reach if they are going through the signup flow --- src/open/ClientView.js | 4 +-- src/open/ClientViewModel.js | 49 +++++++++++++++++++++++++------------ src/utils/copy.js | 25 ++++++++++++------- 3 files changed, 51 insertions(+), 27 deletions(-) diff --git a/src/open/ClientView.js b/src/open/ClientView.js index 76c73e9f..99bbf97d 100644 --- a/src/open/ClientView.js +++ b/src/open/ClientView.js @@ -82,8 +82,8 @@ class InstallClientView extends TemplateView { className: "copy", title: "Copy instructions", "aria-label": "Copy instructions", - onClick: evt => { - if (copy(vm.copyString, copyButton.parentElement)) { + onClick: async (evt) => { + if (await copy(vm.copyString, copyButton.parentElement)) { copyButton.className = "tick"; setTimeout(() => { copyButton.className = "copy"; diff --git a/src/open/ClientViewModel.js b/src/open/ClientViewModel.js index 2cd72449..c00bab84 100644 --- a/src/open/ClientViewModel.js +++ b/src/open/ClientViewModel.js @@ -16,7 +16,7 @@ limitations under the License. import {isWebPlatform, isDesktopPlatform, Platform} from "../Platform.js"; import {ViewModel} from "../utils/ViewModel.js"; -import {IdentifierKind} from "../Link.js"; +import { copy } from "../utils/copy.js"; function getMatchingPlatforms(client, supportedPlatforms) { const clientPlatforms = client.platforms; @@ -51,32 +51,37 @@ export class ClientViewModel extends ViewModel { this._showOpen = this.openActions.length && !this._clientCanIntercept; } + _onDeepLinkClicked = async () => { + await copy(this.proposedDeepLink); + this._pickClient(this._client); + this.preferences.setClient(this._client.id, this._proposedPlatform); + // only show install screen if we tried to open a native deeplink + if (this._showOpen && this._proposedPlatform === this._nativePlatform) { + this._showOpen = false; + this.emitChange(); + } + } + // these are only shown in the open stage _createOpenActions() { const hasPreferredWebInstance = this.hasPreferredWebInstance; - let deepLinkLabel = "Continue"; + this.deepLinkLabel = "Continue"; if (hasPreferredWebInstance) { if (this._proposedPlatform === this._nativePlatform) { - deepLinkLabel = "Open in app"; + this.deepLinkLabel = "Open in app"; } else { - deepLinkLabel = `Open on ${this._client.getPreferredWebInstance(this._link)}`; + this.deepLinkLabel = `Open on ${this._client.getPreferredWebInstance(this._link)}`; } } const actions = []; - const proposedDeepLink = this._client.getDeepLink(this._proposedPlatform, this._link); - if (proposedDeepLink) { + this.proposedDeepLink = this._client.getDeepLink(this._proposedPlatform, this._link); + if (this.proposedDeepLink) { actions.push({ - label: deepLinkLabel, - url: proposedDeepLink, + label: this.deepLinkLabel, + url: this.proposedDeepLink, primary: true, - activated: () => { - this._pickClient(this._client); - this.preferences.setClient(this._client.id, this._proposedPlatform); - // only show install screen if we tried to open a native deeplink - if (this._showOpen && this._proposedPlatform === this._nativePlatform) { - this._showOpen = false; - this.emitChange(); - } + activated: async () => { + this._onDeepLinkClicked(); }, }); } @@ -105,6 +110,18 @@ export class ClientViewModel extends ViewModel { activated: () => this.preferences.setClient(this._client.id, this._nativePlatform), }; }); + + if (!this._webPlatform && this.proposedDeepLink) { + actions.push({ + label: this.deepLinkLabel, + url: this.proposedDeepLink, + primary: true, + activated: async () => { + this._onDeepLinkClicked(); + }, + }) + } + actions.push(...nativeActions); } if (this._webPlatform) { diff --git a/src/utils/copy.js b/src/utils/copy.js index c417bfda..7da62796 100644 --- a/src/utils/copy.js +++ b/src/utils/copy.js @@ -1,5 +1,5 @@ /* -Copyright 2020 The Matrix.org Foundation C.I.C. +Copyright 2020 - 2022 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. @@ -22,14 +22,21 @@ function selectNode(node) { selection.addRange(range); } -export function copy(text, parent) { - const span = document.createElement("span"); - span.innerText = text; - parent.appendChild(span); - selectNode(span); - const result = document.execCommand("copy"); - parent.removeChild(span); - return result; +export async function copy(text, parent) { + if ("clipboard" in navigator) { + const type = "text/plain"; + const blob = new Blob([text], { type }); + const data = [new ClipboardItem({ [type]: blob })]; + return navigator.clipboard.write(data); + } else { + const span = document.createElement("span"); + span.innerText = text; + parent.appendChild(span); + selectNode(span); + const result = document.execCommand("copy"); + parent.removeChild(span); + return result; + } } export function copyButton(t, getCopyText, label, classNames) {