Merge pull request #5045 from h3poteto/iss-4794/settings

refs #4794 Add proxy settings
This commit is contained in:
AkiraFukushima 2024-09-11 00:35:54 +09:00 committed by GitHub
commit 5137bc9f32
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 162 additions and 5 deletions

View File

@ -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"

View File

@ -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
}
})

View File

@ -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>
) )
} }

View File

@ -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 })
} }
} }

View File

@ -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