fix thumbnail issues
This commit is contained in:
@@ -5,6 +5,7 @@ import { useThree } from '@react-three/fiber'
|
|||||||
import { useEffect, useRef } from 'react'
|
import { useEffect, useRef } from 'react'
|
||||||
import * as THREE from 'three'
|
import * as THREE from 'three'
|
||||||
import { uploadProjectThumbnail } from '@/features/community/lib/projects/actions'
|
import { uploadProjectThumbnail } from '@/features/community/lib/projects/actions'
|
||||||
|
import { useProjectStore } from '@/features/community/lib/projects/store'
|
||||||
|
|
||||||
const THUMBNAIL_WIDTH = 1920
|
const THUMBNAIL_WIDTH = 1920
|
||||||
const THUMBNAIL_HEIGHT = 1080
|
const THUMBNAIL_HEIGHT = 1080
|
||||||
@@ -70,8 +71,7 @@ export const ThumbnailGenerator = ({ projectId: propProjectId }: ThumbnailGenera
|
|||||||
const result = await uploadProjectThumbnail(projectId, blob)
|
const result = await uploadProjectThumbnail(projectId, blob)
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
console.log('✅ Thumbnail uploaded successfully!')
|
useProjectStore.getState().updateActiveThumbnail(result.data.thumbnail_url)
|
||||||
console.log('🔗 URL:', result.data.thumbnail_url)
|
|
||||||
} else {
|
} else {
|
||||||
console.error('❌ Failed to upload thumbnail:', result.error)
|
console.error('❌ Failed to upload thumbnail:', result.error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,15 +71,9 @@ export function SettingsPanel() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleGenerateThumbnail = () => {
|
const handleGenerateThumbnail = () => {
|
||||||
if (!projectId) {
|
if (!projectId) return;
|
||||||
console.error('❌ No project ID found');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.log('🎯 Generate thumbnail clicked for project:', projectId);
|
|
||||||
setIsGeneratingThumbnail(true);
|
setIsGeneratingThumbnail(true);
|
||||||
emitter.emit('camera-controls:generate-thumbnail', { projectId });
|
emitter.emit('camera-controls:generate-thumbnail', { projectId });
|
||||||
console.log('📤 Event emitted with project ID:', projectId);
|
|
||||||
// Reset loading state after a delay (thumbnail generation is async)
|
|
||||||
setTimeout(() => setIsGeneratingThumbnail(false), 3000);
|
setTimeout(() => setIsGeneratingThumbnail(false), 3000);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -106,6 +100,16 @@ export function SettingsPanel() {
|
|||||||
<label className="font-medium text-muted-foreground text-xs uppercase">
|
<label className="font-medium text-muted-foreground text-xs uppercase">
|
||||||
Thumbnail
|
Thumbnail
|
||||||
</label>
|
</label>
|
||||||
|
{activeProject?.thumbnail_url && (
|
||||||
|
<div className="rounded overflow-hidden border border-border aspect-video w-full bg-muted">
|
||||||
|
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||||
|
<img
|
||||||
|
src={activeProject.thumbnail_url}
|
||||||
|
alt="Project thumbnail"
|
||||||
|
className="w-full h-full object-cover"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<Button
|
<Button
|
||||||
className="w-full justify-start gap-2"
|
className="w-full justify-start gap-2"
|
||||||
onClick={handleGenerateThumbnail}
|
onClick={handleGenerateThumbnail}
|
||||||
|
|||||||
@@ -1020,16 +1020,14 @@ export async function uploadProjectThumbnail(
|
|||||||
return { success: false, error: 'Not authorized to update this project' }
|
return { success: false, error: 'Not authorized to update this project' }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a unique filename
|
const filename = `${projectId}/thumbnail.png`
|
||||||
const timestamp = Date.now()
|
|
||||||
const filename = `${projectId}/${timestamp}.png`
|
|
||||||
|
|
||||||
// Upload to Supabase Storage
|
// Upload to Supabase Storage (upsert to override existing thumbnail)
|
||||||
const { data: uploadData, error: uploadError } = await supabase.storage
|
const { data: uploadData, error: uploadError } = await supabase.storage
|
||||||
.from('project-thumbnails')
|
.from('project-thumbnails')
|
||||||
.upload(filename, blob, {
|
.upload(filename, blob, {
|
||||||
contentType: 'image/png',
|
contentType: 'image/png',
|
||||||
upsert: false,
|
upsert: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (uploadError) {
|
if (uploadError) {
|
||||||
@@ -1041,7 +1039,7 @@ export async function uploadProjectThumbnail(
|
|||||||
.from('project-thumbnails')
|
.from('project-thumbnails')
|
||||||
.getPublicUrl(uploadData.path)
|
.getPublicUrl(uploadData.path)
|
||||||
|
|
||||||
const thumbnailUrl = urlData.publicUrl
|
const thumbnailUrl = `${urlData.publicUrl}?t=${Date.now()}`
|
||||||
|
|
||||||
// Update the project with the new thumbnail URL
|
// Update the project with the new thumbnail URL
|
||||||
const { error: updateError } = await (supabase
|
const { error: updateError } = await (supabase
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ interface ProjectStore {
|
|||||||
fetchActiveProject: () => Promise<void>
|
fetchActiveProject: () => Promise<void>
|
||||||
setActiveProject: (projectId: string) => Promise<void>
|
setActiveProject: (projectId: string) => Promise<void>
|
||||||
initialize: () => Promise<void>
|
initialize: () => Promise<void>
|
||||||
|
updateActiveThumbnail: (thumbnailUrl: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useProjectStore = create<ProjectStore>((set, get) => ({
|
export const useProjectStore = create<ProjectStore>((set, get) => ({
|
||||||
@@ -78,6 +79,15 @@ export const useProjectStore = create<ProjectStore>((set, get) => ({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Patch the active project's thumbnail URL in place (no refetch)
|
||||||
|
updateActiveThumbnail: (thumbnailUrl: string) => {
|
||||||
|
set((state) => ({
|
||||||
|
activeProject: state.activeProject
|
||||||
|
? { ...state.activeProject, thumbnail_url: thumbnailUrl }
|
||||||
|
: null,
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
|
||||||
// Initialize - fetch both projects and active project
|
// Initialize - fetch both projects and active project
|
||||||
initialize: async () => {
|
initialize: async () => {
|
||||||
set({ isLoading: true })
|
set({ isLoading: true })
|
||||||
|
|||||||
@@ -2,6 +2,11 @@ import type { NextConfig } from 'next'
|
|||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
transpilePackages: ['three', '@pascal-app/viewer', '@pascal-app/core'],
|
transpilePackages: ['three', '@pascal-app/viewer', '@pascal-app/core'],
|
||||||
|
experimental: {
|
||||||
|
serverActions: {
|
||||||
|
bodySizeLimit: '10mb',
|
||||||
|
},
|
||||||
|
},
|
||||||
images: {
|
images: {
|
||||||
remotePatterns: [
|
remotePatterns: [
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user