From f7ef8d7f38af0f049288a58787bc7b9f931599df Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Mon, 1 Sep 2025 23:17:48 +0200 Subject: [PATCH] move logic to zustand store --- .../editor/media-panel/views/stickers.tsx | 41 ++------------ apps/web/src/stores/stickers-store.ts | 53 +++++++++++++++++++ 2 files changed, 56 insertions(+), 38 deletions(-) diff --git a/apps/web/src/components/editor/media-panel/views/stickers.tsx b/apps/web/src/components/editor/media-panel/views/stickers.tsx index 0d293242..f67450cc 100644 --- a/apps/web/src/components/editor/media-panel/views/stickers.tsx +++ b/apps/web/src/components/editor/media-panel/views/stickers.tsx @@ -181,12 +181,12 @@ function StickersContentView({ category }: { category: StickerCategory }) { setSelectedCollection, loadCollections, searchStickers, - downloadSticker, + addStickerToTimeline, clearRecentStickers, setSelectedCategory, + addingSticker, } = useStickersStore(); - const [addingSticker, setAddingSticker] = useState(null); const [localSearchQuery, setLocalSearchQuery] = useState(searchQuery); const [collectionsToShow, setCollectionsToShow] = useState(20); const [showCollectionItems, setShowCollectionItems] = useState(false); @@ -250,46 +250,11 @@ function StickersContentView({ category }: { category: StickerCategory }) { }, [localSearchQuery]); const handleAddSticker = async (iconName: string) => { - if (!activeProject) { - toast.error("No active project"); - return; - } - - setAddingSticker(iconName); - try { - const file = await downloadSticker(iconName); - - if (!file) { - throw new Error("Failed to download sticker"); - } - - const mediaItem: Omit = { - name: iconName.replace(":", "-"), - type: "image", - file, - url: URL.createObjectURL(file), - width: 200, - height: 200, - duration: TIMELINE_CONSTANTS.DEFAULT_IMAGE_DURATION, - ephemeral: false, - }; - - await addMediaFile(activeProject.id, mediaItem); - - const added = useMediaStore - .getState() - .mediaFiles.find( - (m) => m.url === mediaItem.url && m.name === mediaItem.name - ); - if (!added) throw new Error("Sticker not in media store"); - - addElementAtTime(added, currentTime); + await addStickerToTimeline(iconName); } catch (error) { console.error("Failed to add sticker:", error); toast.error("Failed to add sticker to timeline"); - } finally { - setAddingSticker(null); } }; diff --git a/apps/web/src/stores/stickers-store.ts b/apps/web/src/stores/stickers-store.ts index da8b926b..c7c9ef98 100644 --- a/apps/web/src/stores/stickers-store.ts +++ b/apps/web/src/stores/stickers-store.ts @@ -9,6 +9,12 @@ import { type CollectionInfo, type IconSearchResult, } from "@/lib/iconify-api"; +import { useProjectStore } from "@/stores/project-store"; +import { useMediaStore } from "@/stores/media-store"; +import { useTimelineStore } from "@/stores/timeline-store"; +import { usePlaybackStore } from "@/stores/playback-store"; +import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants"; +import type { MediaFile } from "@/types/media"; export type StickerCategory = "all" | "general" | "brands" | "emoji"; @@ -26,6 +32,7 @@ interface StickersStore { isLoadingCollection: boolean; isSearching: boolean; isDownloading: boolean; + addingSticker: string | null; setSearchQuery: (query: string) => void; setSelectedCategory: (category: StickerCategory) => void; @@ -36,6 +43,7 @@ interface StickersStore { loadCollection: (prefix: string) => Promise; searchStickers: (query: string) => Promise; downloadSticker: (iconName: string) => Promise; + addStickerToTimeline: (iconName: string) => Promise; addToRecentStickers: (iconName: string) => void; clearRecentStickers: () => void; @@ -58,6 +66,7 @@ export const useStickersStore = create((set, get) => ({ isLoadingCollection: false, isSearching: false, isDownloading: false, + addingSticker: null, setSearchQuery: (query) => set({ searchQuery: query }), @@ -162,6 +171,50 @@ export const useStickersStore = create((set, get) => ({ } }, + addStickerToTimeline: async (iconName: string) => { + set({ addingSticker: iconName }); + try { + const { activeProject } = useProjectStore.getState(); + if (!activeProject) { + throw new Error("No active project"); + } + + const file = await get().downloadSticker(iconName); + if (!file) { + throw new Error("Failed to download sticker"); + } + + const mediaItem: Omit = { + name: iconName.replace(":", "-"), + type: "image", + file, + url: URL.createObjectURL(file), + width: 200, + height: 200, + duration: TIMELINE_CONSTANTS.DEFAULT_IMAGE_DURATION, + ephemeral: false, + }; + + const { addMediaFile } = useMediaStore.getState(); + await addMediaFile(activeProject.id, mediaItem); + + const added = useMediaStore + .getState() + .mediaFiles.find( + (m) => m.url === mediaItem.url && m.name === mediaItem.name + ); + if (!added) { + throw new Error("Sticker not in media store"); + } + + const { currentTime } = usePlaybackStore.getState(); + const { addElementAtTime } = useTimelineStore.getState(); + addElementAtTime(added, currentTime); + } finally { + set({ addingSticker: null }); + } + }, + addToRecentStickers: (iconName: string) => { set((state) => { const recent = [