feat: added proxy settings and handling functionality

This commit is contained in:
kangfenmao 2024-11-18 14:05:17 +08:00
parent 1b8a3885f7
commit 7342a0afef
11 changed files with 118 additions and 17 deletions

View File

@ -26,7 +26,21 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
filesPath: path.join(app.getPath('userData'), 'Data', 'Files')
}))
ipcMain.handle('app:proxy', (_, proxy: string) => session.defaultSession.setProxy(proxy ? { proxyRules: proxy } : {}))
ipcMain.handle('app:proxy', async (_, proxy: string) => {
if (proxy === 'system') {
await session.defaultSession.setProxy({ mode: 'system' })
const webviewSession = session.fromPartition('persist:webview')
await webviewSession.setProxy({ mode: 'system' })
} else if (proxy) {
await session.defaultSession.setProxy({ proxyRules: proxy })
const webviewSession = session.fromPartition('persist:webview')
await webviewSession.setProxy({ proxyRules: proxy })
} else {
await session.defaultSession.setProxy({})
const webviewSession = session.fromPartition('persist:webview')
await webviewSession.setProxy({})
}
})
ipcMain.handle('app:reload', () => mainWindow.reload())
ipcMain.handle('open:website', (_, url: string) => shell.openExternal(url))

View File

@ -114,7 +114,15 @@ const PopupContainer: React.FC<Props> = ({ app, resolve }) => {
<BeatLoader color="var(--color-text-2)" size="10" style={{ marginTop: 15 }} />
</EmptyView>
)}
{opened && <webview src={app.url} ref={webviewRef} style={WebviewStyle} allowpopups={'true' as any} />}
{opened && (
<webview
src={app.url}
ref={webviewRef}
style={WebviewStyle}
allowpopups={'true' as any}
partition="persist:webview"
/>
)}
</Drawer>
)
}

View File

