Skip to content

Commit b8b5104

Browse files
authored
Merge pull request #418 from besscroft/fix/mobile-memory-crash
2 parents 838e746 + d43443b commit b8b5104

File tree

4 files changed

+57
-30
lines changed

4 files changed

+57
-30
lines changed

components/album/blur-image.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ export default function BlurImage({ photo, dataList }: { photo: any, dataList: a
3939
alt={photo.alt || 'Photo'}
4040
width={photo.width}
4141
height={photo.height}
42-
unoptimized
4342
loading="lazy"
43+
unoptimized={!!photo.preview_url}
4444
placeholder={(photo.blurhash === DEFAULT_HASH || !photo.blurhash) ? 'empty' : 'blur'}
4545
blurDataURL={dataURL}
4646
onClick={() => router.push(`/preview/${photo?.id}`)}

components/album/progressive-image.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ export default function ProgressiveImage(
2121
) {
2222
const t = useTranslations()
2323

24+
const [isMobile] = useState(() => typeof window !== 'undefined' && window.innerWidth < 768)
2425
const [loadingProgress, setLoadingProgress] = useState(0)
25-
const [isLoading, setIsLoading] = useState(true)
26+
const [isLoading, setIsLoading] = useState(!isMobile)
2627
const [error, setError] = useState<string | null>(null)
2728
const [highResImageUrl, setHighResImageUrl] = useState<string | null>(null)
2829
const [highResImageLoaded, setHighResImageLoaded] = useState(false)
@@ -37,10 +38,17 @@ export default function ProgressiveImage(
3738
}, [])
3839
useEffect(() => {
3940
setShowFullScreenViewer(Boolean(props.showLightbox))
41+
// On mobile, load full-res only when lightbox is requested
42+
if (isMobile && props.showLightbox && !highResImageUrl && !isLoading) {
43+
loadHighResolutionImage()
44+
}
4045
}, [props.showLightbox])
4146

4247
useEffect(() => {
43-
loadHighResolutionImage()
48+
// On mobile, defer full-res loading until user requests lightbox
49+
if (!isMobile) {
50+
loadHighResolutionImage()
51+
}
4452
return () => {
4553
if (highResImageUrl) {
4654
URL.revokeObjectURL(highResImageUrl)

components/gallery/masonry-photo-item.tsx

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,30 @@ export default function MasonryPhotoItem({ photo }: { photo: ImageType }) {
2828
}
2929
}}
3030
>
31-
<Image
32-
className="transition-transform duration-500 group-hover:scale-105 object-cover"
33-
src={photo.preview_url || photo.url}
34-
alt={photo.detail || photo.title || ''}
35-
fill
36-
sizes="(max-width: 768px) 50vw, (max-width: 1200px) 33vw, 25vw"
37-
loading="lazy"
38-
unoptimized
39-
placeholder={(photo.blurhash === DEFAULT_HASH || !photo.blurhash) ? 'empty' : 'blur'}
40-
blurDataURL={dataURL}
41-
/>
31+
{photo.preview_url ? (
32+
<Image
33+
className="transition-transform duration-500 group-hover:scale-105 object-cover"
34+
src={photo.preview_url}
35+
alt={photo.detail || photo.title || ''}
36+
fill
37+
sizes="(max-width: 768px) 50vw, (max-width: 1200px) 33vw, 25vw"
38+
loading="lazy"
39+
unoptimized
40+
placeholder={(photo.blurhash === DEFAULT_HASH || !photo.blurhash) ? 'empty' : 'blur'}
41+
blurDataURL={dataURL}
42+
/>
43+
) : (
44+
<Image
45+
className="transition-transform duration-500 group-hover:scale-105 object-cover"
46+
src={photo.url}
47+
alt={photo.detail || photo.title || ''}
48+
fill
49+
sizes="(max-width: 768px) 50vw, (max-width: 1200px) 33vw, 25vw"
50+
loading="lazy"
51+
placeholder={(photo.blurhash === DEFAULT_HASH || !photo.blurhash) ? 'empty' : 'blur'}
52+
blurDataURL={dataURL}
53+
/>
54+
)}
4255
{/* Hover gradient overlay */}
4356
<div className="pointer-events-none absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100" />
4457
{/* Hover content */}

components/gallery/simple/gallery-image.tsx

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,22 +51,28 @@ export default function GalleryImage({ photo, configData }: { photo: ImageType,
5151
{(photo.blurhash === DEFAULT_HASH || !photo.blurhash) && isLoading && (
5252
<Skeleton className="absolute inset-0 z-10 rounded-none" />
5353
)}
54-
<MotionImage
55-
className={cn('w-full h-auto', isLoading && 'animate-pulse')}
56-
initial={{ opacity: 0 }}
57-
animate={{ opacity: 1 }}
58-
transition={{ duration: 0.5 }}
59-
src={customIndexOriginEnable ? photo.url || photo.preview_url : photo.preview_url || photo.url}
60-
overrideSrc={customIndexOriginEnable ? photo.url || photo.preview_url : photo.preview_url || photo.url}
61-
alt={photo.title}
62-
width={photo.width}
63-
height={photo.height}
64-
loading="lazy"
65-
unoptimized
66-
placeholder={(photo.blurhash === DEFAULT_HASH || !photo.blurhash) ? 'empty' : 'blur'}
67-
blurDataURL={dataURL}
68-
onLoad={() => setIsLoading(false)}
69-
/>
54+
{(() => {
55+
const imgSrc = customIndexOriginEnable ? photo.url || photo.preview_url : photo.preview_url || photo.url
56+
const useUnoptimized = customIndexOriginEnable ? true : !!photo.preview_url
57+
return (
58+
<MotionImage
59+
className={cn('w-full h-auto', isLoading && 'animate-pulse')}
60+
initial={{ opacity: 0 }}
61+
animate={{ opacity: 1 }}
62+
transition={{ duration: 0.5 }}
63+
src={imgSrc}
64+
overrideSrc={imgSrc}
65+
alt={photo.title}
66+
width={photo.width}
67+
height={photo.height}
68+
loading="lazy"
69+
unoptimized={useUnoptimized}
70+
placeholder={(photo.blurhash === DEFAULT_HASH || !photo.blurhash) ? 'empty' : 'blur'}
71+
blurDataURL={dataURL}
72+
onLoad={() => setIsLoading(false)}
73+
/>
74+
)
75+
})()}
7076
{photo.type === 2 && (
7177
<div className="absolute top-2 left-2 p-5 rounded-full">
7278
<svg xmlns="http://www.w3.org/2000/svg" className="absolute bottom-3 right-3 text-white opacity-75 z-10"

0 commit comments

Comments
 (0)