|
"use client" |
|
|
|
import { create } from "zustand" |
|
|
|
import { FontName } from "@/lib/fonts" |
|
import { Preset, PresetName, defaultPreset, getPreset, getRandomPreset } from "@/app/engine/presets" |
|
import { LayoutName, defaultLayout, getRandomLayoutName, getRandomLayoutNames } from "../layouts" |
|
import html2canvas from "html2canvas" |
|
import { RenderedScene } from "@/types" |
|
|
|
export const useStore = create<{ |
|
prompt: string |
|
font: FontName |
|
preset: Preset |
|
nbFrames: number |
|
panels: string[] |
|
captions: string[] |
|
upscaleQueue: Record<string, RenderedScene> |
|
showCaptions: boolean |
|
renderedScenes: Record<string, RenderedScene> |
|
layout: LayoutName |
|
layouts: LayoutName[] |
|
zoomLevel: number |
|
page: HTMLDivElement |
|
isGeneratingStory: boolean |
|
panelGenerationStatus: Record<number, boolean> |
|
isGeneratingText: boolean |
|
atLeastOnePanelIsBusy: boolean |
|
setRendered: (panelId: string, renderedScene: RenderedScene) => void |
|
addToUpscaleQueue: (panelId: string, renderedScene: RenderedScene) => void |
|
removeFromUpscaleQueue: (panelId: string) => void |
|
setPrompt: (prompt: string) => void |
|
setFont: (font: FontName) => void |
|
setPreset: (preset: Preset) => void |
|
setPanels: (panels: string[]) => void |
|
setShowCaptions: (showCaptions: boolean) => void |
|
setLayout: (layout: LayoutName) => void |
|
setLayouts: (layouts: LayoutName[]) => void |
|
setCaptions: (captions: string[]) => void |
|
setZoomLevel: (zoomLevel: number) => void |
|
setPage: (page: HTMLDivElement) => void |
|
setGeneratingStory: (isGeneratingStory: boolean) => void |
|
setGeneratingImages: (panelId: string, value: boolean) => void |
|
setGeneratingText: (isGeneratingText: boolean) => void |
|
pageToImage: () => Promise<string> |
|
download: () => Promise<void> |
|
generate: (prompt: string, presetName: PresetName, layoutName: LayoutName) => void |
|
}>((set, get) => ({ |
|
prompt: "", |
|
font: "actionman", |
|
preset: getPreset(defaultPreset), |
|
nbFrames: 1, |
|
panels: [], |
|
captions: [], |
|
upscaleQueue: {} as Record<string, RenderedScene>, |
|
renderedScenes: {} as Record<string, RenderedScene>, |
|
showCaptions: false, |
|
layout: defaultLayout, |
|
layouts: [defaultLayout, defaultLayout], |
|
zoomLevel: 60, |
|
page: undefined as unknown as HTMLDivElement, |
|
isGeneratingStory: false, |
|
panelGenerationStatus: {}, |
|
isGeneratingText: false, |
|
atLeastOnePanelIsBusy: false, |
|
setRendered: (panelId: string, renderedScene: RenderedScene) => { |
|
const { renderedScenes } = get() |
|
set({ |
|
renderedScenes: { |
|
...renderedScenes, |
|
[panelId]: renderedScene |
|
} |
|
}) |
|
}, |
|
addToUpscaleQueue: (panelId: string, renderedScene: RenderedScene) => { |
|
const { upscaleQueue } = get() |
|
set({ |
|
upscaleQueue: { |
|
...upscaleQueue, |
|
[panelId]: renderedScene |
|
}, |
|
}) |
|
}, |
|
removeFromUpscaleQueue: (panelId: string) => { |
|
const upscaleQueue = { ...get().upscaleQueue } |
|
delete upscaleQueue[panelId] |
|
set({ |
|
upscaleQueue, |
|
}) |
|
}, |
|
setPrompt: (prompt: string) => { |
|
const existingPrompt = get().prompt |
|
if (prompt === existingPrompt) { return } |
|
set({ |
|
prompt, |
|
}) |
|
}, |
|
setFont: (font: FontName) => { |
|
const existingFont = get().font |
|
if (font === existingFont) { return } |
|
set({ |
|
font, |
|
}) |
|
}, |
|
setPreset: (preset: Preset) => { |
|
const existingPreset = get().preset |
|
if (preset.label === existingPreset.label) { return } |
|
set({ |
|
preset, |
|
}) |
|
}, |
|
setNbFrames: (nbFrames: number) => { |
|
const existingNbFrames = get().nbFrames |
|
if (nbFrames === existingNbFrames) { return } |
|
set({ |
|
nbFrames, |
|
}) |
|
}, |
|
setPanels: (panels: string[]) => set({ panels }), |
|
setCaptions: (captions: string[]) => { |
|
set({ |
|
captions, |
|
}) |
|
}, |
|
setShowCaptions: (showCaptions: boolean) => { |
|
set({ |
|
showCaptions, |
|
}) |
|
}, |
|
setLayout: (layoutName: LayoutName) => { |
|
const layout = layoutName === "random" |
|
? getRandomLayoutName() |
|
: layoutName |
|
|
|
set({ |
|
layout, |
|
layouts: [layout, layout] |
|
}) |
|
}, |
|
setLayouts: (layouts: LayoutName[]) => set({ layouts }), |
|
setZoomLevel: (zoomLevel: number) => set({ zoomLevel }), |
|
setPage: (page: HTMLDivElement) => { |
|
if (!page) { return } |
|
set({ page }) |
|
}, |
|
setGeneratingStory: (isGeneratingStory: boolean) => set({ isGeneratingStory }), |
|
setGeneratingImages: (panelId: string, value: boolean) => { |
|
const panelGenerationStatus: Record<string, boolean> = { |
|
...get().panelGenerationStatus, |
|
[panelId]: value |
|
} |
|
|
|
const atLeastOnePanelIsBusy = Object.values(panelGenerationStatus).includes(true) |
|
|
|
set({ |
|
panelGenerationStatus, |
|
atLeastOnePanelIsBusy |
|
}) |
|
}, |
|
setGeneratingText: (isGeneratingText: boolean) => set({ isGeneratingText }), |
|
pageToImage: async () => { |
|
const { page } = get() |
|
if (!page) { return "" } |
|
|
|
|
|
const canvas = await html2canvas(page) |
|
console.log("canvas:", canvas) |
|
|
|
const data = canvas.toDataURL('image/jpeg', 0.5) |
|
return data |
|
}, |
|
download: async () => { |
|
const { pageToImage } = get() |
|
const data = await pageToImage() |
|
|
|
const link = document.createElement('a') |
|
|
|
if (typeof link.download === 'string') { |
|
link.href = data |
|
link.download = 'comic.jpg' |
|
document.body.appendChild(link) |
|
link.click() |
|
document.body.removeChild(link) |
|
} else { |
|
window.open(data) |
|
} |
|
}, |
|
generate: (prompt: string, presetName: PresetName, layoutName: LayoutName) => { |
|
const layout = layoutName === "random" |
|
? getRandomLayoutName() |
|
: layoutName |
|
set({ |
|
prompt, |
|
panels: [], |
|
captions: [], |
|
preset: presetName === "random" |
|
? getRandomPreset() |
|
: getPreset(presetName), |
|
layout, |
|
layouts: [layout, layout], |
|
}) |
|
} |
|
})) |
|
|