Kaynağa Gözat

feat: add qr code to live session share dialog. (#10588)

* add qr code to live session share dialog

* use uqr

---------

Co-authored-by: dwelle <[email protected]>
kish dizon 18 saat önce
ebeveyn
işleme
0586fc138c

+ 1 - 0
excalidraw-app/package.json

@@ -36,6 +36,7 @@
     "react": "19.0.0",
     "react-dom": "19.0.0",
     "socket.io-client": "4.7.2",
+    "uqr": "0.1.2",
     "vite-plugin-html": "3.2.2"
   },
   "prettier": "@excalidraw/prettier-config",

+ 56 - 0
excalidraw-app/share/QRCode.tsx

@@ -0,0 +1,56 @@
+import { useEffect, useState } from "react";
+import Spinner from "@excalidraw/excalidraw/components/Spinner";
+
+interface QRCodeProps {
+  value: string;
+}
+
+export const QRCode = ({ value }: QRCodeProps) => {
+  const [svgData, setSvgData] = useState<string | null>(null);
+  const [error, setError] = useState<boolean>(false);
+
+  useEffect(() => {
+    let mounted = true;
+
+    import("./qrcode.chunk")
+      .then(({ generateQRCodeSVG }) => {
+        if (mounted) {
+          try {
+            setSvgData(generateQRCodeSVG(value));
+          } catch {
+            setError(true);
+          }
+        }
+      })
+      .catch(() => {
+        if (mounted) {
+          setError(true);
+        }
+      });
+
+    return () => {
+      mounted = false;
+    };
+  }, [value]);
+
+  if (error) {
+    return null;
+  }
+
+  if (!svgData) {
+    return (
+      <div className="ShareDialog__active__qrcode ShareDialog__active__qrcode--loading">
+        <Spinner />
+      </div>
+    );
+  }
+
+  return (
+    <div
+      className="ShareDialog__active__qrcode"
+      role="img"
+      aria-label="QR code for collaboration link"
+      dangerouslySetInnerHTML={{ __html: svgData }}
+    />
+  );
+};

+ 25 - 0
excalidraw-app/share/ShareDialog.scss

@@ -140,6 +140,31 @@
         gap: 0.75rem;
       }
 
+      &__qrcode {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        align-self: center;
+        padding: 1rem;
+        background: #fff;
+        border-radius: 0.5rem;
+        border: 1px solid #e0e0e0;
+
+        $size: 150px;
+        width: $size;
+        height: $size;
+
+        & svg {
+          width: $size;
+          height: $size;
+        }
+
+        &--loading {
+          background: var(--island-bg-color);
+          border: 1px solid var(--dialog-border-color);
+        }
+      }
+
       &__description {
         border-top: 1px solid var(--color-gray-20);
 

+ 2 - 0
excalidraw-app/share/ShareDialog.tsx

@@ -22,6 +22,7 @@ import { atom, useAtom, useAtomValue } from "../app-jotai";
 import { activeRoomLinkAtom } from "../collab/Collab";
 
 import "./ShareDialog.scss";
+import { QRCode } from "./QRCode";
 
 import type { CollabAPI } from "../collab/Collab";
 
@@ -142,6 +143,7 @@ const ActiveRoomDialog = ({
           }}
         />
       </div>
+      <QRCode value={activeRoomLink} />
       <div className="ShareDialog__active__description">
         <p>
           <span

+ 5 - 0
excalidraw-app/share/qrcode.chunk.ts

@@ -0,0 +1,5 @@
+import { renderSVG } from "uqr";
+
+export const generateQRCodeSVG = (text: string): string => {
+  return renderSVG(text);
+};

+ 5 - 0
yarn.lock

@@ -9409,6 +9409,11 @@ update-browserslist-db@^1.1.1:
     escalade "^3.2.0"
     picocolors "^1.1.1"
 
[email protected]:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/uqr/-/uqr-0.1.2.tgz#5c6cd5dcff9581f9bb35b982cb89e2c483a41d7d"
+  integrity sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==
+
 uri-js@^4.2.2:
   version "4.4.1"
   resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"