mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-06 05:09:09 +08:00
refactor(ocr): move provider logo logic to component and consolidate hooks
Move OcrProviderLogo implementation from useOcrProviders hook to the component file Extract common OCR provider logic into a separate useOcrProviders hook Clean up and reorganize related imports and exports
This commit is contained in:
parent
7658b1e79f
commit
beb44eea61
@ -1,98 +1,15 @@
|
|||||||
import { Avatar } from '@cherrystudio/ui'
|
|
||||||
import { usePreference } from '@data/hooks/usePreference'
|
|
||||||
import { loggerService } from '@logger'
|
import { loggerService } from '@logger'
|
||||||
import IntelLogo from '@renderer/assets/images/providers/intel.png'
|
import { updateOcrProviderConfig } from '@renderer/store/ocr'
|
||||||
import PaddleocrLogo from '@renderer/assets/images/providers/paddleocr.png'
|
import type { OcrProviderConfig } from '@renderer/types'
|
||||||
import TesseractLogo from '@renderer/assets/images/providers/Tesseract.js.png'
|
import { isBuiltinOcrProviderId } from '@renderer/types'
|
||||||
import { getBuiltinOcrProviderLabel } from '@renderer/i18n/label'
|
|
||||||
import { useAppSelector } from '@renderer/store'
|
|
||||||
import { addOcrProvider, removeOcrProvider, updateOcrProviderConfig } from '@renderer/store/ocr'
|
|
||||||
import type { OcrProvider, OcrProviderConfig } from '@renderer/types'
|
|
||||||
import { isBuiltinOcrProvider, isBuiltinOcrProviderId, isImageOcrProvider } from '@renderer/types'
|
|
||||||
import { BUILTIN_OCR_PROVIDERS_MAP } from '@shared/config/ocr'
|
import { BUILTIN_OCR_PROVIDERS_MAP } from '@shared/config/ocr'
|
||||||
import { FileQuestionMarkIcon, MonitorIcon } from 'lucide-react'
|
|
||||||
import { useCallback, useMemo } from 'react'
|
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useDispatch } from 'react-redux'
|
import { useDispatch } from 'react-redux'
|
||||||
|
|
||||||
|
import { useOcrProviders } from './useOcrProviders'
|
||||||
|
|
||||||
const logger = loggerService.withContext('useOcrProvider')
|
const logger = loggerService.withContext('useOcrProvider')
|
||||||
|
|
||||||
export const useOcrProviders = () => {
|
|
||||||
// TODO: migrate to useQuery
|
|
||||||
const providers = useAppSelector((state) => state.ocr.providers)
|
|
||||||
const imageProviders = providers.filter(isImageOcrProvider)
|
|
||||||
const [imageProviderId, setImageProviderId] = usePreference('ocr.settings.image_provider_id')
|
|
||||||
const imageProvider = useMemo(() => {
|
|
||||||
return imageProviders.find((p) => p.id === imageProviderId)
|
|
||||||
}, [imageProviderId, imageProviders])
|
|
||||||
const dispatch = useDispatch()
|
|
||||||
const { t } = useTranslation()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 添加一个新的OCR服务提供者
|
|
||||||
* @param provider - OCR提供者对象,包含id和其他配置信息
|
|
||||||
* @throws {Error} 当尝试添加一个已存在ID的提供者时抛出错误
|
|
||||||
*/
|
|
||||||
const addProvider = useCallback(
|
|
||||||
(provider: OcrProvider) => {
|
|
||||||
if (providers.some((p) => p.id === provider.id)) {
|
|
||||||
const msg = `Provider with id ${provider.id} already exists`
|
|
||||||
logger.error(msg)
|
|
||||||
window.toast.error(t('ocr.error.provider.existing'))
|
|
||||||
throw new Error(msg)
|
|
||||||
}
|
|
||||||
dispatch(addOcrProvider(provider))
|
|
||||||
},
|
|
||||||
[dispatch, providers, t]
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 移除一个OCR服务提供者
|
|
||||||
* @param id - 要移除的OCR提供者ID
|
|
||||||
* @throws {Error} 当尝试移除一个内置提供商时抛出错误
|
|
||||||
*/
|
|
||||||
const removeProvider = (id: string) => {
|
|
||||||
if (isBuiltinOcrProviderId(id)) {
|
|
||||||
const msg = `Cannot remove builtin provider ${id}`
|
|
||||||
logger.error(msg)
|
|
||||||
window.toast.error(t('ocr.error.provider.cannot_remove_builtin'))
|
|
||||||
throw new Error(msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch(removeOcrProvider(id))
|
|
||||||
}
|
|
||||||
|
|
||||||
const getOcrProviderName = (p: OcrProvider) => {
|
|
||||||
return isBuiltinOcrProvider(p) ? getBuiltinOcrProviderLabel(p.id) : p.name
|
|
||||||
}
|
|
||||||
|
|
||||||
const OcrProviderLogo = ({ provider: p, size = 14 }: { provider: OcrProvider; size?: number }) => {
|
|
||||||
if (isBuiltinOcrProvider(p)) {
|
|
||||||
switch (p.id) {
|
|
||||||
case 'tesseract':
|
|
||||||
return <Avatar src={TesseractLogo} style={{ width: size, height: size }} />
|
|
||||||
case 'system':
|
|
||||||
return <MonitorIcon size={size} />
|
|
||||||
case 'paddleocr':
|
|
||||||
return <Avatar src={PaddleocrLogo} style={{ width: size, height: size }} />
|
|
||||||
case 'ovocr':
|
|
||||||
return <Avatar src={IntelLogo} style={{ width: size, height: size }} />
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return <FileQuestionMarkIcon size={size} />
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
providers,
|
|
||||||
imageProvider,
|
|
||||||
addProvider,
|
|
||||||
removeProvider,
|
|
||||||
setImageProviderId,
|
|
||||||
getOcrProviderName,
|
|
||||||
OcrProviderLogo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useOcrProvider = (id: string) => {
|
export const useOcrProvider = (id: string) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
|
|||||||
71
src/renderer/src/hooks/ocr/useOcrProviders.ts
Normal file
71
src/renderer/src/hooks/ocr/useOcrProviders.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import { usePreference } from '@data/hooks/usePreference'
|
||||||
|
import { loggerService } from '@logger'
|
||||||
|
import { getBuiltinOcrProviderLabel } from '@renderer/i18n/label'
|
||||||
|
import { useAppSelector } from '@renderer/store'
|
||||||
|
import { addOcrProvider, removeOcrProvider } from '@renderer/store/ocr'
|
||||||
|
import type { OcrProvider } from '@renderer/types'
|
||||||
|
import { isBuiltinOcrProvider, isBuiltinOcrProviderId, isImageOcrProvider } from '@renderer/types'
|
||||||
|
import { useCallback, useMemo } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { useDispatch } from 'react-redux'
|
||||||
|
|
||||||
|
const logger = loggerService.withContext('useOcrProviders')
|
||||||
|
|
||||||
|
export const useOcrProviders = () => {
|
||||||
|
// TODO: migrate to useQuery
|
||||||
|
const providers = useAppSelector((state) => state.ocr.providers)
|
||||||
|
const imageProviders = providers.filter(isImageOcrProvider)
|
||||||
|
const [imageProviderId, setImageProviderId] = usePreference('ocr.settings.image_provider_id')
|
||||||
|
const imageProvider = useMemo(() => {
|
||||||
|
return imageProviders.find((p) => p.id === imageProviderId)
|
||||||
|
}, [imageProviderId, imageProviders])
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加一个新的OCR服务提供者
|
||||||
|
* @param provider - OCR提供者对象,包含id和其他配置信息
|
||||||
|
* @throws {Error} 当尝试添加一个已存在ID的提供者时抛出错误
|
||||||
|
*/
|
||||||
|
const addProvider = useCallback(
|
||||||
|
(provider: OcrProvider) => {
|
||||||
|
if (providers.some((p) => p.id === provider.id)) {
|
||||||
|
const msg = `Provider with id ${provider.id} already exists`
|
||||||
|
logger.error(msg)
|
||||||
|
window.toast.error(t('ocr.error.provider.existing'))
|
||||||
|
throw new Error(msg)
|
||||||
|
}
|
||||||
|
dispatch(addOcrProvider(provider))
|
||||||
|
},
|
||||||
|
[dispatch, providers, t]
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除一个OCR服务提供者
|
||||||
|
* @param id - 要移除的OCR提供者ID
|
||||||
|
* @throws {Error} 当尝试移除一个内置提供商时抛出错误
|
||||||
|
*/
|
||||||
|
const removeProvider = (id: string) => {
|
||||||
|
if (isBuiltinOcrProviderId(id)) {
|
||||||
|
const msg = `Cannot remove builtin provider ${id}`
|
||||||
|
logger.error(msg)
|
||||||
|
window.toast.error(t('ocr.error.provider.cannot_remove_builtin'))
|
||||||
|
throw new Error(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(removeOcrProvider(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
const getOcrProviderName = (p: OcrProvider) => {
|
||||||
|
return isBuiltinOcrProvider(p) ? getBuiltinOcrProviderLabel(p.id) : p.name
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
providers,
|
||||||
|
imageProvider,
|
||||||
|
addProvider,
|
||||||
|
removeProvider,
|
||||||
|
setImageProviderId,
|
||||||
|
getOcrProviderName
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,7 +2,7 @@ import { Alert, Skeleton } from '@heroui/react'
|
|||||||
import { loggerService } from '@logger'
|
import { loggerService } from '@logger'
|
||||||
import { ErrorTag } from '@renderer/components/Tags/ErrorTag'
|
import { ErrorTag } from '@renderer/components/Tags/ErrorTag'
|
||||||
import { isMac, isWin } from '@renderer/config/constant'
|
import { isMac, isWin } from '@renderer/config/constant'
|
||||||
import { useOcrProviders } from '@renderer/hooks/ocr/useOcrProvider'
|
import { useOcrProviders } from '@renderer/hooks/ocr/useOcrProviders'
|
||||||
import type { ImageOcrProvider } from '@renderer/types'
|
import type { ImageOcrProvider } from '@renderer/types'
|
||||||
import { BuiltinOcrProviderIds, isImageOcrProvider } from '@renderer/types'
|
import { BuiltinOcrProviderIds, isImageOcrProvider } from '@renderer/types'
|
||||||
import { getErrorMessage } from '@renderer/utils'
|
import { getErrorMessage } from '@renderer/utils'
|
||||||
|
|||||||
@ -1,12 +1,16 @@
|
|||||||
// import { loggerService } from '@logger'
|
// import { loggerService } from '@logger'
|
||||||
import { Flex } from '@cherrystudio/ui'
|
import { Avatar, Flex } from '@cherrystudio/ui'
|
||||||
|
import IntelLogo from '@renderer/assets/images/providers/intel.png'
|
||||||
|
import PaddleocrLogo from '@renderer/assets/images/providers/paddleocr.png'
|
||||||
|
import TesseractLogo from '@renderer/assets/images/providers/Tesseract.js.png'
|
||||||
import { ErrorBoundary } from '@renderer/components/ErrorBoundary'
|
import { ErrorBoundary } from '@renderer/components/ErrorBoundary'
|
||||||
import { isMac, isWin } from '@renderer/config/constant'
|
import { isMac, isWin } from '@renderer/config/constant'
|
||||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||||
import { useOcrProviders } from '@renderer/hooks/ocr/useOcrProvider'
|
import { useOcrProviders } from '@renderer/hooks/ocr/useOcrProviders'
|
||||||
import type { OcrProvider } from '@renderer/types'
|
import type { OcrProvider } from '@renderer/types'
|
||||||
import { isBuiltinOcrProvider, isOcrSystemProvider } from '@renderer/types'
|
import { isBuiltinOcrProvider, isOcrSystemProvider } from '@renderer/types'
|
||||||
import { Divider } from 'antd'
|
import { Divider } from 'antd'
|
||||||
|
import { FileQuestionMarkIcon, MonitorIcon } from 'lucide-react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
import { SettingGroup, SettingTitle } from '..'
|
import { SettingGroup, SettingTitle } from '..'
|
||||||
@ -23,7 +27,7 @@ type Props = {
|
|||||||
|
|
||||||
const OcrProviderSettings = ({ provider }: Props) => {
|
const OcrProviderSettings = ({ provider }: Props) => {
|
||||||
const { theme: themeMode } = useTheme()
|
const { theme: themeMode } = useTheme()
|
||||||
const { OcrProviderLogo, getOcrProviderName } = useOcrProviders()
|
const { getOcrProviderName } = useOcrProviders()
|
||||||
|
|
||||||
if (!provider || (!isWin && !isMac && isOcrSystemProvider(provider))) {
|
if (!provider || (!isWin && !isMac && isOcrSystemProvider(provider))) {
|
||||||
return null
|
return null
|
||||||
@ -69,4 +73,20 @@ const ProviderName = styled.span`
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const OcrProviderLogo = ({ provider: p, size = 14 }: { provider: OcrProvider; size?: number }) => {
|
||||||
|
if (isBuiltinOcrProvider(p)) {
|
||||||
|
switch (p.id) {
|
||||||
|
case 'tesseract':
|
||||||
|
return <Avatar src={TesseractLogo} style={{ width: size, height: size }} />
|
||||||
|
case 'system':
|
||||||
|
return <MonitorIcon size={size} />
|
||||||
|
case 'paddleocr':
|
||||||
|
return <Avatar src={PaddleocrLogo} style={{ width: size, height: size }} />
|
||||||
|
case 'ovocr':
|
||||||
|
return <Avatar src={IntelLogo} style={{ width: size, height: size }} />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return <FileQuestionMarkIcon size={size} />
|
||||||
|
}
|
||||||
|
|
||||||
export default OcrProviderSettings
|
export default OcrProviderSettings
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { ErrorBoundary } from '@renderer/components/ErrorBoundary'
|
import { ErrorBoundary } from '@renderer/components/ErrorBoundary'
|
||||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||||
import { useOcrProviders } from '@renderer/hooks/ocr/useOcrProvider'
|
import { useOcrProviders } from '@renderer/hooks/ocr/useOcrProviders'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user