@ -14,7 +14,7 @@ import { useSettings } from './useSettings'
export function useAppInit() {
const dispatch = useAppDispatch()
const { proxyUrl, language, windowStyle, manualUpdateCheck } = useSettings()
const { proxyUrl, language, windowStyle, manualUpdateCheck, proxyMode } = useSettings()
const { minappShow } = useRuntime()
const { setDefaultModel, setTopicNamingModel, setTranslateModel } = useDefaultModel()
const avatar = useLiveQuery(() => db.settings.get('image://avatar'))
@ -35,8 +35,14 @@ export function useAppInit() {
}, [])
useEffect(() => {
proxyUrl && window.api.setProxy(proxyUrl)
}, [proxyUrl])
if (proxyMode === 'system') {
window.api.setProxy('system')
} else if (proxyMode === 'custom') {
proxyUrl && window.api.setProxy(proxyUrl)
} else {
window.api.setProxy('')
}
}, [proxyUrl, proxyMode])
useEffect(() => {
i18n.changeLanguage(language || navigator.language || 'en-US')

View File

@ -382,6 +382,15 @@
"add.name.placeholder": "Example: OpenAI",
"add.type": "Provider Type",
"no_models": "Please add models first before checking the API connection"
},
"proxy": {
"title": "Proxy Settings",
"mode": {
"title": "Proxy Mode",
"system": "System Proxy",
"custom": "Custom Proxy",
"none": "No Proxy"
}
}
},
"translate": {

View File

@ -382,6 +382,15 @@
"add.name.placeholder": "Пример: OpenAI",
"add.type": "Тип провайдера",
"no_models": "Пожалуйста, добавьте модели перед проверкой соединения с API"
},
"proxy": {
"title": "Настройки прокси",
"mode": {
"title": "Режим прокси",
"system": "Системный прокси",
"custom": "Пользовательский прокси",
"none": "Не использовать прокси"
}
}
},
"translate": {

View File

@ -370,6 +370,15 @@
"add.name.placeholder": "例如 OpenAI",
"add.type": "提供商类型",
"no_models": "请先添加模型再检查 API 连接"
},
"proxy": {
"title": "代理设置",
"mode": {
"title": "代理模式",
"system": "系统代理",
"custom": "自定义代理",
"none": "不使用代理"
}
}
},
"translate": {

View File

@ -370,6 +370,15 @@
"add.name.placeholder": "例如OpenAI",
"add.type": "提供商類型",
"no_models": "請先添加模型再檢查 API 連接"
},
"proxy": {
"title": "代理設定",
"mode": {
"title": "代理模式",
"system": "系統代理",
"custom": "自定義代理",
"none": "不使用代理"
}
}
},
"translate": {

View File

@ -3,7 +3,7 @@ import { useSettings } from '@renderer/hooks/useSettings'
import i18n from '@renderer/i18n'
import { useAppDispatch } from '@renderer/store'
import { setLanguage } from '@renderer/store/settings'
import { setProxyUrl as _setProxyUrl } from '@renderer/store/settings'
import { setProxyMode, setProxyUrl as _setProxyUrl } from '@renderer/store/settings'
import { LanguageVarious, ThemeMode } from '@renderer/types'
import { isValidProxyUrl } from '@renderer/utils'
import { Input, Select, Space, Switch } from 'antd'
@ -21,7 +21,8 @@ const GeneralSettings: FC = () => {
setTray,
tray,
windowStyle,
setWindowStyle
setWindowStyle,
proxyMode: storeProxyMode
} = useSettings()
const [proxyUrl, setProxyUrl] = useState<string | undefined>(storeProxyUrl)
@ -50,6 +51,23 @@ const GeneralSettings: FC = () => {
window.api.setProxy(proxyUrl)
}
const proxyModeOptions = [
{ value: 'system', label: t('settings.proxy.mode.system') },
{ value: 'custom', label: t('settings.proxy.mode.custom') },
{ value: 'none', label: t('settings.proxy.mode.none') }
]
const onProxyModeChange = (mode: 'system' | 'custom' | 'none') => {
dispatch(setProxyMode(mode))
if (mode === 'system') {
window.api.setProxy('system')
dispatch(_setProxyUrl(undefined))
} else if (mode === 'none') {
window.api.setProxy(undefined)
dispatch(_setProxyUrl(undefined))
}
}
const languagesOptions: { value: LanguageVarious; label: string; flag: string }[] = [
{ value: 'zh-CN', label: '中文', flag: '🇨🇳' },
{ value: 'zh-TW', label: '中文(繁体)', flag: '🇹🇼' },
@ -109,16 +127,25 @@ const GeneralSettings: FC = () => {
)}
<SettingDivider />
<SettingRow>
<SettingRowTitle>{t('settings.proxy.title')}</SettingRowTitle>
<Input
placeholder="socks5://127.0.0.1:6153"
value={proxyUrl}
onChange={(e) => setProxyUrl(e.target.value)}
style={{ width: 180 }}
onBlur={() => onSetProxyUrl()}
type="url"
/>
<SettingRowTitle>{t('settings.proxy.mode.title')}</SettingRowTitle>
<Select value={storeProxyMode} style={{ width: 180 }} onChange={onProxyModeChange} options={proxyModeOptions} />
</SettingRow>
{storeProxyMode === 'custom' && (
<>
<SettingDivider />
<SettingRow>
<SettingRowTitle>{t('settings.proxy.title')}</SettingRowTitle>
<Input
placeholder="socks5://127.0.0.1:6153"
value={proxyUrl}
onChange={(e) => setProxyUrl(e.target.value)}
style={{ width: 180 }}
onBlur={() => onSetProxyUrl()}
type="url"
/>
</SettingRow>
</>
)}
<SettingDivider />
<SettingRow>
<SettingRowTitle>{t('settings.tray.title')}</SettingRowTitle>

View File

@ -24,7 +24,7 @@ const persistedReducer = persistReducer(
{
key: 'cherry-studio',
storage,
version: 41,
version: 42,
blacklist: ['runtime'],
migrate
},

View File

@ -689,6 +689,10 @@ const migrateConfig = {
}
})
return state
},
'42': (state: RootState) => {
state.settings.proxyMode = state.settings.proxyUrl ? 'custom' : 'none'
return state
}
}

View File

@ -8,6 +8,7 @@ export interface SettingsState {
showTopics: boolean
sendMessageShortcut: SendMessageShortcut
language: LanguageVarious
proxyMode: 'system' | 'custom' | 'none'
proxyUrl?: string
userName: string
showMessageDivider: boolean
@ -39,6 +40,7 @@ const initialState: SettingsState = {
showTopics: true,
sendMessageShortcut: 'Enter',
language: navigator.language as LanguageVarious,
proxyMode: 'none',
proxyUrl: undefined,
userName: '',
showMessageDivider: false,
@ -86,6 +88,9 @@ const settingsSlice = createSlice({
setLanguage: (state, action: PayloadAction<LanguageVarious>) => {
state.language = action.payload
},
setProxyMode: (state, action: PayloadAction<'system' | 'custom' | 'none'>) => {
state.proxyMode = action.payload
},
setProxyUrl: (state, action: PayloadAction<string | undefined>) => {
state.proxyUrl = action.payload
},
@ -166,6 +171,7 @@ export const {
toggleShowTopics,
setSendMessageShortcut,
setLanguage,
setProxyMode,
setProxyUrl,
setUserName,
setShowMessageDivider,