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/lib | |
| 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/lib')
| -rw-r--r-- | apps/web/src/lib/rate-limit.ts | 6 | ||||
| -rw-r--r-- | apps/web/src/lib/storage/storage-service.ts | 96 | ||||
| -rw-r--r-- | apps/web/src/lib/storage/types.ts | 2 | ||||
| -rw-r--r-- | apps/web/src/lib/waitlist.ts | 13 |
4 files changed, 101 insertions, 16 deletions
diff --git a/apps/web/src/lib/rate-limit.ts b/apps/web/src/lib/rate-limit.ts index e1996cf5..92f70805 100644 --- a/apps/web/src/lib/rate-limit.ts +++ b/apps/web/src/lib/rate-limit.ts @@ -8,9 +8,9 @@ const redis = new Redis({ token: env.UPSTASH_REDIS_REST_TOKEN, }); -export const waitlistRateLimit = new Ratelimit({ +export const baseRateLimit = new Ratelimit({ redis, - limiter: Ratelimit.slidingWindow(5, "1 m"), // 5 requests per minute + limiter: Ratelimit.slidingWindow(100, "1 m"), // 100 requests per minute analytics: true, - prefix: "waitlist-rate-limit", + prefix: "rate-limit", }); diff --git a/apps/web/src/lib/storage/storage-service.ts b/apps/web/src/lib/storage/storage-service.ts index 0037dbdb..98001591 100644 --- a/apps/web/src/lib/storage/storage-service.ts +++ b/apps/web/src/lib/storage/storage-service.ts @@ -9,9 +9,11 @@ import { TimelineData, } from "./types"; import { TimelineTrack } from "@/types/timeline"; +import { SavedSoundsData, SavedSound, SoundEffect } from "@/types/sounds"; class StorageService { private projectsAdapter: IndexedDBAdapter<SerializedProject>; + private savedSoundsAdapter: IndexedDBAdapter<SavedSoundsData>; private config: StorageConfig; constructor() { @@ -19,6 +21,7 @@ class StorageService { projectsDb: "video-editor-projects", mediaDb: "video-editor-media", timelineDb: "video-editor-timelines", + savedSoundsDb: "video-editor-saved-sounds", version: 1, }; @@ -27,6 +30,12 @@ class StorageService { "projects", this.config.version ); + + this.savedSoundsAdapter = new IndexedDBAdapter<SavedSoundsData>( + this.config.savedSoundsDb, + "saved-sounds", + this.config.version + ); } // Helper to get project-specific media adapters @@ -63,6 +72,8 @@ class StorageService { backgroundColor: project.backgroundColor, backgroundType: project.backgroundType, blurIntensity: project.blurIntensity, + bookmarks: project.bookmarks, + fps: project.fps, }; await this.projectsAdapter.set(project.id, serializedProject); @@ -83,6 +94,8 @@ class StorageService { backgroundColor: serializedProject.backgroundColor, backgroundType: serializedProject.backgroundType, blurIntensity: serializedProject.blurIntensity, + bookmarks: serializedProject.bookmarks, + fps: serializedProject.fps, }; } @@ -260,6 +273,89 @@ class StorageService { }; } + async loadSavedSounds(): Promise<SavedSoundsData> { + try { + const savedSoundsData = await this.savedSoundsAdapter.get("user-sounds"); + return ( + savedSoundsData || { + sounds: [], + lastModified: new Date().toISOString(), + } + ); + } catch (error) { + console.error("Failed to load saved sounds:", error); + return { sounds: [], lastModified: new Date().toISOString() }; + } + } + + async saveSoundEffect(soundEffect: SoundEffect): Promise<void> { + try { + const currentData = await this.loadSavedSounds(); + + // Check if sound is already saved + if (currentData.sounds.some((sound) => sound.id === soundEffect.id)) { + return; // Already saved + } + + const savedSound: SavedSound = { + id: soundEffect.id, + name: soundEffect.name, + username: soundEffect.username, + previewUrl: soundEffect.previewUrl, + downloadUrl: soundEffect.downloadUrl, + duration: soundEffect.duration, + tags: soundEffect.tags, + license: soundEffect.license, + savedAt: new Date().toISOString(), + }; + + const updatedData: SavedSoundsData = { + sounds: [...currentData.sounds, savedSound], + lastModified: new Date().toISOString(), + }; + + await this.savedSoundsAdapter.set("user-sounds", updatedData); + } catch (error) { + console.error("Failed to save sound effect:", error); + throw error; + } + } + + async removeSavedSound(soundId: number): Promise<void> { + try { + const currentData = await this.loadSavedSounds(); + + const updatedData: SavedSoundsData = { + sounds: currentData.sounds.filter((sound) => sound.id !== soundId), + lastModified: new Date().toISOString(), + }; + + await this.savedSoundsAdapter.set("user-sounds", updatedData); + } catch (error) { + console.error("Failed to remove saved sound:", error); + throw error; + } + } + + async isSoundSaved(soundId: number): Promise<boolean> { + try { + const currentData = await this.loadSavedSounds(); + return currentData.sounds.some((sound) => sound.id === soundId); + } catch (error) { + console.error("Failed to check if sound is saved:", error); + return false; + } + } + + async clearSavedSounds(): Promise<void> { + try { + await this.savedSoundsAdapter.remove("user-sounds"); + } catch (error) { + console.error("Failed to clear saved sounds:", error); + throw error; + } + } + // Check browser support isOPFSSupported(): boolean { return OPFSAdapter.isSupported(); diff --git a/apps/web/src/lib/storage/types.ts b/apps/web/src/lib/storage/types.ts index b662c164..127b1690 100644 --- a/apps/web/src/lib/storage/types.ts +++ b/apps/web/src/lib/storage/types.ts @@ -30,6 +30,7 @@ export interface StorageConfig { projectsDb: string; mediaDb: string; timelineDb: string; + savedSoundsDb: string; version: number; } @@ -37,6 +38,7 @@ export interface StorageConfig { export type SerializedProject = Omit<TProject, "createdAt" | "updatedAt"> & { createdAt: string; updatedAt: string; + bookmarks?: number[]; }; // Extend FileSystemDirectoryHandle with missing async iterator methods diff --git a/apps/web/src/lib/waitlist.ts b/apps/web/src/lib/waitlist.ts deleted file mode 100644 index 43a620b0..00000000 --- a/apps/web/src/lib/waitlist.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { db, sql, waitlist } from "@opencut/db"; - -export async function getWaitlistCount() { - try { - const result = await db - .select({ count: sql<number>`count(*)` }) - .from(waitlist); - return result[0]?.count || 0; - } catch (error) { - console.error("Failed to fetch waitlist count:", error); - return 0; - } -} |
