Merge pull request #5045 from h3poteto/iss-4794/settings
refs #4794 Add proxy settings
This commit is contained in:
commit
5137bc9f32
|
@ -173,12 +173,25 @@
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"title": "Settings",
|
"title": "Settings",
|
||||||
|
"cancel": "Cancel",
|
||||||
|
"save": "Save",
|
||||||
"language": "Language",
|
"language": "Language",
|
||||||
"font_size": "Font size",
|
"font_size": "Font size",
|
||||||
"mode": "Color mode",
|
"mode": "Color mode",
|
||||||
"dark_mode": "Dark mode",
|
"dark_mode": "Dark mode",
|
||||||
"light_mode": "Light mode",
|
"light_mode": "Light mode",
|
||||||
"theme": "Color theme"
|
"theme": "Color theme",
|
||||||
|
"proxy": {
|
||||||
|
"title": "Proxy",
|
||||||
|
"no": "No proxy",
|
||||||
|
"os": "Use system proxy settings",
|
||||||
|
"manual": "Manual proxy configuration",
|
||||||
|
"protocol": "Protocol",
|
||||||
|
"http": "http",
|
||||||
|
"socks": "socks",
|
||||||
|
"host": "Host",
|
||||||
|
"port": "Port"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"thirdparty": {
|
"thirdparty": {
|
||||||
"title": "Third-party licenses"
|
"title": "Third-party licenses"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { app, ipcMain, shell, IpcMainInvokeEvent } from 'electron'
|
import { app, ipcMain, shell, IpcMainInvokeEvent, BrowserWindow } from 'electron'
|
||||||
import serve from 'electron-serve'
|
import serve from 'electron-serve'
|
||||||
import { createWindow } from './helpers'
|
import { createWindow } from './helpers'
|
||||||
|
|
||||||
|
@ -11,6 +11,8 @@ if (isProd) {
|
||||||
app.setPath('userData', `${app.getPath('userData')} (development)`)
|
app.setPath('userData', `${app.getPath('userData')} (development)`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let main: BrowserWindow = null
|
||||||
|
|
||||||
;(async () => {
|
;(async () => {
|
||||||
await app.whenReady()
|
await app.whenReady()
|
||||||
|
|
||||||
|
@ -24,6 +26,7 @@ if (isProd) {
|
||||||
preload: path.join(__dirname, 'preload.js')
|
preload: path.join(__dirname, 'preload.js')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
main = mainWindow
|
||||||
|
|
||||||
if (isProd) {
|
if (isProd) {
|
||||||
await mainWindow.loadURL('app://./')
|
await mainWindow.loadURL('app://./')
|
||||||
|
@ -45,3 +48,24 @@ ipcMain.on('message', async (event, arg) => {
|
||||||
ipcMain.handle('open-browser', (_event: IpcMainInvokeEvent, url: string) => {
|
ipcMain.handle('open-browser', (_event: IpcMainInvokeEvent, url: string) => {
|
||||||
shell.openExternal(url)
|
shell.openExternal(url)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ipcMain.handle('set-proxy', (_event: IpcMainInvokeEvent, data: any) => {
|
||||||
|
if (main === null) return
|
||||||
|
const { mode, protocol, host, port } = data
|
||||||
|
switch (mode) {
|
||||||
|
case 'os':
|
||||||
|
console.log('Using system proxy')
|
||||||
|
main.webContents.session.setProxy({ mode: 'system' })
|
||||||
|
break
|
||||||
|
case 'manual':
|
||||||
|
console.log(`Using proxy: ${protocol}=${host}:${port}`)
|
||||||
|
main.webContents.session.setProxy({
|
||||||
|
proxyRules: `${protocol}=${host}:${port}`
|
||||||
|
})
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
console.log('No proxy configuration')
|
||||||
|
main.webContents.session.setProxy({ mode: 'direct' })
|
||||||
|
break
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { localeType } from '@/provider/i18n'
|
import { localeType } from '@/provider/i18n'
|
||||||
import { Dialog, DialogBody, DialogHeader, Input, Option, Radio, Select, Typography } from '@material-tailwind/react'
|
import { Button, Dialog, DialogBody, DialogFooter, DialogHeader, Input, Option, Radio, Select, Typography } from '@material-tailwind/react'
|
||||||
import { ChangeEvent, useEffect, useState } from 'react'
|
import { ChangeEvent, useEffect, useState } from 'react'
|
||||||
import { FormattedMessage } from 'react-intl'
|
import { FormattedMessage, useIntl } from 'react-intl'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
opened: boolean
|
opened: boolean
|
||||||
|
@ -59,11 +59,18 @@ const themes = [
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
type ProxyValue = 'no' | 'os' | 'manual'
|
||||||
|
|
||||||
export default function Settings(props: Props) {
|
export default function Settings(props: Props) {
|
||||||
const [language, setLanguage] = useState<localeType>('en')
|
const [language, setLanguage] = useState<localeType>('en')
|
||||||
const [fontSize, setFontSize] = useState<number>(16)
|
const [fontSize, setFontSize] = useState<number>(16)
|
||||||
const [theme, setTheme] = useState<string>('theme-blue')
|
const [theme, setTheme] = useState<string>('theme-blue')
|
||||||
const [isDark, setIsDark] = useState(false)
|
const [isDark, setIsDark] = useState(false)
|
||||||
|
const [proxy, setProxy] = useState<ProxyValue>('no')
|
||||||
|
const [proxyProtocol, setProxyProtocol] = useState<string | null>(null)
|
||||||
|
const [proxyHost, setProxyHost] = useState<string | null>(null)
|
||||||
|
const [proxyPort, setProxyPort] = useState<string | null>(null)
|
||||||
|
const { formatMessage } = useIntl()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (typeof localStorage !== 'undefined') {
|
if (typeof localStorage !== 'undefined') {
|
||||||
|
@ -79,6 +86,22 @@ export default function Settings(props: Props) {
|
||||||
} else {
|
} else {
|
||||||
setIsDark(false)
|
setIsDark(false)
|
||||||
}
|
}
|
||||||
|
const proxyMode = localStorage.getItem('proxyMode')
|
||||||
|
if (proxyMode) {
|
||||||
|
setProxy(proxyMode as ProxyValue)
|
||||||
|
}
|
||||||
|
const proxyProtocol = localStorage.getItem('proxyProtocol')
|
||||||
|
if (proxyProtocol) {
|
||||||
|
setProxyProtocol(proxyProtocol)
|
||||||
|
}
|
||||||
|
const proxyHost = localStorage.getItem('proxyHost')
|
||||||
|
if (proxyHost) {
|
||||||
|
setProxyHost(proxyHost)
|
||||||
|
}
|
||||||
|
const proxyPort = localStorage.getItem('proxyPort')
|
||||||
|
if (proxyPort) {
|
||||||
|
setProxyPort(proxyPort)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
@ -118,6 +141,17 @@ export default function Settings(props: Props) {
|
||||||
props.reloadSettings()
|
props.reloadSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const save = () => {
|
||||||
|
if (typeof localStorage !== 'undefined') {
|
||||||
|
localStorage.setItem('proxyMode', proxy)
|
||||||
|
localStorage.setItem('proxyProtocol', proxyProtocol)
|
||||||
|
localStorage.setItem('proxyHost', proxyHost)
|
||||||
|
localStorage.setItem('proxyPort', proxyPort)
|
||||||
|
}
|
||||||
|
props.reloadSettings()
|
||||||
|
props.close()
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={props.opened} handler={props.close} size="sm">
|
<Dialog open={props.opened} handler={props.close} size="sm">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
|
@ -190,8 +224,86 @@ export default function Settings(props: Props) {
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="mb-2">
|
||||||
|
<Typography>
|
||||||
|
<FormattedMessage id="settings.proxy.title" />
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<Radio
|
||||||
|
name="proxy"
|
||||||
|
color="blue"
|
||||||
|
label={<FormattedMessage id="settings.proxy.no" />}
|
||||||
|
defaultChecked={proxy === 'no'}
|
||||||
|
onClick={() => setProxy('no')}
|
||||||
|
/>
|
||||||
|
<Radio
|
||||||
|
name="proxy"
|
||||||
|
color="blue"
|
||||||
|
label={<FormattedMessage id="settings.proxy.os" />}
|
||||||
|
defaultChecked={proxy === 'os'}
|
||||||
|
onClick={() => setProxy('os')}
|
||||||
|
/>
|
||||||
|
<Radio
|
||||||
|
name="proxy"
|
||||||
|
color="blue"
|
||||||
|
label={
|
||||||
|
<div>
|
||||||
|
<FormattedMessage id="settings.proxy.manual" />
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<div className="w-1/5">
|
||||||
|
<Select
|
||||||
|
label={formatMessage({ id: 'settings.proxy.protocol' })}
|
||||||
|
containerProps={{
|
||||||
|
className: '!min-w-2'
|
||||||
|
}}
|
||||||
|
value={proxyProtocol}
|
||||||
|
onChange={val => setProxyProtocol(val)}
|
||||||
|
>
|
||||||
|
<Option value="http">
|
||||||
|
<FormattedMessage id="settings.proxy.http" />
|
||||||
|
</Option>
|
||||||
|
<Option value="socks">
|
||||||
|
<FormattedMessage id="settings.proxy.socks" />
|
||||||
|
</Option>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="w-3/5">
|
||||||
|
<Input
|
||||||
|
defaultValue={proxyHost}
|
||||||
|
label={formatMessage({ id: 'settings.proxy.host' })}
|
||||||
|
onChange={e => setProxyHost(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/5">
|
||||||
|
<Input
|
||||||
|
defaultValue={proxyPort}
|
||||||
|
label={formatMessage({ id: 'settings.proxy.port' })}
|
||||||
|
containerProps={{
|
||||||
|
className: '!min-w-2'
|
||||||
|
}}
|
||||||
|
onChange={e => setProxyPort(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
defaultChecked={proxy === 'manual'}
|
||||||
|
onClick={() => setProxy('manual')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</DialogBody>
|
</DialogBody>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button variant="text" color="red" onClick={props.close}>
|
||||||
|
<FormattedMessage id="settings.cancel" />
|
||||||
|
</Button>
|
||||||
|
<Button variant="gradient" color="blue" onClick={save}>
|
||||||
|
<FormattedMessage id="settings.save" />
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {
|
||||||
import Thirdparty from '../Thirdparty'
|
import Thirdparty from '../Thirdparty'
|
||||||
import { useUnreads } from '@/provider/unreads'
|
import { useUnreads } from '@/provider/unreads'
|
||||||
import { useAccounts } from '@/provider/accounts'
|
import { useAccounts } from '@/provider/accounts'
|
||||||
|
import { invoke } from '@/utils/invoke'
|
||||||
|
|
||||||
type LayoutProps = {
|
type LayoutProps = {
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
|
@ -128,12 +129,16 @@ export default function Layout({ children }: LayoutProps) {
|
||||||
setTheme(t)
|
setTheme(t)
|
||||||
}
|
}
|
||||||
const dark = localStorage.getItem('color-mode')
|
const dark = localStorage.getItem('color-mode')
|
||||||
console.log(dark)
|
|
||||||
if (dark && dark === 'dark') {
|
if (dark && dark === 'dark') {
|
||||||
setIsDark(true)
|
setIsDark(true)
|
||||||
} else {
|
} else {
|
||||||
setIsDark(false)
|
setIsDark(false)
|
||||||
}
|
}
|
||||||
|
const proxyMode = localStorage.getItem('proxyMode')
|
||||||
|
const proxyProtocol = localStorage.getItem('proxyProtocol')
|
||||||
|
const proxyHost = localStorage.getItem('proxyHost')
|
||||||
|
const proxyPort = localStorage.getItem('proxyPort')
|
||||||
|
invoke('set-proxy', { mode: proxyMode, protocol: proxyProtocol, host: proxyHost, port: proxyPort })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,9 @@ export function invoke(event: string, data: any) {
|
||||||
case 'open-browser':
|
case 'open-browser':
|
||||||
window.open(data, '_blank').focus()
|
window.open(data, '_blank').focus()
|
||||||
return
|
return
|
||||||
|
case 'set-proxy':
|
||||||
|
console.warn('Can not use proxy in this environment')
|
||||||
|
return
|
||||||
default:
|
default:
|
||||||
console.error(`Unknown event: ${event}`)
|
console.error(`Unknown event: ${event}`)
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue