Skip to content

WIP: Playing around with QR codes on multiplayer experience #779

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

thomshutt
Copy link
Contributor

@thomshutt thomshutt commented Jun 6, 2025

PR Type

Enhancement


Description

  • Add reusable QRCodeComponent for canvas

  • Embed QR codes in VideoSection overlay

  • Dynamically build mobile prompt stream URL

  • Install qrcode and @types/qrcode dependencies


Changes walkthrough 📝

Relevant files
Enhancement
QRCode.tsx
Add reusable QRCodeComponent                                                         

apps/app/components/QRCode.tsx

  • Create QRCodeComponent functional component
  • Use qrcode.toCanvas for canvas rendering
  • Expose url, size, className props
  • Handle and log generation errors
  • +50/-0   
    VideoSection.tsx
    Embed QR code overlay in video section                                     

    apps/app/components/home/VideoSection.tsx

  • Import and render QRCodeComponent
  • Conditionally overlay QR on video load
  • Build prompt URL with streamId
  • Apply opacity hover effects
  • +12/-0   
    Dependencies
    package.json
    Install qrcode package in app                                                       

    apps/app/package.json

    • Add qrcode dependency
    • Add @types/qrcode typing dependency
    +2/-0     
    package.json
    Install qrcode package in root                                                     

    package.json

  • Add qrcode to root dependencies
  • Add @types/qrcode to root dependencies
  • +3/-1     
    pnpm-lock.yaml
    Update lockfile with qrcode packages                                         

    pnpm-lock.yaml

  • Add qrcode lockfile entries
  • Add @types/qrcode lockfile entries
  • Update resolutions and integrity hashes
  • +21/-0   

    Need help?
  • Type /help how to ... in the comments thread for any questions about PR-Agent usage.
  • Check out the documentation for more information.
  • Copy link

    vercel bot commented Jun 6, 2025

    The latest updates on your projects. Learn more about Vercel for Git ↗︎

    Name Status Preview Comments Updated (UTC)
    pipelines-app ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 6, 2025 9:35pm

    Copy link

    github-actions bot commented Jun 6, 2025

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
    🧪 No relevant tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    Accessibility

    The QR code canvas lacks an accessible label or fallback description, making it unreadable by screen readers. Add an aria-label or visually hidden text to describe the QR code.

    <canvas
      ref={canvasRef}
      className="block"
      style={{ width: size, height: size }}
    />
    SSR Hydration

    The url prop uses window.location.origin during render, which differs between server and client. Resolve the origin inside a client-only effect or memoize it to prevent hydration mismatches.

    <QRCodeComponent
      url={`${typeof window !== "undefined" ? window.location.origin : ""}/stream/${currentStream.streamId}/prompt`}
      size={80}
      className="opacity-90 hover:opacity-100 transition-opacity"
    />
    Missing Tests

    No unit or integration tests were added for the new QRCodeComponent. Adding tests would help ensure QR code generation and rendering work correctly across scenarios.

    "use client";
    
    import { useEffect, useRef } from "react";
    import QRCode from "qrcode";
    
    interface QRCodeProps {
      url: string;
      size?: number;
      className?: string;
    }
    
    export function QRCodeComponent({
      url,
      size = 80,
      className = "",
    }: QRCodeProps) {
      const canvasRef = useRef<HTMLCanvasElement>(null);
    
      useEffect(() => {
        if (!canvasRef.current || !url) return;
    
        QRCode.toCanvas(
          canvasRef.current,
          url,
          {
            width: size,
            margin: 1,
            color: {
              dark: "#000000",
              light: "#FFFFFF",
            },
          },
          error => {
            if (error) {
              console.error("QR Code generation error:", error);
            }
          },
        );
      }, [url, size]);
    
      return (
        <div className={`bg-white p-2 rounded-lg shadow-lg ${className}`}>
          <canvas
            ref={canvasRef}
            className="block"
            style={{ width: size, height: size }}
          />
        </div>
      );
    }

    Copy link

    github-actions bot commented Jun 6, 2025

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Impact
    General
    Set canvas element dimensions

    Explicitly set the canvas width and height attributes to match the drawing size to
    avoid blurry or distorted QR codes. This ensures the drawing buffer matches the
    CSS-rendered dimensions.

    apps/app/components/QRCode.tsx [43-47]

     <canvas
       ref={canvasRef}
       className="block"
    +  width={size}
    +  height={size}
       style={{ width: size, height: size }}
     />
    Suggestion importance[1-10]: 7

    __

    Why: The canvas without explicit width/height attributes will be scaled via CSS and can look blurry; adding matching attributes ensures a crisp QR render.

    Medium
    Possible issue
    Delay QR render until mounted

    Prevent rendering the QR code before the component is mounted to avoid generating an
    incomplete URL (""/stream/...) during SSR and causing hydration mismatches.
    Introduce a mounted flag with useEffect and render only when mounted is true.

    apps/app/components/home/VideoSection.tsx [69-77]

    -{currentStream && (
    +const [mounted, setMounted] = useState(false);
    +useEffect(() => { setMounted(true); }, []);
    +...
    +{mounted && currentStream && (
       <div className="absolute top-4 left-4 z-40">
         <QRCodeComponent
    -      url={`${typeof window !== "undefined" ? window.location.origin : ""}/stream/${currentStream.streamId}/prompt`}
    +      url={`${window.location.origin}/stream/${currentStream.streamId}/prompt`}
           size={80}
           className="opacity-90 hover:opacity-100 transition-opacity"
         />
       </div>
     )}
    Suggestion importance[1-10]: 7

    __

    Why: Introducing a mounted flag avoids SSR/client URL mismatches (empty origin vs. actual window.location.origin), preventing hydration errors during rendering.

    Medium
    Clear canvas on empty URL

    Clear the canvas when url is empty to avoid leaving a stale QR image. Move the url
    check into a branch that clears the drawing context before returning.

    apps/app/components/QRCode.tsx [19-39]

     useEffect(() => {
    -  if (!canvasRef.current || !url) return;
    +  if (!canvasRef.current) return;
    +  if (!url) {
    +    const ctx = canvasRef.current.getContext("2d");
    +    ctx?.clearRect(0, 0, canvasRef.current.width, canvasRef.current.height);
    +    return;
    +  }
       QRCode.toCanvas(
         canvasRef.current,
         url,
         { width: size, margin: 1, color: { dark: "#000000", light: "#FFFFFF" } },
         error => { if (error) console.error("QR Code generation error:", error); },
       );
     }, [url, size]);
    Suggestion importance[1-10]: 5

    __

    Why: Clearing the canvas when url is falsy prevents leftover QR images from persisting, but it's a minor UX improvement rather than a critical fix.

    Low

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    1 participant