refactor(skill-editor): hoist SkillEditorProvider for state persistence

Move SkillEditorProvider from SkillMain to WorkflowAppWrapper so that
store state persists across view switches between Graph and Skill views.
Also add URL query state for view type using nuqs.
This commit is contained in:
yyh
2026-01-15 15:09:12 +08:00
parent e6a4a08120
commit ce9ed88b03
2 changed files with 25 additions and 36 deletions

View File

@ -3,10 +3,11 @@
import type { Features as FeaturesData } from '@/app/components/base/features/types'
import type { InjectWorkflowStoreSliceFn } from '@/app/components/workflow/store'
import { useSearchParams } from 'next/navigation'
import { useQueryState } from 'nuqs'
import {
useCallback,
useEffect,
useMemo,
useState,
} from 'react'
import { useStore as useAppStore } from '@/app/components/app/store'
import { FeaturesProvider } from '@/app/components/base/features'
@ -16,6 +17,7 @@ import WorkflowWithDefaultContext from '@/app/components/workflow'
import {
WorkflowContextProvider,
} from '@/app/components/workflow/context'
import { SkillEditorProvider } from '@/app/components/workflow/skill/context'
import SkillMain from '@/app/components/workflow/skill/main'
import { useWorkflowStore } from '@/app/components/workflow/store'
import { useTriggerStatusStore } from '@/app/components/workflow/store/trigger-status'
@ -37,6 +39,7 @@ import { useGetRunAndTraceUrl } from './hooks/use-get-run-and-trace-url'
import {
useWorkflowInit,
} from './hooks/use-workflow-init'
import { parseAsViewType, WORKFLOW_VIEW_PARAM_KEY } from './search-params'
import { createWorkflowSlice } from './store/workflow/workflow-slice'
const WorkflowAppWithAdditionalContext = () => {
@ -49,13 +52,12 @@ const WorkflowAppWithAdditionalContext = () => {
const workflowStore = useWorkflowStore()
const { isLoadingCurrentWorkspace, currentWorkspace } = useAppContext()
const [viewType, doSetViewType] = useState(ViewType.graph)
const setViewType = (type: ViewType) => {
const [viewType, doSetViewType] = useQueryState(WORKFLOW_VIEW_PARAM_KEY, parseAsViewType)
const setViewType = useCallback((type: ViewType) => {
doSetViewType(type)
if (type === ViewType.graph) {
if (type === ViewType.graph)
reload()
}
}
}, [doSetViewType, reload])
// Initialize trigger status at application level
const { setTriggerStatuses } = useTriggerStatusStore()
@ -250,7 +252,9 @@ const WorkflowAppWrapper = () => {
<WorkflowContextProvider
injectWorkflowStoreSliceFn={createWorkflowSlice as InjectWorkflowStoreSliceFn}
>
<WorkflowAppWithAdditionalContext />
<SkillEditorProvider>
<WorkflowAppWithAdditionalContext />
</SkillEditorProvider>
</WorkflowContextProvider>
)
}

View File

@ -2,7 +2,6 @@
import type { FC } from 'react'
import * as React from 'react'
import { SkillEditorProvider } from './context'
import EditorArea from './editor-area'
import EditorBody from './editor-body'
import EditorTabs from './editor-tabs'
@ -12,36 +11,22 @@ import SidebarSearchAdd from './sidebar-search-add'
import SkillDocEditor from './skill-doc-editor'
import SkillPageLayout from './skill-page-layout'
/**
* SkillMain - Main entry point for Skill Editor view
*
* This component provides the SkillEditorContext and renders the
* complete Skill Editor UI including:
* - File tree sidebar
* - Tab bar
* - Editor area
*
* The store is created at this level and shared with all child components.
* API data is fetched using TanStack Query hooks within child components.
*/
const SkillMain: FC = () => {
return (
<SkillEditorProvider>
<div className="h-full bg-workflow-canvas-workflow-top-bar-1 pl-3 pt-[52px]">
<SkillPageLayout>
<Sidebar>
<SidebarSearchAdd />
<Files />
</Sidebar>
<EditorArea>
<EditorTabs />
<EditorBody>
<SkillDocEditor />
</EditorBody>
</EditorArea>
</SkillPageLayout>
</div>
</SkillEditorProvider>
<div className="h-full bg-workflow-canvas-workflow-top-bar-1 pl-3 pt-[52px]">
<SkillPageLayout>
<Sidebar>
<SidebarSearchAdd />
<Files />
</Sidebar>
<EditorArea>
<EditorTabs />
<EditorBody>
<SkillDocEditor />
</EditorBody>
</EditorArea>
</SkillPageLayout>
</div>
)
}