mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-09 06:49:02 +08:00
refactor(ocr): improve ocr provider handling and error states
- Add ListOcrProvidersQuery type for better type safety - Update useOcrProviders hook to accept query params and handle undefined data - Improve error handling and loading states in OcrImageSettings component - Memoize filtered image providers for better performance
This commit is contained in:
parent
389dfc08f6
commit
a2e628d7e9
@ -4,6 +4,7 @@ import type {
|
|||||||
CreateOcrProviderRequest,
|
CreateOcrProviderRequest,
|
||||||
CreateOcrProviderResponse,
|
CreateOcrProviderResponse,
|
||||||
GetOcrProviderResponse,
|
GetOcrProviderResponse,
|
||||||
|
ListOcrProvidersQuery,
|
||||||
ListOcrProvidersResponse,
|
ListOcrProvidersResponse,
|
||||||
OcrProviderId,
|
OcrProviderId,
|
||||||
PatchOcrProviderRequest,
|
PatchOcrProviderRequest,
|
||||||
@ -360,7 +361,7 @@ export interface ApiSchemas {
|
|||||||
|
|
||||||
'/ocr/providers': {
|
'/ocr/providers': {
|
||||||
GET: {
|
GET: {
|
||||||
query: { registered?: boolean }
|
query: ListOcrProvidersQuery
|
||||||
response: ListOcrProvidersResponse
|
response: ListOcrProvidersResponse
|
||||||
}
|
}
|
||||||
POST: {
|
POST: {
|
||||||
|
|||||||
@ -7,10 +7,10 @@ import { useOcrProviders } from './useOcrProviders'
|
|||||||
|
|
||||||
export const useOcrImageProvider = () => {
|
export const useOcrImageProvider = () => {
|
||||||
const { providers, loading, error } = useOcrProviders()
|
const { providers, loading, error } = useOcrProviders()
|
||||||
const imageProviders: ImageOcrProvider[] = providers.filter((p) => isImageOcrProvider(p))
|
const imageProviders: ImageOcrProvider[] | undefined = providers?.filter((p) => isImageOcrProvider(p))
|
||||||
const [imageProviderId, setImageProviderId] = usePreference('ocr.settings.image_provider_id')
|
const [imageProviderId, setImageProviderId] = usePreference('ocr.settings.image_provider_id')
|
||||||
const imageProvider = useMemo(() => {
|
const imageProvider = useMemo(() => {
|
||||||
return imageProviders.find((p) => p.id === imageProviderId)
|
return imageProviders?.find((p) => p.id === imageProviderId)
|
||||||
}, [imageProviderId, imageProviders])
|
}, [imageProviderId, imageProviders])
|
||||||
return { imageProvider, loading, error, setImageProviderId }
|
return { imageProvider, loading, error, imageProviderId, setImageProviderId }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,23 +1,17 @@
|
|||||||
import { useQuery } from '@data/hooks/useDataApi'
|
import { useQuery } from '@data/hooks/useDataApi'
|
||||||
import { getBuiltinOcrProviderLabel } from '@renderer/i18n/label'
|
import { getBuiltinOcrProviderLabel } from '@renderer/i18n/label'
|
||||||
import type { OcrProvider } from '@renderer/types'
|
import type { ListOcrProvidersQuery, OcrProvider } from '@renderer/types'
|
||||||
import { isBuiltinOcrProvider } from '@renderer/types'
|
import { isBuiltinOcrProvider } from '@renderer/types'
|
||||||
import { BUILTIN_OCR_PROVIDERS } from '@shared/config/ocr'
|
|
||||||
import { useMemo } from 'react'
|
|
||||||
|
|
||||||
export const useOcrProviders = () => {
|
export const useOcrProviders = (query?: ListOcrProvidersQuery) => {
|
||||||
const { data: validProviderIds, loading, error } = useQuery('/ocr/providers')
|
const { data, loading, error } = useQuery('/ocr/providers', { query })
|
||||||
const providers = useMemo(
|
|
||||||
() => BUILTIN_OCR_PROVIDERS.filter((p) => validProviderIds?.includes(p.id)),
|
|
||||||
[validProviderIds]
|
|
||||||
)
|
|
||||||
|
|
||||||
const getOcrProviderName = (p: OcrProvider) => {
|
const getOcrProviderName = (p: OcrProvider) => {
|
||||||
return isBuiltinOcrProvider(p) ? getBuiltinOcrProviderLabel(p.id) : p.name
|
return isBuiltinOcrProvider(p) ? getBuiltinOcrProviderLabel(p.id) : p.name
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
providers,
|
providers: data?.data,
|
||||||
loading,
|
loading,
|
||||||
error,
|
error,
|
||||||
getOcrProviderName
|
getOcrProviderName
|
||||||
|
|||||||
@ -17,10 +17,10 @@ const logger = loggerService.withContext('OcrImageSettings')
|
|||||||
|
|
||||||
const OcrImageSettings = () => {
|
const OcrImageSettings = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { providers, loading, error, getOcrProviderName } = useOcrProviders()
|
const { providers, loading, error, getOcrProviderName } = useOcrProviders({ registered: true })
|
||||||
const { imageProvider, setImageProviderId } = useOcrImageProvider()
|
const { imageProvider, setImageProviderId, imageProviderId } = useOcrImageProvider()
|
||||||
|
|
||||||
const imageProviders = providers.filter((p) => isImageOcrProvider(p))
|
const imageProviders = useMemo(() => providers?.filter((p) => isImageOcrProvider(p)) ?? [], [providers])
|
||||||
|
|
||||||
const setImageProvider = (id: string) => {
|
const setImageProvider = (id: string) => {
|
||||||
const provider = imageProviders.find((p) => p.id === id)
|
const provider = imageProviders.find((p) => p.id === id)
|
||||||
@ -43,29 +43,48 @@ const OcrImageSettings = () => {
|
|||||||
|
|
||||||
const isSystem = imageProvider?.id === BuiltinOcrProviderIdMap.system
|
const isSystem = imageProvider?.id === BuiltinOcrProviderIdMap.system
|
||||||
|
|
||||||
if (!imageProvider) {
|
const content = useMemo(() => {
|
||||||
return <Alert color="danger" title={t('ocr.error.provider.not_found')} />
|
if (loading) {
|
||||||
}
|
return <Skeleton className="h-full w-50" />
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<Alert
|
||||||
|
color="danger"
|
||||||
|
title={t('ocr.provider.get.error.failed', { provider: imageProviderId })}
|
||||||
|
description={getErrorMessage(error)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!imageProvider) {
|
||||||
|
return <Alert color="danger" title={t('ocr.error.provider.not_found')} />
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{!platformSupport && isSystem && <ErrorTag message={t('settings.tool.ocr.error.not_system')} />}
|
||||||
|
{!loading && !error && (
|
||||||
|
<Select
|
||||||
|
value={imageProvider.id}
|
||||||
|
className="w-50"
|
||||||
|
onChange={(id: string) => setImageProvider(id)}
|
||||||
|
options={options}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{!loading && error && (
|
||||||
|
<Alert color="danger" title={t('ocr.error.provider.get_providers')} description={getErrorMessage(error)} />
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SettingRow>
|
<SettingRow>
|
||||||
<SettingRowTitle>{t('settings.tool.ocr.image_provider')}</SettingRowTitle>
|
<SettingRowTitle>{t('settings.tool.ocr.image_provider')}</SettingRowTitle>
|
||||||
<div className="flex items-center gap-2 self-stretch">
|
<div className="flex items-center gap-2 self-stretch">{content}</div>
|
||||||
{!platformSupport && isSystem && <ErrorTag message={t('settings.tool.ocr.error.not_system')} />}
|
|
||||||
{loading && <Skeleton className="h-full w-50" />}
|
|
||||||
{!loading && !error && (
|
|
||||||
<Select
|
|
||||||
value={imageProvider.id}
|
|
||||||
className="w-50"
|
|
||||||
onChange={(id: string) => setImageProvider(id)}
|
|
||||||
options={options}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{!loading && error && (
|
|
||||||
<Alert color="danger" title={t('ocr.error.provider.get_providers')} description={getErrorMessage(error)} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</SettingRow>
|
</SettingRow>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -268,6 +268,8 @@ const TimestampExtendShape = {
|
|||||||
|
|
||||||
const DbOcrProviderSchema = OcrProviderSchema.extend(TimestampExtendShape)
|
const DbOcrProviderSchema = OcrProviderSchema.extend(TimestampExtendShape)
|
||||||
|
|
||||||
|
export type ListOcrProvidersQuery = { registered?: boolean }
|
||||||
|
|
||||||
export const ListOcrProvidersResponseSchema = z.object({
|
export const ListOcrProvidersResponseSchema = z.object({
|
||||||
data: z.array(DbOcrProviderSchema)
|
data: z.array(DbOcrProviderSchema)
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user