diff options
| author | ryu <ryumacodes@gmail.com> | 2025-08-07 19:37:06 +0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-07 19:37:06 +0500 |
| commit | e71788014d137a74f10420601451ddfbb84701bb (patch) | |
| tree | 2c08f7fbbc7537b12935e842981830aed976ce87 /apps/web/src/stores/project-store.ts | |
| parent | 6412158003f295a350fc66800796f30c8f3c534b (diff) | |
| parent | d022a78ae2330665e7d763fdc6e831a71f3b9ea1 (diff) | |
| download | opencut-e71788014d137a74f10420601451ddfbb84701bb.tar.gz | |
Merge branch 'main' into feat/timeline-return-to-start
Diffstat (limited to 'apps/web/src/stores/project-store.ts')
| -rw-r--r-- | apps/web/src/stores/project-store.ts | 126 |
1 files changed, 125 insertions, 1 deletions
diff --git a/apps/web/src/stores/project-store.ts b/apps/web/src/stores/project-store.ts index 7bb38039..5c617dff 100644 --- a/apps/web/src/stores/project-store.ts +++ b/apps/web/src/stores/project-store.ts @@ -11,6 +11,7 @@ interface ProjectStore { savedProjects: TProject[]; isLoading: boolean; isInitialized: boolean; + invalidProjectIds?: Set<string>; // Actions createNewProject: (name: string) => Promise<string>; @@ -28,10 +29,20 @@ interface ProjectStore { ) => Promise<void>; updateProjectFps: (fps: number) => Promise<void>; + // Bookmark methods + toggleBookmark: (time: number) => Promise<void>; + isBookmarked: (time: number) => boolean; + removeBookmark: (time: number) => Promise<void>; + getFilteredAndSortedProjects: ( searchQuery: string, sortOption: string ) => TProject[]; + + // Global invalid project ID tracking + isInvalidProjectId: (id: string) => boolean; + markProjectIdAsInvalid: (id: string) => void; + clearInvalidProjectIds: () => void; } export const useProjectStore = create<ProjectStore>((set, get) => ({ @@ -39,6 +50,98 @@ export const useProjectStore = create<ProjectStore>((set, get) => ({ savedProjects: [], isLoading: true, isInitialized: false, + invalidProjectIds: new Set<string>(), + + // Implementation of bookmark methods + toggleBookmark: async (time: number) => { + const { activeProject } = get(); + if (!activeProject) return; + + // Round time to the nearest frame + const fps = activeProject.fps || 30; + const frameTime = Math.round(time * fps) / fps; + + const bookmarks = activeProject.bookmarks || []; + let updatedBookmarks: number[]; + + // Check if already bookmarked + const bookmarkIndex = bookmarks.findIndex( + (bookmark) => Math.abs(bookmark - frameTime) < 0.001 + ); + + if (bookmarkIndex !== -1) { + // Remove bookmark + updatedBookmarks = bookmarks.filter((_, i) => i !== bookmarkIndex); + } else { + // Add bookmark + updatedBookmarks = [...bookmarks, frameTime].sort((a, b) => a - b); + } + + const updatedProject = { + ...activeProject, + bookmarks: updatedBookmarks, + updatedAt: new Date(), + }; + + try { + await storageService.saveProject(updatedProject); + set({ activeProject: updatedProject }); + await get().loadAllProjects(); // Refresh the list + } catch (error) { + console.error("Failed to update project bookmarks:", error); + toast.error("Failed to update bookmarks", { + description: "Please try again", + }); + } + }, + + isBookmarked: (time: number) => { + const { activeProject } = get(); + if (!activeProject || !activeProject.bookmarks) return false; + + // Round time to the nearest frame + const fps = activeProject.fps || 30; + const frameTime = Math.round(time * fps) / fps; + + return activeProject.bookmarks.some( + (bookmark) => Math.abs(bookmark - frameTime) < 0.001 + ); + }, + + removeBookmark: async (time: number) => { + const { activeProject } = get(); + if (!activeProject || !activeProject.bookmarks) return; + + // Round time to the nearest frame + const fps = activeProject.fps || 30; + const frameTime = Math.round(time * fps) / fps; + + const updatedBookmarks = activeProject.bookmarks.filter( + (bookmark) => Math.abs(bookmark - frameTime) >= 0.001 + ); + + if (updatedBookmarks.length === activeProject.bookmarks.length) { + // No bookmark found to remove + return; + } + + const updatedProject = { + ...activeProject, + bookmarks: updatedBookmarks, + updatedAt: new Date(), + }; + + try { + await storageService.saveProject(updatedProject); + set({ activeProject: updatedProject }); + await get().loadAllProjects(); // Refresh the list + } catch (error) { + console.error("Failed to update project bookmarks:", error); + toast.error("Failed to remove bookmark", { + description: "Please try again", + }); + } + }, createNewProject: async (name: string) => { const newProject: TProject = { @@ -50,6 +153,8 @@ export const useProjectStore = create<ProjectStore>((set, get) => ({ backgroundColor: "#000000", backgroundType: "color", blurIntensity: 8, + bookmarks: [], + fps: 30, }; set({ activeProject: newProject }); @@ -230,9 +335,9 @@ export const useProjectStore = create<ProjectStore>((set, get) => ({ existingNumbers.length > 0 ? Math.max(...existingNumbers) + 1 : 1; const newProject: TProject = { + ...project, // Copy all properties from the original project id: generateUUID(), name: `(${nextNumber}) ${baseName}`, - thumbnail: project.thumbnail, createdAt: new Date(), updatedAt: new Date(), }; @@ -357,4 +462,23 @@ export const useProjectStore = create<ProjectStore>((set, get) => ({ return sortedProjects; }, + + // Global invalid project ID tracking implementation + isInvalidProjectId: (id: string) => { + const invalidIds = get().invalidProjectIds || new Set(); + return invalidIds.has(id); + }, + + markProjectIdAsInvalid: (id: string) => { + set((state) => ({ + invalidProjectIds: new Set([ + ...(state.invalidProjectIds || new Set()), + id, + ]), + })); + }, + + clearInvalidProjectIds: () => { + set({ invalidProjectIds: new Set() }); + }, })); |
