Wire guest branding theme
This commit is contained in:
@@ -9,9 +9,8 @@ import { useTranslation } from '../i18n/useTranslation';
|
||||
import { DEFAULT_LOCALE, isLocaleCode } from '../i18n/messages';
|
||||
import { AlertTriangle, Download, Loader2, Share, X } from 'lucide-react';
|
||||
import { createPhotoShareLink } from '../services/photosApi';
|
||||
import { Share } from 'lucide-react';
|
||||
import { createPhotoShareLink } from '../services/photosApi';
|
||||
import { getContrastingTextColor } from '../lib/color';
|
||||
import { applyGuestTheme } from '../lib/guestTheme';
|
||||
|
||||
interface GalleryState {
|
||||
meta: GalleryMetaResponse | null;
|
||||
@@ -95,28 +94,34 @@ export default function PublicGalleryPage(): React.ReactElement | null {
|
||||
loadInitial();
|
||||
}, [loadInitial]);
|
||||
|
||||
const resolvedBranding = useMemo(() => {
|
||||
if (!state.meta) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const palette = state.meta.branding.palette ?? {};
|
||||
const primary = palette.primary ?? state.meta.branding.primary_color ?? '#f43f5e';
|
||||
const secondary = palette.secondary ?? state.meta.branding.secondary_color ?? '#fb7185';
|
||||
const background = palette.background ?? state.meta.branding.background_color ?? '#ffffff';
|
||||
const surface = palette.surface ?? state.meta.branding.surface_color ?? background;
|
||||
const mode = state.meta.branding.mode ?? 'auto';
|
||||
|
||||
return {
|
||||
primary,
|
||||
secondary,
|
||||
background,
|
||||
surface,
|
||||
mode,
|
||||
};
|
||||
}, [state.meta]);
|
||||
|
||||
useEffect(() => {
|
||||
const mode = state.meta?.branding.mode;
|
||||
if (!mode || typeof document === 'undefined') {
|
||||
if (!resolvedBranding) {
|
||||
return;
|
||||
}
|
||||
|
||||
const wasDark = document.documentElement.classList.contains('dark');
|
||||
|
||||
if (mode === 'dark') {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else if (mode === 'light') {
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (wasDark) {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
};
|
||||
}, [state.meta?.branding.mode]);
|
||||
return applyGuestTheme(resolvedBranding);
|
||||
}, [resolvedBranding]);
|
||||
|
||||
const loadMore = useCallback(async () => {
|
||||
if (!token || !state.cursor || state.loadingMore) {
|
||||
@@ -164,55 +169,46 @@ export default function PublicGalleryPage(): React.ReactElement | null {
|
||||
}, [state.cursor, loadMore]);
|
||||
|
||||
const themeStyles = useMemo(() => {
|
||||
if (!state.meta) {
|
||||
if (!resolvedBranding) {
|
||||
return {} as React.CSSProperties;
|
||||
}
|
||||
|
||||
const palette = state.meta.branding.palette ?? {};
|
||||
const primary = palette.primary ?? state.meta.branding.primary_color;
|
||||
const secondary = palette.secondary ?? state.meta.branding.secondary_color;
|
||||
const background = palette.background ?? state.meta.branding.background_color;
|
||||
const surface = palette.surface ?? state.meta.branding.surface_color ?? background;
|
||||
|
||||
return {
|
||||
'--gallery-primary': primary,
|
||||
'--gallery-secondary': secondary,
|
||||
'--gallery-background': background,
|
||||
'--gallery-surface': surface,
|
||||
'--gallery-primary': resolvedBranding.primary,
|
||||
'--gallery-secondary': resolvedBranding.secondary,
|
||||
'--gallery-background': resolvedBranding.background,
|
||||
'--gallery-surface': resolvedBranding.surface,
|
||||
} as React.CSSProperties & Record<string, string>;
|
||||
}, [state.meta]);
|
||||
}, [resolvedBranding]);
|
||||
|
||||
const headerStyle = useMemo(() => {
|
||||
if (!state.meta) {
|
||||
if (!resolvedBranding) {
|
||||
return {};
|
||||
}
|
||||
const palette = state.meta.branding.palette ?? {};
|
||||
const primary = palette.primary ?? state.meta.branding.primary_color;
|
||||
const secondary = palette.secondary ?? state.meta.branding.secondary_color ?? primary;
|
||||
const textColor = getContrastingTextColor(primary ?? '#f43f5e', '#0f172a', '#ffffff');
|
||||
const textColor = getContrastingTextColor(resolvedBranding.primary, '#0f172a', '#ffffff');
|
||||
return {
|
||||
background: `linear-gradient(135deg, ${primary}, ${secondary})`,
|
||||
background: `linear-gradient(135deg, ${resolvedBranding.primary}, ${resolvedBranding.secondary})`,
|
||||
color: textColor,
|
||||
} satisfies React.CSSProperties;
|
||||
}, [state.meta]);
|
||||
}, [resolvedBranding]);
|
||||
|
||||
const accentStyle = useMemo(() => {
|
||||
if (!state.meta) {
|
||||
if (!resolvedBranding) {
|
||||
return {};
|
||||
}
|
||||
return {
|
||||
color: (state.meta.branding.palette?.primary ?? state.meta.branding.primary_color),
|
||||
color: resolvedBranding.primary,
|
||||
} satisfies React.CSSProperties;
|
||||
}, [state.meta]);
|
||||
}, [resolvedBranding]);
|
||||
|
||||
const backgroundStyle = useMemo(() => {
|
||||
if (!state.meta) {
|
||||
if (!resolvedBranding) {
|
||||
return {};
|
||||
}
|
||||
return {
|
||||
backgroundColor: state.meta.branding.palette?.background ?? state.meta.branding.background_color,
|
||||
backgroundColor: resolvedBranding.background,
|
||||
} satisfies React.CSSProperties;
|
||||
}, [state.meta]);
|
||||
}, [resolvedBranding]);
|
||||
|
||||
const openLightbox = useCallback((photo: GalleryPhotoResource) => {
|
||||
setSelectedPhoto(photo);
|
||||
|
||||
Reference in New Issue
Block a user