fix default
Build and Deploy Docker Images / build_and_deploy (push) Has been cancelled

This commit is contained in:
hamid zarghami
2026-06-22 15:00:53 +03:30
parent 80acaf743c
commit 8ff2d4adf3
6 changed files with 105 additions and 11 deletions
+4 -2
View File
@@ -1,6 +1,7 @@
"use client"; "use client";
import { usePatternBackground } from "@/components/background/PatternBackgroundProvider"; import { usePatternBackground } from "@/components/background/PatternBackgroundProvider";
import usePreference from "@/hooks/helpers/usePreference";
import { THEME_BG_ELEMENT_ID } from "@/lib/helpers/themeCache"; import { THEME_BG_ELEMENT_ID } from "@/lib/helpers/themeCache";
import { useLayoutEffect } from "react"; import { useLayoutEffect } from "react";
@@ -8,11 +9,12 @@ const THEME_BG_IMG_ID = "cached-theme-bg-img";
const THEME_BG_OVERLAY_ID = "cached-theme-bg-overlay"; const THEME_BG_OVERLAY_ID = "cached-theme-bg-overlay";
export default function AppBackground() { export default function AppBackground() {
const { state: nightMode } = usePreference("night-mode", false);
const { isPattern, backgroundStyle, isCustomImage, customImageSettings } = const { isPattern, backgroundStyle, isCustomImage, customImageSettings } =
usePatternBackground(); usePatternBackground();
useLayoutEffect(() => { useLayoutEffect(() => {
if (!isPattern && !isCustomImage) { if (nightMode || (!isPattern && !isCustomImage)) {
document.getElementById(THEME_BG_ELEMENT_ID)?.remove(); document.getElementById(THEME_BG_ELEMENT_ID)?.remove();
return; return;
} }
@@ -75,7 +77,7 @@ export default function AppBackground() {
overlayLayer.style.backgroundColor = overlayLayer.style.backgroundColor =
overlayOpacity > 0 ? `rgba(0,0,0,${overlayOpacity})` : ""; overlayOpacity > 0 ? `rgba(0,0,0,${overlayOpacity})` : "";
} }
}, [backgroundStyle, isPattern, isCustomImage, customImageSettings]); }, [backgroundStyle, isCustomImage, isPattern, customImageSettings, nightMode]);
return null; return null;
} }
@@ -2,6 +2,7 @@
import { useGetAbout } from "@/app/[name]/(Main)/about/hooks/useAboutData"; import { useGetAbout } from "@/app/[name]/(Main)/about/hooks/useAboutData";
import { import {
applyColorBackgroundCssVariables,
applyCustomImageCssVariables, applyCustomImageCssVariables,
applyPatternCssVariables, applyPatternCssVariables,
clearCustomImageCssVariables, clearCustomImageCssVariables,
@@ -12,9 +13,11 @@ import {
PATTERN_BACKGROUND_OPACITY, PATTERN_BACKGROUND_OPACITY,
resolveBgType, resolveBgType,
} from "@/lib/helpers/backgroundUtils"; } from "@/lib/helpers/backgroundUtils";
import usePreference from "@/hooks/helpers/usePreference";
import { import {
applyCachedThemeToDom, applyCachedThemeToDom,
buildThemeCacheFromRestaurant, buildThemeCacheFromRestaurant,
clearRestaurantBackgroundOverrides,
getThemeCache, getThemeCache,
removeCachedThemeBackground, removeCachedThemeBackground,
setThemeCache, setThemeCache,
@@ -59,6 +62,7 @@ const PatternBackgroundContext = createContext<PatternBackgroundContextValue>({
export function PatternBackgroundProvider({ children }: { children: ReactNode }) { export function PatternBackgroundProvider({ children }: { children: ReactNode }) {
const { name: restaurantSlug } = useParams<{ name: string }>(); const { name: restaurantSlug } = useParams<{ name: string }>();
const { state: nightMode } = usePreference("night-mode", false);
const { data: aboutData } = useGetAbout(); const { data: aboutData } = useGetAbout();
const restaurant = aboutData?.data; const restaurant = aboutData?.data;
const [hydratedCache, setHydratedCache] = useState<CachedRestaurantTheme | null>(null); const [hydratedCache, setHydratedCache] = useState<CachedRestaurantTheme | null>(null);
@@ -70,8 +74,8 @@ export function PatternBackgroundProvider({ children }: { children: ReactNode })
? resolveBgType(hydratedCache) ? resolveBgType(hydratedCache)
: "color"; : "color";
const isPattern = bgType === "pattern"; const isPattern = !nightMode && bgType === "pattern";
const isCustomImage = bgType === "custom"; const isCustomImage = !nightMode && bgType === "custom";
const menuColor = const menuColor =
restaurant?.menuColor || hydratedCache?.menuColor || DEFAULT_MENU_COLOR; restaurant?.menuColor || hydratedCache?.menuColor || DEFAULT_MENU_COLOR;
const baseTint = hexToRgba(menuColor, PATTERN_BACKGROUND_OPACITY); const baseTint = hexToRgba(menuColor, PATTERN_BACKGROUND_OPACITY);
@@ -85,10 +89,10 @@ export function PatternBackgroundProvider({ children }: { children: ReactNode })
if (!cached) return; if (!cached) return;
applyCachedThemeToDom(cached); applyCachedThemeToDom(cached);
if (cached.patternDataUrl) { if (!nightMode && cached.patternDataUrl) {
setPatternImageUrl(cached.patternDataUrl); setPatternImageUrl(cached.patternDataUrl);
} }
}, [restaurantSlug]); }, [nightMode, restaurantSlug]);
useEffect(() => { useEffect(() => {
if (!restaurantSlug) { if (!restaurantSlug) {
@@ -99,16 +103,24 @@ export function PatternBackgroundProvider({ children }: { children: ReactNode })
return; return;
} }
if (nightMode) {
clearPatternCssVariables();
clearCustomImageCssVariables();
clearRestaurantBackgroundOverrides();
setPatternImageUrl(null);
return;
}
if (!restaurant) return; if (!restaurant) return;
const themeBase = buildThemeCacheFromRestaurant(restaurant); const themeBase = buildThemeCacheFromRestaurant(restaurant);
const currentBgType = themeBase.bgType; const currentBgType = themeBase.bgType;
if (currentBgType === "color") { if (currentBgType === "color") {
clearPatternCssVariables();
clearCustomImageCssVariables(); clearCustomImageCssVariables();
removeCachedThemeBackground(); removeCachedThemeBackground();
setPatternImageUrl(null); setPatternImageUrl(null);
applyColorBackgroundCssVariables(menuColor);
setThemeCache(restaurantSlug, { ...themeBase, patternDataUrl: null }); setThemeCache(restaurantSlug, { ...themeBase, patternDataUrl: null });
return; return;
} }
@@ -192,7 +204,7 @@ export function PatternBackgroundProvider({ children }: { children: ReactNode })
return () => { return () => {
cancelled = true; cancelled = true;
}; };
}, [menuColor, restaurant, restaurantSlug]); }, [menuColor, nightMode, restaurant, restaurantSlug]);
const backgroundStyle = useMemo<CSSProperties>( const backgroundStyle = useMemo<CSSProperties>(
() => ({ () => ({
+19 -1
View File
@@ -9,6 +9,7 @@ import { hexToOklch, calculateBrightness } from '@/lib/helpers/colorUtils';
import { import {
applyCachedThemeToDom, applyCachedThemeToDom,
buildThemeCacheFromRestaurant, buildThemeCacheFromRestaurant,
clearRestaurantBackgroundOverrides,
getCachedMenuColor, getCachedMenuColor,
getThemeCache, getThemeCache,
setThemeCache, setThemeCache,
@@ -143,6 +144,11 @@ function PreferenceWrapper({ children }: Props) {
patternDataUrl: cached?.patternDataUrl ?? null, patternDataUrl: cached?.patternDataUrl ?? null,
}); });
const updatedTheme = getThemeCache(restaurantSlug);
if (updatedTheme) {
applyCachedThemeToDom(updatedTheme);
}
if (restaurant.logo) { if (restaurant.logo) {
localStorage.setItem('restaurant-logo', restaurant.logo); localStorage.setItem('restaurant-logo', restaurant.logo);
} }
@@ -164,7 +170,19 @@ function PreferenceWrapper({ children }: Props) {
useEffect(() => { useEffect(() => {
document.documentElement.setAttribute('data-theme', nightMode ? 'dark' : 'light'); document.documentElement.setAttribute('data-theme', nightMode ? 'dark' : 'light');
}, [nightMode]);
if (nightMode) {
clearRestaurantBackgroundOverrides();
return;
}
if (!restaurantSlug) return;
const cached = getThemeCache(restaurantSlug);
if (cached) {
applyCachedThemeToDom(cached);
}
}, [nightMode, restaurantSlug]);
const splashLogo = mounted const splashLogo = mounted
? (aboutData?.data?.logo || cachedLogo || undefined) ? (aboutData?.data?.logo || cachedLogo || undefined)
+18
View File
@@ -51,6 +51,8 @@ const isCustomImageBackgroundLegacy = (
export const resolveBgType = ( export const resolveBgType = (
settings: RestaurantBackgroundSettings, settings: RestaurantBackgroundSettings,
): BgType => { ): BgType => {
if (settings.bgType === null) return "color";
const normalized = settings.bgType?.toLowerCase(); const normalized = settings.bgType?.toLowerCase();
if ( if (
normalized === "pattern" || normalized === "pattern" ||
@@ -100,6 +102,22 @@ export const colorizeSvg = (
return result; return result;
}; };
export const applyColorBackgroundCssVariables = (menuColor: string) => {
const root = document.documentElement;
root.removeAttribute("data-pattern-bg");
root.removeAttribute("data-image-bg");
root.style.removeProperty("--bg-pattern-base");
root.style.removeProperty("--bg-pattern-vector");
root.style.setProperty(
"--background",
hexToRgba(menuColor, PATTERN_BACKGROUND_OPACITY),
);
root.style.setProperty(
"--primary-light",
hexToRgba(menuColor, PRIMARY_LIGHT_OPACITY),
);
};
export const applyPatternCssVariables = (menuColor: string) => { export const applyPatternCssVariables = (menuColor: string) => {
const root = document.documentElement; const root = document.documentElement;
const baseTint = hexToRgba(menuColor, PATTERN_BACKGROUND_OPACITY); const baseTint = hexToRgba(menuColor, PATTERN_BACKGROUND_OPACITY);
+1 -1
View File
@@ -1,3 +1,3 @@
export function getThemeBootScript(): string { export function getThemeBootScript(): string {
return `(function(){try{var s=location.pathname.split("/").filter(Boolean)[0],t=null;if(s&&s!=="auth"){var r=localStorage.getItem("restaurant-theme:"+s);if(r)t=JSON.parse(r)}if(!t||t.version!==1||!t.menuColor){var l=localStorage.getItem("theme-primary-color");if(l){var x=l.replace("#","");if(x.length===6){var p=parseInt(x.slice(0,2),16),f=parseInt(x.slice(2,4),16),m=parseInt(x.slice(4,6),16),b="rgba("+p+","+f+","+m+",0.05)";document.documentElement.style.setProperty("--background",b)}}return}function h(n,a){var u=n.replace("#","");if(u.length!==6)return null;var v=parseInt(u.slice(0,2),16),g=parseInt(u.slice(2,4),16),y=parseInt(u.slice(4,6),16);return"rgba("+v+","+g+","+y+","+a+")"}function isUnset(v){return v==null||v===""||v===0}function isCustomImg(th){if(!th.bgUrl)return false;return !isUnset(th.bgBlur)||!isUnset(th.bgOpacity)||!isUnset(th.bgOverlay)}function resolveBgType(th){var bt=(th.bgType||"").toLowerCase();if(bt==="pattern"||bt==="custom"||bt==="color")return bt;if(th.isPattern===true)return"pattern";if(th.isPattern===false&&th.bgUrl&&isCustomImg(th))return"custom";if(th.isPattern===false)return"color";if(isCustomImg(th))return"custom";if(th.bgUrl)return"pattern";return"color"}var e=document.documentElement;if(t.primaryOklch){e.style.setProperty("--primary",t.primaryOklch);e.style.setProperty("--primary-foreground",t.primaryForeground||"oklch(1 0 0)")}var bt=resolveBgType(t);if(bt==="color")return;if(bt==="pattern"){e.setAttribute("data-pattern-bg","true");var k=t.backgroundTint||h(t.menuColor,0.05),w=t.bgPatternVector||h(t.menuColor,0.1),z=t.primaryLight||h(t.menuColor,0.15);k&&(e.style.setProperty("--background",k),e.style.setProperty("--bg-pattern-base",k));w&&e.style.setProperty("--bg-pattern-vector",w);z&&e.style.setProperty("--primary-light",z);if(k){var d=document.createElement("div");d.id="cached-theme-bg";d.setAttribute("aria-hidden","true");d.style.cssText="position:fixed;inset:0;pointer-events:none;z-index:0;background-color:"+k+(t.patternDataUrl?';background-image:url("'+t.patternDataUrl+'");background-repeat:repeat;background-size:auto':"")+";";document.body.appendChild(d)}}else if(bt==="custom"){e.setAttribute("data-image-bg","true");var d2=document.createElement("div");d2.id="cached-theme-bg";d2.setAttribute("aria-hidden","true");d2.style.cssText="position:fixed;inset:0;pointer-events:none;z-index:0;overflow:hidden;";var i=document.createElement("div");i.id="cached-theme-bg-img";i.style.cssText="position:absolute;inset:-40px;background-size:cover;background-position:center;background-repeat:no-repeat;background-image:url(\\""+t.bgUrl+"\\");"+(t.bgBlur?"filter:blur("+t.bgBlur+"px);":"")+"opacity:"+(t.bgOpacity!=null?t.bgOpacity/100:1)+";";d2.appendChild(i);var ov=document.createElement("div");ov.id="cached-theme-bg-overlay";ov.style.cssText="position:absolute;inset:0;"+(t.bgOverlay&&Number(t.bgOverlay)>0?"background-color:rgba(0,0,0,"+Number(t.bgOverlay)/100+");":"");d2.appendChild(ov);document.body.appendChild(d2)}}catch(u){}})();`; return `(function(){try{function isNight(){try{var p=localStorage.getItem("preference-storage");if(!p)return false;var o=JSON.parse(p);return o&&o.state&&o.state.items&&o.state.items["night-mode"]&&o.state.items["night-mode"].value===true}catch(v){return false}}var night=isNight(),e=document.documentElement;e.setAttribute("data-theme",night?"dark":"light");var s=location.pathname.split("/").filter(Boolean)[0],t=null;if(s&&s!=="auth"){var r=localStorage.getItem("restaurant-theme:"+s);if(r)t=JSON.parse(r)}if(!t||t.version!==1||!t.menuColor){var l=localStorage.getItem("theme-primary-color");if(l&&!night){var x=l.replace("#","");if(x.length===6){var p=parseInt(x.slice(0,2),16),f=parseInt(x.slice(2,4),16),m=parseInt(x.slice(4,6),16),b="rgba("+p+","+f+","+m+",0.05)";e.style.setProperty("--background",b)}}return}function h(n,a){var u=n.replace("#","");if(u.length!==6)return null;var v=parseInt(u.slice(0,2),16),g=parseInt(u.slice(2,4),16),y=parseInt(u.slice(4,6),16);return"rgba("+v+","+g+","+y+","+a+")"}function isUnset(v){return v==null||v===""||v===0}function isCustomImg(th){if(!th.bgUrl)return false;return !isUnset(th.bgBlur)||!isUnset(th.bgOpacity)||!isUnset(th.bgOverlay)}function resolveBgType(th){if(th.bgType===null)return"color";var bt=(th.bgType||"").toLowerCase();if(bt==="pattern"||bt==="custom"||bt==="color")return bt;if(th.isPattern===true)return"pattern";if(th.isPattern===false&&th.bgUrl&&isCustomImg(th))return"custom";if(th.isPattern===false)return"color";if(isCustomImg(th))return"custom";if(th.bgUrl)return"pattern";return"color"}if(t.primaryOklch){e.style.setProperty("--primary",t.primaryOklch);e.style.setProperty("--primary-foreground",t.primaryForeground||"oklch(1 0 0)")}if(night)return;var bt=resolveBgType(t);if(bt==="color"){var k=t.backgroundTint||h(t.menuColor,0.05),z=t.primaryLight||h(t.menuColor,0.15);k&&e.style.setProperty("--background",k);z&&e.style.setProperty("--primary-light",z);return};if(bt==="pattern"){e.setAttribute("data-pattern-bg","true");var k=t.backgroundTint||h(t.menuColor,0.05),w=t.bgPatternVector||h(t.menuColor,0.1),z=t.primaryLight||h(t.menuColor,0.15);k&&(e.style.setProperty("--background",k),e.style.setProperty("--bg-pattern-base",k));w&&e.style.setProperty("--bg-pattern-vector",w);z&&e.style.setProperty("--primary-light",z);if(k){var d=document.createElement("div");d.id="cached-theme-bg";d.setAttribute("aria-hidden","true");d.style.cssText="position:fixed;inset:0;pointer-events:none;z-index:0;background-color:"+k+(t.patternDataUrl?';background-image:url("'+t.patternDataUrl+'");background-repeat:repeat;background-size:auto':"")+";";document.body.appendChild(d)}}else if(bt==="custom"){e.setAttribute("data-image-bg","true");var d2=document.createElement("div");d2.id="cached-theme-bg";d2.setAttribute("aria-hidden","true");d2.style.cssText="position:fixed;inset:0;pointer-events:none;z-index:0;overflow:hidden;";var i=document.createElement("div");i.id="cached-theme-bg-img";i.style.cssText="position:absolute;inset:-40px;background-size:cover;background-position:center;background-repeat:no-repeat;background-image:url(\\""+t.bgUrl+"\\");"+(t.bgBlur?"filter:blur("+t.bgBlur+"px);":"")+"opacity:"+(t.bgOpacity!=null?t.bgOpacity/100:1)+";";d2.appendChild(i);var ov=document.createElement("div");ov.id="cached-theme-bg-overlay";ov.style.cssText="position:absolute;inset:0;"+(t.bgOverlay&&Number(t.bgOverlay)>0?"background-color:rgba(0,0,0,"+Number(t.bgOverlay)/100+");":"");d2.appendChild(ov);document.body.appendChild(d2)}}catch(u){}})();`;
} }
+45 -1
View File
@@ -42,6 +42,35 @@ const CATEGORIES_CACHE_PREFIX = "restaurant-categories";
export const THEME_BG_ELEMENT_ID = "cached-theme-bg"; export const THEME_BG_ELEMENT_ID = "cached-theme-bg";
const THEME_BG_IMG_ID = "cached-theme-bg-img"; const THEME_BG_IMG_ID = "cached-theme-bg-img";
const THEME_BG_OVERLAY_ID = "cached-theme-bg-overlay"; const THEME_BG_OVERLAY_ID = "cached-theme-bg-overlay";
const PREFERENCE_STORAGE_KEY = "preference-storage";
export function isNightModeEnabled(): boolean {
if (typeof window === "undefined") return false;
try {
const raw = localStorage.getItem(PREFERENCE_STORAGE_KEY);
if (!raw) return false;
const parsed = JSON.parse(raw) as {
state?: { items?: Record<string, { value?: unknown }> };
};
return parsed?.state?.items?.["night-mode"]?.value === true;
} catch {
return false;
}
}
export function clearRestaurantBackgroundOverrides(): void {
if (typeof document === "undefined") return;
const root = document.documentElement;
root.removeAttribute("data-pattern-bg");
root.removeAttribute("data-image-bg");
root.style.removeProperty("--background");
root.style.removeProperty("--bg-pattern-base");
root.style.removeProperty("--bg-pattern-vector");
root.style.removeProperty("--primary-light");
document.getElementById(THEME_BG_ELEMENT_ID)?.remove();
}
export function getThemeCacheKey(slug: string): string { export function getThemeCacheKey(slug: string): string {
return `${CACHE_KEY_PREFIX}:${slug}`; return `${CACHE_KEY_PREFIX}:${slug}`;
@@ -320,12 +349,27 @@ export function applyCachedThemeToDom(theme: CachedRestaurantTheme): void {
); );
} }
if (isNightModeEnabled()) {
clearRestaurantBackgroundOverrides();
return;
}
const bgType = resolveBgType(theme); const bgType = resolveBgType(theme);
if (bgType === "color") { if (bgType === "color") {
document.getElementById(THEME_BG_ELEMENT_ID)?.remove();
const tint =
theme.backgroundTint ??
hexToRgba(theme.menuColor, PATTERN_BACKGROUND_OPACITY);
const primaryLight =
theme.primaryLight ??
hexToRgba(theme.menuColor, PRIMARY_LIGHT_OPACITY);
root.removeAttribute("data-pattern-bg"); root.removeAttribute("data-pattern-bg");
root.removeAttribute("data-image-bg"); root.removeAttribute("data-image-bg");
document.getElementById(THEME_BG_ELEMENT_ID)?.remove(); root.style.removeProperty("--bg-pattern-base");
root.style.removeProperty("--bg-pattern-vector");
root.style.setProperty("--background", tint);
root.style.setProperty("--primary-light", primaryLight);
return; return;
} }