mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-06 21:35:52 +08:00
feat(OCR设置): 添加OCR提供商设置组件及状态管理
新增OCR提供商设置组件,支持显示当前选择的OCR提供商信息 在OCR图片设置中添加状态管理,同步提供商选择到父组件 添加Tesseract OCR设置组件,支持多语言选择(暂不可用)
This commit is contained in:
parent
c549fff44a
commit
cb362a4e2e
@ -1,8 +1,9 @@
|
|||||||
import { loggerService } from '@logger'
|
import { loggerService } from '@logger'
|
||||||
import { useAppSelector } from '@renderer/store'
|
import { useAppSelector } from '@renderer/store'
|
||||||
import { setImageOcrProvider } from '@renderer/store/ocr'
|
import { setImageOcrProvider } from '@renderer/store/ocr'
|
||||||
import { isImageOcrProvider } from '@renderer/types'
|
import { isImageOcrProvider, OcrProvider } from '@renderer/types'
|
||||||
import { Select } from 'antd'
|
import { Select } from 'antd'
|
||||||
|
import { useEffect } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useDispatch } from 'react-redux'
|
import { useDispatch } from 'react-redux'
|
||||||
|
|
||||||
@ -10,13 +11,22 @@ import { SettingRow, SettingRowTitle } from '..'
|
|||||||
|
|
||||||
const logger = loggerService.withContext('OcrImageSettings')
|
const logger = loggerService.withContext('OcrImageSettings')
|
||||||
|
|
||||||
const OcrImageSettings = () => {
|
type Props = {
|
||||||
|
setProvider: (provider: OcrProvider) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const OcrImageSettings = ({ setProvider }: Props) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const providers = useAppSelector((state) => state.ocr.providers)
|
const providers = useAppSelector((state) => state.ocr.providers)
|
||||||
const imageProvider = useAppSelector((state) => state.ocr.imageProvider)
|
const imageProvider = useAppSelector((state) => state.ocr.imageProvider)
|
||||||
const imageProviders = providers.filter((p) => isImageOcrProvider(p))
|
const imageProviders = providers.filter((p) => isImageOcrProvider(p))
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
|
|
||||||
|
// 挂载时更新外部状态
|
||||||
|
useEffect(() => {
|
||||||
|
setProvider(imageProvider)
|
||||||
|
}, [imageProvider, setProvider])
|
||||||
|
|
||||||
const updateImageProvider = (id: string) => {
|
const updateImageProvider = (id: string) => {
|
||||||
const provider = imageProviders.find((p) => p.id === id)
|
const provider = imageProviders.find((p) => p.id === id)
|
||||||
if (!provider) {
|
if (!provider) {
|
||||||
@ -25,6 +35,7 @@ const OcrImageSettings = () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setProvider(provider)
|
||||||
dispatch(setImageOcrProvider(provider))
|
dispatch(setImageOcrProvider(provider))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,51 @@
|
|||||||
|
// import { loggerService } from '@logger'
|
||||||
|
import { isBuiltinOcrProvider, OcrProvider } from '@renderer/types'
|
||||||
|
import { getOcrProviderLogo } from '@renderer/utils/ocr'
|
||||||
|
import { Avatar, Divider, Flex } from 'antd'
|
||||||
|
import styled from 'styled-components'
|
||||||
|
|
||||||
|
import { SettingTitle } from '..'
|
||||||
|
import { OcrTesseractSettings } from './OcrTesseractSettings'
|
||||||
|
|
||||||
|
// const logger = loggerService.withContext('OcrTesseractSettings')
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
provider: OcrProvider
|
||||||
|
}
|
||||||
|
|
||||||
|
const OcrProviderSettings = ({ provider }: Props) => {
|
||||||
|
// const { t } = useTranslation()
|
||||||
|
const getProviderSettings = () => {
|
||||||
|
if (isBuiltinOcrProvider(provider)) {
|
||||||
|
switch (provider.id) {
|
||||||
|
case 'tesseract':
|
||||||
|
return <OcrTesseractSettings />
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error('Not supported OCR provider')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<SettingTitle>
|
||||||
|
<Flex align="center" gap={8}>
|
||||||
|
<ProviderLogo shape="square" src={getOcrProviderLogo(provider.id)} size={16} />
|
||||||
|
<ProviderName> {provider.name}</ProviderName>
|
||||||
|
</Flex>
|
||||||
|
</SettingTitle>
|
||||||
|
<Divider style={{ width: '100%', margin: '10px 0' }} />
|
||||||
|
{getProviderSettings()}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProviderName = styled.span`
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
`
|
||||||
|
const ProviderLogo = styled(Avatar)`
|
||||||
|
border: 0.5px solid var(--color-border);
|
||||||
|
`
|
||||||
|
|
||||||
|
export default OcrProviderSettings
|
||||||
@ -1,22 +1,27 @@
|
|||||||
import { PictureOutlined } from '@ant-design/icons'
|
import { PictureOutlined } from '@ant-design/icons'
|
||||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||||
|
import { useAppSelector } from '@renderer/store'
|
||||||
|
import { OcrProvider } from '@renderer/types'
|
||||||
import { Tabs, TabsProps } from 'antd'
|
import { Tabs, TabsProps } from 'antd'
|
||||||
import { FC } from 'react'
|
import { FC, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
import { SettingDivider, SettingGroup, SettingTitle } from '..'
|
import { SettingDivider, SettingGroup, SettingTitle } from '..'
|
||||||
import OcrImageSettings from './OcrImageSettings'
|
import OcrImageSettings from './OcrImageSettings'
|
||||||
|
import OcrProviderSettings from './OcrProviderSettings'
|
||||||
|
|
||||||
const OcrSettings: FC = () => {
|
const OcrSettings: FC = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { theme: themeMode } = useTheme()
|
const { theme: themeMode } = useTheme()
|
||||||
|
const imageProvider = useAppSelector((state) => state.ocr.imageProvider)
|
||||||
|
const [provider, setProvider] = useState<OcrProvider>(imageProvider) // since default to image provider
|
||||||
|
|
||||||
const tabs: TabsProps['items'] = [
|
const tabs: TabsProps['items'] = [
|
||||||
{
|
{
|
||||||
key: 'image',
|
key: 'image',
|
||||||
label: t('settings.tool.ocr.image.title'),
|
label: t('settings.tool.ocr.image.title'),
|
||||||
icon: <PictureOutlined />,
|
icon: <PictureOutlined />,
|
||||||
children: <OcrImageSettings />
|
children: <OcrImageSettings setProvider={setProvider} />
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -27,6 +32,9 @@ const OcrSettings: FC = () => {
|
|||||||
<SettingDivider />
|
<SettingDivider />
|
||||||
<Tabs defaultActiveKey="image" items={tabs} />
|
<Tabs defaultActiveKey="image" items={tabs} />
|
||||||
</SettingGroup>
|
</SettingGroup>
|
||||||
|
<SettingGroup theme={themeMode}>
|
||||||
|
<OcrProviderSettings provider={provider} />
|
||||||
|
</SettingGroup>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,52 @@
|
|||||||
|
// import { loggerService } from '@logger'
|
||||||
|
import InfoTooltip from '@renderer/components/InfoTooltip'
|
||||||
|
import { useOcrProvider } from '@renderer/hooks/useOcrProvider'
|
||||||
|
import { BuiltinOcrProviderIds, isOcrTesseractProvider } from '@renderer/types'
|
||||||
|
import { Flex, Select } from 'antd'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
import { SettingRow, SettingRowTitle } from '..'
|
||||||
|
|
||||||
|
// const logger = loggerService.withContext('OcrTesseractSettings')
|
||||||
|
|
||||||
|
export const OcrTesseractSettings = () => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const { provider } = useOcrProvider(BuiltinOcrProviderIds.tesseract)
|
||||||
|
|
||||||
|
// TODO: use error boundary
|
||||||
|
if (!isOcrTesseractProvider(provider)) {
|
||||||
|
throw new Error('Not tesseract provider.')
|
||||||
|
}
|
||||||
|
|
||||||
|
// const [langs, setLangs] = useState<OcrTesseractConfig['langs']>(provider.config?.langs ?? {})
|
||||||
|
|
||||||
|
// currently static
|
||||||
|
const options = [
|
||||||
|
{ value: 'chi_sim', label: t('languages.chinese') },
|
||||||
|
{ value: 'chi_tra', label: t('languages.chinese-traditional') },
|
||||||
|
{ value: 'eng', label: t('languages.english') }
|
||||||
|
]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<SettingRow>
|
||||||
|
<SettingRowTitle>
|
||||||
|
<Flex align="center" gap={4}>
|
||||||
|
{t('settings.tool.ocr.image.tesseract.langs')}
|
||||||
|
<InfoTooltip title={t('settings.tool.ocr.image.tesseract.temp_tooltip')} />
|
||||||
|
</Flex>
|
||||||
|
</SettingRowTitle>
|
||||||
|
<div style={{ display: 'flex', gap: '8px' }}>
|
||||||
|
<Select
|
||||||
|
mode="multiple"
|
||||||
|
disabled
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
placeholder="Please select"
|
||||||
|
defaultValue={'chi_sim'}
|
||||||
|
options={options}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</SettingRow>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user