fix: improve storage file handling (#325)

- Improve storage files handling
- Incremented version in package.json from 2.12.2 to 2.12.3.
- Updated ImageUploader component to improve label and image styles, adding cursor pointer and transition effects for better user interaction.
This commit is contained in:
Giancarlo Buomprisco
2025-08-19 20:37:44 +07:00
committed by GitHub
parent e0560a3685
commit e6ecd63a59
4 changed files with 25 additions and 28 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "next-supabase-saas-kit-turbo", "name": "next-supabase-saas-kit-turbo",
"version": "2.12.2", "version": "2.12.3",
"private": true, "private": true,
"sideEffects": false, "sideEffects": false,
"engines": { "engines": {

View File

@@ -140,29 +140,23 @@ async function uploadUserProfilePhoto(
) { ) {
const bytes = await photoFile.arrayBuffer(); const bytes = await photoFile.arrayBuffer();
const bucket = client.storage.from(AVATARS_BUCKET); const bucket = client.storage.from(AVATARS_BUCKET);
const extension = photoFile.name.split('.').pop(); const fileName = getAvatarFileName(userId);
const fileName = await getAvatarFileName(userId, extension); const { nanoid } = await import('nanoid');
const cacheBuster = nanoid(16);
const result = await bucket.upload(fileName, bytes, { const result = await bucket.upload(fileName, bytes, {
contentType: photoFile.type,
upsert: true, upsert: true,
}); });
if (!result.error) { if (!result.error) {
return bucket.getPublicUrl(fileName).data.publicUrl; const url = bucket.getPublicUrl(userId).data.publicUrl;
return `${url}?v=${cacheBuster}`;
} }
throw result.error; throw result.error;
} }
async function getAvatarFileName( function getAvatarFileName(userId: string) {
userId: string, return userId;
extension: string | undefined,
) {
const { nanoid } = await import('nanoid');
// we add a version to the URL to ensure
// the browser always fetches the latest image
const uniqueId = nanoid(16);
return `${userId}.${extension}?v=${uniqueId}`;
} }

View File

@@ -118,26 +118,23 @@ async function uploadUserProfilePhoto(
) { ) {
const bytes = await photoFile.arrayBuffer(); const bytes = await photoFile.arrayBuffer();
const bucket = client.storage.from(AVATARS_BUCKET); const bucket = client.storage.from(AVATARS_BUCKET);
const extension = photoFile.name.split('.').pop(); const fileName = getAvatarFileName(userId);
const fileName = await getAvatarFileName(userId, extension); const { nanoid } = await import('nanoid');
const cacheBuster = nanoid(16);
const result = await bucket.upload(fileName, bytes, { const result = await bucket.upload(fileName, bytes, {
contentType: photoFile.type,
upsert: true, upsert: true,
}); });
if (!result.error) { if (!result.error) {
return bucket.getPublicUrl(fileName).data.publicUrl; const url = bucket.getPublicUrl(userId).data.publicUrl;
return `${url}?v=${cacheBuster}`;
} }
throw result.error; throw result.error;
} }
async function getAvatarFileName( function getAvatarFileName(userId: string) {
userId: string, return userId;
extension: string | undefined,
) {
const { nanoid } = await import('nanoid');
const uniqueId = nanoid(16);
return `${userId}.${extension}?v=${uniqueId}`;
} }

View File

@@ -69,11 +69,17 @@ export function ImageUploader(
return ( return (
<div className={'flex items-center space-x-4'}> <div className={'flex items-center space-x-4'}>
<label className={'animate-in fade-in zoom-in-50 relative h-20 w-20'}> <label
className={
'animate-in fade-in zoom-in-50 group/label relative h-20 w-20 cursor-pointer'
}
>
{/* eslint-disable-next-line @next/next/no-img-element */} {/* eslint-disable-next-line @next/next/no-img-element */}
<img <img
decoding="async" decoding="async"
className={'h-20 w-20 rounded-full object-cover'} className={
'h-20 w-20 rounded-full object-cover transition-all duration-300 group-hover/label:opacity-80'
}
src={image} src={image}
alt={''} alt={''}
/> />