mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-01 07:57:14 +00:00
refactor(settings): reorganize subscription settings into clearer tabs
- Split the Happ and Clash/Mihomo routing sections out of Information into their own dedicated tabs. - Extract the profile/branding fields (title, support URL, profile page, announcement, theme dir) out of the mislabeled "Subscription Title" divider into a new Profile tab. - Move the Update Interval setting into Information and drop the single-field Intervals tab. - Add the "profile" tab label across all locales.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { Divider, Input, InputNumber, Select, Space, Switch, Tabs } from 'antd';
|
import { Input, InputNumber, Select, Space, Switch, Tabs } from 'antd';
|
||||||
import { ClockCircleOutlined, InfoCircleOutlined, SafetyCertificateOutlined, SettingOutlined } from '@ant-design/icons';
|
import { BranchesOutlined, IdcardOutlined, InfoCircleOutlined, NodeIndexOutlined, SafetyCertificateOutlined, SettingOutlined } from '@ant-design/icons';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import type { AllSetting } from '@/models/setting';
|
import type { AllSetting } from '@/models/setting';
|
||||||
import { SettingListItem } from '@/components/ui';
|
import { SettingListItem } from '@/components/ui';
|
||||||
@@ -139,8 +139,18 @@ export default function SubscriptionGeneralTab({ allSetting, updateSetting }: Su
|
|||||||
</Space.Compact>
|
</Space.Compact>
|
||||||
</SettingListItem>
|
</SettingListItem>
|
||||||
|
|
||||||
<Divider>{t('pages.settings.subTitle')}</Divider>
|
<SettingListItem paddings="small" title={t('pages.settings.subUpdates')} description={t('pages.settings.subUpdatesDesc')}>
|
||||||
|
<InputNumber value={allSetting.subUpdates} min={1} style={{ width: '100%' }}
|
||||||
|
onChange={(v) => updateSetting({ subUpdates: Number(v) || 0 })} />
|
||||||
|
</SettingListItem>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '3',
|
||||||
|
label: catTabLabel(<IdcardOutlined />, t('pages.settings.profile'), isMobile),
|
||||||
|
children: (
|
||||||
|
<>
|
||||||
<SettingListItem paddings="small" title={t('pages.settings.subTitle')} description={t('pages.settings.subTitleDesc')}>
|
<SettingListItem paddings="small" title={t('pages.settings.subTitle')} description={t('pages.settings.subTitleDesc')}>
|
||||||
<Input value={allSetting.subTitle} onChange={(e) => updateSetting({ subTitle: e.target.value })} />
|
<Input value={allSetting.subTitle} onChange={(e) => updateSetting({ subTitle: e.target.value })} />
|
||||||
</SettingListItem>
|
</SettingListItem>
|
||||||
@@ -156,7 +166,6 @@ export default function SubscriptionGeneralTab({ allSetting, updateSetting }: Su
|
|||||||
<Input.TextArea value={allSetting.subAnnounce}
|
<Input.TextArea value={allSetting.subAnnounce}
|
||||||
onChange={(e) => updateSetting({ subAnnounce: e.target.value })} />
|
onChange={(e) => updateSetting({ subAnnounce: e.target.value })} />
|
||||||
</SettingListItem>
|
</SettingListItem>
|
||||||
|
|
||||||
<SettingListItem
|
<SettingListItem
|
||||||
paddings="small"
|
paddings="small"
|
||||||
title={t('pages.settings.subThemeDir')}
|
title={t('pages.settings.subThemeDir')}
|
||||||
@@ -176,9 +185,28 @@ export default function SubscriptionGeneralTab({ allSetting, updateSetting }: Su
|
|||||||
<Input value={allSetting.subThemeDir} placeholder="/etc/3x-ui/sub_templates/my-theme/"
|
<Input value={allSetting.subThemeDir} placeholder="/etc/3x-ui/sub_templates/my-theme/"
|
||||||
onChange={(e) => updateSetting({ subThemeDir: e.target.value })} />
|
onChange={(e) => updateSetting({ subThemeDir: e.target.value })} />
|
||||||
</SettingListItem>
|
</SettingListItem>
|
||||||
|
</>
|
||||||
<Divider>Happ</Divider>
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '4',
|
||||||
|
label: catTabLabel(<SafetyCertificateOutlined />, t('pages.settings.certs'), isMobile),
|
||||||
|
children: (
|
||||||
|
<>
|
||||||
|
<SettingListItem paddings="small" title={t('pages.settings.subCertPath')} description={t('pages.settings.subCertPathDesc')}>
|
||||||
|
<Input value={allSetting.subCertFile} onChange={(e) => updateSetting({ subCertFile: e.target.value })} />
|
||||||
|
</SettingListItem>
|
||||||
|
<SettingListItem paddings="small" title={t('pages.settings.subKeyPath')} description={t('pages.settings.subKeyPathDesc')}>
|
||||||
|
<Input value={allSetting.subKeyFile} onChange={(e) => updateSetting({ subKeyFile: e.target.value })} />
|
||||||
|
</SettingListItem>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '5',
|
||||||
|
label: catTabLabel(<BranchesOutlined />, 'Happ', isMobile),
|
||||||
|
children: (
|
||||||
|
<>
|
||||||
<SettingListItem paddings="small" title={t('pages.settings.subEnableRouting')} description={t('pages.settings.subEnableRoutingDesc')}>
|
<SettingListItem paddings="small" title={t('pages.settings.subEnableRouting')} description={t('pages.settings.subEnableRoutingDesc')}>
|
||||||
<Switch checked={allSetting.subEnableRouting} onChange={(v) => updateSetting({ subEnableRouting: v })} />
|
<Switch checked={allSetting.subEnableRouting} onChange={(v) => updateSetting({ subEnableRouting: v })} />
|
||||||
</SettingListItem>
|
</SettingListItem>
|
||||||
@@ -186,9 +214,14 @@ export default function SubscriptionGeneralTab({ allSetting, updateSetting }: Su
|
|||||||
<Input.TextArea value={allSetting.subRoutingRules} placeholder="happ://routing/add/..."
|
<Input.TextArea value={allSetting.subRoutingRules} placeholder="happ://routing/add/..."
|
||||||
onChange={(e) => updateSetting({ subRoutingRules: e.target.value })} />
|
onChange={(e) => updateSetting({ subRoutingRules: e.target.value })} />
|
||||||
</SettingListItem>
|
</SettingListItem>
|
||||||
|
</>
|
||||||
<Divider>Clash / Mihomo</Divider>
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '6',
|
||||||
|
label: catTabLabel(<NodeIndexOutlined />, 'Clash / Mihomo', isMobile),
|
||||||
|
children: (
|
||||||
|
<>
|
||||||
<SettingListItem paddings="small" title={t('pages.settings.subClashEnableRouting')} description={t('pages.settings.subClashEnableRoutingDesc')}>
|
<SettingListItem paddings="small" title={t('pages.settings.subClashEnableRouting')} description={t('pages.settings.subClashEnableRoutingDesc')}>
|
||||||
<Switch checked={allSetting.subClashEnableRouting} onChange={(v) => updateSetting({ subClashEnableRouting: v })} />
|
<Switch checked={allSetting.subClashEnableRouting} onChange={(v) => updateSetting({ subClashEnableRouting: v })} />
|
||||||
</SettingListItem>
|
</SettingListItem>
|
||||||
@@ -203,32 +236,6 @@ export default function SubscriptionGeneralTab({ allSetting, updateSetting }: Su
|
|||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
key: '3',
|
|
||||||
label: catTabLabel(<SafetyCertificateOutlined />, t('pages.settings.certs'), isMobile),
|
|
||||||
children: (
|
|
||||||
<>
|
|
||||||
<SettingListItem paddings="small" title={t('pages.settings.subCertPath')} description={t('pages.settings.subCertPathDesc')}>
|
|
||||||
<Input value={allSetting.subCertFile} onChange={(e) => updateSetting({ subCertFile: e.target.value })} />
|
|
||||||
</SettingListItem>
|
|
||||||
<SettingListItem paddings="small" title={t('pages.settings.subKeyPath')} description={t('pages.settings.subKeyPathDesc')}>
|
|
||||||
<Input value={allSetting.subKeyFile} onChange={(e) => updateSetting({ subKeyFile: e.target.value })} />
|
|
||||||
</SettingListItem>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: '4',
|
|
||||||
label: catTabLabel(<ClockCircleOutlined />, t('pages.settings.intervals'), isMobile),
|
|
||||||
children: (
|
|
||||||
<>
|
|
||||||
<SettingListItem paddings="small" title={t('pages.settings.subUpdates')} description={t('pages.settings.subUpdatesDesc')}>
|
|
||||||
<InputNumber value={allSetting.subUpdates} min={1} style={{ width: '100%' }}
|
|
||||||
onChange={(v) => updateSetting({ subUpdates: Number(v) || 0 })} />
|
|
||||||
</SettingListItem>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
]} />
|
]} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1151,6 +1151,7 @@
|
|||||||
"proxyAndServer": "البروكسي والسيرفر",
|
"proxyAndServer": "البروكسي والسيرفر",
|
||||||
"intervals": "الفترات",
|
"intervals": "الفترات",
|
||||||
"information": "المعلومات",
|
"information": "المعلومات",
|
||||||
|
"profile": "الملف الشخصي",
|
||||||
"language": "اللغة",
|
"language": "اللغة",
|
||||||
"telegramBotLanguage": "لغة بوت Telegram",
|
"telegramBotLanguage": "لغة بوت Telegram",
|
||||||
"security": {
|
"security": {
|
||||||
|
|||||||
@@ -1152,6 +1152,7 @@
|
|||||||
"proxyAndServer": "Proxy and Server",
|
"proxyAndServer": "Proxy and Server",
|
||||||
"intervals": "Intervals",
|
"intervals": "Intervals",
|
||||||
"information": "Information",
|
"information": "Information",
|
||||||
|
"profile": "Profile",
|
||||||
"language": "Language",
|
"language": "Language",
|
||||||
"telegramBotLanguage": "Telegram Bot Language",
|
"telegramBotLanguage": "Telegram Bot Language",
|
||||||
"security": {
|
"security": {
|
||||||
|
|||||||
@@ -1151,6 +1151,7 @@
|
|||||||
"proxyAndServer": "Proxy y Servidor",
|
"proxyAndServer": "Proxy y Servidor",
|
||||||
"intervals": "Intervalos",
|
"intervals": "Intervalos",
|
||||||
"information": "Información",
|
"information": "Información",
|
||||||
|
"profile": "Perfil",
|
||||||
"language": "Idioma",
|
"language": "Idioma",
|
||||||
"telegramBotLanguage": "Idioma del Bot de Telegram",
|
"telegramBotLanguage": "Idioma del Bot de Telegram",
|
||||||
"security": {
|
"security": {
|
||||||
|
|||||||
@@ -1151,6 +1151,7 @@
|
|||||||
"proxyAndServer": "پراکسی و سرور",
|
"proxyAndServer": "پراکسی و سرور",
|
||||||
"intervals": "فواصل",
|
"intervals": "فواصل",
|
||||||
"information": "اطلاعات",
|
"information": "اطلاعات",
|
||||||
|
"profile": "پروفایل",
|
||||||
"language": "زبان",
|
"language": "زبان",
|
||||||
"telegramBotLanguage": "زبان ربات تلگرام",
|
"telegramBotLanguage": "زبان ربات تلگرام",
|
||||||
"security": {
|
"security": {
|
||||||
|
|||||||
@@ -1151,6 +1151,7 @@
|
|||||||
"proxyAndServer": "Proxy dan Server",
|
"proxyAndServer": "Proxy dan Server",
|
||||||
"intervals": "Interval",
|
"intervals": "Interval",
|
||||||
"information": "Informasi",
|
"information": "Informasi",
|
||||||
|
"profile": "Profil",
|
||||||
"language": "Bahasa",
|
"language": "Bahasa",
|
||||||
"telegramBotLanguage": "Bahasa Bot Telegram",
|
"telegramBotLanguage": "Bahasa Bot Telegram",
|
||||||
"security": {
|
"security": {
|
||||||
|
|||||||
@@ -1151,6 +1151,7 @@
|
|||||||
"proxyAndServer": "プロキシとサーバー",
|
"proxyAndServer": "プロキシとサーバー",
|
||||||
"intervals": "間隔",
|
"intervals": "間隔",
|
||||||
"information": "情報",
|
"information": "情報",
|
||||||
|
"profile": "プロフィール",
|
||||||
"language": "言語",
|
"language": "言語",
|
||||||
"telegramBotLanguage": "Telegram Botの言語",
|
"telegramBotLanguage": "Telegram Botの言語",
|
||||||
"security": {
|
"security": {
|
||||||
|
|||||||
@@ -1151,6 +1151,7 @@
|
|||||||
"proxyAndServer": "Proxy e Servidor",
|
"proxyAndServer": "Proxy e Servidor",
|
||||||
"intervals": "Intervalos",
|
"intervals": "Intervalos",
|
||||||
"information": "Informação",
|
"information": "Informação",
|
||||||
|
"profile": "Perfil",
|
||||||
"language": "Idioma",
|
"language": "Idioma",
|
||||||
"telegramBotLanguage": "Idioma do Bot do Telegram",
|
"telegramBotLanguage": "Idioma do Bot do Telegram",
|
||||||
"security": {
|
"security": {
|
||||||
|
|||||||
@@ -1151,6 +1151,7 @@
|
|||||||
"proxyAndServer": "Прокси и сервер",
|
"proxyAndServer": "Прокси и сервер",
|
||||||
"intervals": "Интервалы",
|
"intervals": "Интервалы",
|
||||||
"information": "Информация",
|
"information": "Информация",
|
||||||
|
"profile": "Профиль",
|
||||||
"language": "Язык интерфейса",
|
"language": "Язык интерфейса",
|
||||||
"telegramBotLanguage": "Язык Telegram-бота",
|
"telegramBotLanguage": "Язык Telegram-бота",
|
||||||
"security": {
|
"security": {
|
||||||
|
|||||||
@@ -1150,6 +1150,7 @@
|
|||||||
"proxyAndServer": "Proxy ve Sunucu",
|
"proxyAndServer": "Proxy ve Sunucu",
|
||||||
"intervals": "Aralıklar",
|
"intervals": "Aralıklar",
|
||||||
"information": "Bilgi",
|
"information": "Bilgi",
|
||||||
|
"profile": "Profil",
|
||||||
"language": "Dil",
|
"language": "Dil",
|
||||||
"telegramBotLanguage": "Telegram Bot Dili",
|
"telegramBotLanguage": "Telegram Bot Dili",
|
||||||
"security": {
|
"security": {
|
||||||
|
|||||||
@@ -1151,6 +1151,7 @@
|
|||||||
"proxyAndServer": "Проксі та сервер",
|
"proxyAndServer": "Проксі та сервер",
|
||||||
"intervals": "Інтервали",
|
"intervals": "Інтервали",
|
||||||
"information": "Інформація",
|
"information": "Інформація",
|
||||||
|
"profile": "Профіль",
|
||||||
"language": "Мова",
|
"language": "Мова",
|
||||||
"telegramBotLanguage": "Мова Telegram-бота",
|
"telegramBotLanguage": "Мова Telegram-бота",
|
||||||
"security": {
|
"security": {
|
||||||
|
|||||||
@@ -1151,6 +1151,7 @@
|
|||||||
"proxyAndServer": "Proxy và máy chủ",
|
"proxyAndServer": "Proxy và máy chủ",
|
||||||
"intervals": "Khoảng thời gian",
|
"intervals": "Khoảng thời gian",
|
||||||
"information": "Thông tin",
|
"information": "Thông tin",
|
||||||
|
"profile": "Hồ sơ",
|
||||||
"language": "Ngôn ngữ",
|
"language": "Ngôn ngữ",
|
||||||
"telegramBotLanguage": "Ngôn ngữ của Bot Telegram",
|
"telegramBotLanguage": "Ngôn ngữ của Bot Telegram",
|
||||||
"security": {
|
"security": {
|
||||||
|
|||||||
@@ -1151,6 +1151,7 @@
|
|||||||
"proxyAndServer": "代理和服务器",
|
"proxyAndServer": "代理和服务器",
|
||||||
"intervals": "间隔",
|
"intervals": "间隔",
|
||||||
"information": "信息",
|
"information": "信息",
|
||||||
|
"profile": "资料",
|
||||||
"language": "语言",
|
"language": "语言",
|
||||||
"telegramBotLanguage": "Telegram 机器人语言",
|
"telegramBotLanguage": "Telegram 机器人语言",
|
||||||
"security": {
|
"security": {
|
||||||
|
|||||||
@@ -1151,6 +1151,7 @@
|
|||||||
"proxyAndServer": "代理和伺服器",
|
"proxyAndServer": "代理和伺服器",
|
||||||
"intervals": "間隔",
|
"intervals": "間隔",
|
||||||
"information": "資訊",
|
"information": "資訊",
|
||||||
|
"profile": "資料",
|
||||||
"language": "語言",
|
"language": "語言",
|
||||||
"telegramBotLanguage": "Telegram 機器人語言",
|
"telegramBotLanguage": "Telegram 機器人語言",
|
||||||
"security": {
|
"security": {
|
||||||
|
|||||||
Reference in New Issue
Block a user