mirror of
https://github.com/langgenius/dify.git
synced 2026-04-30 15:38:08 +08:00
- Add START_TAB_ID constant and StartTabItem/StartTabContent components - Default to Start tab when no file tabs are open - Optimize zustand selectors to subscribe to specific Map values instead of entire Map objects, reducing unnecessary re-renders when other tabs change - Refactor useSkillFileSave to accept precise values instead of Map/Set
82 lines
2.2 KiB
TypeScript
82 lines
2.2 KiB
TypeScript
import type { TFunction } from 'i18next'
|
|
import type { StoreApi } from 'zustand'
|
|
import type { Shape } from '@/app/components/workflow/store'
|
|
import { useCallback, useEffect } from 'react'
|
|
import Toast from '@/app/components/base/toast'
|
|
import { useUpdateAppAssetFileContent } from '@/service/use-app-asset'
|
|
|
|
type UseSkillFileSaveParams = {
|
|
appId: string
|
|
activeTabId: string | null
|
|
isEditable: boolean
|
|
draftContent: string | undefined
|
|
isMetadataDirty: boolean
|
|
originalContent: string
|
|
currentMetadata: Record<string, unknown> | undefined
|
|
storeApi: StoreApi<Shape>
|
|
t: TFunction<'workflow'>
|
|
}
|
|
|
|
/**
|
|
* Hook to handle file save logic and Ctrl+S keyboard shortcut.
|
|
* Returns the save handler function.
|
|
*/
|
|
export function useSkillFileSave({
|
|
appId,
|
|
activeTabId,
|
|
isEditable,
|
|
draftContent,
|
|
isMetadataDirty,
|
|
originalContent,
|
|
currentMetadata,
|
|
storeApi,
|
|
t,
|
|
}: UseSkillFileSaveParams): () => Promise<void> {
|
|
const updateContent = useUpdateAppAssetFileContent()
|
|
|
|
const handleSave = useCallback(async () => {
|
|
if (!activeTabId || !appId || !isEditable)
|
|
return
|
|
|
|
if (draftContent === undefined && !isMetadataDirty)
|
|
return
|
|
|
|
try {
|
|
await updateContent.mutateAsync({
|
|
appId,
|
|
nodeId: activeTabId,
|
|
payload: {
|
|
content: draftContent ?? originalContent,
|
|
...(currentMetadata ? { metadata: currentMetadata } : {}),
|
|
},
|
|
})
|
|
storeApi.getState().clearDraftContent(activeTabId)
|
|
storeApi.getState().clearDraftMetadata(activeTabId)
|
|
Toast.notify({
|
|
type: 'success',
|
|
message: t('api.saved', { ns: 'common' }),
|
|
})
|
|
}
|
|
catch (error) {
|
|
Toast.notify({
|
|
type: 'error',
|
|
message: String(error),
|
|
})
|
|
}
|
|
}, [activeTabId, appId, currentMetadata, draftContent, isMetadataDirty, isEditable, originalContent, storeApi, t, updateContent])
|
|
|
|
useEffect(() => {
|
|
function handleKeyDown(e: KeyboardEvent): void {
|
|
if ((e.ctrlKey || e.metaKey) && e.key === 's') {
|
|
e.preventDefault()
|
|
handleSave()
|
|
}
|
|
}
|
|
|
|
window.addEventListener('keydown', handleKeyDown)
|
|
return () => window.removeEventListener('keydown', handleKeyDown)
|
|
}, [handleSave])
|
|
|
|
return handleSave
|
|
}
|