mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-10-18 11:55:02 +03:00
style(settings): fold the Happ settings into four tabs
Seven tabs, several holding one or two settings, made the page hard to scan. The encrypted-links switch moves above the tabs under auto-detection, the colour profile joins the banners under Appearance & Theme, and Android per-app proxy joins Network & TUN Engine. The QR modal's settings link no longer needs a happTab selector, and the three orphaned tab-label keys are dropped from every locale.
This commit is contained in:
@@ -50,7 +50,7 @@ type QrVariant = 'standard' | 'happ';
|
||||
type HappError = 'too_long' | 'unavailable' | null;
|
||||
|
||||
const HAPP_CRYPT5_PREFIX = 'happ://crypt5/';
|
||||
const HAPP_SETTINGS_PATH = '/settings?subscriptionTab=happ&happTab=links#subscription';
|
||||
const HAPP_SETTINGS_PATH = '/settings?subscriptionTab=happ#subscription';
|
||||
// QrPanel encodes at error level L; QR version 40 holds 2953 UTF-8 bytes at that level.
|
||||
const HAPP_QR_MAX_BYTES = 2953;
|
||||
const UTF8_ENCODER = new TextEncoder();
|
||||
|
||||
@@ -6,9 +6,6 @@ import {
|
||||
BuildOutlined,
|
||||
CloudSyncOutlined,
|
||||
DesktopOutlined,
|
||||
LinkOutlined,
|
||||
MobileOutlined,
|
||||
NotificationOutlined,
|
||||
ThunderboltOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import type { AllSetting } from '@/models/setting';
|
||||
@@ -22,7 +19,6 @@ interface HappSettingsContentProps {
|
||||
updateSetting: (patch: Partial<AllSetting>) => void;
|
||||
isMobile: boolean;
|
||||
remoteSourceBadge: (val: string) => React.ReactNode;
|
||||
defaultActiveTab?: 'routing' | 'links';
|
||||
}
|
||||
|
||||
export default function HappSettingsContent({
|
||||
@@ -30,7 +26,6 @@ export default function HappSettingsContent({
|
||||
updateSetting,
|
||||
isMobile,
|
||||
remoteSourceBadge,
|
||||
defaultActiveTab = 'routing',
|
||||
}: HappSettingsContentProps) {
|
||||
const { t } = useTranslation();
|
||||
// Generator choices stay local until Apply updates the draft; page Save persists it.
|
||||
@@ -65,17 +60,27 @@ export default function HappSettingsContent({
|
||||
/>
|
||||
</SettingListItem>
|
||||
|
||||
<SettingListItem
|
||||
paddings="small"
|
||||
title={t('pages.settings.happLinkEnable')}
|
||||
description={t('pages.settings.happLinkEnableDesc')}
|
||||
>
|
||||
<Switch
|
||||
checked={allSetting.happLinkEnable}
|
||||
onChange={(v) => updateSetting({ happLinkEnable: v })}
|
||||
/>
|
||||
</SettingListItem>
|
||||
|
||||
<Tabs
|
||||
type="card"
|
||||
size="small"
|
||||
defaultActiveKey={defaultActiveTab}
|
||||
items={[
|
||||
{
|
||||
key: 'routing',
|
||||
label: (
|
||||
<span>
|
||||
<BranchesOutlined /> {!isMobile && t('pages.settings.subHappGroupRouting')}
|
||||
</span>
|
||||
label: catTabLabel(
|
||||
<BranchesOutlined />,
|
||||
t('pages.settings.subHappGroupRouting'),
|
||||
isMobile,
|
||||
),
|
||||
children: (
|
||||
<>
|
||||
@@ -173,27 +178,11 @@ export default function HappSettingsContent({
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'links',
|
||||
label: catTabLabel(<LinkOutlined />, t('pages.settings.subHappGroupLinks'), isMobile),
|
||||
children: (
|
||||
<SettingListItem
|
||||
paddings="small"
|
||||
title={t('pages.settings.happLinkEnable')}
|
||||
description={t('pages.settings.happLinkEnableDesc')}
|
||||
>
|
||||
<Switch
|
||||
checked={allSetting.happLinkEnable}
|
||||
onChange={(v) => updateSetting({ happLinkEnable: v })}
|
||||
/>
|
||||
</SettingListItem>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'banners',
|
||||
label: (
|
||||
<span>
|
||||
<NotificationOutlined /> {!isMobile && t('pages.settings.subHappGroupBanners')}
|
||||
</span>
|
||||
key: 'appearance',
|
||||
label: catTabLabel(
|
||||
<DesktopOutlined />,
|
||||
t('pages.settings.subHappGroupThemes'),
|
||||
isMobile,
|
||||
),
|
||||
children: (
|
||||
<>
|
||||
@@ -285,15 +274,59 @@ export default function HappSettingsContent({
|
||||
onChange={(v) => updateSetting({ subHappNotificationExpire: v })}
|
||||
/>
|
||||
</SettingListItem>
|
||||
|
||||
<SettingListItem
|
||||
paddings="small"
|
||||
title={t('pages.settings.subHappColorProfile')}
|
||||
description={t('pages.settings.subHappColorProfileDesc')}
|
||||
>
|
||||
<Space orientation="vertical" style={{ width: '100%' }}>
|
||||
<Input
|
||||
value={allSetting.subHappColorProfile}
|
||||
placeholder='{"serverRowBackgroundColor":"#21003D67"} or resetcolors'
|
||||
onChange={(e) => updateSetting({ subHappColorProfile: e.target.value })}
|
||||
/>
|
||||
<Space wrap size="small">
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => updateSetting({ subHappColorProfile: 'resetcolors' })}
|
||||
>
|
||||
{t('reset')}
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() =>
|
||||
updateSetting({
|
||||
subHappColorProfile:
|
||||
'{"serverRowBackgroundColor":"#21003D67","cardBackgroundColor":"#120023B3"}',
|
||||
})
|
||||
}
|
||||
>
|
||||
Violet
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() =>
|
||||
updateSetting({
|
||||
subHappColorProfile:
|
||||
'{"serverRowBackgroundColor":"#002B3667","cardBackgroundColor":"#001F27B3"}',
|
||||
})
|
||||
}
|
||||
>
|
||||
Turquoise
|
||||
</Button>
|
||||
</Space>
|
||||
</Space>
|
||||
</SettingListItem>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'network',
|
||||
label: (
|
||||
<span>
|
||||
<ThunderboltOutlined /> {!isMobile && t('pages.settings.subHappGroupNetwork')}
|
||||
</span>
|
||||
label: catTabLabel(
|
||||
<ThunderboltOutlined />,
|
||||
t('pages.settings.subHappGroupNetwork'),
|
||||
isMobile,
|
||||
),
|
||||
children: (
|
||||
<>
|
||||
@@ -422,70 +455,45 @@ export default function HappSettingsContent({
|
||||
]}
|
||||
/>
|
||||
</SettingListItem>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'themes',
|
||||
label: (
|
||||
<span>
|
||||
<DesktopOutlined /> {!isMobile && t('pages.settings.subHappGroupThemes')}
|
||||
</span>
|
||||
),
|
||||
children: (
|
||||
<>
|
||||
|
||||
<SettingListItem
|
||||
paddings="small"
|
||||
title={t('pages.settings.subHappColorProfile')}
|
||||
description={t('pages.settings.subHappColorProfileDesc')}
|
||||
title={t('pages.settings.subHappPerAppMode')}
|
||||
description={t('pages.settings.subHappPerAppModeDesc')}
|
||||
>
|
||||
<Space orientation="vertical" style={{ width: '100%' }}>
|
||||
<Input
|
||||
value={allSetting.subHappColorProfile}
|
||||
placeholder='{"serverRowBackgroundColor":"#21003D67"} or resetcolors'
|
||||
onChange={(e) => updateSetting({ subHappColorProfile: e.target.value })}
|
||||
/>
|
||||
<Space wrap size="small">
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => updateSetting({ subHappColorProfile: 'resetcolors' })}
|
||||
>
|
||||
{t('reset')}
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() =>
|
||||
updateSetting({
|
||||
subHappColorProfile:
|
||||
'{"serverRowBackgroundColor":"#21003D67","cardBackgroundColor":"#120023B3"}',
|
||||
})
|
||||
}
|
||||
>
|
||||
Violet
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() =>
|
||||
updateSetting({
|
||||
subHappColorProfile:
|
||||
'{"serverRowBackgroundColor":"#002B3667","cardBackgroundColor":"#001F27B3"}',
|
||||
})
|
||||
}
|
||||
>
|
||||
Turquoise
|
||||
</Button>
|
||||
</Space>
|
||||
</Space>
|
||||
<Select
|
||||
value={allSetting.subHappPerAppMode || 'off'}
|
||||
style={{ width: '100%' }}
|
||||
onChange={(v) => updateSetting({ subHappPerAppMode: v })}
|
||||
options={[
|
||||
{ value: 'off', label: t('pages.settings.subHappPerAppOff') },
|
||||
{ value: 'on', label: t('pages.settings.subHappPerAppOn') },
|
||||
{ value: 'bypass', label: t('pages.settings.subHappPerAppBypass') },
|
||||
]}
|
||||
/>
|
||||
</SettingListItem>
|
||||
|
||||
<SettingListItem
|
||||
paddings="small"
|
||||
title={t('pages.settings.subHappPerAppList')}
|
||||
description={t('pages.settings.subHappPerAppListDesc')}
|
||||
>
|
||||
<Input.TextArea
|
||||
value={allSetting.subHappPerAppList}
|
||||
rows={4}
|
||||
placeholder="org.telegram.messenger, com.google.android.youtube"
|
||||
onChange={(e) => updateSetting({ subHappPerAppList: e.target.value })}
|
||||
/>
|
||||
</SettingListItem>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'failover',
|
||||
label: (
|
||||
<span>
|
||||
<CloudSyncOutlined /> {!isMobile && t('pages.settings.subHappGroupFailover')}
|
||||
</span>
|
||||
label: catTabLabel(
|
||||
<CloudSyncOutlined />,
|
||||
t('pages.settings.subHappGroupFailover'),
|
||||
isMobile,
|
||||
),
|
||||
children: (
|
||||
<>
|
||||
@@ -538,47 +546,6 @@ export default function HappSettingsContent({
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'android',
|
||||
label: (
|
||||
<span>
|
||||
<MobileOutlined /> {!isMobile && t('pages.settings.subHappGroupAndroid')}
|
||||
</span>
|
||||
),
|
||||
children: (
|
||||
<>
|
||||
<SettingListItem
|
||||
paddings="small"
|
||||
title={t('pages.settings.subHappPerAppMode')}
|
||||
description={t('pages.settings.subHappPerAppModeDesc')}
|
||||
>
|
||||
<Select
|
||||
value={allSetting.subHappPerAppMode || 'off'}
|
||||
style={{ width: '100%' }}
|
||||
onChange={(v) => updateSetting({ subHappPerAppMode: v })}
|
||||
options={[
|
||||
{ value: 'off', label: t('pages.settings.subHappPerAppOff') },
|
||||
{ value: 'on', label: t('pages.settings.subHappPerAppOn') },
|
||||
{ value: 'bypass', label: t('pages.settings.subHappPerAppBypass') },
|
||||
]}
|
||||
/>
|
||||
</SettingListItem>
|
||||
|
||||
<SettingListItem
|
||||
paddings="small"
|
||||
title={t('pages.settings.subHappPerAppList')}
|
||||
description={t('pages.settings.subHappPerAppListDesc')}
|
||||
>
|
||||
<Input.TextArea
|
||||
value={allSetting.subHappPerAppList}
|
||||
rows={4}
|
||||
placeholder="org.telegram.messenger, com.google.android.youtube"
|
||||
onChange={(e) => updateSetting({ subHappPerAppList: e.target.value })}
|
||||
/>
|
||||
</SettingListItem>
|
||||
</>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
|
||||
@@ -414,8 +414,6 @@ export default function SubscriptionGeneralTab({
|
||||
updateSetting={updateSetting}
|
||||
isMobile={isMobile}
|
||||
remoteSourceBadge={remoteSourceBadge}
|
||||
// QR settings links select the link control; ordinary Happ visits still start on routing.
|
||||
defaultActiveTab={searchParams.get('happTab') === 'links' ? 'links' : 'routing'}
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user