This commit is contained in:
seb
2026-10-28 21:55:24 +01:00
parent 2e69f49e4d
commit 87ef79bea3
3 changed files with 58 additions and 3 deletions

View File

@@ -120,6 +120,12 @@ function toIndexRecord(article, categoryId) {
? String(categoryId) ? String(categoryId)
: (Array.isArray(article.categoryIds) ? article.categoryIds.join(',') : (article.categories ?? null)); : (Array.isArray(article.categoryIds) ? article.categoryIds.join(',') : (article.categories ?? null));
const firstPhoto = Array.isArray(article.photos) && article.photos.length > 0 ? article.photos[0] : null;
const fullHash = article.fullHash ?? firstPhoto?.fullHash ?? null;
const thumbHash = article.thumbHash ?? firstPhoto?.thumbHash ?? null;
const smallThumbBinary = article.smallThumbBinary ?? firstPhoto?.smallThumbBinary ?? null;
const photos = article.photos ?? (fullHash ? [{ fullHash, thumbHash }] : []);
return { return {
...article, ...article,
id: article.id, id: article.id,
@@ -137,6 +143,10 @@ function toIndexRecord(article, categoryId) {
categories, categories,
isParent: Boolean(article.isParent ?? article.is_parent ?? (childCount > 0)), isParent: Boolean(article.isParent ?? article.is_parent ?? (childCount > 0)),
childCount, childCount,
fullHash,
thumbHash,
photos,
smallThumbBinary,
}; };
} }
@@ -377,14 +387,24 @@ export function updateArticleIndexRecord(article) {
let nextItems; let nextItems;
if (existingIndex >= 0) { if (existingIndex >= 0) {
const existing = items[existingIndex]; const existing = items[existingIndex];
const firstPhoto = Array.isArray(article.photos) && article.photos.length > 0 ? article.photos[0] : null;
const hasPhotosProp = 'photos' in article;
const fullHash = article.fullHash ?? firstPhoto?.fullHash ?? (hasPhotosProp ? null : existing.fullHash);
const thumbHash = article.thumbHash ?? firstPhoto?.thumbHash ?? (hasPhotosProp ? null : existing.thumbHash);
const photos = article.photos ?? (hasPhotosProp ? [] : (existing.photos ?? []));
const smallThumbBinary = article.smallThumbBinary ?? firstPhoto?.smallThumbBinary ?? (hasPhotosProp ? null : existing.smallThumbBinary);
nextItems = [...items]; nextItems = [...items];
nextItems[existingIndex] = { nextItems[existingIndex] = {
...existing, ...existing,
...record, ...record,
categories: record.categories ?? existing.categories, categories: record.categories ?? existing.categories,
smallThumbBinary: article.smallThumbBinary ?? article.photos?.[0]?.smallThumbBinary ?? existing.smallThumbBinary,
brand: article.brand ?? existing.brand, brand: article.brand ?? existing.brand,
brandName: article.brand?.name ?? article.brandName ?? existing.brandName, brandName: article.brand?.name ?? article.brandName ?? existing.brandName,
fullHash,
thumbHash,
photos,
smallThumbBinary,
}; };
} else { } else {
nextItems = [...items, record]; nextItems = [...items, record];

View File

@@ -352,6 +352,13 @@ export function updateArticleInCategoryViews(article) {
// Update in-place // Update in-place
const existing = item.data.articles[existingIndex]; const existing = item.data.articles[existingIndex];
const updatedArticles = [...item.data.articles]; const updatedArticles = [...item.data.articles];
const firstPhoto = Array.isArray(article.photos) && article.photos.length > 0 ? article.photos[0] : null;
const hasPhotosProp = 'photos' in article;
const fullHash = article.fullHash ?? firstPhoto?.fullHash ?? (hasPhotosProp ? null : existing.fullHash);
const thumbHash = article.thumbHash ?? firstPhoto?.thumbHash ?? (hasPhotosProp ? null : existing.thumbHash);
const photos = article.photos ?? (hasPhotosProp ? [] : (existing.photos ?? []));
const smallThumbBinary = article.smallThumbBinary ?? firstPhoto?.smallThumbBinary ?? (hasPhotosProp ? null : existing.smallThumbBinary);
updatedArticles[existingIndex] = { updatedArticles[existingIndex] = {
...existing, ...existing,
...article, ...article,
@@ -365,6 +372,10 @@ export function updateArticleInCategoryViews(article) {
brandName: article.brand?.name ?? article.brandName ?? existing.brandName, brandName: article.brand?.name ?? article.brandName ?? existing.brandName,
childCount: article.childCount ?? existing.childCount, childCount: article.childCount ?? existing.childCount,
isParent: Boolean(article.childCount > 0 || article.isParent || existing.isParent), isParent: Boolean(article.childCount > 0 || article.isParent || existing.isParent),
fullHash,
thumbHash,
photos,
smallThumbBinary,
}; };
categoryViews.key(slug).set({ categoryViews.key(slug).set({
...item.data, ...item.data,

View File

@@ -22,6 +22,8 @@ import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
import articleSearchAutomat from '../automats/articleSearchAutomat'; import articleSearchAutomat from '../automats/articleSearchAutomat';
import BackendError from '../components/BackendError'; import BackendError from '../components/BackendError';
import { formatPrice, getArticleGross } from '../utils/price'; import { formatPrice, getArticleGross } from '../utils/price';
import { thumb } from '../api';
import { getThumbHashDataUrl } from '../utils/thumbHashCache';
import { import {
buildSearchUrl, buildSearchUrl,
queryFromParams, queryFromParams,
@@ -110,6 +112,15 @@ class ResultRow extends Component {
const showChildBadge = isParent || childCount > 0; const showChildBadge = isParent || childCount > 0;
const price = getArticleGross(row, companyAutomat.state.current?.taxrate); const price = getArticleGross(row, companyAutomat.state.current?.taxrate);
const firstPhoto = Array.isArray(row.photos) && row.photos.length > 0 ? row.photos[0] : null;
const fullHash = row.fullHash ?? firstPhoto?.fullHash ?? null;
const thumbHash = row.thumbHash ?? firstPhoto?.thumbHash ?? null;
const smallThumbBinary = row.smallThumbBinary ?? firstPhoto?.smallThumbBinary ?? null;
const thumbSrc = smallThumbBinary
? `data:image/avif;base64,${smallThumbBinary}`
: (fullHash ? thumb.url(fullHash) : null);
const thumbHashUrl = thumbHash ? getThumbHashDataUrl(thumbHash) : null;
return ( return (
<ListItemButton <ListItemButton
type="button" type="button"
@@ -127,15 +138,28 @@ class ResultRow extends Component {
borderRadius: 0.5, borderRadius: 0.5,
overflow: 'hidden', overflow: 'hidden',
bgcolor: 'action.hover', bgcolor: 'action.hover',
backgroundImage: thumbHashUrl ? `url("${thumbHashUrl}")` : undefined,
backgroundSize: 'cover',
backgroundPosition: 'center',
}} }}
> >
{row.smallThumbBinary && ( {thumbSrc ? (
<Box <Box
component="img" component="img"
alt="" alt=""
src={`data:image/avif;base64,${row.smallThumbBinary}`} src={thumbSrc}
loading="lazy"
sx={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} sx={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
/> />
) : (
thumbHashUrl && (
<Box
component="img"
alt=""
src={thumbHashUrl}
sx={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
/>
)
)} )}
</Box> </Box>
<Typography <Typography