Add image fallback debug logging

This commit is contained in:
Sam Becker 2025-06-24 10:14:08 -05:00
parent 6d7c5d6903
commit e1cd7d23f1
8 changed files with 54 additions and 15 deletions

View File

@ -11,6 +11,7 @@ import {
HTML_LANG,
NAV_CAPTION,
SITE_FEEDS_ENABLED,
ADMIN_DEBUG_TOOLS_ENABLED,
} from '@/app/config';
import AppStateProvider from '@/state/AppStateProvider';
import ToasterWithThemes from '@/toast/ToasterWithThemes';
@ -91,7 +92,7 @@ export default function RootLayout({
// Center on large screens
'3xl:flex flex-col items-center',
)}>
<AppStateProvider>
<AppStateProvider areAdminDebugToolsEnabled={ADMIN_DEBUG_TOOLS_ENABLED}>
<AppTextProvider>
<ThemeColors />
<ThemeProvider attribute="class" defaultTheme={DEFAULT_THEME}>

View File

@ -1,7 +1,6 @@
import CommandKClient from './CommandKClient';
import { getPhotosMetaCached } from '@/photo/cache';
import { photoQuantityText } from '@/photo';
import { ADMIN_DEBUG_TOOLS_ENABLED } from '../app/config';
import { getDataForCategoriesCached } from '@/category/cache';
import { getAppText } from '@/i18n/state/server';
@ -21,7 +20,6 @@ export default async function CommandK() {
return (
<CommandKClient
{...categories}
showDebugTools={ADMIN_DEBUG_TOOLS_ENABLED}
footer={photoQuantityText(count, appText, false)}
/>
);

View File

@ -122,10 +122,8 @@ export default function CommandKClient({
recipes,
films,
focalLengths,
showDebugTools,
footer,
}: {
showDebugTools?: boolean
footer?: string
} & PhotoSetCategories) {
const pathname = usePathname();
@ -146,6 +144,7 @@ export default function CommandKClient({
isGridHighDensity,
areZoomControlsShown,
arePhotosMatted,
areAdminDebugToolsEnabled,
shouldShowBaselineGrid,
shouldDebugImageFallbacks,
shouldDebugInsights,
@ -406,7 +405,7 @@ export default function CommandKClient({
}],
}];
if (isUserSignedIn && showDebugTools) {
if (isUserSignedIn && areAdminDebugToolsEnabled) {
clientSections.push({
heading: 'Debug Tools',
accessory: <RiToolsFill size={16} className="translate-x-[-1px]" />,
@ -537,7 +536,7 @@ export default function CommandKClient({
annotation: <IconLock narrow />,
path: PATH_ADMIN_CONFIGURATION,
});
if (showDebugTools) {
if (areAdminDebugToolsEnabled) {
adminSection.items.push({
label: 'Baseline Overview',
annotation: <BiLockAlt />,

View File

@ -10,6 +10,7 @@ import { useCallback, useEffect, useRef, useState } from 'react';
export default function ImageWithFallback({
className,
classNameImage = 'object-cover h-full',
debug,
priority,
blurDataURL,
blurCompatibilityLevel = 'low',
@ -17,8 +18,12 @@ export default function ImageWithFallback({
}: ImageProps & {
blurCompatibilityLevel?: 'none' | 'low' | 'high'
classNameImage?: string
debug?: boolean
}) {
const { shouldDebugImageFallbacks } = useAppState();
const {
shouldDebugImageFallbacks,
areAdminDebugToolsEnabled,
} = useAppState();
const [wasCached, setWasCached] = useState(true);
const [isLoading, setIsLoading] = useState(true);
@ -39,10 +44,28 @@ export default function ImageWithFallback({
);
}, []);
const shouldDebugFallback = areAdminDebugToolsEnabled && debug;
const debugFallbackStyles = useCallback(() => {
const stylesMap = refFallback.current?.computedStyleMap();
const styles = stylesMap
? Array.from(stylesMap.entries()).reduce((acc, [key, value]) => {
acc[key] = value.toString();
return acc;
}, {} as Record<string, string>) : {};
const opacity = (stylesMap?.get('opacity') as CSSUnitValue)?.value;
return {
styles,
opacity,
classList: refFallback.current?.classList,
};
}, []);
const outerTimeout = useRef<NodeJS.Timeout>(undefined);
const innerTimeout = useRef<NodeJS.Timeout>(undefined);
useEffect(() => {
if (!isLoading && !didError) {
let innerTimeout: NodeJS.Timeout;
const timeout = setTimeout(() => {
outerTimeout.current = setTimeout(() => {
if (refFallback.current) {
const fallbackOpacity = (refFallback
.current
@ -54,22 +77,32 @@ export default function ImageWithFallback({
if (fallbackOpacity === 0) {
// Image has loaded and fallback is already hidden
setHideFallback(true);
if (shouldDebugFallback) {
console.log('Hide fallback: 01', debugFallbackStyles());
}
} else {
// Image has loaded but fallback is still visible
// Delay hiding fallback to avoid abrupt transition
innerTimeout = setTimeout(() =>{
console.log('Delayed hide fallback');
innerTimeout.current = setTimeout(() =>{
setHideFallback(true);
if (shouldDebugFallback) {
console.log('Hide fallback: 02', debugFallbackStyles());
}
}, 1000);
}
}
}, 1000);
return () => {
clearTimeout(timeout);
clearTimeout(innerTimeout);
clearTimeout(outerTimeout.current);
clearTimeout(innerTimeout.current);
};
}
}, [isLoading, didError]);
}, [
isLoading,
didError,
shouldDebugFallback,
debugFallbackStyles,
]);
const showFallback =
!wasCached &&

View File

@ -78,6 +78,7 @@ export default function PhotoLarge({
includeFavoriteInAdminMenu,
onVisible,
showAdminKeyCommands,
debugImageFallback,
}: {
photo: Photo
className?: string
@ -104,6 +105,7 @@ export default function PhotoLarge({
includeFavoriteInAdminMenu?: boolean
onVisible?: () => void
showAdminKeyCommands?: boolean
debugImageFallback?: boolean
}) {
const ref = useRef<HTMLDivElement>(null);
const refZoomControls = useRef<ZoomControlsRef>(null);
@ -224,6 +226,7 @@ export default function PhotoLarge({
blurDataURL={photo.blurData}
blurCompatibilityMode={doesPhotoNeedBlurCompatibility(photo)}
priority={priority}
debug={debugImageFallback}
/>
</ZoomControls>
<div className={clsx(

View File

@ -35,6 +35,7 @@ export default function PhotosLarge({
onVisible={index === photos.length - 1
? onLastPhotoVisible
: undefined}
debugImageFallback={index === 0}
/>)}
itemKeys={photos.map(photo => photo.id)}
/>

View File

@ -64,6 +64,7 @@ export type AppStateContextType = {
setUploadState?: (uploadState: Partial<UploadState>) => void
resetUploadState?: () => void
// DEBUG
areAdminDebugToolsEnabled?: boolean
isGridHighDensity?: boolean
setIsGridHighDensity?: Dispatch<SetStateAction<boolean>>
areZoomControlsShown?: boolean

View File

@ -30,8 +30,10 @@ import { toastSuccess } from '@/toast';
export default function AppStateProvider({
children,
areAdminDebugToolsEnabled,
}: {
children: ReactNode
areAdminDebugToolsEnabled?: boolean
}) {
const router = useRouter();
@ -243,6 +245,7 @@ export default function AppStateProvider({
setUploadState,
resetUploadState,
// DEBUG
areAdminDebugToolsEnabled,
isGridHighDensity,
setIsGridHighDensity,
areZoomControlsShown,