Cache
This commit is contained in:
@@ -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>(
|
||||
() => ({
|
||||
|
||||
Reference in New Issue
Block a user