polish realtime canvas controls
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-03-08 01:55:53 +08:00
parent f0340d3d96
commit 440f778bf3

View File

@ -26,6 +26,7 @@ import {
Eraser,
Layers3,
Loader2,
MousePointer2,
Paintbrush,
Plus,
Square,
@ -69,6 +70,7 @@ type RealtimeConfig = {
};
type RealtimeStatus = "idle" | "connecting" | "live" | "error";
type RealtimeBrushMode = "select" | "brush" | "eraser" | "rect" | "circle" | "line";
type ImageLayer = {
id: string;
@ -160,7 +162,7 @@ const defaultRealtimeConfig: RealtimeConfig = {
},
};
function isShapeMode(mode: "brush" | "eraser" | "rect" | "circle" | "line") {
function isShapeMode(mode: RealtimeBrushMode) {
return mode === "rect" || mode === "circle" || mode === "line";
}
@ -685,10 +687,10 @@ export function RealtimeCanvasDialog({
const [config, setConfig] = useState<RealtimeConfig>(defaultRealtimeConfig);
const [status, setStatus] = useState<RealtimeStatus>("idle");
const [statusMessage, setStatusMessage] = useState("等待连接");
const [, setStatusMessage] = useState("等待连接");
const [prompt, setPrompt] = useState(FALLBACK_PROMPT);
const [previewUrl, setPreviewUrl] = useState("");
const [brushMode, setBrushMode] = useState<"brush" | "eraser" | "rect" | "circle" | "line">("brush");
const [brushMode, setBrushMode] = useState<RealtimeBrushMode>("brush");
const [brushColor, setBrushColor] = useState<string>(DEFAULT_BRUSH_COLOR);
const [canvasBackground, setCanvasBackground] = useState<string>(canvasBackgroundRef.current);
const [imageLayers, setImageLayers] = useState<ImageLayer[]>([]);
@ -1734,6 +1736,12 @@ export function RealtimeCanvasDialog({
event.currentTarget.setPointerCapture(event.pointerId);
return;
}
if (brushMode === "select") {
setSelectedLayerId(DRAW_LAYER_ID);
lastPointRef.current = null;
shapeStartPointRef.current = null;
return;
}
if (isShapeMode(brushMode)) {
shapeStartPointRef.current = point;
clearPreviewCanvas();
@ -2347,6 +2355,21 @@ export function RealtimeCanvasDialog({
</div>
<div className="flex h-10 shrink-0 items-center gap-0.5 rounded-full border border-black/10 bg-white px-1">
<Button
size="icon"
variant="ghost"
className={cn(
"h-8 w-8 rounded-full text-zinc-600 hover:bg-zinc-100",
brushMode === "select" && "bg-black text-white hover:bg-black"
)}
onClick={() => {
setSelectedLayerId(DRAW_LAYER_ID);
setBrushMode("select");
}}
title="鼠标"
>
<MousePointer2 className="h-4.5 w-4.5" />
</Button>
<Button
size="icon"
variant="ghost"
@ -2625,7 +2648,9 @@ export function RealtimeCanvasDialog({
? "cursor-move"
: brushMode === "brush" || brushMode === "eraser"
? "cursor-none"
: "cursor-crosshair"
: brushMode === "select"
? "cursor-default"
: "cursor-crosshair"
)}
onPointerDown={handlePointerDown}
onPointerMove={handlePointerMove}
@ -2853,12 +2878,9 @@ export function RealtimeCanvasDialog({
placeholder="输入指令,基于当前画布实时生成"
className="h-9 flex-1 border-0 bg-transparent px-1 text-sm shadow-none focus-visible:ring-0"
/>
<span className="hidden whitespace-nowrap text-xs text-zinc-500 xl:inline">
{statusMessage}
</span>
<Button
size="sm"
className="h-9 shrink-0 rounded-full px-4 font-medium"
className="h-9 shrink-0 rounded-full bg-black px-4 font-medium text-white hover:bg-black/90"
onClick={triggerGenerate}
disabled={status === "connecting"}
>