<commit_before>// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

import type { ReactElement } from 'react';
import React, { useEffect, useMemo, useRef } from 'react';
import qrcode from 'qrcode-generator';
import { strictAssert } from '../util/assert';
import { useDevicePixelRatio } from '../hooks/useDevicePixelRatio';

const AUTODETECT_TYPE_NUMBER = 0;
const ERROR_CORRECTION_LEVEL = 'L';

type PropsType = Readonly<{
  'aria-label': string;
  className?: string;
  data: string;
  size: number;
}>;

export function QrCode(props: PropsType): ReactElement {
  // I don't think it's possible to destructure this.
  // eslint-disable-next-line react/destructuring-assignment
  const ariaLabel = props['aria-label'];
  const { className, data, size } = props;

  const qrCode = useMemo(() => {
    const result = qrcode(AUTODETECT_TYPE_NUMBER, ERROR_CORRECTION_LEVEL);
    result.addData(data);
    result.make();
    return result;
  }, [data]);

  const canvasRef = useRef<null | HTMLCanvasElement>(null);
  const dpi = useDevicePixelRatio();
  const canvasSize = size * dpi;

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) {
      return;
    }

    const context = canvas.getContext('2d');
    strictAssert(context, 'Expected a canvas context');

    const cellSize = canvasSize / qrCode.getModuleCount();
    context.clearRect(0, 0, canvasSize, canvasSize);
    qrCode.renderTo2dContext(context, cellSize);
  }, [canvasSize, qrCode]);

  return (
    <canvas
      aria-label={ariaLabel}
      className={className}
      height={canvasSize}
      ref={canvasRef}
      style={{ width: size, height: size }}
      width={canvasSize}
    />
  );
}<commit_msg>In non-production builds, copy the linking QR code on double-click<commit_after>// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

import type { ReactElement } from 'react';
import React, { useEffect, useMemo, useRef } from 'react';
import qrcode from 'qrcode-generator';
import { getEnvironment, Environment } from '../environment';
import { strictAssert } from '../util/assert';
import { useDevicePixelRatio } from '../hooks/useDevicePixelRatio';

const AUTODETECT_TYPE_NUMBER = 0;
const ERROR_CORRECTION_LEVEL = 'L';

type PropsType = Readonly<{
  'aria-label': string;
  className?: string;
  data: string;
  size: number;
}>;

export function QrCode(props: PropsType): ReactElement {
  // I don't think it's possible to destructure this.
  // eslint-disable-next-line react/destructuring-assignment
  const ariaLabel = props['aria-label'];
  const { className, data, size } = props;

  const qrCode = useMemo(() => {
    const result = qrcode(AUTODETECT_TYPE_NUMBER, ERROR_CORRECTION_LEVEL);
    result.addData(data);
    result.make();
    return result;
  }, [data]);

  const canvasRef = useRef<null | HTMLCanvasElement>(null);
  const dpi = useDevicePixelRatio();
  const canvasSize = size * dpi;

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) {
      return;
    }

    const context = canvas.getContext('2d');
    strictAssert(context, 'Expected a canvas context');

    const cellSize = canvasSize / qrCode.getModuleCount();
    context.clearRect(0, 0, canvasSize, canvasSize);
    qrCode.renderTo2dContext(context, cellSize);
  }, [canvasSize, qrCode]);

  // Add a development-only feature to copy a QR code to the clipboard by double-clicking.
  // This can be used to quickly inspect the code, or to link this Desktop with an iOS
  // simulator primary, which has a debug-only option to paste the linking URL instead of
  // scanning it. (By the time you read this comment Android may have a similar feature.)
  const onDoubleClick = () => {
    if (getEnvironment() === Environment.Production) {
      return;
    }

    navigator.clipboard.writeText(data);

    const canvas = canvasRef.current;
    if (!canvas) {
      return;
    }
    canvas.style.filter = 'brightness(50%)';
    window.setTimeout(() => {
      canvas.style.filter = '';
    }, 150);
  };

  return (
    <canvas
      aria-label={ariaLabel}
      className={className}
      height={canvasSize}
      ref={canvasRef}
      style={{ width: size, height: size }}
      width={canvasSize}
      onDoubleClick={onDoubleClick}
    />
  );
}
{'fraction_non_alphanumeric': 0.1271461716937355, 'fraction_numerical': 0.0062645011600928075, 'mean_word_length': 3.5959488272921107, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3710388', 'n_tokens_mistral': 1355, 'n_tokens_neox': 1301, 'n_words': 361}