03a4410272
主要工作是共享同一套“画布内核与通用 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>
155 lines
4.7 KiB
TypeScript
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>
|
|
);
|
|
}
|