DEV Community

Cover image for Build a Secretkeeper app and generate QR code for your message
Satyam Kumar
Satyam Kumar

Posted on

Build a Secretkeeper app and generate QR code for your message

Summary:

Secretkeeper app let you generate a QR code for your text message which you can share and download and when you scan that QR code with scanner you will get the text message.It is a React+Vite+Typescript app which uses react-qr-code package for generating QR code.

Prerequisites#

  • Basic knowledge of React.js
  • Basic Typescript
  • Tailwind css

To create vite application with react template follow these commands:

Terminal

$npx create-vite secretkeeper
Enter fullscreen mode Exit fullscreen mode

After that choose React template and then choose typescript and press enter.

Now move to secretkeeper directory in terminal or open that folder in terminal directly.

Terminal

$cd secretkeeper
Enter fullscreen mode Exit fullscreen mode

Setup tailwind css in our project#

To setup tailwind css the best way is ofcourse go through tailwind css docs https://tailwindcss.com/docs/guides/vite

Make sure to add content in tailwind.config.js

tailwind.config.js

/** @type {import('tailwindcss').Config} */
export default {
  content: ["./src/**/*.{html,js,ts,jsx,tsx}"],
  theme: {
    extend: {},
  },
  plugins: [],
};
Enter fullscreen mode Exit fullscreen mode

Now, install all of the dependencies needed to build this app:

Terminal

npm install @iconify/react html-to-image react-qr-code 
Enter fullscreen mode Exit fullscreen mode

Documentation related to these packages:

Delete everything from App.tsx in src directory and code it as:

App.tsx

import React from "react";
import QRCodeGenerator from "./Qrcode";

import "./index.css";

const App: React.FC = () => {
  return (
    <div className="flex items-center justify-center w-screen h-screen bg-red-200 App">
      <div className="w-[400px] max-[700px]:w-full max-[700px]:h-full py-8  bg-[#FFBBBB]
     flex flex-col items-center relative">
        <h1 className="text-xl">SecretKeeper</h1>
        <QRCodeGenerator />
      </div>
    </div>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

In App.tsx we import Qrcode component as QRCodeGenerator.

Now we create Qrcode.jsx component in src directory.This component will include an input box for entering text messages and a button to generate a QR code. Additionally, it will provide options todownload the QR code as a PNG file or share it using the Web Share API.

Qrcode.tsx

import React, { useRef, useState } from "react";
import QRCode from "react-qr-code";
import { Icon } from "@iconify/react";
import * as htmlToImage from "html-to-image";

const QRCodeGenerator: React.FC = () => {
  const [inputValue, setInputValue] = useState<string>("");
  const [qrData, setQRData] = useState("");
  const [IsQrcode, setIsQrcode] = useState<boolean>(false);

  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setInputValue(e.target.value);
  };

  const qrRef = useRef(null);

  const generateQRCode = () => {
    // Generate your QR code data here, for example:
    setIsQrcode(true);
    setQRData(inputValue);
  };

  const downloadQRCode = async () => {
    if (!qrRef.current) return;

    const dataUrl = await htmlToImage.toPng(qrRef.current, {
      quality: 1,
      // width: qrRef.current.offsetWidth * 2,
      // height: qrRef.current.offsetHeight * 2,
    });

    // download image
    const link = document.createElement("a");
    link.download = "html-to-img.png";
    link.href = dataUrl;
    link.click();
  };

  const shareQRCode = () => {
    if (!qrRef.current) return;
    // Fallback for sharing via WhatsApp

    htmlToImage.toBlob(qrRef.current).then(function (blob) {
      if (!blob) return;
      const filesArray = [
        new File([blob], "qrcode.png", { type: "image/png" }),
      ];
      if (navigator.share) {
        navigator
          .share({
            files: filesArray,
            title: "QR Code",
            text: "Scan this QR code",
          })
          .then(() => console.log("Shared successfully"))
          .catch((error) => console.error("Error sharing:", error));
      } else {
        // console.log("Web Share API not supported");
        const blobUrl = URL.createObjectURL(blob); // Convert Blob to a data URL
        const whatsappURL = `whatsapp://send?text=Scan this QR code&files=${encodeURIComponent(
          blobUrl
        )}`;

        // Fallback for sharing via email
        const emailBody = "Scan this QR code";
        const emailSubject = "QR Code";
        const emailURL = `mailto:?subject=${encodeURIComponent(
          emailSubject
        )}&body=${encodeURIComponent(emailBody)}`;
        // Open a new window to trigger the default email client
        window.open(emailURL);
        // Open WhatsApp if the device supports it
        window.location.href = whatsappURL;
      }
    });
  };

  return (
    <div className="relative flex flex-col items-center justify-center flex-1 w-full p-4">
      <input
        className="w-full p-4 border-none outline-none"
        type="text"
        value={inputValue}
        onChange={handleInputChange}
        placeholder="Enter text for QR code"
      />
      <button
        className="px-4 py-2 my-4 bg-white border-none outline-none"
        onClick={generateQRCode}
      >
        Generate QRCode
      </button>
      {IsQrcode && (
        <div className="flex justify-between w-full my-4 ">
          <div className="qrcode">
            <QRCode
              style={{
                background: "white",

                border: "2px solid black", // Set border style
                padding: "10px", // Add some padding for better appearance
                display: "inline-block", // Ensure the container wraps QR code
              }}
              ref={qrRef}
              className="w-[150px] h-[150px] rounded-md"
              value={qrData}
            />
          </div>
          <div className="flex items-center justify-center buttons">
            <button
              className="p-2 mx-4 bg-white rounded-full download"
              onClick={downloadQRCode}
            >
              <Icon
                className="w-10 h-10"
                icon="material-symbols:download-sharp"
              />
            </button>
            <button
              className="p-2 mx-4 bg-white rounded-full send"
              onClick={shareQRCode}
            >
              <Icon className="w-10 h-10" icon="bitcoin-icons:share-filled" />
            </button>
          </div>
        </div>
      )}
    </div>
  );
};

export default QRCodeGenerator;

Enter fullscreen mode Exit fullscreen mode

In this file we have used React useRef Hook to refer qrcode html element.qrRef is refering to QRCode html element so that we can download it using html-to-tmage package and share it.

Here we imported QRCode from react-qr-code package.To generate QRCode using this package we just need to pass a prop value={qrData}, qrData is the message we want to encode as QRCode.


Then we created a function handleInputChange for contorolled input box and other function generateQRCode, generate QRCode button will call this function onclick and this will set isqrcode=true so that qrcode will be visible on the page and also setQRData(inputValue) using Reacthook. Then we will use qrData to generate QRCode.

Basically there is two more function one for downloading QRCode as png and other for sharing using Web Share API.

d

  • ownloadQRCode( ): This function invoked when user click on download button and then uses html-to-image package to generate png of QRCode and it will be automatically downloaded using anchor tag.
  • shareQRCode( ): In the context of the htmlToImage.toBlob() function, it converts the content of an HTML element (in this case, the QR code container) into an image Blob. This Blob can then be used for various purposes, such as downloading the image or sharing it via the Web Share API.

I hope you like this post, don't forget to follow me for more
exciting post like this.

Git Repo:
https://github.com/silentvoice143/secretkeeper

........Thanks........

Top comments (0)