feat: Add inline support and missing translations

This commit is contained in:
ezequielnick 2025-01-03 00:33:01 +08:00
parent bb6021877d
commit 9d84c6ac9b
6 changed files with 59 additions and 20 deletions

View File

@ -256,7 +256,7 @@ const ProfileItem: React.FC<Props> = (props) => {
await patchAppConfig({ profileDisplayDate: 'update' }) await patchAppConfig({ profileDisplayDate: 'update' })
}} }}
> >
{extra.expire ? dayjs.unix(extra.expire).format('YYYY-MM-DD') : '长期有效'} {extra.expire ? dayjs.unix(extra.expire).format('YYYY-MM-DD') : t('profiles.neverExpire')}
</Button> </Button>
) : ( ) : (
<Button <Button

View File

@ -15,13 +15,15 @@ import { MdEditDocument } from 'react-icons/md'
import dayjs from '@renderer/utils/dayjs' import dayjs from '@renderer/utils/dayjs'
import { calcTraffic } from '@renderer/utils/calc' import { calcTraffic } from '@renderer/utils/calc'
import { getHash } from '@renderer/utils/hash' import { getHash } from '@renderer/utils/hash'
import { useTranslation } from 'react-i18next'
const ProxyProvider: React.FC = () => { const ProxyProvider: React.FC = () => {
const { t } = useTranslation()
const [showDetails, setShowDetails] = useState({ const [showDetails, setShowDetails] = useState({
show: false, show: false,
path: '', path: '',
type: '', type: '',
title: '' title: '',
privderType: ''
}) })
useEffect(() => { useEffect(() => {
if (showDetails.title) { if (showDetails.title) {
@ -90,10 +92,11 @@ const ProxyProvider: React.FC = () => {
path={showDetails.path} path={showDetails.path}
type={showDetails.type} type={showDetails.type}
title={showDetails.title} title={showDetails.title}
onClose={() => setShowDetails({ show: false, path: '', type: '', title: '' })} privderType={showDetails.privderType}
onClose={() => setShowDetails({ show: false, path: '', type: '', title: '', privderType: '' })}
/> />
)} )}
<SettingItem title="代理集合" divider> <SettingItem title={t('resources.proxyProviders.title')} divider>
<Button <Button
size="sm" size="sm"
color="primary" color="primary"
@ -103,7 +106,7 @@ const ProxyProvider: React.FC = () => {
}) })
}} }}
> >
{t('resources.proxyProviders.updateAll')}
</Button> </Button>
</SettingItem> </SettingItem>
{providers.map((provider, index) => ( {providers.map((provider, index) => (
@ -124,12 +127,13 @@ const ProxyProvider: React.FC = () => {
</Button> */} </Button> */}
<Button <Button
isIconOnly isIconOnly
title={provider.vehicleType == 'File' ? '编辑' : '查看'} title={provider.vehicleType == 'File' ? t('common.editor.edit') : t('common.viewer.view')}
className="ml-2" className="ml-2"
size="sm" size="sm"
onPress={() => { onPress={() => {
setShowDetails({ setShowDetails({
show: false, show: false,
privderType: 'proxy-providers',
path: provider.name, path: provider.name,
type: provider.vehicleType, type: provider.vehicleType,
title: provider.name title: provider.name
@ -144,7 +148,7 @@ const ProxyProvider: React.FC = () => {
</Button> </Button>
<Button <Button
isIconOnly isIconOnly
title="更新" title={t('common.updater.update')}
className="ml-2" className="ml-2"
size="sm" size="sm"
onPress={() => { onPress={() => {
@ -169,7 +173,7 @@ const ProxyProvider: React.FC = () => {
<div className="h-[32px] leading-[32px] text-foreground-500"> <div className="h-[32px] leading-[32px] text-foreground-500">
{provider.subscriptionInfo.Expire {provider.subscriptionInfo.Expire
? dayjs.unix(provider.subscriptionInfo.Expire).format('YYYY-MM-DD') ? dayjs.unix(provider.subscriptionInfo.Expire).format('YYYY-MM-DD')
: '长期有效'} : t('profiles.neverExpire')}
</div> </div>
</SettingItem> </SettingItem>
)} )}

View File

@ -14,14 +14,17 @@ import { IoMdRefresh } from 'react-icons/io'
import { CgLoadbarDoc } from 'react-icons/cg' import { CgLoadbarDoc } from 'react-icons/cg'
import { MdEditDocument } from 'react-icons/md' import { MdEditDocument } from 'react-icons/md'
import dayjs from '@renderer/utils/dayjs' import dayjs from '@renderer/utils/dayjs'
import { useTranslation } from 'react-i18next'
const RuleProvider: React.FC = () => { const RuleProvider: React.FC = () => {
const { t } = useTranslation()
const [showDetails, setShowDetails] = useState({ const [showDetails, setShowDetails] = useState({
show: false, show: false,
path: '', path: '',
type: '', type: '',
title: '', title: '',
format: '' format: '',
privderType: ''
}) })
useEffect(() => { useEffect(() => {
if (showDetails.title) { if (showDetails.title) {
@ -89,10 +92,11 @@ const RuleProvider: React.FC = () => {
type={showDetails.type} type={showDetails.type}
title={showDetails.title} title={showDetails.title}
format={showDetails.format} format={showDetails.format}
onClose={() => setShowDetails({ show: false, path: '', type: '', title: '', format: '' })} privderType={showDetails.privderType}
onClose={() => setShowDetails({ show: false, path: '', type: '', title: '', format: '', privderType: '' })}
/> />
)} )}
<SettingItem title="规则集合" divider> <SettingItem title={t('resources.ruleProviders.title')} divider>
<Button <Button
size="sm" size="sm"
color="primary" color="primary"
@ -102,7 +106,7 @@ const RuleProvider: React.FC = () => {
}) })
}} }}
> >
{t('resources.ruleProviders.updateAll')}
</Button> </Button>
</SettingItem> </SettingItem>
{providers.map((provider, index) => ( {providers.map((provider, index) => (
@ -120,12 +124,13 @@ const RuleProvider: React.FC = () => {
{provider.format !== 'MrsRule' && ( {provider.format !== 'MrsRule' && (
<Button <Button
isIconOnly isIconOnly
title={provider.vehicleType == 'File' ? '编辑' : '查看'} title={provider.vehicleType == 'File' ? t('common.editor.edit') : t('common.viewer.view')}
className="ml-2" className="ml-2"
size="sm" size="sm"
onPress={() => { onPress={() => {
setShowDetails({ setShowDetails({
show: false, show: false,
privderType: 'rule-providers',
path: provider.name, path: provider.name,
type: provider.vehicleType, type: provider.vehicleType,
title: provider.name, title: provider.name,
@ -142,7 +147,7 @@ const RuleProvider: React.FC = () => {
)} )}
<Button <Button
isIconOnly isIconOnly
title="更新" title={t('common.updater.update')}
className="ml-2" className="ml-2"
size="sm" size="sm"
onPress={() => { onPress={() => {

View File

@ -2,6 +2,8 @@ import { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Button } from
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { BaseEditor } from '../base/base-editor' import { BaseEditor } from '../base/base-editor'
import { getFileStr, setFileStr } from '@renderer/utils/ipc' import { getFileStr, setFileStr } from '@renderer/utils/ipc'
import yaml from 'js-yaml'
import { useTranslation } from 'react-i18next'
type Language = 'yaml' | 'javascript' | 'css' | 'json' | 'text' type Language = 'yaml' | 'javascript' | 'css' | 'json' | 'text'
interface Props { interface Props {
@ -9,15 +11,37 @@ interface Props {
path: string path: string
type: string type: string
title: string title: string
privderType: string
format?: string format?: string
} }
const Viewer: React.FC<Props> = (props) => { const Viewer: React.FC<Props> = (props) => {
const { type, path, title, format, onClose } = props const { t } = useTranslation()
const { type, path, title, format, privderType, onClose } = props
const [currData, setCurrData] = useState('') const [currData, setCurrData] = useState('')
const language: Language = !format || format === 'YamlRule' ? 'yaml' : 'text' let language: Language = !format || format === 'YamlRule' ? 'yaml' : 'text'
const getContent = async (): Promise<void> => { const getContent = async (): Promise<void> => {
setCurrData(await getFileStr(path)) let fileContent: React.SetStateAction<string>
if (type === 'Inline') {
fileContent = await getFileStr('config.yaml')
language = 'yaml'
} else {
fileContent = await getFileStr(path)
}
try {
const parsedYaml = yaml.load(fileContent)
if (privderType === 'proxy-providers') {
setCurrData(yaml.dump({
'proxies': parsedYaml[privderType][title].payload
}))
} else {
setCurrData(yaml.dump({
'rules': parsedYaml[privderType][title].payload
}))
}
} catch (error) {
setCurrData(fileContent)
}
} }
useEffect(() => { useEffect(() => {
@ -46,7 +70,7 @@ const Viewer: React.FC<Props> = (props) => {
</ModalBody> </ModalBody>
<ModalFooter className="pt-0"> <ModalFooter className="pt-0">
<Button size="sm" variant="light" onPress={onClose}> <Button size="sm" variant="light" onPress={onClose}>
{t('common.close')}
</Button> </Button>
{type == 'File' && ( {type == 'File' && (
<Button <Button
@ -57,7 +81,7 @@ const Viewer: React.FC<Props> = (props) => {
onClose() onClose()
}} }}
> >
{t('common.save')}
</Button> </Button>
)} )}
</ModalFooter> </ModalFooter>

View File

@ -350,6 +350,9 @@
"profiles.traffic.remainingDays": "{{days}} days", "profiles.traffic.remainingDays": "{{days}} days",
"profiles.traffic.lastUpdate": "Last updated: {{time}}", "profiles.traffic.lastUpdate": "Last updated: {{time}}",
"profiles.notification.importSuccess": "Subscription imported successfully", "profiles.notification.importSuccess": "Subscription imported successfully",
"resources.proxyProviders.title": "Proxy Providers",
"resources.proxyProviders.updateAll": "Update All",
"resources.ruleProviders.title": "Rule Providers",
"outbound.title": "Outbound Mode", "outbound.title": "Outbound Mode",
"outbound.modes.rule": "Rule", "outbound.modes.rule": "Rule",
"outbound.modes.global": "Global", "outbound.modes.global": "Global",

View File

@ -350,6 +350,9 @@
"profiles.openFile": "打开文件", "profiles.openFile": "打开文件",
"profiles.home": "主页", "profiles.home": "主页",
"profiles.notification.importSuccess": "订阅导入成功", "profiles.notification.importSuccess": "订阅导入成功",
"resources.proxyProviders.title": "代理集合",
"resources.proxyProviders.updateAll": "更新全部",
"resources.ruleProviders.title": "规则集合",
"outbound.title": "出站模式", "outbound.title": "出站模式",
"outbound.modes.rule": "规则", "outbound.modes.rule": "规则",
"outbound.modes.global": "全局", "outbound.modes.global": "全局",