diff --git a/src/stores/settings.store.ts b/src/stores/settings.store.ts new file mode 100644 index 0000000..cd9e623 --- /dev/null +++ b/src/stores/settings.store.ts @@ -0,0 +1,55 @@ +import { create } from "zustand"; +import { createMMKV } from "react-native-mmkv"; + +const storage = createMMKV({ id: "lively-settings" }); + +interface SettingsState { + exportQuality: "low" | "medium" | "high"; + fps: 15 | 24 | 30; + hapticFeedback: boolean; + autoDepthMap: boolean; + + setExportQuality: (quality: "low" | "medium" | "high") => void; + setFps: (fps: 15 | 24 | 30) => void; + setHapticFeedback: (enabled: boolean) => void; + setAutoDepthMap: (enabled: boolean) => void; + loadSettings: () => void; +} + +export const useSettingsStore = create((set) => ({ + exportQuality: "high", + fps: 24, + hapticFeedback: true, + autoDepthMap: false, + + setExportQuality: (quality) => { + storage.set("exportQuality", quality); + set({ exportQuality: quality }); + }, + setFps: (fps) => { + storage.set("fps", fps); + set({ fps }); + }, + setHapticFeedback: (enabled) => { + storage.set("hapticFeedback", enabled); + set({ hapticFeedback: enabled }); + }, + setAutoDepthMap: (enabled) => { + storage.set("autoDepthMap", enabled); + set({ autoDepthMap: enabled }); + }, + + loadSettings: () => { + const quality = storage.getString("exportQuality"); + const fps = storage.getNumber("fps"); + const haptic = storage.getBoolean("hapticFeedback"); + const autoDepth = storage.getBoolean("autoDepthMap"); + + set({ + ...(quality && { exportQuality: quality as "low" | "medium" | "high" }), + ...(fps && { fps: fps as 15 | 24 | 30 }), + ...(haptic !== undefined && { hapticFeedback: haptic }), + ...(autoDepth !== undefined && { autoDepthMap: autoDepth }), + }); + }, +})); diff --git a/src/stores/wallpaper.store.ts b/src/stores/wallpaper.store.ts new file mode 100644 index 0000000..73dfb80 --- /dev/null +++ b/src/stores/wallpaper.store.ts @@ -0,0 +1,110 @@ +import { create } from "zustand"; +import { createMMKV } from "react-native-mmkv"; +import type { + AnimationType, + AnimationUniforms, + WallpaperConfig, + ParticlePreset, +} from "@/types/wallpaper"; + +const storage = createMMKV({ id: "lively-wallpapers" }); + +interface WallpaperState { + // Current editing session + sourceUri: string | null; + depthMapUri: string | null; + animation: AnimationType; + uniforms: AnimationUniforms; + particlePreset: ParticlePreset; + + // Saved wallpapers + savedWallpapers: WallpaperConfig[]; + + // Actions + setSourceImage: (uri: string) => void; + setDepthMap: (uri: string | null) => void; + setAnimation: (type: AnimationType) => void; + setUniform: (key: string, value: number) => void; + setParticlePreset: (preset: ParticlePreset) => void; + resetEditor: () => void; + saveWallpaper: () => WallpaperConfig | null; + deleteWallpaper: (id: string) => void; + loadSavedWallpapers: () => void; +} + +const DEFAULT_UNIFORMS_VALUES: AnimationUniforms = { + intensity: 0.5, + speed: 0.3, + direction: 0, + scale: 1.0, +}; + +export const useWallpaperStore = create((set, get) => ({ + sourceUri: null, + depthMapUri: null, + animation: "ken-burns", + uniforms: { ...DEFAULT_UNIFORMS_VALUES }, + particlePreset: "snow", + savedWallpapers: [], + + setSourceImage: (uri) => set({ sourceUri: uri }), + setDepthMap: (uri) => set({ depthMapUri: uri }), + setAnimation: (type) => set({ animation: type }), + setUniform: (key, value) => + set((state) => ({ + uniforms: { ...state.uniforms, [key]: value }, + })), + setParticlePreset: (preset) => set({ particlePreset: preset }), + + resetEditor: () => + set({ + sourceUri: null, + depthMapUri: null, + animation: "ken-burns", + uniforms: { ...DEFAULT_UNIFORMS_VALUES }, + particlePreset: "snow", + }), + + saveWallpaper: () => { + const { sourceUri, depthMapUri, animation, uniforms, particlePreset } = get(); + if (!sourceUri) return null; + + const config: WallpaperConfig = { + id: `wp_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`, + sourceUri, + depthMapUri: depthMapUri ?? undefined, + animation, + uniforms: { ...uniforms }, + particlePreset: animation === "particles" ? particlePreset : undefined, + fps: 24, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + + set((state) => { + const updated = [config, ...state.savedWallpapers]; + storage.set("wallpapers", JSON.stringify(updated)); + return { savedWallpapers: updated }; + }); + + return config; + }, + + deleteWallpaper: (id) => + set((state) => { + const updated = state.savedWallpapers.filter((w) => w.id !== id); + storage.set("wallpapers", JSON.stringify(updated)); + return { savedWallpapers: updated }; + }), + + loadSavedWallpapers: () => { + const raw = storage.getString("wallpapers"); + if (raw) { + try { + set({ savedWallpapers: JSON.parse(raw) }); + } catch { + storage.remove("wallpapers"); + } + } + }, +}));