You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
173 lines
5.7 KiB
173 lines
5.7 KiB
import { create } from "zustand";
|
|
import type { GenerationBatchSize, SelectedModel } from "@/types";
|
|
import {
|
|
createPopiserverDefaultAudioModel,
|
|
createPopiserverDefaultImageModel,
|
|
createPopiserverDefaultVideoModel,
|
|
} from "@/store/utils/defaultImageModel";
|
|
|
|
export type GenerationPreferenceType = "image" | "video" | "audio";
|
|
|
|
export interface GenerationPreferenceNodeSize {
|
|
width: number;
|
|
height: number;
|
|
}
|
|
|
|
export interface ImageGenerationPreference {
|
|
type: "image";
|
|
model: SelectedModel;
|
|
aspectRatio: string;
|
|
resolution: string;
|
|
batchSize: GenerationBatchSize;
|
|
parameters?: Record<string, unknown>;
|
|
extraTaskParams?: Record<string, unknown>;
|
|
subType?: number;
|
|
nodeSize?: GenerationPreferenceNodeSize;
|
|
}
|
|
|
|
export interface VideoGenerationPreference {
|
|
type: "video";
|
|
model: SelectedModel;
|
|
parameters?: Record<string, unknown>;
|
|
extraTaskParams?: Record<string, unknown>;
|
|
subType?: number;
|
|
batchSize: GenerationBatchSize;
|
|
nodeSize?: GenerationPreferenceNodeSize;
|
|
}
|
|
|
|
export interface AudioGenerationPreference {
|
|
type: "audio";
|
|
model: SelectedModel;
|
|
voiceId?: string;
|
|
parameters?: Record<string, unknown>;
|
|
extraTaskParams?: Record<string, unknown>;
|
|
subType?: number;
|
|
batchSize?: GenerationBatchSize;
|
|
nodeSize?: GenerationPreferenceNodeSize;
|
|
}
|
|
|
|
type GenerationPreferencePatch = {
|
|
model?: SelectedModel;
|
|
selectedModel?: SelectedModel;
|
|
aspectRatio?: unknown;
|
|
resolution?: unknown;
|
|
parameters?: unknown;
|
|
extraTaskParams?: unknown;
|
|
subType?: unknown;
|
|
batchSize?: unknown;
|
|
voiceId?: unknown;
|
|
audioVoiceId?: unknown;
|
|
nodeSize?: unknown;
|
|
};
|
|
|
|
interface GenerationPreferenceState {
|
|
image: ImageGenerationPreference;
|
|
video: VideoGenerationPreference;
|
|
audio: AudioGenerationPreference;
|
|
updateImagePreference: (patch: GenerationPreferencePatch) => void;
|
|
updateVideoPreference: (patch: GenerationPreferencePatch) => void;
|
|
updateAudioPreference: (patch: GenerationPreferencePatch) => void;
|
|
}
|
|
|
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
}
|
|
|
|
function normalizeCommonPreferencePatch(patch: GenerationPreferencePatch) {
|
|
const next: {
|
|
model?: SelectedModel;
|
|
parameters?: Record<string, unknown>;
|
|
extraTaskParams?: Record<string, unknown>;
|
|
subType?: number;
|
|
batchSize?: GenerationBatchSize;
|
|
nodeSize?: GenerationPreferenceNodeSize;
|
|
} = {};
|
|
const model = patch.model ?? patch.selectedModel;
|
|
if (model) next.model = model;
|
|
if (isRecord(patch.parameters)) next.parameters = { ...patch.parameters };
|
|
if (isRecord(patch.extraTaskParams)) next.extraTaskParams = { ...patch.extraTaskParams };
|
|
if (typeof patch.subType === "number") next.subType = patch.subType;
|
|
if (typeof patch.batchSize === "number") next.batchSize = patch.batchSize;
|
|
if (isRecord(patch.nodeSize)) {
|
|
const width = patch.nodeSize.width;
|
|
const height = patch.nodeSize.height;
|
|
if (typeof width === "number" && Number.isFinite(width) && width > 0 &&
|
|
typeof height === "number" && Number.isFinite(height) && height > 0) {
|
|
next.nodeSize = { width, height };
|
|
}
|
|
}
|
|
return next;
|
|
}
|
|
|
|
function normalizeImagePreferencePatch(patch: GenerationPreferencePatch): Partial<Omit<ImageGenerationPreference, "type">> {
|
|
const next: Partial<Omit<ImageGenerationPreference, "type">> = normalizeCommonPreferencePatch(patch);
|
|
if (typeof patch.aspectRatio === "string") next.aspectRatio = patch.aspectRatio;
|
|
if (typeof patch.resolution === "string") next.resolution = patch.resolution;
|
|
return next;
|
|
}
|
|
|
|
function normalizeVideoPreferencePatch(patch: GenerationPreferencePatch): Partial<Omit<VideoGenerationPreference, "type">> {
|
|
return normalizeCommonPreferencePatch(patch);
|
|
}
|
|
|
|
function normalizeAudioPreferencePatch(patch: GenerationPreferencePatch): Partial<Omit<AudioGenerationPreference, "type">> {
|
|
const next: Partial<Omit<AudioGenerationPreference, "type">> = normalizeCommonPreferencePatch(patch);
|
|
if (Object.prototype.hasOwnProperty.call(patch, "voiceId")) {
|
|
next.voiceId = typeof patch.voiceId === "string" ? patch.voiceId : undefined;
|
|
} else if (Object.prototype.hasOwnProperty.call(patch, "audioVoiceId")) {
|
|
next.voiceId = typeof patch.audioVoiceId === "string" ? patch.audioVoiceId : undefined;
|
|
}
|
|
return next;
|
|
}
|
|
|
|
function createInitialImagePreference(): ImageGenerationPreference {
|
|
return {
|
|
type: "image",
|
|
model: createPopiserverDefaultImageModel(),
|
|
aspectRatio: "9:16",
|
|
resolution: "1K",
|
|
batchSize: 1,
|
|
};
|
|
}
|
|
|
|
function createInitialVideoPreference(): VideoGenerationPreference {
|
|
const model = createPopiserverDefaultVideoModel();
|
|
return {
|
|
type: "video",
|
|
model,
|
|
parameters: {},
|
|
extraTaskParams: {},
|
|
subType: model.subType,
|
|
batchSize: 1,
|
|
};
|
|
}
|
|
|
|
function createInitialAudioPreference(): AudioGenerationPreference {
|
|
return {
|
|
type: "audio",
|
|
model: createPopiserverDefaultAudioModel(),
|
|
};
|
|
}
|
|
|
|
export function createInitialGenerationPreferences(): Pick<GenerationPreferenceState, "image" | "video" | "audio"> {
|
|
return {
|
|
image: createInitialImagePreference(),
|
|
video: createInitialVideoPreference(),
|
|
audio: createInitialAudioPreference(),
|
|
};
|
|
}
|
|
|
|
export const useGenerationPreferenceStore = create<GenerationPreferenceState>()(
|
|
(set) => ({
|
|
...createInitialGenerationPreferences(),
|
|
updateImagePreference: (patch) => set((state) => ({
|
|
image: { ...state.image, ...normalizeImagePreferencePatch(patch), type: "image" },
|
|
})),
|
|
updateVideoPreference: (patch) => set((state) => ({
|
|
video: { ...state.video, ...normalizeVideoPreferencePatch(patch), type: "video" },
|
|
})),
|
|
updateAudioPreference: (patch) => set((state) => ({
|
|
audio: { ...state.audio, ...normalizeAudioPreferencePatch(patch), type: "audio" },
|
|
})),
|
|
})
|
|
);
|
|
|