From beb44eea61afcb518f95c87f719f93d5a30b3e13 Mon Sep 17 00:00:00 2001 From: icarus Date: Mon, 20 Oct 2025 02:06:17 +0800 Subject: [PATCH] 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 --- src/renderer/src/hooks/ocr/useOcrProvider.tsx | 93 +------------------ src/renderer/src/hooks/ocr/useOcrProviders.ts | 71 ++++++++++++++ .../DocProcessSettings/OcrImageSettings.tsx | 2 +- .../OcrProviderSettings.tsx | 26 +++++- .../DocProcessSettings/OcrSettings.tsx | 2 +- 5 files changed, 101 insertions(+), 93 deletions(-) create mode 100644 src/renderer/src/hooks/ocr/useOcrProviders.ts diff --git a/src/renderer/src/hooks/ocr/useOcrProvider.tsx b/src/renderer/src/hooks/ocr/useOcrProvider.tsx index c0a650f78e..bb6efb8bef 100644 --- a/src/renderer/src/hooks/ocr/useOcrProvider.tsx +++ b/src/renderer/src/hooks/ocr/useOcrProvider.tsx @@ -1,98 +1,15 @@ -import { Avatar } from '@cherrystudio/ui' -import { usePreference } from '@data/hooks/usePreference' import { loggerService } from '@logger' -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 { 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 { updateOcrProviderConfig } from '@renderer/store/ocr' +import type { OcrProviderConfig } from '@renderer/types' +import { isBuiltinOcrProviderId } from '@renderer/types' 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 { useDispatch } from 'react-redux' +import { useOcrProviders } from './useOcrProviders' + 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 - case 'system': - return - case 'paddleocr': - return - case 'ovocr': - return - } - } - return - } - - return { - providers, - imageProvider, - addProvider, - removeProvider, - setImageProviderId, - getOcrProviderName, - OcrProviderLogo - } -} - export const useOcrProvider = (id: string) => { const { t } = useTranslation() const dispatch = useDispatch() diff --git a/src/renderer/src/hooks/ocr/useOcrProviders.ts b/src/renderer/src/hooks/ocr/useOcrProviders.ts new file mode 100644 index 0000000000..552e0208a9 --- /dev/null +++ b/src/renderer/src/hooks/ocr/useOcrProviders.ts @@ -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 + } +} diff --git a/src/renderer/src/pages/settings/DocProcessSettings/OcrImageSettings.tsx b/src/renderer/src/pages/settings/DocProcessSettings/OcrImageSettings.tsx index 66db685f68..0e3a809ea0 100644 --- a/src/renderer/src/pages/settings/DocProcessSettings/OcrImageSettings.tsx +++ b/src/renderer/src/pages/settings/DocProcessSettings/OcrImageSettings.tsx @@ -2,7 +2,7 @@ import { Alert, Skeleton } from '@heroui/react' import { loggerService } from '@logger' import { ErrorTag } from '@renderer/components/Tags/ErrorTag' 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 { BuiltinOcrProviderIds, isImageOcrProvider } from '@renderer/types' import { getErrorMessage } from '@renderer/utils' diff --git a/src/renderer/src/pages/settings/DocProcessSettings/OcrProviderSettings.tsx b/src/renderer/src/pages/settings/DocProcessSettings/OcrProviderSettings.tsx index b34f7fa185..43de14d9f1 100644 --- a/src/renderer/src/pages/settings/DocProcessSettings/OcrProviderSettings.tsx +++ b/src/renderer/src/pages/settings/DocProcessSettings/OcrProviderSettings.tsx @@ -1,12 +1,16 @@ // 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 { isMac, isWin } from '@renderer/config/constant' 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 { isBuiltinOcrProvider, isOcrSystemProvider } from '@renderer/types' import { Divider } from 'antd' +import { FileQuestionMarkIcon, MonitorIcon } from 'lucide-react' import styled from 'styled-components' import { SettingGroup, SettingTitle } from '..' @@ -23,7 +27,7 @@ type Props = { const OcrProviderSettings = ({ provider }: Props) => { const { theme: themeMode } = useTheme() - const { OcrProviderLogo, getOcrProviderName } = useOcrProviders() + const { getOcrProviderName } = useOcrProviders() if (!provider || (!isWin && !isMac && isOcrSystemProvider(provider))) { return null @@ -69,4 +73,20 @@ const ProviderName = styled.span` font-weight: 500; ` +const OcrProviderLogo = ({ provider: p, size = 14 }: { provider: OcrProvider; size?: number }) => { + if (isBuiltinOcrProvider(p)) { + switch (p.id) { + case 'tesseract': + return + case 'system': + return + case 'paddleocr': + return + case 'ovocr': + return + } + } + return +} + export default OcrProviderSettings diff --git a/src/renderer/src/pages/settings/DocProcessSettings/OcrSettings.tsx b/src/renderer/src/pages/settings/DocProcessSettings/OcrSettings.tsx index 77316e37d5..e99c164439 100644 --- a/src/renderer/src/pages/settings/DocProcessSettings/OcrSettings.tsx +++ b/src/renderer/src/pages/settings/DocProcessSettings/OcrSettings.tsx @@ -1,6 +1,6 @@ import { ErrorBoundary } from '@renderer/components/ErrorBoundary' 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 { useTranslation } from 'react-i18next'