完善画布素材与抠图任务体验

素材库资产支持直接下载。

画布复制图片时同步写入系统剪贴板。

手动抠图请求直接进入画布任务列表并支持聚焦。
This commit is contained in:
2026-06-29 19:53:05 +08:00
parent dbf38f3a8c
commit 10b170e7a2
14 changed files with 294 additions and 13 deletions
@@ -17,7 +17,10 @@ import {
import type { ExternalGenerationTaskRecord } from '../../../packages/shared/src/contracts/externalGeneration';
import { listExternalGenerationTasks } from '../../services/external-generation';
import { EditorIconButton } from './ImageCanvasEditorPrimitives';
import type { CanvasTaskStatus } from './ImageCanvasEditorTypes';
import type {
CanvasTaskListItem,
CanvasTaskStatus,
} from './ImageCanvasEditorTypes';
const COMPLETED_TASK_LIST_LIMIT = 20;
const ACTIVE_TASK_LIST_LIMIT = 100;
@@ -40,9 +43,11 @@ type TaskSidebarItem = {
type ImageCanvasTaskSidebarViewProps = {
projectId?: string | null;
localTasks?: CanvasTaskListItem[];
open: boolean;
onToggleOpen: () => void;
onFocusExternalTask: (task: ExternalGenerationTaskRecord) => void;
onFocusLocalTask?: (task: CanvasTaskListItem) => void;
};
function parseTaskTimeMs(value?: string | null) {
@@ -212,9 +217,11 @@ function mergeExternalTaskRefresh(
export function ImageCanvasTaskSidebarView({
projectId,
localTasks = [],
open,
onToggleOpen,
onFocusExternalTask,
onFocusLocalTask,
}: ImageCanvasTaskSidebarViewProps) {
const [activeTab, setActiveTab] = useState<TaskSidebarTab>('active');
const [now, setNow] = useState(() => Date.now());
@@ -342,9 +349,9 @@ export function ImageCanvasTaskSidebarView({
]);
useEffect(() => {
const hasRunningTask = externalTasks.some(
(task) => task.status === 'running',
);
const hasRunningTask =
externalTasks.some((task) => task.status === 'running') ||
localTasks.some((task) => task.status === 'running');
if (!hasRunningTask) {
return undefined;
}
@@ -352,7 +359,7 @@ export function ImageCanvasTaskSidebarView({
setNow(Date.now());
}, 1000);
return () => window.clearInterval(timerId);
}, [externalTasks]);
}, [externalTasks, localTasks]);
const items = useMemo<TaskSidebarItem[]>(() => {
const externalVisibleTasks = mergeExternalTasks(
@@ -401,8 +408,27 @@ export function ImageCanvasTaskSidebarView({
0,
};
});
return externalItems;
}, [externalTasks, now, onFocusExternalTask]);
const localItems = localTasks.map<TaskSidebarItem>((task) => ({
id: `local-${task.id}`,
title: task.title,
detail: task.detail,
status: task.status,
startedAt: task.startedAt,
finishedAt: task.finishedAt,
elapsedMs:
task.status === 'running'
? now - task.startedAt
: task.elapsedMs ??
(task.finishedAt ? task.finishedAt - task.startedAt : undefined),
errorMessage: task.errorMessage,
onClick:
task.focusLayerId && onFocusLocalTask
? () => onFocusLocalTask(task)
: undefined,
sortTime: task.finishedAt ?? task.startedAt,
}));
return [...localItems, ...externalItems];
}, [externalTasks, localTasks, now, onFocusExternalTask, onFocusLocalTask]);
const activeItems = useMemo(
() =>