mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-24 18:50:56 +08:00
refactor(ocr): improve type safety and config handling in useOcrProvider
- Replace dynamic provider lookup with type-safe registry pattern - Add separate config management for each provider type - Remove unused imports and simplify provider fallback logic
This commit is contained in:
parent
94ed39ab27
commit
a34426d431
@ -1,35 +1,106 @@
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
import { updateOcrProviderConfig } from '@renderer/store/ocr'
|
||||
import type { OcrProviderConfig } from '@renderer/types'
|
||||
import type {
|
||||
BuiltinOcrProviderId,
|
||||
OcrOvConfig,
|
||||
OcrOvProvider,
|
||||
OcrPpocrConfig,
|
||||
OcrPpocrProvider,
|
||||
OcrSystemConfig,
|
||||
OcrSystemProvider,
|
||||
OcrTesseractConfig,
|
||||
OcrTesseractProvider
|
||||
} from '@renderer/types'
|
||||
import { BUILTIN_OCR_PROVIDERS_MAP } from '@shared/config/ocr'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useDispatch } from 'react-redux'
|
||||
|
||||
import { useOcrProviders } from './useOcrProviders'
|
||||
import { merge } from 'lodash'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
|
||||
const logger = loggerService.withContext('useOcrProvider')
|
||||
|
||||
export const useOcrProvider = (id: string) => {
|
||||
const { t } = useTranslation()
|
||||
const dispatch = useDispatch()
|
||||
const { providers } = useOcrProviders()
|
||||
let provider = providers.find((p) => p.id === id)
|
||||
const PROVIDER_REGISTRY = {
|
||||
ovocr: null as unknown as OcrOvProvider,
|
||||
paddleocr: null as unknown as OcrPpocrProvider,
|
||||
system: null as unknown as OcrSystemProvider,
|
||||
tesseract: null as unknown as OcrTesseractProvider
|
||||
}
|
||||
|
||||
// safely fallback
|
||||
if (!provider) {
|
||||
logger.error(`Ocr Provider ${id} not found`)
|
||||
logger.warn(`Fallback to tesseract`)
|
||||
window.toast.error(t('ocr.error.provider.not_found'))
|
||||
window.toast.warning(t('ocr.warning.provider.fallback', { name: 'Tesseract' }))
|
||||
provider = BUILTIN_OCR_PROVIDERS_MAP.tesseract
|
||||
}
|
||||
const CONFIG_REGISTRY = {
|
||||
ovocr: null as unknown as OcrOvConfig,
|
||||
paddleocr: null as unknown as OcrPpocrConfig,
|
||||
system: null as unknown as OcrSystemConfig,
|
||||
tesseract: null as unknown as OcrTesseractConfig
|
||||
} as const
|
||||
|
||||
const updateConfig = (update: Partial<OcrProviderConfig>) => {
|
||||
dispatch(updateOcrProviderConfig({ id: provider.id, update }))
|
||||
}
|
||||
type ProviderMap = typeof PROVIDER_REGISTRY
|
||||
|
||||
type ConfigMap = typeof CONFIG_REGISTRY
|
||||
|
||||
type TProvider<T extends BuiltinOcrProviderId> = ProviderMap[T]
|
||||
|
||||
type TConfig<T extends BuiltinOcrProviderId> = ConfigMap[T]
|
||||
|
||||
type UseOcrProviderReturn<T extends BuiltinOcrProviderId> = {
|
||||
provider: TProvider<T>
|
||||
config: TConfig<T>
|
||||
updateConfig: (update: Partial<TConfig<T>>) => void
|
||||
}
|
||||
|
||||
export const useOcrProvider = <T extends BuiltinOcrProviderId>(id: T): UseOcrProviderReturn<T> => {
|
||||
const provider = useMemo(() => {
|
||||
switch (id) {
|
||||
case 'ovocr':
|
||||
return BUILTIN_OCR_PROVIDERS_MAP.ovocr
|
||||
case 'paddleocr':
|
||||
return BUILTIN_OCR_PROVIDERS_MAP.paddleocr
|
||||
case 'system':
|
||||
return BUILTIN_OCR_PROVIDERS_MAP.system
|
||||
case 'tesseract':
|
||||
return BUILTIN_OCR_PROVIDERS_MAP.tesseract
|
||||
}
|
||||
}, [id])
|
||||
const [ovConfig, setOvConfig] = usePreference('ocr.provider.config.ovocr')
|
||||
const [ppConfig, setPpConfig] = usePreference('ocr.provider.config.paddleocr')
|
||||
const [sysConfig, setSysConfig] = usePreference('ocr.provider.config.system')
|
||||
const [tesConfig, setTesConfig] = usePreference('ocr.provider.config.tesseract')
|
||||
|
||||
const config = useMemo(() => {
|
||||
switch (id) {
|
||||
case 'ovocr':
|
||||
return ovConfig
|
||||
case 'paddleocr':
|
||||
return ppConfig
|
||||
case 'system':
|
||||
return sysConfig
|
||||
case 'tesseract':
|
||||
return tesConfig
|
||||
}
|
||||
}, [id, ovConfig, ppConfig, sysConfig, tesConfig])
|
||||
|
||||
const updateConfig = useCallback(
|
||||
(update: Partial<TConfig<T>>) => {
|
||||
switch (id) {
|
||||
case 'ovocr':
|
||||
setOvConfig(merge({}, ovConfig, update))
|
||||
break
|
||||
case 'paddleocr':
|
||||
setPpConfig(merge({}, ppConfig, update))
|
||||
break
|
||||
case 'system':
|
||||
setSysConfig(merge({}, sysConfig, update))
|
||||
break
|
||||
case 'tesseract':
|
||||
setTesConfig(merge({}, tesConfig, update))
|
||||
break
|
||||
default:
|
||||
logger.warn(`Unsupported OCR provider id: ${id}`)
|
||||
}
|
||||
},
|
||||
[id, ovConfig, ppConfig, setOvConfig, setPpConfig, setSysConfig, setTesConfig, sysConfig, tesConfig]
|
||||
)
|
||||
|
||||
return {
|
||||
provider,
|
||||
config,
|
||||
updateConfig
|
||||
}
|
||||
} as UseOcrProviderReturn<T>
|
||||
}
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
import { useQuery } from '@data/hooks/useDataApi'
|
||||
import { loggerService } from '@logger'
|
||||
import { getBuiltinOcrProviderLabel } from '@renderer/i18n/label'
|
||||
import type { OcrProvider } from '@renderer/types'
|
||||
import { isBuiltinOcrProvider } from '@renderer/types'
|
||||
import { BUILTIN_OCR_PROVIDERS } from '@shared/config/ocr'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
const logger = loggerService.withContext('useOcrProviders')
|
||||
|
||||
export const useOcrProviders = () => {
|
||||
const { data: validProviderIds, loading, error } = useQuery('/ocr/providers')
|
||||
const providers = useMemo(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user