This commit is contained in:
Qing
2023-12-13 22:56:09 +08:00
parent 354a1280a4
commit 142aa64cc6
19 changed files with 360 additions and 181 deletions

View File

@@ -1,7 +1,6 @@
import { FormEvent, useState } from "react"
import { useToggle, useWindowSize } from "react-use"
import { useStore } from "@/lib/states"
import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover"
import { Switch } from "./ui/switch"
import { Label } from "./ui/label"
import { NumberInput } from "./ui/input"
@@ -15,38 +14,36 @@ import {
} from "./ui/select"
import { Textarea } from "./ui/textarea"
import { SDSampler } from "@/lib/types"
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "./ui/accordion"
import { Separator } from "./ui/separator"
import { useHotkeys } from "react-hotkeys-hook"
import { ScrollArea } from "./ui/scroll-area"
import {
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "./ui/sheet"
import { ChevronLeft } from "lucide-react"
import { ChevronLeft, ChevronRight } from "lucide-react"
import { Button } from "./ui/button"
import useHotKey from "@/hooks/useHotkey"
import { Slider } from "./ui/slider"
const RowContainer = ({ children }: { children: React.ReactNode }) => (
<div className="flex justify-between items-center pr-2">{children}</div>
)
const SidePanel = () => {
const [settings, updateSettings, showSidePanel] = useStore((state) => [
state.settings,
state.updateSettings,
state.showSidePanel(),
])
const [open, toggleOpen] = useToggle(true)
const [expandedAccordionItems, setExpandedAccordionItems] = useState<
string[]
>([])
const [settings, updateSettings, showSidePanel, runInpainting] = useStore(
(state) => [
state.settings,
state.updateSettings,
state.showSidePanel(),
state.runInpainting,
]
)
const [open, toggleOpen] = useToggle(false)
useHotkeys("c", () => {
useHotKey("c", () => {
toggleOpen()
})
@@ -58,13 +55,8 @@ const SidePanel = () => {
const onKeyUp = (e: React.KeyboardEvent) => {
// negativePrompt 回车触发 inpainting
if (
e.key === "Enter" &&
e.ctrlKey &&
settings.prompt.length !== 0
// !isInpainting
) {
console.log("trigger negativePrompt")
if (e.key === "Enter" && e.ctrlKey && settings.prompt.length !== 0) {
runInpainting()
}
}
@@ -75,41 +67,62 @@ const SidePanel = () => {
return (
<div className="flex flex-col gap-4">
<div className="flex flex-col items-start gap-4">
<Label htmlFor="controlnet">Controlnet</Label>
<Select
value={settings.controlnetMethod}
onValueChange={(value) => {
updateSettings({ controlnetMethod: value })
}}
>
<SelectTrigger id="controlnet">
<SelectValue placeholder="Select control method" />
</SelectTrigger>
<SelectContent align="end">
<SelectGroup>
{Object.values(settings.model.controlnets).map((method) => (
<SelectItem key={method} value={method}>
{method.split("/")[1]}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
<div className="flex flex-col gap-4">
<div className="flex justify-between items-center pr-2">
<Label htmlFor="controlnet">Controlnet</Label>
<Switch
id="controlnet"
checked={settings.enableControlNet}
onCheckedChange={(value) => {
updateSettings({ enableControlNet: value })
}}
/>
</div>
<div className="pl-1 pr-2">
<Select
value={settings.controlnetMethod}
onValueChange={(value) => {
updateSettings({ controlnetMethod: value })
}}
disabled={!settings.enableControlNet}
>
<SelectTrigger>
<SelectValue placeholder="Select control method" />
</SelectTrigger>
<SelectContent align="end">
<SelectGroup>
{Object.values(settings.model.controlnets).map((method) => (
<SelectItem key={method} value={method}>
{method.split("/")[1]}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
</div>
</div>
<div className="flex justify-between items-center">
<Label htmlFor="controlnet-weight">weight</Label>
<RowContainer>
<Label
htmlFor="controlnet-weight"
disabled={!settings.enableControlNet}
>
weight
</Label>
<NumberInput
id="controlnet-weight"
className="w-14"
disabled={!settings.enableControlNet}
numberValue={settings.controlnetConditioningScale}
allowFloat
onNumberValueChange={(value) => {
updateSettings({ controlnetConditioningScale: value })
}}
/>
</div>
</RowContainer>
<Separator />
</div>
)
}
@@ -120,16 +133,19 @@ const SidePanel = () => {
}
return (
<div className="flex justify-between items-center">
<Label htmlFor="lcm-lora">LCM Lora</Label>
<Switch
id="lcm-lora"
checked={settings.enableLCMLora}
onCheckedChange={(value) => {
updateSettings({ enableLCMLora: value })
}}
/>
</div>
<>
<RowContainer>
<Label htmlFor="lcm-lora">LCM Lora</Label>
<Switch
id="lcm-lora"
checked={settings.enableLCMLora}
onCheckedChange={(value) => {
updateSettings({ enableLCMLora: value })
}}
/>
</RowContainer>
<Separator />
</>
)
}
@@ -140,7 +156,7 @@ const SidePanel = () => {
return (
<div className="flex flex-col gap-4">
<div className="flex justify-between items-center">
<div className="flex justify-between items-center pr-2">
<Label htmlFor="freeu">Freeu</Label>
<Switch
id="freeu"
@@ -152,10 +168,13 @@ const SidePanel = () => {
</div>
<div className="flex gap-3">
<div className="flex flex-col gap-2 items-start">
<Label htmlFor="freeu-s1">s1</Label>
<Label htmlFor="freeu-s1" disabled={!settings.enableFreeu}>
s1
</Label>
<NumberInput
id="freeu-s1"
className="w-14"
disabled={!settings.enableFreeu}
numberValue={settings.freeuConfig.s1}
allowFloat
onNumberValueChange={(value) => {
@@ -166,10 +185,13 @@ const SidePanel = () => {
/>
</div>
<div className="flex flex-col gap-2 items-start">
<Label htmlFor="freeu-s2">s2</Label>
<Label htmlFor="freeu-s2" disabled={!settings.enableFreeu}>
s2
</Label>
<NumberInput
id="freeu-s2"
className="w-14"
disabled={!settings.enableFreeu}
numberValue={settings.freeuConfig.s2}
allowFloat
onNumberValueChange={(value) => {
@@ -180,10 +202,13 @@ const SidePanel = () => {
/>
</div>
<div className="flex flex-col gap-2 items-start">
<Label htmlFor="freeu-b1">b1</Label>
<Label htmlFor="freeu-b1" disabled={!settings.enableFreeu}>
b1
</Label>
<NumberInput
id="freeu-b1"
className="w-14"
disabled={!settings.enableFreeu}
numberValue={settings.freeuConfig.b1}
allowFloat
onNumberValueChange={(value) => {
@@ -194,10 +219,13 @@ const SidePanel = () => {
/>
</div>
<div className="flex flex-col gap-2 items-start">
<Label htmlFor="freeu-b2">b2</Label>
<Label htmlFor="freeu-b2" disabled={!settings.enableFreeu}>
b2
</Label>
<NumberInput
id="freeu-b2"
className="w-14"
disabled={!settings.enableFreeu}
numberValue={settings.freeuConfig.b2}
allowFloat
onNumberValueChange={(value) => {
@@ -208,28 +236,51 @@ const SidePanel = () => {
/>
</div>
</div>
<Separator />
</div>
)
}
return (
<Sheet open={open} onOpenChange={toggleOpen} modal={false}>
<Sheet open={open} modal={false}>
<SheetTrigger
tabIndex={-1}
className="z-10 outline-none absolute top-[68px] right-6 rounded-lg border bg-background"
>
<Button variant="ghost" size="icon" asChild className="p-1.5">
<Button
variant="ghost"
size="icon"
asChild
className="p-1.5"
onClick={toggleOpen}
>
<ChevronLeft strokeWidth={1} />
</Button>
</SheetTrigger>
<SheetContent
side="right"
className="w-[300px] mt-[60px] outline-none pl-4 pr-1"
className="w-[300px] mt-[60px] outline-none pl-4 pr-1 backdrop-filter backdrop-blur-md bg-background/70"
onOpenAutoFocus={(event) => event.preventDefault()}
onPointerDownOutside={(event) => event.preventDefault()}
>
<SheetHeader className="mb-4">
<SheetTitle>Diffusion Paramers</SheetTitle>
<RowContainer>
<div className="overflow-hidden mr-8">
{
settings.model.name.split("/")[
settings.model.name.split("/").length - 1
]
}
</div>
<Button
variant="ghost"
size="icon"
className="border h-6 w-6"
onClick={toggleOpen}
>
<ChevronRight strokeWidth={1} />
</Button>
</RowContainer>
<Separator />
</SheetHeader>
<ScrollArea
@@ -237,7 +288,7 @@ const SidePanel = () => {
className="pr-3"
>
<div className="flex flex-col gap-3">
<div className="flex justify-between items-center">
<RowContainer>
<Label htmlFor="cropper">Cropper</Label>
<Switch
id="cropper"
@@ -246,9 +297,9 @@ const SidePanel = () => {
updateSettings({ showCroper: value })
}}
/>
</div>
</RowContainer>
<div className="flex justify-between items-center">
<RowContainer>
<Label htmlFor="steps">Steps</Label>
<NumberInput
id="steps"
@@ -259,9 +310,9 @@ const SidePanel = () => {
updateSettings({ sdSteps: value })
}}
/>
</div>
</RowContainer>
<div className="flex justify-between items-center">
<RowContainer>
<Label htmlFor="guidance-scale">Guidance scale</Label>
<NumberInput
id="guidance-scale"
@@ -272,22 +323,28 @@ const SidePanel = () => {
updateSettings({ sdGuidanceScale: value })
}}
/>
</div>
</RowContainer>
<div className="flex justify-between items-center">
<Label htmlFor="strength">Strength</Label>
<NumberInput
id="strength"
className="w-14"
numberValue={settings.sdStrength}
allowFloat
onNumberValueChange={(value) => {
updateSettings({ sdStrength: value })
}}
<RowContainer>
<div className="flex gap-2 items-center">
<Label htmlFor="strength">Strength</Label>
<div className="text-sm">({settings.sdStrength})</div>
</div>
<Slider
className="w-24"
defaultValue={[100]}
min={10}
max={100}
step={1}
tabIndex={-1}
value={[Math.floor(settings.sdStrength * 100)]}
onValueChange={(vals) =>
updateSettings({ sdStrength: vals[0] / 100 })
}
/>
</div>
</RowContainer>
<div className="flex justify-between items-center">
<RowContainer>
<Label htmlFor="sampler">Sampler</Label>
<Select
value={settings.sdSampler as string}
@@ -312,9 +369,9 @@ const SidePanel = () => {
</SelectGroup>
</SelectContent>
</Select>
</div>
</RowContainer>
<div className="flex justify-between items-center">
<RowContainer>
{/* 每次会从服务器返回更新该值 */}
<Label htmlFor="seed">Seed</Label>
<div className="flex gap-2 justify-center items-center">
@@ -336,24 +393,26 @@ const SidePanel = () => {
}}
/>
</div>
</div>
</RowContainer>
<div className="flex flex-col gap-4">
<Label htmlFor="negative-prompt">Negative prompt</Label>
<Textarea
rows={4}
onKeyUp={onKeyUp}
className="max-h-[8rem] overflow-y-auto mb-2"
placeholder=""
id="negative-prompt"
value={settings.negativePrompt}
onInput={(evt: FormEvent<HTMLTextAreaElement>) => {
evt.preventDefault()
evt.stopPropagation()
const target = evt.target as HTMLTextAreaElement
updateSettings({ negativePrompt: target.value })
}}
/>
<div className="pl-2 pr-4">
<Textarea
rows={4}
onKeyUp={onKeyUp}
className="max-h-[8rem] overflow-y-auto mb-2"
placeholder=""
id="negative-prompt"
value={settings.negativePrompt}
onInput={(evt: FormEvent<HTMLTextAreaElement>) => {
evt.preventDefault()
evt.stopPropagation()
const target = evt.target as HTMLTextAreaElement
updateSettings({ negativePrompt: target.value })
}}
/>
</div>
</div>
<Separator />
@@ -361,15 +420,10 @@ const SidePanel = () => {
<div className="flex flex-col gap-4">
{renderConterNetSetting()}
</div>
<Separator />
{renderFreeu()}
<Separator />
{renderLCMLora()}
<Separator />
<div className="flex justify-between items-center">
<RowContainer>
<Label htmlFor="mask-blur">Mask blur</Label>
<NumberInput
id="mask-blur"
@@ -380,9 +434,9 @@ const SidePanel = () => {
updateSettings({ sdMaskBlur: value })
}}
/>
</div>
</RowContainer>
<div className="flex justify-between items-center">
<RowContainer>
<Label htmlFor="match-histograms">Match histograms</Label>
<Switch
id="match-histograms"
@@ -391,7 +445,7 @@ const SidePanel = () => {
updateSettings({ sdMatchHistograms: value })
}}
/>
</div>
</RowContainer>
</div>
</ScrollArea>
</SheetContent>