refactor(skill): move skill editor slice to core workflow store

Move SkillEditorSlice from injection pattern to core workflow store,
making it available to all workflow contexts (workflow-app, chatflow,
and future rag-pipeline).

- Add createSkillEditorSlice to core createWorkflowStore
- Remove complex type conversion logic from workflow-app/index.tsx
- Remove optional chaining (?.) and non-null assertions (!) from components
- Simplify slice composition with type assertions via unknown
This commit is contained in:
yyh
2026-01-16 13:22:10 +08:00
parent 7022e4b9ca
commit 7093962f30
10 changed files with 46 additions and 59 deletions

View File

@ -49,8 +49,8 @@ const FileTree: React.FC<FileTreeProps> = ({ className }) => {
const { data: treeData, isLoading, error } = useSkillAssetTreeData()
const isMutating = useIsMutating() > 0
const expandedFolderIds = useStore(s => s.expandedFolderIds!)
const activeTabId = useStore(s => s.activeTabId!)
const expandedFolderIds = useStore(s => s.expandedFolderIds)
const activeTabId = useStore(s => s.activeTabId)
const storeApi = useWorkflowStore()
const renameNode = useRenameAppAssetNode()
@ -62,12 +62,12 @@ const FileTree: React.FC<FileTreeProps> = ({ className }) => {
}, [expandedFolderIds])
const handleToggle = useCallback((id: string) => {
storeApi.getState().toggleFolder?.(id)
storeApi.getState().toggleFolder(id)
}, [storeApi])
const handleActivate = useCallback((node: NodeApi<TreeNodeData>) => {
if (node.data.node_type === 'file')
storeApi.getState().openTab?.(node.data.id, { pinned: true })
storeApi.getState().openTab(node.data.id, { pinned: true })
else
node.toggle()
}, [storeApi])
@ -95,7 +95,7 @@ const FileTree: React.FC<FileTreeProps> = ({ className }) => {
const ancestors = getAncestorIds(activeTabId, treeData.children)
if (ancestors.length > 0)
storeApi.getState().revealFile?.(ancestors)
storeApi.getState().revealFile(ancestors)
requestAnimationFrame(() => {
const node = tree.get(activeTabId)
if (node) {

View File

@ -22,7 +22,7 @@ const TreeContextMenu: FC<TreeContextMenuProps> = ({ treeRef }) => {
const { data: treeData } = useSkillAssetTreeData()
const handleClose = useCallback(() => {
storeApi.getState().setContextMenu?.(null)
storeApi.getState().setContextMenu(null)
}, [storeApi])
useClickAway(() => {

View File

@ -26,7 +26,7 @@ const TreeNode = ({ node, style, dragHandle }: NodeRendererProps<TreeNodeData>)
const { t } = useTranslation('workflow')
const isFolder = node.data.node_type === 'folder'
const isSelected = node.isSelected
const isDirty = useStore(s => s.dirtyContents?.has(node.data.id) ?? false)
const isDirty = useStore(s => s.dirtyContents.has(node.data.id))
const contextMenuNodeId = useStore(s => s.contextMenu?.nodeId)
const hasContextMenu = contextMenuNodeId === node.data.id
const storeApi = useWorkflowStore()
@ -41,11 +41,11 @@ const TreeNode = ({ node, style, dragHandle }: NodeRendererProps<TreeNodeData>)
)
const openFilePreview = useCallback(() => {
storeApi.getState().openTab?.(node.data.id, { pinned: false })
storeApi.getState().openTab(node.data.id, { pinned: false })
}, [node.data.id, storeApi])
const openFilePinned = useCallback(() => {
storeApi.getState().openTab?.(node.data.id, { pinned: true })
storeApi.getState().openTab(node.data.id, { pinned: true })
}, [node.data.id, storeApi])
const { handleClick: handleFileClick, handleDoubleClick: handleFileDoubleClick } = useDelayedClick({
@ -79,7 +79,7 @@ const TreeNode = ({ node, style, dragHandle }: NodeRendererProps<TreeNodeData>)
e.preventDefault()
e.stopPropagation()
storeApi.getState().setContextMenu?.({
storeApi.getState().setContextMenu({
top: e.clientY,
left: e.clientX,
nodeId: node.data.id,
@ -97,7 +97,7 @@ const TreeNode = ({ node, style, dragHandle }: NodeRendererProps<TreeNodeData>)
if (isFolder)
node.toggle()
else
storeApi.getState().openTab?.(node.data.id, { pinned: true })
storeApi.getState().openTab(node.data.id, { pinned: true })
}
}, [isFolder, node, storeApi])