This commit is contained in:
hamid zarghami
2026-06-21 14:52:20 +03:30
parent ba82744219
commit de45b1f197
19 changed files with 622 additions and 157 deletions
@@ -9,13 +9,22 @@ import {
isPatternBackground,
PATTERN_BACKGROUND_OPACITY,
} from "@/lib/helpers/backgroundUtils";
import {
applyCachedThemeToDom,
buildThemeCacheFromRestaurant,
getThemeCache,
removeCachedThemeBackground,
setThemeCache,
svgToDataUrl,
type CachedRestaurantTheme,
} from "@/lib/helpers/themeCache";
import { useParams } from "next/navigation";
import {
createContext,
useContext,
useEffect,
useLayoutEffect,
useMemo,
useRef,
useState,
type CSSProperties,
type ReactNode,
@@ -37,32 +46,74 @@ export function PatternBackgroundProvider({ children }: { children: ReactNode })
const { name: restaurantSlug } = useParams<{ name: string }>();
const { data: aboutData } = useGetAbout();
const restaurant = aboutData?.data;
const [hydratedCache, setHydratedCache] = useState<CachedRestaurantTheme | null>(null);
const [patternImageUrl, setPatternImageUrl] = useState<string | null>(null);
const blobUrlRef = useRef<string | null>(null);
const isPattern = restaurant ? isPatternBackground(restaurant) : false;
const menuColor = restaurant?.menuColor || DEFAULT_MENU_COLOR;
const isPattern = restaurant
? isPatternBackground(restaurant)
: (hydratedCache?.isPattern ?? false);
const menuColor =
restaurant?.menuColor || hydratedCache?.menuColor || DEFAULT_MENU_COLOR;
const baseTint = hexToRgba(menuColor, PATTERN_BACKGROUND_OPACITY);
useEffect(() => {
const revokeBlobUrl = () => {
if (blobUrlRef.current) {
URL.revokeObjectURL(blobUrlRef.current);
blobUrlRef.current = null;
}
setPatternImageUrl(null);
};
useLayoutEffect(() => {
if (!restaurantSlug) return;
if (!isPattern || !restaurant?.bgUrl || !restaurantSlug) {
const cached = getThemeCache(restaurantSlug);
setHydratedCache(cached);
if (!cached) return;
applyCachedThemeToDom(cached);
if (cached.patternDataUrl) {
setPatternImageUrl(cached.patternDataUrl);
}
}, [restaurantSlug]);
useEffect(() => {
if (!restaurantSlug) {
clearPatternCssVariables();
revokeBlobUrl();
removeCachedThemeBackground();
setPatternImageUrl(null);
return;
}
if (!restaurant) return;
const themeBase = buildThemeCacheFromRestaurant(restaurant);
if (!themeBase.isPattern || !themeBase.bgUrl) {
clearPatternCssVariables();
removeCachedThemeBackground();
setPatternImageUrl(null);
setThemeCache(restaurantSlug, {
...themeBase,
patternDataUrl: null,
});
return;
}
applyPatternCssVariables(menuColor);
const cached = getThemeCache(restaurantSlug);
const cacheHit =
cached?.isPattern &&
cached.bgUrl === themeBase.bgUrl &&
cached.menuColor === menuColor &&
cached.patternDataUrl;
if (cacheHit) {
setPatternImageUrl(cached.patternDataUrl!);
setThemeCache(restaurantSlug, {
...themeBase,
patternDataUrl: cached.patternDataUrl,
});
applyCachedThemeToDom(cached);
return;
}
let cancelled = false;
const proxyUrl = `/${restaurantSlug}/api/proxy-svg?url=${encodeURIComponent(restaurant.bgUrl)}`;
const proxyUrl = `/${restaurantSlug}/api/proxy-svg?url=${encodeURIComponent(themeBase.bgUrl)}`;
fetch(proxyUrl)
.then((response) => {
@@ -74,26 +125,31 @@ export function PatternBackgroundProvider({ children }: { children: ReactNode })
.then((svg) => {
if (cancelled) return;
revokeBlobUrl();
const blob = new Blob([colorizeSvg(svg, menuColor)], {
type: "image/svg+xml;charset=utf-8",
});
const blobUrl = URL.createObjectURL(blob);
blobUrlRef.current = blobUrl;
setPatternImageUrl(blobUrl);
const dataUrl = svgToDataUrl(colorizeSvg(svg, menuColor));
setPatternImageUrl(dataUrl);
const nextCache = {
...themeBase,
patternDataUrl: dataUrl,
};
setThemeCache(restaurantSlug, nextCache);
const saved = getThemeCache(restaurantSlug);
if (saved) {
applyCachedThemeToDom(saved);
}
})
.catch(() => {
if (!cancelled) {
revokeBlobUrl();
if (!cancelled && cached?.patternDataUrl) {
setPatternImageUrl(cached.patternDataUrl);
applyCachedThemeToDom(cached);
}
});
return () => {
cancelled = true;
clearPatternCssVariables();
revokeBlobUrl();
};
}, [isPattern, menuColor, restaurant?.bgUrl, restaurantSlug]);
}, [menuColor, restaurant, restaurantSlug]);
const backgroundStyle = useMemo<CSSProperties>(
() => ({