From fc4bb5ed66d266bc16e1fcf923f560680e8a5775 Mon Sep 17 00:00:00 2001 From: fusagiko / takayamaki <24884114+takayamaki@users.noreply.github.com> Date: Tue, 2 May 2023 19:54:00 +0900 Subject: [PATCH] Add type annotation for Blurhash component (#24750) --- .../mastodon/components/blurhash.jsx | 65 ------------------- .../mastodon/components/blurhash.tsx | 45 +++++++++++++ 2 files changed, 45 insertions(+), 65 deletions(-) delete mode 100644 app/javascript/mastodon/components/blurhash.jsx create mode 100644 app/javascript/mastodon/components/blurhash.tsx diff --git a/app/javascript/mastodon/components/blurhash.jsx b/app/javascript/mastodon/components/blurhash.jsx deleted file mode 100644 index f5c58e04ef..0000000000 --- a/app/javascript/mastodon/components/blurhash.jsx +++ /dev/null @@ -1,65 +0,0 @@ -// @ts-check - -import { decode } from 'blurhash'; -import React, { useRef, useEffect } from 'react'; -import PropTypes from 'prop-types'; - -/** - * @typedef BlurhashPropsBase - * @property {string?} hash Hash to render - * @property {number} width - * Width of the blurred region in pixels. Defaults to 32 - * @property {number} [height] - * Height of the blurred region in pixels. Defaults to width - * @property {boolean} [dummy] - * Whether dummy mode is enabled. If enabled, nothing is rendered - * and canvas left untouched - */ - -/** @typedef {JSX.IntrinsicElements['canvas'] & BlurhashPropsBase} BlurhashProps */ - -/** - * Component that is used to render blurred of blurhash string - * @param {BlurhashProps} param1 Props of the component - * @returns {JSX.Element} Canvas which will render blurred region element to embed - */ -function Blurhash({ - hash, - width = 32, - height = width, - dummy = false, - ...canvasProps -}) { - const canvasRef = /** @type {import('react').MutableRefObject} */ (useRef()); - - useEffect(() => { - const { current: canvas } = canvasRef; - canvas.width = canvas.width; // resets canvas - - if (dummy || !hash) return; - - try { - const pixels = decode(hash, width, height); - const ctx = canvas.getContext('2d'); - const imageData = new ImageData(pixels, width, height); - - // @ts-expect-error - ctx.putImageData(imageData, 0, 0); - } catch (err) { - console.error('Blurhash decoding failure', { err, hash }); - } - }, [dummy, hash, width, height]); - - return ( - - ); -} - -Blurhash.propTypes = { - hash: PropTypes.string.isRequired, - width: PropTypes.number, - height: PropTypes.number, - dummy: PropTypes.bool, -}; - -export default React.memo(Blurhash); diff --git a/app/javascript/mastodon/components/blurhash.tsx b/app/javascript/mastodon/components/blurhash.tsx new file mode 100644 index 0000000000..6fec6e1ef7 --- /dev/null +++ b/app/javascript/mastodon/components/blurhash.tsx @@ -0,0 +1,45 @@ +import { decode } from 'blurhash'; +import React, { useRef, useEffect } from 'react'; + +type Props = { + hash: string; + width?: number; + height?: number; + dummy?: boolean; // Whether dummy mode is enabled. If enabled, nothing is rendered and canvas left untouched + children?: never; + [key: string]: any; +} +function Blurhash({ + hash, + width = 32, + height = width, + dummy = false, + ...canvasProps +}: Props) { + const canvasRef = useRef(null); + + useEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const canvas = canvasRef.current!; + // eslint-disable-next-line no-self-assign + canvas.width = canvas.width; // resets canvas + + if (dummy || !hash) return; + + try { + const pixels = decode(hash, width, height); + const ctx = canvas.getContext('2d'); + const imageData = new ImageData(pixels, width, height); + + ctx?.putImageData(imageData, 0, 0); + } catch (err) { + console.error('Blurhash decoding failure', { err, hash }); + } + }, [dummy, hash, width, height]); + + return ( + + ); +} + +export default React.memo(Blurhash);