"use client"; import { useEffect, useState } from "react"; import { usePathname } from "next/navigation"; import { storageService } from "@/lib/storage/storage-service"; import { TProject } from "@/types/project"; import { TScene } from "@/types/timeline"; import { generateUUID } from "@/lib/utils"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Progress } from "@/components/ui/progress"; interface MigrationProgress { current: number; total: number; currentProjectName: string; } export function ScenesMigrator({ children }: { children: React.ReactNode }) { const pathname = usePathname(); const [isMigrating, setIsMigrating] = useState(false); const [progress, setProgress] = useState({ current: 0, total: 0, currentProjectName: "", }); const shouldCheckMigration = pathname.startsWith("/editor") || pathname.startsWith("/projects"); useEffect(() => { if (!shouldCheckMigration) return; checkAndMigrateProjects(); }, [shouldCheckMigration]); const checkAndMigrateProjects = async () => { try { const projects = await storageService.loadAllProjects(); const legacyProjects = projects.filter( (project) => !project.scenes || project.scenes.length === 0 ); if (legacyProjects.length === 0) { // No migration needed return; } setIsMigrating(true); setProgress({ current: 0, total: legacyProjects.length, currentProjectName: "", }); // Migrate each legacy project for (let i = 0; i < legacyProjects.length; i++) { const project = legacyProjects[i]; setProgress({ current: i, total: legacyProjects.length, currentProjectName: project.name, }); await migrateLegacyProject(project); } setProgress({ current: legacyProjects.length, total: legacyProjects.length, currentProjectName: "Complete!", }); setTimeout(() => { setIsMigrating(false); }, 1000); } catch (error) { console.error("Migration failed:", error); setIsMigrating(false); } }; const migrateLegacyProject = async (project: TProject) => { try { const mainScene: TScene = { id: generateUUID(), name: "Main Scene", isMain: true, createdAt: new Date(), updatedAt: new Date(), }; const migratedProject: TProject = { ...project, scenes: [mainScene], currentSceneId: mainScene.id, updatedAt: new Date(), }; // Load existing timeline data (legacy format) const legacyTimeline = await storageService.loadTimeline({ projectId: project.id, }); await storageService.saveProject({ project: migratedProject }); // If timeline data, migrate it to the main scene if (legacyTimeline && legacyTimeline.length > 0) { await storageService.saveTimeline({ projectId: project.id, tracks: legacyTimeline, sceneId: mainScene.id, }); } // Clean up legacy timeline storage await storageService.deleteProjectTimeline({ projectId: project.id }); } catch (error) { console.error(`Failed to migrate project ${project.name}:`, error); throw error; } }; if (!shouldCheckMigration) { return children; } if (isMigrating) { const progressPercent = progress.total > 0 ? (progress.current / progress.total) * 100 : 0; return ( e.preventDefault()} > Updating Projects We're adding scene support to your projects. This will only take a moment.
Progress {progress.current} of {progress.total}
{progress.currentProjectName && (
{progress.current < progress.total ? `Updating: ${progress.currentProjectName}` : progress.currentProjectName}
)}
); } return children; }