浏览代码

feat: Implement the Web Share API for the collaboration dialog (#3222)

* feat: Implement the Web Share API for the collaboration dialog

* Make requested changes
Arun 4 年之前
父节点
当前提交
6252b22b42
共有 3 个文件被更改,包括 54 次插入10 次删除
  1. 10 0
      src/components/icons.tsx
  2. 40 8
      src/excalidraw-app/collab/RoomDialog.tsx
  3. 4 2
      src/locales/en.json

+ 10 - 0
src/components/icons.tsx

@@ -113,6 +113,16 @@ export const questionCircle = createIcon(
   { mirror: true },
 );
 
+export const share = createIcon(
+  "M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z",
+  { width: 24, height: 24 },
+);
+
+export const shareIOS = createIcon(
+  "M16 5l-1.42 1.42-1.59-1.59V16h-1.98V4.83L9.42 6.42 8 5l4-4 4 4zm4 5v11c0 1.1-.9 2-2 2H6c-1.11 0-2-.9-2-2V10c0-1.11.89-2 2-2h3v2H6v11h12V10h-3V8h3c1.1 0 2 .89 2 2z",
+  { width: 24, height: 24 },
+);
+
 // Icon imported form Storybook
 // Storybook is licensed under MIT https://github.com/storybookjs/storybook/blob/next/LICENSE
 export const resetZoom = createIcon(

+ 40 - 8
src/excalidraw-app/collab/RoomDialog.tsx

@@ -1,10 +1,17 @@
 import React, { useRef } from "react";
 import { copyTextToSystemClipboard } from "../../clipboard";
 import { Dialog } from "../../components/Dialog";
-import { clipboard, start, stop } from "../../components/icons";
+import {
+  clipboard,
+  start,
+  stop,
+  share,
+  shareIOS,
+} from "../../components/icons";
 import { ToolButton } from "../../components/ToolButton";
 import { t } from "../../i18n";
 import "./RoomDialog.scss";
+import Stack from "../../components/Stack";
 
 const RoomDialog = ({
   handleClose,
@@ -24,6 +31,8 @@ const RoomDialog = ({
   setErrorMessage: (message: string) => void;
 }) => {
   const roomLinkInput = useRef<HTMLInputElement>(null);
+  const navigator = window.navigator as any;
+  const isAppleBrowser = /Apple/.test(navigator.vendor);
 
   const copyRoomLink = async () => {
     try {
@@ -36,6 +45,18 @@ const RoomDialog = ({
     }
   };
 
+  const shareRoomLink = async () => {
+    try {
+      await navigator.share({
+        title: t("roomDialog.shareTitle"),
+        text: t("roomDialog.shareTitle"),
+        url: activeRoomLink,
+      });
+    } catch (error) {
+      // Just ignore.
+    }
+  };
+
   const selectInput = (event: React.MouseEvent<HTMLInputElement>) => {
     if (event.target !== document.activeElement) {
       event.preventDefault();
@@ -68,13 +89,24 @@ const RoomDialog = ({
             <p>{t("roomDialog.desc_inProgressIntro")}</p>
             <p>{t("roomDialog.desc_shareLink")}</p>
             <div className="RoomDialog-linkContainer">
-              <ToolButton
-                type="button"
-                icon={clipboard}
-                title={t("labels.copy")}
-                aria-label={t("labels.copy")}
-                onClick={copyRoomLink}
-              />
+              <Stack.Row gap={2}>
+                {"share" in navigator ? (
+                  <ToolButton
+                    type="button"
+                    icon={isAppleBrowser ? shareIOS : share}
+                    title={t("labels.share")}
+                    aria-label={t("labels.share")}
+                    onClick={shareRoomLink}
+                  />
+                ) : null}
+                <ToolButton
+                  type="button"
+                  icon={clipboard}
+                  title={t("labels.copy")}
+                  aria-label={t("labels.copy")}
+                  onClick={copyRoomLink}
+                />
+              </Stack.Row>
               <input
                 value={activeRoomLink}
                 readOnly={true}

+ 4 - 2
src/locales/en.json

@@ -93,7 +93,8 @@
     "distributeHorizontally": "Distribute horizontally",
     "distributeVertically": "Distribute vertically",
     "viewMode": "View mode",
-    "toggleExportColorScheme": "Toggle export color scheme"
+    "toggleExportColorScheme": "Toggle export color scheme",
+    "share": "Share"
   },
   "buttons": {
     "clearReset": "Reset the canvas",
@@ -199,7 +200,8 @@
     "button_stopSession": "Stop session",
     "desc_inProgressIntro": "Live-collaboration session is now in progress.",
     "desc_shareLink": "Share this link with anyone you want to collaborate with:",
-    "desc_exitSession": "Stopping the session will disconnect you from the room, but you'll be able to continue working with the scene, locally. Note that this won't affect other people, and they'll still be able to collaborate on their version."
+    "desc_exitSession": "Stopping the session will disconnect you from the room, but you'll be able to continue working with the scene, locally. Note that this won't affect other people, and they'll still be able to collaborate on their version.",
+    "shareTitle": "Join a live collaboration session on Excalidraw"
   },
   "errorDialog": {
     "title": "Error"