chore: cache avatar image for offline usage (#1140)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import clsx from 'clsx';
|
||||
import Image from 'next/image';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { IconType } from 'react-icons';
|
||||
|
||||
interface UserAvatarProps {
|
||||
@@ -17,6 +18,41 @@ const UserAvatar: React.FC<UserAvatarProps> = ({
|
||||
borderClassName,
|
||||
DefaultIcon,
|
||||
}) => {
|
||||
const [cachedImageUrl, setCachedImageUrl] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!url) return;
|
||||
|
||||
const storageKey = `avatar_${btoa(url).replace(/[^a-zA-Z0-9]/g, '')}`;
|
||||
const cached = localStorage.getItem(storageKey);
|
||||
if (cached) {
|
||||
setCachedImageUrl(cached);
|
||||
return;
|
||||
}
|
||||
|
||||
const cacheImage = async () => {
|
||||
try {
|
||||
const response = await fetch(url, { referrerPolicy: 'no-referrer' });
|
||||
const blob = await response.blob();
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = () => {
|
||||
const base64data = reader.result as string;
|
||||
try {
|
||||
localStorage.setItem(storageKey, base64data);
|
||||
setCachedImageUrl(base64data);
|
||||
} catch (e) {
|
||||
console.warn('Failed to cache avatar in localStorage:', e);
|
||||
}
|
||||
};
|
||||
reader.readAsDataURL(blob);
|
||||
} catch (error) {
|
||||
console.error('Failed to cache avatar:', error);
|
||||
}
|
||||
};
|
||||
|
||||
cacheImage();
|
||||
}, [url]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className='relative flex h-full w-full items-center justify-center rounded-full'
|
||||
@@ -25,7 +61,7 @@ const UserAvatar: React.FC<UserAvatarProps> = ({
|
||||
{url ? (
|
||||
<div>
|
||||
<Image
|
||||
src={url}
|
||||
src={cachedImageUrl || url}
|
||||
alt='User Avatar'
|
||||
className={clsx('rounded-full', className, borderClassName)}
|
||||
referrerPolicy='no-referrer'
|
||||
|
||||
Reference in New Issue
Block a user