HomePilot / frontend /src /ui /studio /stores /studioStore.js
HomePilot Deploy Bot
chore(hf): sync HomePilot to HF Space
921d377
Raw
History Blame Contribute Delete
4.92 kB
import { create } from "zustand";
import { persist } from "zustand/middleware";
const DEFAULT_SETTINGS = {
model: "abyssOrangeMix3_aom3a1b.safetensors",
width: 512,
height: 768,
steps: 25,
cfg: 6.0,
sampler: "dpm++_2m_karras",
clipSkip: 2,
seed: "random",
};
const initialState = {
// Connection
backendUrl: "",
apiKey: "",
// Content Rating
contentRating: "sfw",
matureVerified: false,
matureEnabled: false,
// Generation
currentPrompt: "",
currentNegativePrompt: "lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry",
currentSettings: DEFAULT_SETTINGS,
selectedPresetId: null,
selectedModelId: DEFAULT_SETTINGS.model,
isGenerating: false,
generationProgress: 0,
// Policy
policyResult: null,
// Gallery
generatedImages: [],
selectedImageId: null,
// UI State
sidebarCollapsed: false,
activeTab: "generate",
showAdvancedSettings: false,
};
export const useStudioStore = create()(persist((set, get) => ({
...initialState,
// Connection
setConnection: (backendUrl, apiKey) => set({ backendUrl, apiKey }),
// Content Rating
setContentRating: (rating) => set({ contentRating: rating }),
setMatureVerified: (verified) => set({ matureVerified: verified }),
setMatureEnabled: (enabled) => set({ matureEnabled: enabled }),
// Generation
setCurrentPrompt: (prompt) => set({ currentPrompt: prompt }),
setCurrentNegativePrompt: (prompt) => set({ currentNegativePrompt: prompt }),
setCurrentSettings: (settings) => set((state) => ({
currentSettings: { ...state.currentSettings, ...settings },
})),
setSelectedPresetId: (presetId) => set({ selectedPresetId: presetId }),
setSelectedModelId: (modelId) => set((state) => ({
selectedModelId: modelId,
currentSettings: { ...state.currentSettings, model: modelId },
})),
setIsGenerating: (generating) => set({ isGenerating: generating }),
setGenerationProgress: (progress) => set({ generationProgress: progress }),
applyPreset: (preset) => set((state) => ({
selectedPresetId: preset.id,
currentSettings: {
...state.currentSettings,
steps: preset.sampler_settings.steps,
cfg: preset.sampler_settings.cfg_scale,
sampler: preset.sampler_settings.sampler,
clipSkip: preset.sampler_settings.clip_skip,
model: preset.recommended_models[0] || state.currentSettings.model,
},
currentNegativePrompt: preset.prompt_injection?.negative || state.currentNegativePrompt,
selectedModelId: preset.recommended_models[0] || state.selectedModelId,
})),
// Policy
setPolicyResult: (result) => set({ policyResult: result }),
// Gallery
addGeneratedImage: (image) => set((state) => ({
generatedImages: [image, ...state.generatedImages].slice(0, 200),
})),
removeGeneratedImage: (id) => set((state) => ({
generatedImages: state.generatedImages.filter((img) => img.id !== id),
selectedImageId: state.selectedImageId === id ? null : state.selectedImageId,
})),
toggleFavorite: (id) => set((state) => ({
generatedImages: state.generatedImages.map((img) => img.id === id ? { ...img, favorite: !img.favorite } : img),
})),
setSelectedImageId: (id) => set({ selectedImageId: id }),
clearGallery: () => set({ generatedImages: [], selectedImageId: null }),
// UI State
setSidebarCollapsed: (collapsed) => set({ sidebarCollapsed: collapsed }),
setActiveTab: (tab) => set({ activeTab: tab }),
setShowAdvancedSettings: (show) => set({ showAdvancedSettings: show }),
// Reset
reset: () => set(initialState),
}), {
name: "studio-storage",
partialize: (state) => ({
contentRating: state.contentRating,
matureVerified: state.matureVerified,
generatedImages: state.generatedImages,
sidebarCollapsed: state.sidebarCollapsed,
currentSettings: state.currentSettings,
selectedModelId: state.selectedModelId,
}),
}));
// Selectors
export const selectContentRating = (state) => state.contentRating;
export const selectIsNsfwAllowed = (state) => state.matureEnabled && state.contentRating === "mature" && state.matureVerified;
export const selectFavoriteImages = (state) => state.generatedImages.filter((img) => img.favorite);
export const selectRecentImages = (state) => state.generatedImages.slice(0, 20);
/**
* Get the current studio configuration (backendUrl and apiKey).
* Used by the API helpers to make authenticated requests.
*/
export function getStudioConfig() {
const state = useStudioStore.getState();
return { backendUrl: state.backendUrl, apiKey: state.apiKey };
}