feat(websearch): enhance web search provider settings and localization
- Updated web search provider settings to include API key and free status indicators. - Improved localization for English, Japanese, Russian, Chinese, and Taiwanese languages to reflect new API key and free status fields. - Refactored web search provider management to prevent duplicates and streamline provider addition during state migration. - Adjusted UI components to conditionally render based on provider type, enhancing user experience.
This commit is contained in:
parent
f9c6bddae5
commit
efcffbaa30
@ -25,6 +25,7 @@ export const useDefaultWebSearchProvider = () => {
|
||||
|
||||
export const useWebSearchProviders = () => {
|
||||
const providers = useAppSelector((state) => state.websearch.providers)
|
||||
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
return {
|
||||
@ -45,6 +46,7 @@ export const useWebSearchProvider = (id: string) => {
|
||||
const providers = useAppSelector((state) => state.websearch.providers)
|
||||
const provider = providers.find((provider) => provider.id === id)
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
if (!provider) {
|
||||
throw new Error(`Web search provider with id ${id} not found`)
|
||||
}
|
||||
|
||||
@ -1301,7 +1301,9 @@
|
||||
},
|
||||
"title": "Web Search",
|
||||
"overwrite": "Override search service",
|
||||
"overwrite_tooltip": "Force use search service instead of LLM"
|
||||
"overwrite_tooltip": "Force use search service instead of LLM",
|
||||
"apikey": "API key",
|
||||
"free": "Free"
|
||||
},
|
||||
"quickPhrase": {
|
||||
"title": "Quick Phrases",
|
||||
|
||||
@ -1300,7 +1300,9 @@
|
||||
},
|
||||
"title": "ウェブ検索",
|
||||
"overwrite": "サービス検索を上書き",
|
||||
"overwrite_tooltip": "大規模言語モデルではなく、サービス検索を使用する"
|
||||
"overwrite_tooltip": "大規模言語モデルではなく、サービス検索を使用する",
|
||||
"apikey": "API キー",
|
||||
"free": "無料"
|
||||
},
|
||||
"general.auto_check_update.title": "自動更新チェックを有効にする",
|
||||
"quickPhrase": {
|
||||
|
||||
@ -1300,7 +1300,9 @@
|
||||
},
|
||||
"title": "Поиск в Интернете",
|
||||
"overwrite": "Переопределить поставщика поиска",
|
||||
"overwrite_tooltip": "Использовать поставщика поиска вместо LLM"
|
||||
"overwrite_tooltip": "Использовать поставщика поиска вместо LLM",
|
||||
"apikey": "Ключ API",
|
||||
"free": "Бесплатно"
|
||||
},
|
||||
"general.auto_check_update.title": "Включить автоматическую проверку обновлений",
|
||||
"quickPhrase": {
|
||||
|
||||
@ -1301,7 +1301,9 @@
|
||||
"description": "Tavily 是一个为 AI 代理量身定制的搜索引擎,提供实时、准确的结果、智能查询建议和深入的研究能力",
|
||||
"title": "Tavily"
|
||||
},
|
||||
"title": "网络搜索"
|
||||
"title": "网络搜索",
|
||||
"apikey": "API 密钥",
|
||||
"free": "免费"
|
||||
},
|
||||
"quickPhrase": {
|
||||
"title": "快捷短语",
|
||||
|
||||
@ -1300,7 +1300,9 @@
|
||||
},
|
||||
"title": "網路搜尋",
|
||||
"overwrite": "覆蓋搜尋服務商",
|
||||
"overwrite_tooltip": "強制使用搜尋服務商而不是大語言模型進行搜尋"
|
||||
"overwrite_tooltip": "強制使用搜尋服務商而不是大語言模型進行搜尋",
|
||||
"apikey": "API 金鑰",
|
||||
"free": "免費"
|
||||
},
|
||||
"general.auto_check_update.title": "啟用自動更新檢查",
|
||||
"quickPhrase": {
|
||||
|
||||
@ -117,7 +117,6 @@ const WebSearchProviderSetting: FC<Props> = ({ provider: _provider }) => {
|
||||
<SettingTitle>
|
||||
<Flex align="center" gap={8}>
|
||||
<ProviderLogo shape="square" src={getWebSearchProviderLogo(provider.id)} size={16} />
|
||||
|
||||
<ProviderName> {provider.name}</ProviderName>
|
||||
{officialWebsite && webSearchProviderConfig?.websites && (
|
||||
<Link target="_blank" href={webSearchProviderConfig.websites.official}>
|
||||
@ -156,7 +155,6 @@ const WebSearchProviderSetting: FC<Props> = ({ provider: _provider }) => {
|
||||
</SettingHelpTextRow>
|
||||
</>
|
||||
)}
|
||||
|
||||
{hasObjectKey(provider, 'apiHost') && (
|
||||
<>
|
||||
<SettingSubtitle style={{ marginTop: 5, marginBottom: 10 }}>
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useDefaultWebSearchProvider, useWebSearchProviders } from '@renderer/hooks/useWebSearchProviders'
|
||||
import { defaultWebSearchProviders } from '@renderer/store/websearch'
|
||||
import { WebSearchProvider } from '@renderer/types'
|
||||
import { hasObjectKey } from '@renderer/utils'
|
||||
import { Select } from 'antd'
|
||||
import { FC, useEffect, useState } from 'react'
|
||||
import { FC, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { SettingContainer, SettingDivider, SettingGroup, SettingRow, SettingRowTitle, SettingTitle } from '..'
|
||||
@ -13,15 +12,13 @@ import BlacklistSettings from './BlacklistSettings'
|
||||
import WebSearchProviderSetting from './WebSearchProviderSetting'
|
||||
|
||||
const WebSearchSettings: FC = () => {
|
||||
const { providers, addWebSearchProvider } = useWebSearchProviders()
|
||||
const { providers } = useWebSearchProviders()
|
||||
const { provider: defaultProvider, setDefaultProvider } = useDefaultWebSearchProvider()
|
||||
const { t } = useTranslation()
|
||||
const [selectedProvider, setSelectedProvider] = useState<WebSearchProvider | undefined>(defaultProvider)
|
||||
const { theme: themeMode } = useTheme()
|
||||
|
||||
useEffect(() => {
|
||||
defaultWebSearchProviders.map((p) => addWebSearchProvider(p))
|
||||
})
|
||||
const isLocalProvider = selectedProvider?.id.startsWith('local')
|
||||
|
||||
function updateSelectedWebSearchProvider(providerId: string) {
|
||||
const provider = providers.find((p) => p.id === providerId)
|
||||
@ -45,19 +42,19 @@ const WebSearchSettings: FC = () => {
|
||||
style={{ width: '200px' }}
|
||||
onChange={(value: string) => updateSelectedWebSearchProvider(value)}
|
||||
placeholder={t('settings.websearch.search_provider_placeholder')}
|
||||
options={providers
|
||||
.toSorted((p1, p2) => p1.name.localeCompare(p2.name))
|
||||
.map((p) => ({
|
||||
value: p.id,
|
||||
label: `${p.name} (${hasObjectKey(p, 'apiKey') ? 'ApiKey' : 'Free'})`
|
||||
}))}
|
||||
options={providers.map((p) => ({
|
||||
value: p.id,
|
||||
label: `${p.name} (${hasObjectKey(p, 'apiKey') ? t('settings.websearch.apikey') : t('settings.websearch.free')})`
|
||||
}))}
|
||||
/>
|
||||
</div>
|
||||
</SettingRow>
|
||||
</SettingGroup>
|
||||
<SettingGroup theme={themeMode}>
|
||||
{selectedProvider && <WebSearchProviderSetting provider={selectedProvider} />}
|
||||
</SettingGroup>
|
||||
{!isLocalProvider && (
|
||||
<SettingGroup theme={themeMode}>
|
||||
{selectedProvider && <WebSearchProviderSetting provider={selectedProvider} />}
|
||||
</SettingGroup>
|
||||
)}
|
||||
<BasicSettings />
|
||||
<BlacklistSettings />
|
||||
</SettingContainer>
|
||||
|
||||
@ -83,7 +83,7 @@ export default class LocalSearchProvider extends BaseWebSearchProvider {
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
protected parseValidUrls(htmlContent: string): SearchItem[] {
|
||||
protected parseValidUrls(_htmlContent: string): SearchItem[] {
|
||||
throw new Error('Not implemented')
|
||||
}
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ const persistedReducer = persistReducer(
|
||||
{
|
||||
key: 'cherry-studio',
|
||||
storage,
|
||||
version: 94,
|
||||
version: 95,
|
||||
blacklist: ['runtime', 'messages'],
|
||||
migrate
|
||||
},
|
||||
|
||||
@ -14,6 +14,7 @@ import { RootState } from '.'
|
||||
import { INITIAL_PROVIDERS, moveProvider } from './llm'
|
||||
import { mcpSlice } from './mcp'
|
||||
import { DEFAULT_SIDEBAR_ICONS, initialState as settingsInitialState } from './settings'
|
||||
import { defaultWebSearchProviders } from './websearch'
|
||||
|
||||
// remove logo base64 data to reduce the size of the state
|
||||
function removeMiniAppIconsFromState(state: RootState) {
|
||||
@ -52,6 +53,17 @@ function addProvider(state: RootState, id: string) {
|
||||
}
|
||||
}
|
||||
|
||||
function addWebSearchProvider(state: RootState, id: string) {
|
||||
if (state.websearch && state.websearch.providers) {
|
||||
if (!state.websearch.providers.find((p) => p.id === id)) {
|
||||
const provider = defaultWebSearchProviders.find((p) => p.id === id)
|
||||
if (provider) {
|
||||
state.websearch.providers.push(provider)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const migrateConfig = {
|
||||
'2': (state: RootState) => {
|
||||
try {
|
||||
@ -985,21 +997,9 @@ const migrateConfig = {
|
||||
},
|
||||
'77': (state: RootState) => {
|
||||
try {
|
||||
addWebSearchProvider(state, 'searxng')
|
||||
addWebSearchProvider(state, 'exa')
|
||||
if (state.websearch) {
|
||||
if (!state.websearch.providers.find((p) => p.id === 'searxng')) {
|
||||
state.websearch.providers.push(
|
||||
{
|
||||
id: 'searxng',
|
||||
name: 'Searxng',
|
||||
apiHost: ''
|
||||
},
|
||||
{
|
||||
id: 'exa',
|
||||
name: 'Exa',
|
||||
apiKey: ''
|
||||
}
|
||||
)
|
||||
}
|
||||
state.websearch.providers.forEach((p) => {
|
||||
// @ts-ignore eslint-disable-next-line
|
||||
delete p.enabled
|
||||
@ -1192,6 +1192,16 @@ const migrateConfig = {
|
||||
} catch (error) {
|
||||
return state
|
||||
}
|
||||
},
|
||||
'95': (state: RootState) => {
|
||||
try {
|
||||
addWebSearchProvider(state, 'local-google')
|
||||
addWebSearchProvider(state, 'local-bing')
|
||||
addWebSearchProvider(state, 'local-baidu')
|
||||
return state
|
||||
} catch (error) {
|
||||
return state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user