From 9a134b12abf06099bff343e3d2e4408e85414cbb Mon Sep 17 00:00:00 2001 From: AI Bot Date: Sat, 7 Nov 2026 15:42:19 -0500 Subject: [PATCH] fix(media): use Appwrite /view endpoint instead of /preview for Cloud compatibility --- dripzone-app/src/lib/image-optimizer.ts | 20 +++++++------------ src/app/[slug]/page.tsx | 4 ++-- src/app/api/reports/posts/route.tsx | 2 +- src/app/api/webhooks/whatsapp/route.ts | 2 +- src/app/clasificados/page.tsx | 2 +- src/app/dashboard/entity/page.tsx | 2 +- src/app/eventos/page.tsx | 2 +- src/app/layout.tsx | 2 +- src/app/login/page.tsx | 2 +- src/app/page.tsx | 2 +- src/components/ClientSidebars.tsx | 2 +- src/components/Navbar.tsx | 2 +- src/components/NewsTicker.tsx | 2 +- src/components/TopBanner.tsx | 4 ++-- .../dashboard/MediaGridSelector.tsx | 2 +- src/components/dashboard/MediaPickerMini.tsx | 4 ++-- src/components/media/StreamOverlays.tsx | 2 +- src/components/publications/PostCard.tsx | 2 +- .../publications/RelationSelectField.tsx | 2 +- src/lib/preferences.ts | 2 +- 20 files changed, 29 insertions(+), 35 deletions(-) diff --git a/dripzone-app/src/lib/image-optimizer.ts b/dripzone-app/src/lib/image-optimizer.ts index 33429f4..9b91a7a 100644 --- a/dripzone-app/src/lib/image-optimizer.ts +++ b/dripzone-app/src/lib/image-optimizer.ts @@ -11,7 +11,7 @@ export interface ImageOptimizationOptions { format?: 'webp' | 'avif' | 'jpg' | 'png'; } -const DEFAULT_PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c'; +const DEFAULT_PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '6aef63d9002c07371b40'; export function getOptimizedImageUrl( url?: string | null, @@ -42,26 +42,20 @@ export function getOptimizedImageUrl( const format = options.format || 'webp'; try { - // 1. Appwrite Storage URL Optimization + // 1. Appwrite Storage URL Optimization (use /view for Appwrite Cloud Free Plan compatibility) if (trimmed.includes('/storage/buckets/') && (trimmed.includes('/files/') || trimmed.includes('/view') || trimmed.includes('/preview'))) { let optimized = trimmed; - // Convert /view to /preview for Appwrite image transformation engine - if (optimized.includes('/view')) { - optimized = optimized.replace('/view', '/preview'); - } else if (!optimized.includes('/preview') && optimized.includes('/files/')) { - // e.g. /files/fileId -> /files/fileId/preview + if (optimized.includes('/preview')) { + optimized = optimized.replace('/preview', '/view'); + } else if (!optimized.includes('/view') && optimized.includes('/files/')) { const regex = /(\/files\/[^\/\?]+)(.*)/; - optimized = optimized.replace(regex, '$1/preview$2'); + optimized = optimized.replace(regex, '$1/view$2'); } - const urlObj = new URL(optimized, 'https://appwrite.almeira.com.co'); + const urlObj = new URL(optimized, 'https://nyc.cloud.appwrite.io'); if (!urlObj.searchParams.has('project')) { urlObj.searchParams.set('project', DEFAULT_PROJECT_ID); } - urlObj.searchParams.set('width', width.toString()); - urlObj.searchParams.set('height', height.toString()); - urlObj.searchParams.set('quality', quality.toString()); - urlObj.searchParams.set('output', format); return urlObj.toString(); } diff --git a/src/app/[slug]/page.tsx b/src/app/[slug]/page.tsx index cdf6560..99f293a 100644 --- a/src/app/[slug]/page.tsx +++ b/src/app/[slug]/page.tsx @@ -177,7 +177,7 @@ export async function generateMetadata( const client = await createAdminClient(); const mediaRes = await client.databases.getDocument(APPWRITE_ALMEIRA_CONFIG.databaseId, 'media', post.imagen_destacada_id); if (mediaRes) { - imagenUrl = `${ENDPOINT}/storage/buckets/${mediaRes.bucket_id}/files/${mediaRes.file_id}/preview?project=${PROJECT_ID}&width=1200&height=630&quality=90`; + imagenUrl = `${ENDPOINT}/storage/buckets/${mediaRes.bucket_id}/files/${mediaRes.file_id}/view?project=${PROJECT_ID}&width=1200&height=630&quality=90`; } } catch(e) {} } @@ -231,7 +231,7 @@ export default async function NoticiaDetail({ params }: { params: Promise<{ slug const client = await createAdminClient(); const mediaRes = await client.databases.getDocument(APPWRITE_ALMEIRA_CONFIG.databaseId, 'media', post.imagen_destacada_id); if (mediaRes) { - imagenUrl = `${ENDPOINT}/storage/buckets/${mediaRes.bucket_id}/files/${mediaRes.file_id}/preview?project=${PROJECT_ID}&width=640&height=${imgHeight}&quality=90`; + imagenUrl = `${ENDPOINT}/storage/buckets/${mediaRes.bucket_id}/files/${mediaRes.file_id}/view?project=${PROJECT_ID}&width=640&height=${imgHeight}&quality=90`; } } catch(e) {} } diff --git a/src/app/api/reports/posts/route.tsx b/src/app/api/reports/posts/route.tsx index 6ceb1cc..28eb243 100644 --- a/src/app/api/reports/posts/route.tsx +++ b/src/app/api/reports/posts/route.tsx @@ -12,7 +12,7 @@ function getAppwriteImageUrl(fileId: string, bucketId?: string, width = 400, hei if (isVideo) { return `${endpoint}/storage/buckets/${finalBucketId}/files/${fileId}/view?project=${projectId}`; } - return `${endpoint}/storage/buckets/${finalBucketId}/files/${fileId}/preview?project=${projectId}&width=${width}&height=${height}&quality=80`; + return `${endpoint}/storage/buckets/${finalBucketId}/files/${fileId}/view?project=${projectId}&width=${width}&height=${height}&quality=80`; } export const runtime = 'nodejs'; diff --git a/src/app/api/webhooks/whatsapp/route.ts b/src/app/api/webhooks/whatsapp/route.ts index 7fb19c2..ad1ea2f 100644 --- a/src/app/api/webhooks/whatsapp/route.ts +++ b/src/app/api/webhooks/whatsapp/route.ts @@ -397,7 +397,7 @@ function detectExplicitPublicationType(inputText: string): 'noticia' | 'evento' let ogImageUrl = undefined; if (storageFileId) { - ogImageUrl = `${APPWRITE_ALMEIRA_CONFIG.endpoint}/storage/buckets/${APPWRITE_ALMEIRA_CONFIG.mediaBucketId}/files/${storageFileId}/preview?project=${APPWRITE_ALMEIRA_CONFIG.projectId}&width=640&height=${imgHeight}&gravity=${gravity}&quality=85`; + ogImageUrl = `${APPWRITE_ALMEIRA_CONFIG.endpoint}/storage/buckets/${APPWRITE_ALMEIRA_CONFIG.mediaBucketId}/files/${storageFileId}/view?project=${APPWRITE_ALMEIRA_CONFIG.projectId}&width=640&height=${imgHeight}&gravity=${gravity}&quality=85`; } // Determinar fecha de vencimiento diff --git a/src/app/clasificados/page.tsx b/src/app/clasificados/page.tsx index 0734482..1724c5c 100644 --- a/src/app/clasificados/page.tsx +++ b/src/app/clasificados/page.tsx @@ -140,7 +140,7 @@ export default async function ClasificadosPage() { const mediaObj = post.resolved_media || (typeof post.imagen_destacada_id === 'object' ? post.imagen_destacada_id : null) as MediaItem | null; if (mediaObj) { - imagenUrl = `${ENDPOINT}/storage/buckets/${mediaObj.bucket_id}/files/${mediaObj.file_id}/preview?project=${PROJECT_ID}&width=640&height=640&quality=80`; + imagenUrl = `${ENDPOINT}/storage/buckets/${mediaObj.bucket_id}/files/${mediaObj.file_id}/view?project=${PROJECT_ID}&width=640&height=640&quality=80`; } return ( diff --git a/src/app/dashboard/entity/page.tsx b/src/app/dashboard/entity/page.tsx index 93b4f51..3ae98bd 100644 --- a/src/app/dashboard/entity/page.tsx +++ b/src/app/dashboard/entity/page.tsx @@ -73,7 +73,7 @@ export default async function EntityPage() { const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '6aef63d9002c07371b40'; let logoUrl = entity?.logotipo || ''; if (logoUrl && !logoUrl.startsWith('http') && !logoUrl.startsWith('/')) { - logoUrl = `${ENDPOINT}/storage/buckets/media/files/${logoUrl}/view?project=${PROJECT_ID}`; + logoUrl = `${ENDPOINT}/storage/buckets/media_bucket/files/${logoUrl}/view?project=${PROJECT_ID}`; } return ; })()} diff --git a/src/app/eventos/page.tsx b/src/app/eventos/page.tsx index d8eacee..51abfb0 100644 --- a/src/app/eventos/page.tsx +++ b/src/app/eventos/page.tsx @@ -140,7 +140,7 @@ export default async function EventosPage() { const mediaObj = post.resolved_media || (typeof post.imagen_destacada_id === 'object' ? post.imagen_destacada_id : null) as MediaItem | null; if (mediaObj) { - imagenUrl = `${ENDPOINT}/storage/buckets/${mediaObj.bucket_id}/files/${mediaObj.file_id}/preview?project=${PROJECT_ID}&width=640&height=640&quality=80`; + imagenUrl = `${ENDPOINT}/storage/buckets/${mediaObj.bucket_id}/files/${mediaObj.file_id}/view?project=${PROJECT_ID}&width=640&height=640&quality=80`; } return ( diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 7cee09e..47a2fee 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -16,7 +16,7 @@ export async function generateMetadata(): Promise { const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '6aef63d9002c07371b40'; let logoUrl = entity?.logotipo || null; if (logoUrl && !logoUrl.startsWith('http') && !logoUrl.startsWith('/')) { - logoUrl = `${ENDPOINT}/storage/buckets/media/files/${logoUrl}/view?project=${PROJECT_ID}`; + logoUrl = `${ENDPOINT}/storage/buckets/media_bucket/files/${logoUrl}/view?project=${PROJECT_ID}`; } return { diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index eb134b6..6e88c90 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -9,7 +9,7 @@ export default async function LoginPage() { const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '6aef63d9002c07371b40'; let logoUrl = entity?.logotipo || null; if (logoUrl && !logoUrl.startsWith('http') && !logoUrl.startsWith('/')) { - logoUrl = `${ENDPOINT}/storage/buckets/media/files/${logoUrl}/view?project=${PROJECT_ID}`; + logoUrl = `${ENDPOINT}/storage/buckets/media_bucket/files/${logoUrl}/view?project=${PROJECT_ID}`; } return ( diff --git a/src/app/page.tsx b/src/app/page.tsx index 5301538..08d8457 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -224,7 +224,7 @@ export default async function Home(props: { searchParams: Promise<{ [key: string const mediaObj = post.resolved_media || (typeof post.imagen_destacada_id === 'object' ? post.imagen_destacada_id : null) as MediaItem | null; if (mediaObj) { - imagenUrl = `${ENDPOINT}/storage/buckets/${mediaObj.bucket_id}/files/${mediaObj.file_id}/preview?project=${PROJECT_ID}&width=640&height=${imgHeight}&quality=85`; + imagenUrl = `${ENDPOINT}/storage/buckets/${mediaObj.bucket_id}/files/${mediaObj.file_id}/view?project=${PROJECT_ID}&width=640&height=${imgHeight}&quality=85`; } return ( diff --git a/src/components/ClientSidebars.tsx b/src/components/ClientSidebars.tsx index 81a644e..fa8f547 100644 --- a/src/components/ClientSidebars.tsx +++ b/src/components/ClientSidebars.tsx @@ -52,7 +52,7 @@ function ClientCarouselGroup({ eslogan, ads, rotationSeconds }: { eslogan: strin if (typeof activeAd.imagen_destacada_id === 'object' && activeAd.imagen_destacada_id.bucket_id) { imgUrl = `${ENDPOINT}/storage/buckets/${activeAd.imagen_destacada_id.bucket_id}/files/${activeAd.imagen_destacada_id.file_id}/view?project=${PROJECT_ID}`; } else if (typeof activeAd.imagen_destacada_id === 'string') { - imgUrl = `${ENDPOINT}/storage/buckets/media/files/${activeAd.imagen_destacada_id}/view?project=${PROJECT_ID}`; + imgUrl = `${ENDPOINT}/storage/buckets/media_bucket/files/${activeAd.imagen_destacada_id}/view?project=${PROJECT_ID}`; } } diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 0838397..a77b4e5 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -15,7 +15,7 @@ export const Navbar = ({ entity }: { entity?: any }) => { const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '6aef63d9002c07371b40'; let logoUrl = entity?.logotipo || null; if (logoUrl && !logoUrl.startsWith('http') && !logoUrl.startsWith('/')) { - logoUrl = `${ENDPOINT}/storage/buckets/media/files/${logoUrl}/view?project=${PROJECT_ID}`; + logoUrl = `${ENDPOINT}/storage/buckets/media_bucket/files/${logoUrl}/view?project=${PROJECT_ID}`; } useEffect(() => { diff --git a/src/components/NewsTicker.tsx b/src/components/NewsTicker.tsx index e2045cd..e2b2a65 100644 --- a/src/components/NewsTicker.tsx +++ b/src/components/NewsTicker.tsx @@ -55,7 +55,7 @@ export default async function NewsTicker() { const media = typeof post.imagen_destacada_id === 'object' ? post.imagen_destacada_id : mediaMap.get(post.imagen_destacada_id); let imagenUrl = post.og_image_url || null; if (media) { - imagenUrl = `${APPWRITE_ALMEIRA_CONFIG.endpoint}/storage/buckets/${media.bucket_id}/files/${media.file_id}/preview?project=${APPWRITE_ALMEIRA_CONFIG.projectId}`; + imagenUrl = `${APPWRITE_ALMEIRA_CONFIG.endpoint}/storage/buckets/${media.bucket_id}/files/${media.file_id}/view?project=${APPWRITE_ALMEIRA_CONFIG.projectId}`; } tickerItems.push({ diff --git a/src/components/TopBanner.tsx b/src/components/TopBanner.tsx index 61c9979..48a9fe9 100644 --- a/src/components/TopBanner.tsx +++ b/src/components/TopBanner.tsx @@ -33,10 +33,10 @@ export default function TopBanner({ initialBanners, rotationSeconds }: { initial if (activeBanner.imagen_destacada_id) { if (typeof activeBanner.imagen_destacada_id === 'object' && activeBanner.imagen_destacada_id.bucket_id) { - imgUrl = `${ENDPOINT}/storage/buckets/${activeBanner.imagen_destacada_id.bucket_id}/files/${activeBanner.imagen_destacada_id.file_id}/preview?project=${PROJECT_ID}&width=1920&height=500&quality=85`; + imgUrl = `${ENDPOINT}/storage/buckets/${activeBanner.imagen_destacada_id.bucket_id}/files/${activeBanner.imagen_destacada_id.file_id}/view?project=${PROJECT_ID}&width=1920&height=500&quality=85`; } else if (typeof activeBanner.imagen_destacada_id === 'string') { // Fallback to 'media' bucket if we only have the ID - imgUrl = `${ENDPOINT}/storage/buckets/media/files/${activeBanner.imagen_destacada_id}/preview?project=${PROJECT_ID}&width=1920&height=500&quality=85`; + imgUrl = `${ENDPOINT}/storage/buckets/media_bucket/files/${activeBanner.imagen_destacada_id}/view?project=${PROJECT_ID}&width=1920&height=500&quality=85`; } } diff --git a/src/components/dashboard/MediaGridSelector.tsx b/src/components/dashboard/MediaGridSelector.tsx index e1b1b58..842a3ef 100644 --- a/src/components/dashboard/MediaGridSelector.tsx +++ b/src/components/dashboard/MediaGridSelector.tsx @@ -13,7 +13,7 @@ export function getAppwriteImageUrl(fileId: string, bucketId?: string, width = 4 if (isVideo) { return `${endpoint}/storage/buckets/${finalBucketId}/files/${fileId}/view?project=${projectId}`; } - return `${endpoint}/storage/buckets/${finalBucketId}/files/${fileId}/preview?project=${projectId}&width=${width}&height=${height}&quality=80`; + return `${endpoint}/storage/buckets/${finalBucketId}/files/${fileId}/view?project=${projectId}&width=${width}&height=${height}&quality=80`; } interface MediaGridSelectorProps { diff --git a/src/components/dashboard/MediaPickerMini.tsx b/src/components/dashboard/MediaPickerMini.tsx index 43f645d..0df2e11 100644 --- a/src/components/dashboard/MediaPickerMini.tsx +++ b/src/components/dashboard/MediaPickerMini.tsx @@ -60,7 +60,7 @@ export const MediaPickerMini = ({ value, onChange, label }: MediaPickerMiniProps }, [searchTerm, isOpen]); const getImageUrl = (fileId: string) => { - return `${endpoint}/storage/buckets/media/files/${fileId}/view?project=${projectId}&width=200&height=200&gravity=center`; + return `${endpoint}/storage/buckets/media_bucket/files/${fileId}/view?project=${projectId}&width=200&height=200&gravity=center`; }; const filteredItems = mediaItems; @@ -91,7 +91,7 @@ export const MediaPickerMini = ({ value, onChange, label }: MediaPickerMiniProps {value ? ( <> Selected diff --git a/src/components/media/StreamOverlays.tsx b/src/components/media/StreamOverlays.tsx index dc83c6d..f470c75 100644 --- a/src/components/media/StreamOverlays.tsx +++ b/src/components/media/StreamOverlays.tsx @@ -168,7 +168,7 @@ export const StreamOverlays = () => { const bucketId = mediaObj.bucket_id || APPWRITE_ALMEIRA_CONFIG.mediaBucketId; return ( {activeItem.titulo} diff --git a/src/components/publications/PostCard.tsx b/src/components/publications/PostCard.tsx index 944aef6..38bd147 100644 --- a/src/components/publications/PostCard.tsx +++ b/src/components/publications/PostCard.tsx @@ -38,7 +38,7 @@ function resolveImageUrl( const { bucket_id, file_id } = post.imagen_destacada_id; const isSquare = post.tipo === 'evento' || post.tipo === 'aviso'; const height = isSquare ? 640 : 360; - return `${endpoint}/storage/buckets/${bucket_id}/files/${file_id}/preview?project=${projectId}&width=640&height=${height}&quality=80`; + return `${endpoint}/storage/buckets/${bucket_id}/files/${file_id}/view?project=${projectId}&width=640&height=${height}&quality=80`; } // If it's a string, we can't generate a valid URL because it's a document ID, not a file ID. diff --git a/src/components/publications/RelationSelectField.tsx b/src/components/publications/RelationSelectField.tsx index 7d889fa..a7e7ded 100644 --- a/src/components/publications/RelationSelectField.tsx +++ b/src/components/publications/RelationSelectField.tsx @@ -186,7 +186,7 @@ function MediaThumbnail({ fileId }: { fileId: string }) { const endpoint = process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT || 'https://nyc.cloud.appwrite.io/v1'; const projectId = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '6aef63d9002c07371b40'; - const url = `${endpoint}/storage/buckets/media/files/${fileId}/preview?project=${projectId}&width=400&height=250&quality=80`; + const url = `${endpoint}/storage/buckets/media_bucket/files/${fileId}/view?project=${projectId}&width=400&height=250&quality=80`; return (
diff --git a/src/lib/preferences.ts b/src/lib/preferences.ts index a930449..954a680 100644 --- a/src/lib/preferences.ts +++ b/src/lib/preferences.ts @@ -10,7 +10,7 @@ export interface UserPreferences { */ export async function getUserPreferences(): Promise { try { - const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '69b84df5003bd8957c5c'; + const PROJECT_ID = process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID || '6aef63d9002c07371b40'; const { cookies } = await import('next/headers'); const cookieStore = await cookies(); const sessionCookie = cookieStore.get(`a_session_${PROJECT_ID.toLowerCase()}`);