908 lines
22 KiB
TypeScript
908 lines
22 KiB
TypeScript
import { atom, selector } from 'recoil'
|
|
import _ from 'lodash'
|
|
import { HDStrategy, LDMSampler } from '../components/Settings/HDSettingBlock'
|
|
import { ToastState } from '../components/shared/Toast'
|
|
|
|
function strEnum<T extends string>(o: Array<T>): { [K in T]: K } {
|
|
return o.reduce((res, key) => {
|
|
res[key] = key
|
|
return res
|
|
}, Object.create(null))
|
|
}
|
|
|
|
export enum AIModel {
|
|
LAMA = 'lama',
|
|
LDM = 'ldm',
|
|
ZITS = 'zits',
|
|
MAT = 'mat',
|
|
FCF = 'fcf',
|
|
SD15 = 'sd1.5',
|
|
ANYTHING4 = 'anything4',
|
|
REALISTIC_VISION_1_4 = 'realisticVision1.4',
|
|
SD2 = 'sd2',
|
|
CV2 = 'cv2',
|
|
Mange = 'manga',
|
|
PAINT_BY_EXAMPLE = 'paint_by_example',
|
|
PIX2PIX = 'instruct_pix2pix',
|
|
KANDINSKY22 = 'kandinsky2.2',
|
|
}
|
|
|
|
export enum ControlNetMethod {
|
|
canny = 'canny',
|
|
inpaint = 'inpaint',
|
|
openpose = 'openpose',
|
|
depth = 'depth',
|
|
}
|
|
|
|
export const ControlNetMethodMap: any = {
|
|
canny: 'control_v11p_sd15_canny',
|
|
inpaint: 'control_v11p_sd15_inpaint',
|
|
openpose: 'control_v11p_sd15_openpose',
|
|
depth: 'control_v11f1p_sd15_depth',
|
|
}
|
|
|
|
export const ControlNetMethodMap2: any = {
|
|
control_v11p_sd15_canny: 'canny',
|
|
control_v11p_sd15_inpaint: 'inpaint',
|
|
control_v11p_sd15_openpose: 'openpose',
|
|
control_v11f1p_sd15_depth: 'depth',
|
|
}
|
|
|
|
export const maskState = atom<File | undefined>({
|
|
key: 'maskState',
|
|
default: undefined,
|
|
})
|
|
|
|
export const paintByExampleImageState = atom<File | undefined>({
|
|
key: 'paintByExampleImageState',
|
|
default: undefined,
|
|
})
|
|
|
|
export interface Rect {
|
|
x: number
|
|
y: number
|
|
width: number
|
|
height: number
|
|
}
|
|
|
|
interface AppState {
|
|
file: File | undefined
|
|
imageHeight: number
|
|
imageWidth: number
|
|
disableShortCuts: boolean
|
|
isInpainting: boolean
|
|
isDisableModelSwitch: boolean
|
|
isEnableAutoSaving: boolean
|
|
isInteractiveSeg: boolean
|
|
isInteractiveSegRunning: boolean
|
|
interactiveSegClicks: number[][]
|
|
showFileManager: boolean
|
|
enableFileManager: boolean
|
|
gifImage: HTMLImageElement | undefined
|
|
brushSize: number
|
|
isControlNet: boolean
|
|
controlNetMethod: string
|
|
plugins: string[]
|
|
isPluginRunning: boolean
|
|
}
|
|
|
|
export const appState = atom<AppState>({
|
|
key: 'appState',
|
|
default: {
|
|
file: undefined,
|
|
imageHeight: 0,
|
|
imageWidth: 0,
|
|
disableShortCuts: false,
|
|
isInpainting: false,
|
|
isDisableModelSwitch: false,
|
|
isEnableAutoSaving: false,
|
|
isInteractiveSeg: false,
|
|
isInteractiveSegRunning: false,
|
|
interactiveSegClicks: [],
|
|
showFileManager: false,
|
|
enableFileManager: false,
|
|
gifImage: undefined,
|
|
brushSize: 40,
|
|
isControlNet: false,
|
|
controlNetMethod: ControlNetMethod.canny,
|
|
plugins: [],
|
|
isPluginRunning: false,
|
|
},
|
|
})
|
|
|
|
export const propmtState = atom<string>({
|
|
key: 'promptState',
|
|
default: '',
|
|
})
|
|
|
|
export const negativePropmtState = atom<string>({
|
|
key: 'negativePromptState',
|
|
default: '',
|
|
})
|
|
|
|
export const isInpaintingState = selector({
|
|
key: 'isInpainting',
|
|
get: ({ get }) => {
|
|
const app = get(appState)
|
|
return app.isInpainting
|
|
},
|
|
set: ({ get, set }, newValue: any) => {
|
|
const app = get(appState)
|
|
set(appState, { ...app, isInpainting: newValue })
|
|
},
|
|
})
|
|
|
|
export const isPluginRunningState = selector({
|
|
key: 'isPluginRunningState',
|
|
get: ({ get }) => {
|
|
const app = get(appState)
|
|
return app.isPluginRunning
|
|
},
|
|
set: ({ get, set }, newValue: any) => {
|
|
const app = get(appState)
|
|
set(appState, { ...app, isPluginRunning: newValue })
|
|
},
|
|
})
|
|
|
|
export const serverConfigState = selector({
|
|
key: 'serverConfigState',
|
|
get: ({ get }) => {
|
|
const app = get(appState)
|
|
return {
|
|
isControlNet: app.isControlNet,
|
|
controlNetMethod: app.controlNetMethod,
|
|
isDisableModelSwitchState: app.isDisableModelSwitch,
|
|
isEnableAutoSaving: app.isEnableAutoSaving,
|
|
enableFileManager: app.enableFileManager,
|
|
plugins: app.plugins,
|
|
}
|
|
},
|
|
set: ({ get, set }, newValue: any) => {
|
|
const app = get(appState)
|
|
const methodShortName = ControlNetMethodMap2[newValue.controlNetMethod]
|
|
set(appState, { ...app, ...newValue, controlnetMethod: methodShortName })
|
|
|
|
const setting = get(settingState)
|
|
set(settingState, {
|
|
...setting,
|
|
controlnetMethod: methodShortName,
|
|
})
|
|
},
|
|
})
|
|
|
|
export const brushSizeState = selector({
|
|
key: 'brushSizeState',
|
|
get: ({ get }) => {
|
|
const app = get(appState)
|
|
return app.brushSize
|
|
},
|
|
set: ({ get, set }, newValue: any) => {
|
|
const app = get(appState)
|
|
set(appState, { ...app, brushSize: newValue })
|
|
},
|
|
})
|
|
|
|
export const imageHeightState = selector({
|
|
key: 'imageHeightState',
|
|
get: ({ get }) => {
|
|
const app = get(appState)
|
|
return app.imageHeight
|
|
},
|
|
set: ({ get, set }, newValue: any) => {
|
|
const app = get(appState)
|
|
set(appState, { ...app, imageHeight: newValue })
|
|
},
|
|
})
|
|
|
|
export const imageWidthState = selector({
|
|
key: 'imageWidthState',
|
|
get: ({ get }) => {
|
|
const app = get(appState)
|
|
return app.imageWidth
|
|
},
|
|
set: ({ get, set }, newValue: any) => {
|
|
const app = get(appState)
|
|
set(appState, { ...app, imageWidth: newValue })
|
|
},
|
|
})
|
|
|
|
export const showFileManagerState = selector({
|
|
key: 'showFileManager',
|
|
get: ({ get }) => {
|
|
const app = get(appState)
|
|
return app.showFileManager
|
|
},
|
|
set: ({ get, set }, newValue: any) => {
|
|
const app = get(appState)
|
|
set(appState, { ...app, showFileManager: newValue })
|
|
},
|
|
})
|
|
|
|
export const enableFileManagerState = selector({
|
|
key: 'enableFileManagerState',
|
|
get: ({ get }) => {
|
|
const app = get(appState)
|
|
return app.enableFileManager
|
|
},
|
|
set: ({ get, set }, newValue: any) => {
|
|
const app = get(appState)
|
|
set(appState, { ...app, enableFileManager: newValue })
|
|
},
|
|
})
|
|
|
|
export const gifImageState = selector({
|
|
key: 'gifImageState',
|
|
get: ({ get }) => {
|
|
const app = get(appState)
|
|
return app.gifImage
|
|
},
|
|
set: ({ get, set }, newValue: any) => {
|
|
const app = get(appState)
|
|
set(appState, { ...app, gifImage: newValue })
|
|
},
|
|
})
|
|
|
|
export const fileState = selector({
|
|
key: 'fileState',
|
|
get: ({ get }) => {
|
|
const app = get(appState)
|
|
return app.file
|
|
},
|
|
set: ({ get, set }, newValue: any) => {
|
|
const app = get(appState)
|
|
set(appState, {
|
|
...app,
|
|
file: newValue,
|
|
interactiveSegClicks: [],
|
|
isInteractiveSeg: false,
|
|
isInteractiveSegRunning: false,
|
|
})
|
|
|
|
const setting = get(settingState)
|
|
set(settingState, {
|
|
...setting,
|
|
sdScale: 100,
|
|
})
|
|
},
|
|
})
|
|
|
|
export const isInteractiveSegState = selector({
|
|
key: 'isInteractiveSegState',
|
|
get: ({ get }) => {
|
|
const app = get(appState)
|
|
return app.isInteractiveSeg
|
|
},
|
|
set: ({ get, set }, newValue: any) => {
|
|
const app = get(appState)
|
|
set(appState, { ...app, isInteractiveSeg: newValue })
|
|
},
|
|
})
|
|
|
|
export const isInteractiveSegRunningState = selector({
|
|
key: 'isInteractiveSegRunningState',
|
|
get: ({ get }) => {
|
|
const app = get(appState)
|
|
return app.isInteractiveSegRunning
|
|
},
|
|
set: ({ get, set }, newValue: any) => {
|
|
const app = get(appState)
|
|
set(appState, { ...app, isInteractiveSegRunning: newValue })
|
|
},
|
|
})
|
|
|
|
export const isProcessingState = selector({
|
|
key: 'isProcessingState',
|
|
get: ({ get }) => {
|
|
const app = get(appState)
|
|
return (
|
|
app.isInteractiveSegRunning || app.isPluginRunning || app.isInpainting
|
|
)
|
|
},
|
|
})
|
|
|
|
export const interactiveSegClicksState = selector({
|
|
key: 'interactiveSegClicksState',
|
|
get: ({ get }) => {
|
|
const app = get(appState)
|
|
return app.interactiveSegClicks
|
|
},
|
|
set: ({ get, set }, newValue: any) => {
|
|
const app = get(appState)
|
|
set(appState, { ...app, interactiveSegClicks: newValue })
|
|
},
|
|
})
|
|
|
|
export const isDisableModelSwitchState = selector({
|
|
key: 'isDisableModelSwitchState',
|
|
get: ({ get }) => {
|
|
const app = get(appState)
|
|
return app.isDisableModelSwitch
|
|
},
|
|
set: ({ get, set }, newValue: any) => {
|
|
const app = get(appState)
|
|
set(appState, { ...app, isDisableModelSwitch: newValue })
|
|
},
|
|
})
|
|
|
|
export const isControlNetState = selector({
|
|
key: 'isControlNetState',
|
|
get: ({ get }) => {
|
|
const app = get(appState)
|
|
return app.isControlNet
|
|
},
|
|
set: ({ get, set }, newValue: any) => {
|
|
const app = get(appState)
|
|
set(appState, { ...app, isControlNet: newValue })
|
|
},
|
|
})
|
|
|
|
export const isEnableAutoSavingState = selector({
|
|
key: 'isEnableAutoSavingState',
|
|
get: ({ get }) => {
|
|
const app = get(appState)
|
|
return app.isEnableAutoSaving
|
|
},
|
|
set: ({ get, set }, newValue: any) => {
|
|
const app = get(appState)
|
|
set(appState, { ...app, isEnableAutoSaving: newValue })
|
|
},
|
|
})
|
|
|
|
export const croperState = atom<Rect>({
|
|
key: 'croperState',
|
|
default: {
|
|
x: 0,
|
|
y: 0,
|
|
width: 512,
|
|
height: 512,
|
|
},
|
|
})
|
|
|
|
export const SIDE_PANEL_TAB = strEnum(['inpainting', 'outpainting'])
|
|
export type SIDE_PANEL_TAB_TYPE = keyof typeof SIDE_PANEL_TAB
|
|
|
|
export interface SidePanelState {
|
|
tab: SIDE_PANEL_TAB_TYPE
|
|
}
|
|
|
|
export const sidePanelTabState = atom<SidePanelState>({
|
|
key: 'sidePanelTabState',
|
|
default: {
|
|
tab: SIDE_PANEL_TAB.inpainting,
|
|
},
|
|
})
|
|
|
|
export const croperX = selector({
|
|
key: 'croperX',
|
|
get: ({ get }) => get(croperState).x,
|
|
set: ({ get, set }, newValue: any) => {
|
|
const rect = get(croperState)
|
|
set(croperState, { ...rect, x: newValue })
|
|
},
|
|
})
|
|
|
|
export const croperY = selector({
|
|
key: 'croperY',
|
|
get: ({ get }) => get(croperState).y,
|
|
set: ({ get, set }, newValue: any) => {
|
|
const rect = get(croperState)
|
|
set(croperState, { ...rect, y: newValue })
|
|
},
|
|
})
|
|
|
|
export const croperHeight = selector({
|
|
key: 'croperHeight',
|
|
get: ({ get }) => get(croperState).height,
|
|
set: ({ get, set }, newValue: any) => {
|
|
const rect = get(croperState)
|
|
set(croperState, { ...rect, height: newValue })
|
|
},
|
|
})
|
|
|
|
export const croperWidth = selector({
|
|
key: 'croperWidth',
|
|
get: ({ get }) => get(croperState).width,
|
|
set: ({ get, set }, newValue: any) => {
|
|
const rect = get(croperState)
|
|
set(croperState, { ...rect, width: newValue })
|
|
},
|
|
})
|
|
|
|
export const extenderState = atom<Rect>({
|
|
key: 'extenderState',
|
|
default: {
|
|
x: 0,
|
|
y: 0,
|
|
width: 512,
|
|
height: 512,
|
|
},
|
|
})
|
|
|
|
export const extenderX = selector({
|
|
key: 'extenderX',
|
|
get: ({ get }) => get(extenderState).x,
|
|
set: ({ get, set }, newValue: any) => {
|
|
const rect = get(extenderState)
|
|
set(extenderState, { ...rect, x: newValue })
|
|
},
|
|
})
|
|
|
|
export const extenderY = selector({
|
|
key: 'extenderY',
|
|
get: ({ get }) => get(extenderState).y,
|
|
set: ({ get, set }, newValue: any) => {
|
|
const rect = get(extenderState)
|
|
set(extenderState, { ...rect, y: newValue })
|
|
},
|
|
})
|
|
|
|
export const extenderHeight = selector({
|
|
key: 'extenderHeight',
|
|
get: ({ get }) => get(extenderState).height,
|
|
set: ({ get, set }, newValue: any) => {
|
|
const rect = get(extenderState)
|
|
set(extenderState, { ...rect, height: newValue })
|
|
},
|
|
})
|
|
|
|
export const extenderWidth = selector({
|
|
key: 'extenderWidth',
|
|
get: ({ get }) => get(extenderState).width,
|
|
set: ({ get, set }, newValue: any) => {
|
|
const rect = get(extenderState)
|
|
set(extenderState, { ...rect, width: newValue })
|
|
},
|
|
})
|
|
|
|
interface ToastAtomState {
|
|
open: boolean
|
|
desc: string
|
|
state: ToastState
|
|
duration: number
|
|
}
|
|
|
|
export const toastState = atom<ToastAtomState>({
|
|
key: 'toastState',
|
|
default: {
|
|
open: false,
|
|
desc: '',
|
|
state: 'default',
|
|
duration: 3000,
|
|
},
|
|
})
|
|
|
|
export const shortcutsState = atom<boolean>({
|
|
key: 'shortcutsState',
|
|
default: false,
|
|
})
|
|
|
|
export interface HDSettings {
|
|
hdStrategy: HDStrategy
|
|
hdStrategyResizeLimit: number
|
|
hdStrategyCropTrigerSize: number
|
|
hdStrategyCropMargin: number
|
|
enabled: boolean
|
|
}
|
|
|
|
type ModelsHDSettings = { [key in AIModel]: HDSettings }
|
|
|
|
export enum CV2Flag {
|
|
INPAINT_NS = 'INPAINT_NS',
|
|
INPAINT_TELEA = 'INPAINT_TELEA',
|
|
}
|
|
|
|
export interface Settings {
|
|
show: boolean
|
|
showCroper: boolean
|
|
downloadMask: boolean
|
|
graduallyInpainting: boolean
|
|
runInpaintingManually: boolean
|
|
model: AIModel
|
|
hdSettings: ModelsHDSettings
|
|
|
|
// For LDM
|
|
ldmSteps: number
|
|
ldmSampler: LDMSampler
|
|
|
|
// For ZITS
|
|
zitsWireframe: boolean
|
|
|
|
// For SD
|
|
sdMaskBlur: number
|
|
sdMode: SDMode
|
|
sdStrength: number
|
|
sdSteps: number
|
|
sdGuidanceScale: number
|
|
sdSampler: SDSampler
|
|
sdSeed: number
|
|
sdSeedFixed: boolean // true: use sdSeed, false: random generate seed on backend
|
|
sdNumSamples: number
|
|
sdMatchHistograms: boolean
|
|
sdScale: number
|
|
|
|
// For OpenCV2
|
|
cv2Radius: number
|
|
cv2Flag: CV2Flag
|
|
|
|
// Paint by Example
|
|
paintByExampleSteps: number
|
|
paintByExampleGuidanceScale: number
|
|
paintByExampleSeed: number
|
|
paintByExampleSeedFixed: boolean
|
|
paintByExampleMaskBlur: number
|
|
paintByExampleMatchHistograms: boolean
|
|
|
|
// InstructPix2Pix
|
|
p2pSteps: number
|
|
p2pImageGuidanceScale: number
|
|
p2pGuidanceScale: number
|
|
|
|
// ControlNet
|
|
controlnetConditioningScale: number
|
|
controlnetMethod: string
|
|
}
|
|
|
|
const defaultHDSettings: ModelsHDSettings = {
|
|
[AIModel.LAMA]: {
|
|
hdStrategy: HDStrategy.CROP,
|
|
hdStrategyResizeLimit: 2048,
|
|
hdStrategyCropTrigerSize: 800,
|
|
hdStrategyCropMargin: 196,
|
|
enabled: true,
|
|
},
|
|
[AIModel.LDM]: {
|
|
hdStrategy: HDStrategy.CROP,
|
|
hdStrategyResizeLimit: 1080,
|
|
hdStrategyCropTrigerSize: 1080,
|
|
hdStrategyCropMargin: 128,
|
|
enabled: true,
|
|
},
|
|
[AIModel.ZITS]: {
|
|
hdStrategy: HDStrategy.CROP,
|
|
hdStrategyResizeLimit: 1024,
|
|
hdStrategyCropTrigerSize: 1024,
|
|
hdStrategyCropMargin: 128,
|
|
enabled: true,
|
|
},
|
|
[AIModel.MAT]: {
|
|
hdStrategy: HDStrategy.CROP,
|
|
hdStrategyResizeLimit: 1024,
|
|
hdStrategyCropTrigerSize: 512,
|
|
hdStrategyCropMargin: 128,
|
|
enabled: true,
|
|
},
|
|
[AIModel.FCF]: {
|
|
hdStrategy: HDStrategy.CROP,
|
|
hdStrategyResizeLimit: 512,
|
|
hdStrategyCropTrigerSize: 512,
|
|
hdStrategyCropMargin: 128,
|
|
enabled: false,
|
|
},
|
|
[AIModel.SD15]: {
|
|
hdStrategy: HDStrategy.ORIGINAL,
|
|
hdStrategyResizeLimit: 768,
|
|
hdStrategyCropTrigerSize: 512,
|
|
hdStrategyCropMargin: 128,
|
|
enabled: false,
|
|
},
|
|
[AIModel.ANYTHING4]: {
|
|
hdStrategy: HDStrategy.ORIGINAL,
|
|
hdStrategyResizeLimit: 768,
|
|
hdStrategyCropTrigerSize: 512,
|
|
hdStrategyCropMargin: 128,
|
|
enabled: false,
|
|
},
|
|
[AIModel.REALISTIC_VISION_1_4]: {
|
|
hdStrategy: HDStrategy.ORIGINAL,
|
|
hdStrategyResizeLimit: 768,
|
|
hdStrategyCropTrigerSize: 512,
|
|
hdStrategyCropMargin: 128,
|
|
enabled: false,
|
|
},
|
|
[AIModel.SD2]: {
|
|
hdStrategy: HDStrategy.ORIGINAL,
|
|
hdStrategyResizeLimit: 768,
|
|
hdStrategyCropTrigerSize: 512,
|
|
hdStrategyCropMargin: 128,
|
|
enabled: false,
|
|
},
|
|
[AIModel.PAINT_BY_EXAMPLE]: {
|
|
hdStrategy: HDStrategy.ORIGINAL,
|
|
hdStrategyResizeLimit: 768,
|
|
hdStrategyCropTrigerSize: 512,
|
|
hdStrategyCropMargin: 128,
|
|
enabled: false,
|
|
},
|
|
[AIModel.PIX2PIX]: {
|
|
hdStrategy: HDStrategy.ORIGINAL,
|
|
hdStrategyResizeLimit: 768,
|
|
hdStrategyCropTrigerSize: 512,
|
|
hdStrategyCropMargin: 128,
|
|
enabled: false,
|
|
},
|
|
[AIModel.Mange]: {
|
|
hdStrategy: HDStrategy.CROP,
|
|
hdStrategyResizeLimit: 1280,
|
|
hdStrategyCropTrigerSize: 1024,
|
|
hdStrategyCropMargin: 196,
|
|
enabled: true,
|
|
},
|
|
[AIModel.CV2]: {
|
|
hdStrategy: HDStrategy.RESIZE,
|
|
hdStrategyResizeLimit: 1080,
|
|
hdStrategyCropTrigerSize: 512,
|
|
hdStrategyCropMargin: 128,
|
|
enabled: true,
|
|
},
|
|
[AIModel.KANDINSKY22]: {
|
|
hdStrategy: HDStrategy.ORIGINAL,
|
|
hdStrategyResizeLimit: 768,
|
|
hdStrategyCropTrigerSize: 512,
|
|
hdStrategyCropMargin: 128,
|
|
enabled: false,
|
|
},
|
|
}
|
|
|
|
export enum SDSampler {
|
|
ddim = 'ddim',
|
|
pndm = 'pndm',
|
|
klms = 'k_lms',
|
|
kEuler = 'k_euler',
|
|
kEulerA = 'k_euler_a',
|
|
dpmPlusPlus = 'dpm++',
|
|
uni_pc = 'uni_pc',
|
|
}
|
|
|
|
export enum SDMode {
|
|
text2img = 'text2img',
|
|
img2img = 'img2img',
|
|
inpainting = 'inpainting',
|
|
}
|
|
|
|
export const settingStateDefault: Settings = {
|
|
show: false,
|
|
showCroper: false,
|
|
downloadMask: false,
|
|
graduallyInpainting: true,
|
|
runInpaintingManually: false,
|
|
model: AIModel.LAMA,
|
|
hdSettings: defaultHDSettings,
|
|
|
|
ldmSteps: 25,
|
|
ldmSampler: LDMSampler.plms,
|
|
|
|
zitsWireframe: true,
|
|
|
|
// SD
|
|
sdMaskBlur: 5,
|
|
sdMode: SDMode.inpainting,
|
|
sdStrength: 0.75,
|
|
sdSteps: 50,
|
|
sdGuidanceScale: 7.5,
|
|
sdSampler: SDSampler.uni_pc,
|
|
sdSeed: 42,
|
|
sdSeedFixed: false,
|
|
sdNumSamples: 1,
|
|
sdMatchHistograms: false,
|
|
sdScale: 100,
|
|
|
|
// CV2
|
|
cv2Radius: 5,
|
|
cv2Flag: CV2Flag.INPAINT_NS,
|
|
|
|
// Paint by Example
|
|
paintByExampleSteps: 50,
|
|
paintByExampleGuidanceScale: 7.5,
|
|
paintByExampleSeed: 42,
|
|
paintByExampleMaskBlur: 5,
|
|
paintByExampleSeedFixed: false,
|
|
paintByExampleMatchHistograms: false,
|
|
|
|
// InstructPix2Pix
|
|
p2pSteps: 50,
|
|
p2pImageGuidanceScale: 1.5,
|
|
p2pGuidanceScale: 7.5,
|
|
|
|
// ControlNet
|
|
controlnetConditioningScale: 0.4,
|
|
controlnetMethod: ControlNetMethod.canny,
|
|
}
|
|
|
|
const localStorageEffect =
|
|
(key: string) =>
|
|
({ setSelf, onSet }: any) => {
|
|
const savedValue = localStorage.getItem(key)
|
|
if (savedValue != null) {
|
|
const storageSettings = JSON.parse(savedValue)
|
|
storageSettings.show = false
|
|
|
|
const restored = _.merge(
|
|
_.cloneDeep(settingStateDefault),
|
|
storageSettings
|
|
)
|
|
setSelf(restored)
|
|
}
|
|
|
|
onSet((newValue: Settings, val: string, isReset: boolean) =>
|
|
isReset
|
|
? localStorage.removeItem(key)
|
|
: localStorage.setItem(key, JSON.stringify(newValue))
|
|
)
|
|
}
|
|
|
|
const ROOT_STATE_KEY = 'settingsState4'
|
|
// Each atom can reference an array of these atom effect functions which are called in priority order when the atom is initialized
|
|
// https://recoiljs.org/docs/guides/atom-effects/#local-storage-persistence
|
|
export const settingState = atom<Settings>({
|
|
key: ROOT_STATE_KEY,
|
|
default: settingStateDefault,
|
|
effects: [localStorageEffect(ROOT_STATE_KEY)],
|
|
})
|
|
|
|
export const seedState = selector({
|
|
key: 'seed',
|
|
get: ({ get }) => {
|
|
const settings = get(settingState)
|
|
switch (settings.model) {
|
|
case AIModel.PAINT_BY_EXAMPLE:
|
|
return settings.paintByExampleSeedFixed
|
|
? settings.paintByExampleSeed
|
|
: -1
|
|
default:
|
|
return settings.sdSeedFixed ? settings.sdSeed : -1
|
|
}
|
|
},
|
|
set: ({ get, set }, newValue: any) => {
|
|
const settings = get(settingState)
|
|
switch (settings.model) {
|
|
case AIModel.PAINT_BY_EXAMPLE:
|
|
if (!settings.paintByExampleSeedFixed) {
|
|
set(settingState, { ...settings, paintByExampleSeed: newValue })
|
|
}
|
|
break
|
|
default:
|
|
if (!settings.sdSeedFixed) {
|
|
set(settingState, { ...settings, sdSeed: newValue })
|
|
}
|
|
}
|
|
},
|
|
})
|
|
|
|
export const hdSettingsState = selector({
|
|
key: 'hdSettings',
|
|
get: ({ get }) => {
|
|
const settings = get(settingState)
|
|
return settings.hdSettings[settings.model]
|
|
},
|
|
set: ({ get, set }, newValue: any) => {
|
|
const settings = get(settingState)
|
|
const hdSettings = settings.hdSettings[settings.model]
|
|
const newHDSettings = { ...hdSettings, ...newValue }
|
|
|
|
set(settingState, {
|
|
...settings,
|
|
hdSettings: { ...settings.hdSettings, [settings.model]: newHDSettings },
|
|
})
|
|
},
|
|
})
|
|
|
|
export const isSDState = selector({
|
|
key: 'isSD',
|
|
get: ({ get }) => {
|
|
const settings = get(settingState)
|
|
return (
|
|
settings.model === AIModel.SD15 ||
|
|
settings.model === AIModel.SD2 ||
|
|
settings.model === AIModel.ANYTHING4 ||
|
|
settings.model === AIModel.REALISTIC_VISION_1_4 ||
|
|
settings.model === AIModel.KANDINSKY22
|
|
)
|
|
},
|
|
})
|
|
|
|
export const isPaintByExampleState = selector({
|
|
key: 'isPaintByExampleState',
|
|
get: ({ get }) => {
|
|
const settings = get(settingState)
|
|
return settings.model === AIModel.PAINT_BY_EXAMPLE
|
|
},
|
|
})
|
|
|
|
export const isPix2PixState = selector({
|
|
key: 'isPix2PixState',
|
|
get: ({ get }) => {
|
|
const settings = get(settingState)
|
|
return settings.model === AIModel.PIX2PIX
|
|
},
|
|
})
|
|
|
|
export const runManuallyState = selector({
|
|
key: 'runManuallyState',
|
|
get: ({ get }) => {
|
|
const settings = get(settingState)
|
|
const isSD = get(isSDState)
|
|
const isPaintByExample = get(isPaintByExampleState)
|
|
const isPix2Pix = get(isPix2PixState)
|
|
return (
|
|
settings.runInpaintingManually || isSD || isPaintByExample || isPix2Pix
|
|
)
|
|
},
|
|
})
|
|
|
|
export const isDiffusionModelsState = selector({
|
|
key: 'isDiffusionModelsState',
|
|
get: ({ get }) => {
|
|
const isSD = get(isSDState)
|
|
const isPaintByExample = get(isPaintByExampleState)
|
|
const isPix2Pix = get(isPix2PixState)
|
|
return isSD || isPaintByExample || isPix2Pix
|
|
},
|
|
})
|
|
|
|
export enum SortBy {
|
|
NAME = 'name',
|
|
CTIME = 'ctime',
|
|
MTIME = 'mtime',
|
|
}
|
|
|
|
export enum SortOrder {
|
|
DESCENDING = 'desc',
|
|
ASCENDING = 'asc',
|
|
}
|
|
|
|
interface FileManagerState {
|
|
sortBy: SortBy
|
|
sortOrder: SortOrder
|
|
layout: 'rows' | 'masonry'
|
|
searchText: string
|
|
}
|
|
|
|
const FILE_MANAGER_STATE_KEY = 'fileManagerState'
|
|
|
|
export const fileManagerState = atom<FileManagerState>({
|
|
key: FILE_MANAGER_STATE_KEY,
|
|
default: {
|
|
sortBy: SortBy.CTIME,
|
|
sortOrder: SortOrder.DESCENDING,
|
|
layout: 'masonry',
|
|
searchText: '',
|
|
},
|
|
effects: [localStorageEffect(FILE_MANAGER_STATE_KEY)],
|
|
})
|
|
|
|
export const fileManagerSortBy = selector({
|
|
key: 'fileManagerSortBy',
|
|
get: ({ get }) => get(fileManagerState).sortBy,
|
|
set: ({ get, set }, newValue: any) => {
|
|
const val = get(fileManagerState)
|
|
set(fileManagerState, { ...val, sortBy: newValue })
|
|
},
|
|
})
|
|
|
|
export const fileManagerSortOrder = selector({
|
|
key: 'fileManagerSortOrder',
|
|
get: ({ get }) => get(fileManagerState).sortOrder,
|
|
set: ({ get, set }, newValue: any) => {
|
|
const val = get(fileManagerState)
|
|
set(fileManagerState, { ...val, sortOrder: newValue })
|
|
},
|
|
})
|
|
|
|
export const fileManagerLayout = selector({
|
|
key: 'fileManagerLayout',
|
|
get: ({ get }) => get(fileManagerState).layout,
|
|
set: ({ get, set }, newValue: any) => {
|
|
const val = get(fileManagerState)
|
|
set(fileManagerState, { ...val, layout: newValue })
|
|
},
|
|
})
|
|
|
|
export const fileManagerSearchText = selector({
|
|
key: 'fileManagerSearchText',
|
|
get: ({ get }) => get(fileManagerState).searchText,
|
|
set: ({ get, set }, newValue: any) => {
|
|
const val = get(fileManagerState)
|
|
set(fileManagerState, { ...val, searchText: newValue })
|
|
},
|
|
})
|