mirror of
https://github.com/basketikun/infinite-canvas.git
synced 2026-07-24 15:24:06 +08:00
feat(canvas): optimize CanvasAssetsTab and CanvasPromptsTab with memoization to improve performance
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
+ [新增] 左侧画布面板新增「提示词库」Tab,按来源折叠分组。
|
+ [新增] 左侧画布面板新增「提示词库」Tab,按来源折叠分组。
|
||||||
|
+ [修复] 处于「提示词库/资产」Tab 时拖动画布元素卡顿,面板内容不再随节点更新重渲染。
|
||||||
+ [新增] 提示词来源增加自定义脚本抓取功能、支持新增来源。
|
+ [新增] 提示词来源增加自定义脚本抓取功能、支持新增来源。
|
||||||
|
|
||||||
## v0.9.0 - 2026-07-17
|
## v0.9.0 - 2026-07-17
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useMemo, useRef, useState, type PointerEvent as ReactPointerEvent } from "react";
|
import { memo, useMemo, useRef, useState, type PointerEvent as ReactPointerEvent } from "react";
|
||||||
import { App, Empty, Input, Popconfirm, Select, Spin, Tag } from "antd";
|
import { App, Empty, Input, Popconfirm, Select, Spin, Tag } from "antd";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { BookOpen, Check, ChevronRight, Download, Eye, FileText, Image as ImageIcon, ListChecks, Music2, Plus, Search, Settings2, Square, Trash2, Type, Video } from "lucide-react";
|
import { BookOpen, Check, ChevronRight, Download, Eye, FileText, Image as ImageIcon, ListChecks, Music2, Plus, Search, Settings2, Square, Trash2, Type, Video } from "lucide-react";
|
||||||
@@ -286,7 +286,7 @@ function buildInsertPayload(asset: Asset): InsertAssetPayload {
|
|||||||
return { kind: "image", dataUrl: asset.data.dataUrl, storageKey: asset.data.storageKey, title: asset.title };
|
return { kind: "image", dataUrl: asset.data.dataUrl, storageKey: asset.data.storageKey, title: asset.title };
|
||||||
}
|
}
|
||||||
|
|
||||||
function CanvasAssetsTab({ onInsert, theme }: { onInsert: (payload: InsertAssetPayload) => void; theme: CanvasTheme }) {
|
const CanvasAssetsTab = memo(function CanvasAssetsTab({ onInsert, theme }: { onInsert: (payload: InsertAssetPayload) => void; theme: CanvasTheme }) {
|
||||||
const { message } = App.useApp();
|
const { message } = App.useApp();
|
||||||
const assets = useAssetStore((state) => state.assets);
|
const assets = useAssetStore((state) => state.assets);
|
||||||
const addAsset = useAssetStore((state) => state.addAsset);
|
const addAsset = useAssetStore((state) => state.addAsset);
|
||||||
@@ -398,7 +398,7 @@ function CanvasAssetsTab({ onInsert, theme }: { onInsert: (payload: InsertAssetP
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
function AssetCard({ asset, theme, onInsert, onRemove }: { asset: Asset; theme: CanvasTheme; onInsert: () => void; onRemove: () => void }) {
|
function AssetCard({ asset, theme, onInsert, onRemove }: { asset: Asset; theme: CanvasTheme; onInsert: () => void; onRemove: () => void }) {
|
||||||
return (
|
return (
|
||||||
@@ -440,7 +440,7 @@ function AssetCover({ asset }: { asset: Asset }) {
|
|||||||
// 提示词库 Tab —— 按来源折叠分组,展开时按需加载,点击复制 / 插入文本节点
|
// 提示词库 Tab —— 按来源折叠分组,展开时按需加载,点击复制 / 插入文本节点
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
function CanvasPromptsTab({ onInsert, theme }: { onInsert: (payload: InsertAssetPayload) => void; theme: CanvasTheme }) {
|
const CanvasPromptsTab = memo(function CanvasPromptsTab({ onInsert, theme }: { onInsert: (payload: InsertAssetPayload) => void; theme: CanvasTheme }) {
|
||||||
const { message } = App.useApp();
|
const { message } = App.useApp();
|
||||||
const sources = usePromptSourceStore((state) => state.sources);
|
const sources = usePromptSourceStore((state) => state.sources);
|
||||||
const enabledSources = useMemo(() => sources.filter((source) => source.enabled), [sources]);
|
const enabledSources = useMemo(() => sources.filter((source) => source.enabled), [sources]);
|
||||||
@@ -486,7 +486,7 @@ function CanvasPromptsTab({ onInsert, theme }: { onInsert: (payload: InsertAsset
|
|||||||
<PromptDetailDialog prompt={detail} onClose={() => setDetail(null)} onCopy={(prompt) => void copyPrompt(prompt)} />
|
<PromptDetailDialog prompt={detail} onClose={() => setDetail(null)} onCopy={(prompt) => void copyPrompt(prompt)} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
function PromptSourceGroup({
|
function PromptSourceGroup({
|
||||||
sourceId,
|
sourceId,
|
||||||
|
|||||||
Reference in New Issue
Block a user