diff --git a/excalidraw-app/package.json b/excalidraw-app/package.json index 8d5a066e53..0c8446b569 100644 --- a/excalidraw-app/package.json +++ b/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", diff --git a/excalidraw-app/share/QRCode.tsx b/excalidraw-app/share/QRCode.tsx new file mode 100644 index 0000000000..4418328319 --- /dev/null +++ b/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(null); + const [error, setError] = useState(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 ( +
+ +
+ ); + } + + return ( +
+ ); +}; diff --git a/excalidraw-app/share/ShareDialog.scss b/excalidraw-app/share/ShareDialog.scss index 436f411248..169cc03bd1 100644 --- a/excalidraw-app/share/ShareDialog.scss +++ b/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); diff --git a/excalidraw-app/share/ShareDialog.tsx b/excalidraw-app/share/ShareDialog.tsx index 884d64680d..051393910a 100644 --- a/excalidraw-app/share/ShareDialog.tsx +++ b/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 = ({ }} />
+

{ + return renderSVG(text); +}; diff --git a/yarn.lock b/yarn.lock index edd96b0405..87eead8543 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9409,6 +9409,11 @@ update-browserslist-db@^1.1.1: escalade "^3.2.0" picocolors "^1.1.1" +uqr@0.1.2: + 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"