Add support for the native web share API in share dialog (#4201)
authorMatthias Schmidt <gravatronics@live.com>
Fri, 7 May 2021 11:02:56 +0000 (13:02 +0200)
committerGitHub <noreply@github.com>
Fri, 7 May 2021 11:02:56 +0000 (13:02 +0200)
Close #4193

com.woltlab.wcf/templates/headIncludeJavaScript.tpl
ts/WoltLabSuite/Core/Ui/Message/Share/Dialog.ts
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Message/Share/Dialog.js
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index 599f9f1ea63a320631a9251dfd8de3e3d452574a..fe9b47518ae4dc970cd0316aeeceb5e02fda99fe 100644 (file)
@@ -148,6 +148,7 @@ window.addEventListener('pageshow', function(event) {
                        'wcf.message.share.socialMedia': '{jslang}wcf.message.share.socialMedia{/jslang}',
                        'wcf.message.share.copy': '{jslang}wcf.message.share.copy{/jslang}',
                        'wcf.message.share.copy.success': '{jslang}wcf.message.share.copy.success{/jslang}',
+                       'wcf.message.share.nativeShare': '{jslang}wcf.message.share.nativeShare{/jslang}',
                        'wcf.global.button.rss': '{jslang}wcf.global.button.rss{/jslang}',
                        'wcf.global.rss.copy': '{jslang}wcf.global.rss.copy{/jslang}',
                        'wcf.global.rss.copy.success': '{jslang}wcf.global.rss.copy.success{/jslang}',
index e62eb19ebb2583cf895a53f25a5204b55a1f1e78..f090976e0d676ac8af25d2d9a08c5d5da454bcdf 100644 (file)
@@ -20,6 +20,8 @@ import * as UiMessageShareProviders from "./Providers";
 
 const shareButtons = new WeakSet<HTMLElement>();
 
+const offerNativeSharing = window.navigator.share !== undefined;
+
 /**
  * Copies the contents of one of the share dialog's input elements to the clipboard.
  */
@@ -104,6 +106,24 @@ function getProviderButtons(): string {
   return "";
 }
 
+/**
+ * Opens the native share menu.
+ */
+async function nativeShare(event: Event): Promise<void> {
+  event.preventDefault();
+
+  const button = event.currentTarget as HTMLButtonElement;
+
+  const shareOptions: ShareData = {
+    url: button.dataset.url!,
+  };
+  if (button.dataset.title) {
+    shareOptions.title = button.dataset.title;
+  }
+
+  await window.navigator.share(shareOptions);
+}
+
 /**
  * Opens the share dialog after clicking on the share button.
  */
@@ -124,10 +144,27 @@ function openDialog(event: MouseEvent): void {
       `;
     }
 
+    let nativeSharingElement = "";
+    if (offerNativeSharing) {
+      nativeSharingElement = `
+        <dl>
+          <dt></dt>
+          <dd>
+              <button class="shareDialogNativeButton" data-url="${StringUtil.escapeHTML(
+                target.href,
+              )}" data-title="${StringUtil.escapeHTML(target.dataset.linkTitle || "")}">${Language.get(
+        "wcf.message.share.nativeShare",
+      )}</button>
+          </dd>
+        </dl>
+      `;
+    }
+
     const dialogContent = `
       <div class="shareContentDialog">
         ${getDialogElements(target)}
         ${providerElement}
