diff --git a/src/components/article/ThumbHashImage.jsx b/src/components/article/ThumbHashImage.jsx
index b73a18c..a7e8d69 100644
--- a/src/components/article/ThumbHashImage.jsx
+++ b/src/components/article/ThumbHashImage.jsx
@@ -1,126 +1,27 @@
-import { useEffect, useRef } from 'react';
+import { PureComponent } from 'react';
import Box from '@mui/material/Box';
-import { thumbHashToRGBA, thumbHashToDataURL } from 'thumbhash';
+import { thumbHashToDataURL } from 'thumbhash';
-const dataUrlCache = (globalThis.__THUMB_DATA_URL_CACHE__ ??= new Map());
-const loadedImageHashes = (globalThis.__LOADED_IMAGE_HASHES__ ??= new Set());
-export const imageCache = (globalThis.__IMAGE_CACHE__ ??= new Map());
+export default class ThumbHashImage extends PureComponent {
+ constructor(props) {
+ super(props);
+ const bytes = Uint8Array.from(atob(props.thumbHash), (c) => c.charCodeAt(0));
+ this.url = thumbHashToDataURL(bytes);
+ }
-export function isImageLoaded(fullHash) {
- if (!fullHash) return false;
- return loadedImageHashes.has(fullHash) || imageCache.has(fullHash);
-}
-
-export function markImageLoaded(fullHash, img) {
- if (!fullHash) return;
- loadedImageHashes.add(fullHash);
- if (img) {
- imageCache.set(fullHash, img);
+ render() {
+ return (
+
+ );
}
}
-
-export function getCachedImage(fullHash) {
- if (!fullHash) return null;
- const img = imageCache.get(fullHash);
- if (img && img.complete && img.naturalWidth) {
- return img;
- }
- return null;
-}
-
-export function getThumbHashDataUrl(thumbHash) {
- if (!thumbHash || typeof thumbHash !== 'string') return null;
- let url = dataUrlCache.get(thumbHash);
- if (!url) {
- try {
- const bytes = Uint8Array.from(atob(thumbHash), (c) => c.charCodeAt(0));
- url = thumbHashToDataURL(bytes);
- dataUrlCache.set(thumbHash, url);
- } catch (err) {
- console.warn('[ThumbHashImage] thumbHashToDataURL failed:', err);
- return null;
- }
- }
- return url;
-}
-
-export function decodeThumbHash(thumbHash) {
- if (!thumbHash || typeof thumbHash !== 'string') return null;
- try {
- const bytes = Uint8Array.from(atob(thumbHash), (c) => c.charCodeAt(0));
- return thumbHashToRGBA(bytes);
- } catch (err) {
- console.warn('[ThumbHashImage] decode failed:', err);
- return null;
- }
-}
-
-export function getThumbHashDimensions(thumbHash) {
- const decoded = decodeThumbHash(thumbHash);
- if (!decoded) return null;
- return { w: decoded.w, h: decoded.h };
-}
-
-function paintThumbHash(canvas, thumbHash, explicitWidth, explicitHeight) {
- const parent = canvas.parentElement;
- const rect = parent ? parent.getBoundingClientRect() : null;
- const width = explicitWidth || rect?.width;
- const height = explicitHeight || rect?.height;
- if (!width || !height) return;
-
- const decoded = decodeThumbHash(thumbHash);
- if (!decoded) return;
- const { w, h, rgba } = decoded;
-
- const src = document.createElement('canvas');
- src.width = w;
- src.height = h;
- src.getContext('2d').putImageData(
- new ImageData(new Uint8ClampedArray(rgba), w, h),
- 0,
- 0,
- );
-
- canvas.width = Math.round(width);
- canvas.height = Math.round(height);
- const ctx = canvas.getContext('2d');
- if (!ctx) return;
-
- ctx.imageSmoothingEnabled = true;
- ctx.imageSmoothingQuality = 'high';
- ctx.drawImage(src, 0, 0, canvas.width, canvas.height);
-}
-
-export default function ThumbHashImage({ thumbHash, width, height, sx }) {
- const canvasRef = useRef(null);
-
- useEffect(() => {
- const canvas = canvasRef.current;
- if (!canvas || !thumbHash) return;
-
- paintThumbHash(canvas, thumbHash, width, height);
-
- const parent = canvas.parentElement;
- if (!parent || typeof ResizeObserver === 'undefined') return undefined;
-
- const observer = new ResizeObserver(() => {
- paintThumbHash(canvas, thumbHash, width, height);
- });
- observer.observe(parent);
- return () => observer.disconnect();
- }, [thumbHash, width, height]);
-
- return (
-
- );
-}
diff --git a/src/components/tiles/ArticleTile.jsx b/src/components/tiles/ArticleTile.jsx
index f2faf4f..aac760c 100644
--- a/src/components/tiles/ArticleTile.jsx
+++ b/src/components/tiles/ArticleTile.jsx
@@ -7,12 +7,6 @@ import { TILE_SIZE, Tile, tileBaseSx } from 'dashgui/tiles';
import { formatPrice, getArticleGross } from '../../utils/price';
import companyAutomat from '../../automats/companyAutomat';
import { articleSku } from '../article/articleRoute';
-import {
- getThumbHashDataUrl,
- getCachedImage,
- isImageLoaded,
- markImageLoaded,
-} from '../article/ThumbHashImage';
import { BrandLabel } from '../brand';
import { thumb } from '../../api';
import {
diff --git a/src/components/tiles/CategoryTile.jsx b/src/components/tiles/CategoryTile.jsx
index 9b97986..2382ed0 100644
--- a/src/components/tiles/CategoryTile.jsx
+++ b/src/components/tiles/CategoryTile.jsx
@@ -10,7 +10,6 @@ import PointOfSaleIcon from '@mui/icons-material/PointOfSale';
import PhotoCameraIcon from '@mui/icons-material/PhotoCamera';
import DeleteOutlinedIcon from '@mui/icons-material/DeleteOutlined';
import DeleteForeverOutlinedIcon from '@mui/icons-material/DeleteForeverOutlined';
-import { getThumbHashDataUrl, isImageLoaded, markImageLoaded } from '../article/ThumbHashImage';
import { thumb } from '../../api';
import { tileBaseSx } from 'dashgui/tiles';
import {
diff --git a/src/routes/artikel/marken.jsx b/src/routes/artikel/marken.jsx
index 0207474..103c882 100644
--- a/src/routes/artikel/marken.jsx
+++ b/src/routes/artikel/marken.jsx
@@ -1,5 +1,6 @@
import { PureComponent, createRef } from 'react';
import Box from '@mui/material/Box';
+import List from '@mui/material/List';
import CircularProgress from '@mui/material/CircularProgress';
import BackendError from '../../components/BackendError';
import FillSpace from 'dashgui/FillSpace';
@@ -78,6 +79,9 @@ class ArtikelMarkenPage extends PureComponent {
+
+ {brands[0] ? : null}
+
);
}