Files
Genarrative/src/components/image-editor/ImageCanvasBottomToolbarView.tsx
T
menghao 03a4410272
Project CI / Repository checks (push) Successful in 1m5s
Project CI / Frontend tests (push) Successful in 3m20s
Project CI / Backend tests (push) Successful in 4m1s
Project CI / Native shell tests (push) Failing after 11m56s
game agent无限画布开发 (#136)
主要工作是共享同一套“画布内核与通用 UI 源码”,网站和 Tauri 只分别实现宿主适配层。

---------

Co-authored-by: 段舒康 <kdletters@qq.com>
Co-authored-by: kdletters <kdletters@qq.com>
Reviewed-on: http://192.168.35.82/git/GenarrativeAI/Genarrative/pulls/136
Co-authored-by: menghao <mh18530625731@163.com>
Co-committed-by: menghao <mh18530625731@163.com>
2026-08-12 10:54:16 +08:00

155 lines
4.7 KiB
TypeScript

import {
CanvasToolbar,
CanvasToolbarDivider,
CanvasToolbarGroup,
} from '@genarrative/image-canvas-react';
import {
AppWindow,
Clapperboard,
ClipboardList,
Grid2X2,
Hand,
ImageIcon,
Megaphone,
Mountain,
MousePointer2,
Music,
Upload,
UserRound,
} from 'lucide-react';
import type { RefObject } from 'react';
import { EditorIconButton } from './ImageCanvasEditorPrimitives';
import type { CanvasTool } from './ImageCanvasEditorTypes';
type ToolbarOptionTool = Extract<CanvasTool, 'music' | 'spec' | 'publication'>;
type ImageCanvasBottomToolbarViewProps = {
specToolWrapRef: RefObject<HTMLSpanElement | null>;
musicToolWrapRef: RefObject<HTMLSpanElement | null>;
publicationToolWrapRef: RefObject<HTMLSpanElement | null>;
effectiveTool: CanvasTool;
highlight?: boolean;
onSwitchTool: (tool: CanvasTool) => void;
onOpenToolOptions: (tool: ToolbarOptionTool) => void;
onCloseToolOptions: (tool: ToolbarOptionTool) => void;
};
const canvasTools: Array<{
id: CanvasTool;
label: string;
icon: typeof MousePointer2;
separatorBefore?: boolean;
}> = [
{ id: 'select', label: '选择工具', icon: MousePointer2 },
{ id: 'hand', label: '抓手工具', icon: Hand },
{ id: 'upload', label: '上传工具', icon: Upload },
{
id: 'generate',
label: '生成图片',
icon: ImageIcon,
separatorBefore: true,
},
{ id: 'video', label: '生成视频', icon: Clapperboard },
{ id: 'music', label: '生成音乐', icon: Music },
{
id: 'spec',
label: '生成规范',
icon: ClipboardList,
separatorBefore: true,
},
{ id: 'character', label: '生成角色形象', icon: UserRound },
{ id: 'icon', label: '生成图标素材', icon: Grid2X2 },
{ id: 'ui-design', label: '生成UI设计图', icon: AppWindow },
{ id: 'scene', label: '生成游戏场景', icon: Mountain },
{ id: 'publication', label: '宣发素材', icon: Megaphone },
];
function isToolbarOptionTool(tool: CanvasTool): tool is ToolbarOptionTool {
return tool === 'music' || tool === 'spec' || tool === 'publication';
}
function hasPersistentPressedState(tool: CanvasTool) {
return tool === 'select' || tool === 'hand';
}
export function ImageCanvasBottomToolbarView({
specToolWrapRef,
musicToolWrapRef,
publicationToolWrapRef,
effectiveTool,
highlight = false,
onSwitchTool,
onOpenToolOptions,
onCloseToolOptions,
}: ImageCanvasBottomToolbarViewProps) {
return (
<CanvasToolbar
className={[
'image-canvas-editor__bottom-toolbar',
highlight ? 'image-canvas-editor__bottom-toolbar--guided' : '',
]
.filter(Boolean)
.join(' ')}
label="AI画布工具栏"
surface="floating"
onPointerDown={(event) => event.stopPropagation()}
>
{canvasTools.map(({ id, label, icon: Icon, separatorBefore }) => {
if (isToolbarOptionTool(id)) {
return (
<CanvasToolbarGroup key={id}>
{separatorBefore ? <CanvasToolbarDivider /> : null}
<span
ref={
id === 'spec'
? specToolWrapRef
: id === 'music'
? musicToolWrapRef
: publicationToolWrapRef
}
className={[
'image-canvas-editor__bottom-toolbar-option-wrap',
id === 'spec' ? 'image-canvas-editor__spec-tool-wrap' : '',
id === 'publication'
? 'image-canvas-editor__publication-tool-wrap'
: '',
]
.filter(Boolean)
.join(' ')}
onPointerEnter={() => onOpenToolOptions(id)}
onPointerLeave={() => onCloseToolOptions(id)}
onFocus={() => onOpenToolOptions(id)}
onBlur={() => onCloseToolOptions(id)}
>
<EditorIconButton
label={label}
title={label}
icon={Icon}
pressed={
hasPersistentPressedState(id) && effectiveTool === id
}
onClick={() => onSwitchTool(id)}
/>
</span>
</CanvasToolbarGroup>
);
}
return (
<CanvasToolbarGroup key={id}>
{separatorBefore ? <CanvasToolbarDivider /> : null}
<EditorIconButton
label={label}
title={label}
icon={Icon}
pressed={hasPersistentPressedState(id) && effectiveTool === id}
onClick={() => onSwitchTool(id)}
/>
</CanvasToolbarGroup>
);
})}
</CanvasToolbar>
);
}