SubscriptionGeneralTab.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. import { Input, InputNumber, Switch, Tabs } from 'antd';
  2. import { BranchesOutlined, CompassOutlined, IdcardOutlined, InfoCircleOutlined, NodeIndexOutlined, SafetyCertificateOutlined, SettingOutlined } from '@ant-design/icons';
  3. import { useTranslation } from 'react-i18next';
  4. import type { AllSetting } from '@/models/setting';
  5. import { SettingListItem } from '@/components/ui';
  6. import { RemarkTemplateField } from '@/components/form';
  7. import { useMediaQuery } from '@/hooks/useMediaQuery';
  8. import { catTabLabel } from './catTabLabel';
  9. import { sanitizePath, normalizePath } from './uriPath';
  10. interface SubscriptionGeneralTabProps {
  11. allSetting: AllSetting;
  12. updateSetting: (patch: Partial<AllSetting>) => void;
  13. }
  14. export default function SubscriptionGeneralTab({ allSetting, updateSetting }: SubscriptionGeneralTabProps) {
  15. const { t } = useTranslation();
  16. const { isMobile } = useMediaQuery();
  17. return (
  18. <Tabs defaultActiveKey="1" items={[
  19. {
  20. key: '1',
  21. label: catTabLabel(<SettingOutlined />, t('pages.settings.panelSettings'), isMobile),
  22. children: (
  23. <>
  24. <SettingListItem paddings="small" title={t('pages.settings.subEnable')} description={t('pages.settings.subEnableDesc')}>
  25. <Switch checked={allSetting.subEnable} onChange={(v) => updateSetting({ subEnable: v })} />
  26. </SettingListItem>
  27. <SettingListItem paddings="small" title={t('pages.settings.subJsonEnableTitle')} description={t('pages.settings.subJsonEnable')}>
  28. <Switch checked={allSetting.subJsonEnable} onChange={(v) => updateSetting({ subJsonEnable: v })} />
  29. </SettingListItem>
  30. <SettingListItem paddings="small" title={t('pages.settings.subClashEnableTitle')}>
  31. <Switch checked={allSetting.subClashEnable} onChange={(v) => updateSetting({ subClashEnable: v })} />
  32. </SettingListItem>
  33. <SettingListItem paddings="small" title={t('pages.settings.subListen')} description={t('pages.settings.subListenDesc')}>
  34. <Input value={allSetting.subListen} onChange={(e) => updateSetting({ subListen: e.target.value })} />
  35. </SettingListItem>
  36. <SettingListItem paddings="small" title={t('pages.settings.subDomain')} description={t('pages.settings.subDomainDesc')}>
  37. <Input value={allSetting.subDomain} onChange={(e) => updateSetting({ subDomain: e.target.value })} />
  38. </SettingListItem>
  39. <SettingListItem paddings="small" title={t('pages.settings.subPort')} description={t('pages.settings.subPortDesc')}>
  40. <InputNumber value={allSetting.subPort} min={1} max={65535} style={{ width: '100%' }}
  41. onChange={(v) => updateSetting({ subPort: Number(v) || 0 })} />
  42. </SettingListItem>
  43. <SettingListItem paddings="small" title={t('pages.settings.subPath')} description={t('pages.settings.subPathDesc')}>
  44. <Input
  45. value={allSetting.subPath}
  46. placeholder="/sub/"
  47. onChange={(e) => updateSetting({ subPath: sanitizePath(e.target.value) })}
  48. onBlur={() => updateSetting({ subPath: normalizePath(allSetting.subPath) })}
  49. />
  50. </SettingListItem>
  51. <SettingListItem paddings="small" title={t('pages.settings.subURI')} description={t('pages.settings.subURIDesc')}>
  52. <Input value={allSetting.subURI} placeholder="(http|https)://domain[:port]/path/"
  53. onChange={(e) => updateSetting({ subURI: e.target.value })} />
  54. </SettingListItem>
  55. </>
  56. ),
  57. },
  58. {
  59. key: '2',
  60. label: catTabLabel(<InfoCircleOutlined />, t('pages.settings.information'), isMobile),
  61. children: (
  62. <>
  63. <SettingListItem paddings="small" title={t('pages.settings.subEncrypt')} description={t('pages.settings.subEncryptDesc')}>
  64. <Switch checked={allSetting.subEncrypt} onChange={(v) => updateSetting({ subEncrypt: v })} />
  65. </SettingListItem>
  66. <SettingListItem
  67. paddings="small"
  68. title={t('pages.settings.remarkTemplate')}
  69. description={t('pages.settings.remarkTemplateDesc')}
  70. >
  71. <RemarkTemplateField
  72. value={allSetting.remarkTemplate}
  73. onChange={(v) => updateSetting({ remarkTemplate: v })}
  74. maxLength={256}
  75. />
  76. </SettingListItem>
  77. <SettingListItem paddings="small" title={t('pages.settings.subUpdates')} description={t('pages.settings.subUpdatesDesc')}>
  78. <InputNumber value={allSetting.subUpdates} min={0} max={525600} style={{ width: '100%' }}
  79. onChange={(v) => updateSetting({ subUpdates: Number(v) || 0 })} />
  80. </SettingListItem>
  81. </>
  82. ),
  83. },
  84. {
  85. key: '3',
  86. label: catTabLabel(<IdcardOutlined />, t('pages.settings.profile'), isMobile),
  87. children: (
  88. <>
  89. <SettingListItem paddings="small" title={t('pages.settings.subTitle')} description={t('pages.settings.subTitleDesc')}>
  90. <Input value={allSetting.subTitle} onChange={(e) => updateSetting({ subTitle: e.target.value })} />
  91. </SettingListItem>
  92. <SettingListItem paddings="small" title={t('pages.settings.subSupportUrl')} description={t('pages.settings.subSupportUrlDesc')}>
  93. <Input value={allSetting.subSupportUrl} placeholder="https://example.com"
  94. onChange={(e) => updateSetting({ subSupportUrl: e.target.value })} />
  95. </SettingListItem>
  96. <SettingListItem paddings="small" title={t('pages.settings.subProfileUrl')} description={t('pages.settings.subProfileUrlDesc')}>
  97. <Input value={allSetting.subProfileUrl} placeholder="https://example.com"
  98. onChange={(e) => updateSetting({ subProfileUrl: e.target.value })} />
  99. </SettingListItem>
  100. <SettingListItem paddings="small" title={t('pages.settings.subAnnounce')} description={t('pages.settings.subAnnounceDesc')}>
  101. <Input.TextArea value={allSetting.subAnnounce}
  102. onChange={(e) => updateSetting({ subAnnounce: e.target.value })} />
  103. </SettingListItem>
  104. <SettingListItem
  105. paddings="small"
  106. title={t('pages.settings.subThemeDir')}
  107. description={(
  108. <>
  109. {t('pages.settings.subThemeDirDesc')}{' '}
  110. <a
  111. href="https://github.com/MHSanaei/3x-ui/blob/main/docs/custom-subscription-templates.md"
  112. target="_blank"
  113. rel="noopener noreferrer"
  114. >
  115. {t('pages.settings.subThemeDirDocs')}
  116. </a>
  117. </>
  118. )}
  119. >
  120. <Input value={allSetting.subThemeDir} placeholder="/etc/3x-ui/sub_templates/my-theme/"
  121. onChange={(e) => updateSetting({ subThemeDir: e.target.value })} />
  122. </SettingListItem>
  123. </>
  124. ),
  125. },
  126. {
  127. key: '4',
  128. label: catTabLabel(<SafetyCertificateOutlined />, t('pages.settings.certs'), isMobile),
  129. children: (
  130. <>
  131. <SettingListItem paddings="small" title={t('pages.settings.subCertPath')} description={t('pages.settings.subCertPathDesc')}>
  132. <Input value={allSetting.subCertFile} onChange={(e) => updateSetting({ subCertFile: e.target.value })} />
  133. </SettingListItem>
  134. <SettingListItem paddings="small" title={t('pages.settings.subKeyPath')} description={t('pages.settings.subKeyPathDesc')}>
  135. <Input value={allSetting.subKeyFile} onChange={(e) => updateSetting({ subKeyFile: e.target.value })} />
  136. </SettingListItem>
  137. </>
  138. ),
  139. },
  140. {
  141. key: '5',
  142. label: catTabLabel(<BranchesOutlined />, 'Happ', isMobile),
  143. children: (
  144. <>
  145. <SettingListItem paddings="small" title={t('pages.settings.subEnableRouting')} description={t('pages.settings.subEnableRoutingDesc')}>
  146. <Switch checked={allSetting.subEnableRouting} onChange={(v) => updateSetting({ subEnableRouting: v })} />
  147. </SettingListItem>
  148. <SettingListItem paddings="small" title={t('pages.settings.subRoutingRules')} description={t('pages.settings.subRoutingRulesDesc')}>
  149. <Input.TextArea value={allSetting.subRoutingRules} placeholder="happ://routing/add/..."
  150. onChange={(e) => updateSetting({ subRoutingRules: e.target.value })} />
  151. </SettingListItem>
  152. <SettingListItem paddings="small" title={t('pages.settings.subHideSettings')} description={t('pages.settings.subHideSettingsDesc')}>
  153. <Switch checked={allSetting.subHideSettings} onChange={(v) => updateSetting({ subHideSettings: v })} />
  154. </SettingListItem>
  155. </>
  156. ),
  157. },
  158. {
  159. key: '6',
  160. label: catTabLabel(<NodeIndexOutlined />, 'Clash / Mihomo', isMobile),
  161. children: (
  162. <>
  163. <SettingListItem paddings="small" title={t('pages.settings.subClashEnableRouting')} description={t('pages.settings.subClashEnableRoutingDesc')}>
  164. <Switch checked={allSetting.subClashEnableRouting} onChange={(v) => updateSetting({ subClashEnableRouting: v })} />
  165. </SettingListItem>
  166. <SettingListItem paddings="small" title={t('pages.settings.subClashRoutingRules')} description={t('pages.settings.subClashRoutingRulesDesc')}>
  167. <Input.TextArea
  168. value={allSetting.subClashRules}
  169. rows={8}
  170. placeholder={'GEOSITE,category-ir,DIRECT\nGEOIP,private,DIRECT'}
  171. onChange={(e) => updateSetting({ subClashRules: e.target.value })}
  172. />
  173. </SettingListItem>
  174. </>
  175. ),
  176. },
  177. {
  178. key: '7',
  179. label: catTabLabel(<CompassOutlined />, 'Incy', isMobile),
  180. children: (
  181. <>
  182. <SettingListItem paddings="small" title={t('pages.settings.subIncyEnableRouting')} description={t('pages.settings.subIncyEnableRoutingDesc')}>
  183. <Switch checked={allSetting.subIncyEnableRouting} onChange={(v) => updateSetting({ subIncyEnableRouting: v })} />
  184. </SettingListItem>
  185. <SettingListItem paddings="small" title={t('pages.settings.subIncyRoutingRules')} description={t('pages.settings.subIncyRoutingRulesDesc')}>
  186. <Input.TextArea value={allSetting.subIncyRoutingRules} placeholder="incy://routing/onadd/..."
  187. onChange={(e) => updateSetting({ subIncyRoutingRules: e.target.value })} />
  188. </SettingListItem>
  189. </>
  190. ),
  191. },
  192. ]} />
  193. );
  194. }