+        ${nativeSharingElement}
       </div>
     `;
 
@@ -139,6 +176,9 @@ function openDialog(event: MouseEvent): void {
     dialogData.content
       .querySelectorAll(".shareDialogCopyButton")
       .forEach((el) => el.addEventListener("click", (ev) => copy(ev)));
+    if (offerNativeSharing) {
+      dialogData.content.querySelector(".shareDialogNativeButton")!.addEventListener("click", (ev) => nativeShare(ev));
+    }
 
     if (providerButtons) {
       UiMessageShare.init();
index 3c76010fd2d8b6abf3c8a7e64fd3e3d6c0c192a2..ecaf9ec696a01fa37658f16fc216c164be900aa8 100644 (file)
@@ -21,6 +21,7 @@ define(["require", "exports", "tslib", "../../Dialog", "../../../Dom/Util", "../
     UiMessageShare = tslib_1.__importStar(UiMessageShare);
     UiMessageShareProviders = tslib_1.__importStar(UiMessageShareProviders);
     const shareButtons = new WeakSet();
+    const offerNativeSharing = window.navigator.share !== undefined;
     /**
      * Copies the contents of one of the share dialog's input elements to the clipboard.
      */
@@ -83,6 +84,20 @@ define(["require", "exports", "tslib", "../../Dialog", "../../../Dom/Util", "../
         }
         return "";
     }
+    /**
+     * Opens the native share menu.
+     */
+    async function nativeShare(event) {
+        event.preventDefault();
+        const button = event.currentTarget;
+        const shareOptions = {
+            url: button.dataset.url,
+        };
+        if (button.dataset.title) {
+            shareOptions.title = button.dataset.title;
+        }
+        await window.navigator.share(shareOptions);
+    }
     /**
      * Opens the share dialog after clicking on the share button.
      */
@@ -99,12 +114,24 @@ define(["require", "exports", "tslib", "../../Dialog", "../../../Dom/Util", "../
           <dt>${Language.get("wcf.message.share.socialMedia")}</dt>
           <dd>${providerButtons}</dd>
         </dl>
+      `;
+            }
+            let nativeSharingElement = "";
+            if (offerNativeSharing) {
+                nativeSharingElement = `
+        <dl>
+          <dt></dt>
+          <dd>
+              <button class="shareDialogNativeButton" data-url="${StringUtil.escapeHTML(target.href)}" data-title="${StringUtil.escapeHTML(target.dataset.linkTitle || "")}">${Language.get("wcf.message.share.nativeShare")}</button>
+          </dd>
+        </dl>
       `;
             }
             const dialogContent = `
       <div class="shareContentDialog">
         ${getDialogElements(target)}
         ${providerElement}
+        ${nativeSharingElement}
       </div>
     `;
             const dialogData = Dialog_1.default.openStatic(dialogId, dialogContent, {
@@ -114,6 +141,9 @@ define(["require", "exports", "tslib", "../../Dialog", "../../../Dom/Util", "../
             dialogData.content
                 .querySelectorAll(".shareDialogCopyButton")
                 .forEach((el) => el.addEventListener("click", (ev) => copy(ev)));
+            if (offerNativeSharing) {
+                dialogData.content.querySelector(".shareDialogNativeButton").addEventListener("click", (ev) => nativeShare(ev));
+            }
             if (providerButtons) {
                 UiMessageShare.init();
             }
index 2215a10ef8da2cfb7da9ce8d16d1c55b420afffe..59b0bc2c67c7b2dca741b02f42aacc8b661859bc 100644 (file)
@@ -4221,6 +4221,7 @@ Dateianhänge:
                <item name="wcf.message.share.socialMedia"><![CDATA[Social Media]]></item>
                <item name="wcf.message.share.copy"><![CDATA[Code kopieren]]></item>
                <item name="wcf.message.share.copy.success"><![CDATA[Der Code wurde erfolgreich kopiert.]]></item>
+               <item name="wcf.message.share.nativeShare"><![CDATA[Weitere Optionen]]></item>
                <item name="wcf.message.smilies"><![CDATA[Smileys]]></item>
                <item name="wcf.message.button.extendedReply"><![CDATA[Erweiterte Antwort]]></item>
                <item name="wcf.message.button.extendedEdit"><![CDATA[Erweiterte Bearbeitung]]></item>
index f55155d0c1ef544fcaab3cec382f879393c0ed66..883aa69dfc04a19afe8b53e8d3b0ea1face7151b 100644 (file)
@@ -4168,6 +4168,7 @@ Attachments:
                <item name="wcf.message.share.socialMedia"><![CDATA[Social Media]]></item>
                <item name="wcf.message.share.copy"><![CDATA[Copy Code]]></item>
                <item name="wcf.message.share.copy.success"><![CDATA[The code has been successfully copied.]]></item>
+               <item name="wcf.message.share.nativeShare"><![CDATA[More Options]]></item>
                <item name="wcf.message.smilies"><![CDATA[Smilies]]></item>
                <item name="wcf.message.button.extendedReply"><![CDATA[More Options]]></item>
                <item name="wcf.message.button.extendedEdit"><![CDATA[More Options]]></item>