File size: 5,775 Bytes
6da9beb 93ad82e 6da9beb 93ad82e 6da9beb 93ad82e 6da9beb 93ad82e 6da9beb 9d89208 6da9beb 93ad82e 893530c 93ad82e 6da9beb 9d89208 6da9beb 93ad82e 893530c 93ad82e 6da9beb 93ad82e c78f7b4 6da9beb 93ad82e 6da9beb 9d89208 6da9beb 93ad82e 893530c 93ad82e 6da9beb 9d89208 6da9beb 93ad82e 893530c 93ad82e 6da9beb |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
"use client"
import { ClapProject, parseClap, serializeClap } from "@aitube/clap"
import { create } from "zustand"
import { GlobalStatus, TaskStatus } from "@/types"
import { VideoOrientation } from "./types"
import { getVideoOrientation } from "@/lib/utils/getVideoOrientation"
export const useStore = create<{
mainCharacterImage: string
mainCharacterVoice: string
storyPromptDraft: string
storyPrompt: string
// the desired orientation for the next video
// but this won't impact the actual orientation of the fake device container
orientation: VideoOrientation
status: GlobalStatus
storyGenerationStatus: TaskStatus
assetGenerationStatus: TaskStatus
voiceGenerationStatus: TaskStatus
imageGenerationStatus: TaskStatus
videoGenerationStatus: TaskStatus
currentClap?: ClapProject
currentVideo: string
// orientation of the currently loaded video (which can be different from `orientation`)
// it will impact the actual orientation of the fake device container
currentVideoOrientation: VideoOrientation
progress: number
error: string
toggleOrientation: () => void
setCurrentVideoOrientation: (currentVideoOrientation: VideoOrientation) => void
setMainCharacterImage: (mainCharacterImage: string) => void
setMainCharacterVoice: (mainCharacterVoice: string) => void
setStoryPromptDraft: (storyPromptDraft: string) => void
setStoryPrompt: (storyPrompt: string) => void
setStatus: (status: GlobalStatus) => void
setStoryGenerationStatus: (storyGenerationStatus: TaskStatus) => void
setAssetGenerationStatus: (assetGenerationStatus: TaskStatus) => void
setVoiceGenerationStatus: (voiceGenerationStatus: TaskStatus) => void
setImageGenerationStatus: (imageGenerationStatus: TaskStatus) => void
setVideoGenerationStatus: (videoGenerationStatus: TaskStatus) => void
setCurrentClap: (currentClap?: ClapProject) => void
// note: this will preload the video, and compute the orientation too
setGeneratedVideo: (generatedVideo: string) => Promise<void>
setProgress: (progress: number) => void
setError: (error: string) => void
saveClap: (fileName?: string) => Promise<void>
loadClap: (blob: Blob, fileName?: string) => Promise<void>
}>((set, get) => ({
mainCharacterImage: "",
mainCharacterVoice: "",
storyPromptDraft: "Yesterday I was at my favorite pizza place and..",
storyPrompt: "",
orientation: VideoOrientation.PORTRAIT,
status: "idle",
storyGenerationStatus: "idle",
assetGenerationStatus: "idle",
voiceGenerationStatus: "idle",
imageGenerationStatus: "idle",
videoGenerationStatus: "idle",
currentClap: undefined,
currentVideo: "",
currentVideoOrientation: VideoOrientation.PORTRAIT,
progress: 0,
error: "",
toggleOrientation: () => {
const { orientation: previousOrientation, currentVideoOrientation, currentVideo } = get()
const orientation =
previousOrientation === VideoOrientation.LANDSCAPE
? VideoOrientation.PORTRAIT
: VideoOrientation.LANDSCAPE
set({
orientation,
// we normally don't touch the currentVideoOrientation since it will already contain a video
currentVideoOrientation:
currentVideo
? currentVideoOrientation
: orientation
})
},
setCurrentVideoOrientation: (currentVideoOrientation: VideoOrientation) => { set({ currentVideoOrientation }) },
setMainCharacterImage: (mainCharacterImage: string) => { set({ mainCharacterImage }) },
setMainCharacterVoice: (mainCharacterVoice: string) => { set({ mainCharacterVoice }) },
setStoryPromptDraft: (storyPromptDraft: string) => { set({ storyPromptDraft }) },
setStoryPrompt: (storyPrompt: string) => { set({ storyPrompt }) },
setStatus: (status: GlobalStatus) => { set({ status }) },
setStoryGenerationStatus: (storyGenerationStatus: TaskStatus) => { set({ storyGenerationStatus }) },
setAssetGenerationStatus: (assetGenerationStatus: TaskStatus) => { set({ assetGenerationStatus }) },
setVoiceGenerationStatus: (voiceGenerationStatus: TaskStatus) => { set({ voiceGenerationStatus }) },
setImageGenerationStatus: (imageGenerationStatus: TaskStatus) => { set({ imageGenerationStatus }) },
setVideoGenerationStatus: (videoGenerationStatus: TaskStatus) => { set({ videoGenerationStatus }) },
setCurrentClap: (currentClap?: ClapProject) => { set({ currentClap }) },
setGeneratedVideo: async (currentVideo: string): Promise<void> => {
const currentVideoOrientation = await getVideoOrientation(currentVideo)
set({
currentVideo,
currentVideoOrientation
})
},
setProgress: (progress: number) => { set({ progress }) },
setError: (error: string) => { set({ error }) },
saveClap: async (fileName: string = "untitled_story.clap"): Promise<void> => {
const { currentClap } = get()
if (!currentClap) { throw new Error(`cannot save a clap.. if there is no clap`) }
const currentClapBlob: Blob = await serializeClap(currentClap)
// Create an object URL for the compressed clap blob
const objectUrl = URL.createObjectURL(currentClapBlob)
// Create an anchor element and force browser download
const anchor = document.createElement("a")
anchor.href = objectUrl
anchor.download = fileName
document.body.appendChild(anchor) // Append to the body (could be removed once clicked)
anchor.click() // Trigger the download
// Cleanup: revoke the object URL and remove the anchor element
URL.revokeObjectURL(objectUrl)
document.body.removeChild(anchor)
},
loadClap: async (blob: Blob, fileName: string = "untitled_story.clap"): Promise<void> => {
if (!blob) {
throw new Error(`missing blob`)
}
const currentClap: ClapProject = await parseClap(blob)
set({
currentClap,
})
},
})) |