diff --git a/common/constants.go b/common/constants.go index d6b4fb52..cf468089 100644 --- a/common/constants.go +++ b/common/constants.go @@ -12,7 +12,7 @@ import ( var StartTime = time.Now().Unix() // unit: second var Version = "v0.0.0" // this hard coding will be replaced automatically when building, no need to manually change -var SystemName = "New API" +var SystemName = "LFAPI" var Footer = "" var Logo = "" var TopUpLink = "" diff --git a/common/email_test.go b/common/email_test.go index 7ae45ae3..09f4fac2 100644 --- a/common/email_test.go +++ b/common/email_test.go @@ -281,7 +281,7 @@ func TestSendEmailUsesExplicitStartTLSWithInsecureCertificate(t *testing.T) { SMTPAccount = "sender@example.com" SMTPFrom = "sender@example.com" SMTPToken = "secret" - SystemName = "New API" + SystemName = "LFAPI" err := SendEmail("Verification", "receiver@example.com", "

123456

") require.NoError(t, err) @@ -309,7 +309,7 @@ func TestSendEmailExplicitStartTLSRequiresServerSupport(t *testing.T) { SMTPAccount = "sender@example.com" SMTPFrom = "sender@example.com" SMTPToken = "secret" - SystemName = "New API" + SystemName = "LFAPI" err := SendEmail("Verification", "receiver@example.com", "

123456

") require.Error(t, err) @@ -330,7 +330,7 @@ func TestSendEmailDoesNotAutoUpgradeWhenStartTLSDisabled(t *testing.T) { SMTPAccount = "sender@example.com" SMTPFrom = "sender@example.com" SMTPToken = "secret" - SystemName = "New API" + SystemName = "LFAPI" err := SendEmail("Verification", "receiver@example.com", "

123456

") require.NoError(t, err) @@ -433,7 +433,7 @@ func TestSendEmailSkipsAuthWhenCredentialsAreEmpty(t *testing.T) { SMTPAccount = "" SMTPFrom = "sender@example.com" SMTPToken = "" - SystemName = "New API" + SystemName = "LFAPI" err := SendEmail("Verification", "receiver@example.com", "

123456

") require.NoError(t, err) @@ -466,7 +466,7 @@ func TestSendEmailSkipsAuthWhenCredentialsAreIncomplete(t *testing.T) { SMTPAccount = "sender@example.com" SMTPFrom = "sender@example.com" SMTPToken = "" - SystemName = "New API" + SystemName = "LFAPI" err := SendEmail("Verification", "receiver@example.com", "

123456

") require.NoError(t, err) @@ -500,7 +500,7 @@ func TestSendEmailUsesNTLMWhenServerOnlySupportsNTLM(t *testing.T) { SMTPAccount = "no-reply" SMTPFrom = "no-reply@example.com" SMTPToken = "secret" - SystemName = "New API" + SystemName = "LFAPI" err := SendEmail("Verification", "receiver@example.com", "

123456

") require.NoError(t, err) @@ -528,7 +528,7 @@ func TestSendEmailUsesNTLMForMicrosoftAccountWhenServerOnlySupportsNTLM(t *testi SMTPAccount = "no-reply@contoso.onmicrosoft.com" SMTPFrom = "no-reply@contoso.onmicrosoft.com" SMTPToken = "secret" - SystemName = "New API" + SystemName = "LFAPI" err := SendEmail("Verification", "receiver@example.com", "

123456

") require.NoError(t, err) @@ -555,7 +555,7 @@ func TestSendEmailExplicitStartTLSRejectsUntrustedCertificateByDefault(t *testin SMTPAccount = "sender@example.com" SMTPFrom = "sender@example.com" SMTPToken = "secret" - SystemName = "New API" + SystemName = "LFAPI" err := SendEmail("Verification", "receiver@example.com", "

123456

") require.Error(t, err) diff --git a/controller/channel.go b/controller/channel.go index 19ddca8e..2b3baaea 100644 --- a/controller/channel.go +++ b/controller/channel.go @@ -417,8 +417,7 @@ func GetChannel(c *gin.Context) { return } -// GetChannelKey 获取渠道密钥(需要通过安全验证中间件) -// 此函数依赖 SecureVerificationRequired 中间件,确保用户已通过安全验证 +// GetChannelKey 获取渠道密钥。仅 Root 管理员可访问该路由。 func GetChannelKey(c *gin.Context) { channelId, err := strconv.Atoi(c.Param("id")) if err != nil { diff --git a/main.go b/main.go index ac4e6afc..e9f6bbc0 100644 --- a/main.go +++ b/main.go @@ -209,8 +209,12 @@ func main() { port = strconv.Itoa(*common.Port) } + listenAddr := strings.TrimSpace(os.Getenv("LISTEN_ADDR")) + if listenAddr == "" { + listenAddr = "0.0.0.0" + } srv := &http.Server{ - Addr: ":" + port, + Addr: listenAddr + ":" + port, Handler: server, } diff --git a/router/channel-router.go b/router/channel-router.go index b85cbd88..ca75ec44 100644 --- a/router/channel-router.go +++ b/router/channel-router.go @@ -24,7 +24,6 @@ func registerChannelRoutes(apiRouter *gin.RouterGroup) { middleware.RootAuth(), middleware.CriticalRateLimit(), middleware.DisableCache(), - middleware.SecureVerificationRequired(), controller.GetChannelKey, ) diff --git a/setting/operation_setting/general_setting.go b/setting/operation_setting/general_setting.go index b4a3cccc..715bdfdc 100644 --- a/setting/operation_setting/general_setting.go +++ b/setting/operation_setting/general_setting.go @@ -24,7 +24,7 @@ type GeneralSetting struct { // 默认配置 var generalSetting = GeneralSetting{ - DocsLink: "https://docs.newapi.pro", + DocsLink: "/docs", PingIntervalEnabled: false, PingIntervalSeconds: 60, QuotaDisplayType: QuotaDisplayTypeUSD, diff --git a/web/index.html b/web/index.html index 7f280b40..1b956efb 100644 --- a/web/index.html +++ b/web/index.html @@ -2,16 +2,16 @@ - + - New API - + LFAPI + diff --git a/web/public/favicon.ico b/web/public/favicon.ico index ab5f17bcdb35e96cf7673ca8fa7ba8d6a33bd7ce..6bcc394149d3048cd8d059d7f625b21972359789 100644 GIT binary patch literal 28862 zcmeI5&yNg26vx}y%|ZMF2Ju@Waav1=^Nt4KnW-TC6Gnn`?qf&=jNV0 zel&S){B-@${w|_bn$@Eqk9d2m2@7Fo zbx@X$gd@Ir_3GfZt)!jZ6@#6ywlYee=I2Ka*SqVo$I)RkEHAquJ%9St!?xb30{crs zg!XxVYO;4c^|l0F1V7iH@Xq+Sw@JNL5x#^)6i3T3zb1GT>O|}JKF7pjri1iF=<`jT zk);b>(QuOXVA4kAYKL91wiVE+ht(meR<)PxXXA~gpQBl*}*t9Dk9C(VPuPJ9rBBQ*yR zBl)xw=$J#A2Y;RTAW%ta4kFfdJ_rjt@u@h5+;u+i*NIQDR#DrxY3H$l(KEx-&BpBY z3tuNjf8xD)YIbCJ8u=(4tkujzbe#{3sesSk4LeQ_-Mw*nk$IiiHwF2WQuKWGtlvH| z{E)%YB7<6}8#kY01D9I7cKsMDpIvL#ojdx(l}5XKlzeut-FW5HyLM+ia^mBImeXv! z_dtyox*@NTLlePXyA~uT4n7m3 zKZ4L`R}u#wZ9g)`&Kz@U|6}K)*DpJt;9(8vh~nsfbo^{@Ke(wU-+0(W9PJ04Hh=ri z31BpQH2#yGVwu<){7KqCkwkDTqL6VUm0_@m45@bM`HcWKn#G;q3DOaWiSJB;R}0DF-F0v* zqL6ol!6Gue+Efx3{WHTe9;XTrTr_%KK)k_#@;{hr}9TAwtJFa)g!O7_T{Hl1(Cpww>ZyyZtok{fO^UpjM zktF%JKL3p8$w|#Y#KfK83DP{Q7hsx=$n@s=3lDlEAJ_F4y}5p;JU*`LcY1UES9yF~ z*MIfw`axGjzD1Ubp5-X4@!0a1Un)$A>Dt& zj!5@!vGYNx?*G#fk?tR5M}&?@_aEzsD2`SHFZ?#NvGYkw`@Js;vgeo`6s~Cfc+rQ= z1$P^>V=+t7J~4Fcm))f*-hWjP$DCPd*7 zsH`}4EkJNwgoR-PEP*{9Aq%^kTB-z;fD%vwN&50Z(`&^2kI!?v9+^c9`XO{defYxiK>*+r*Yhq4|$s^&ZDba~Bmy3VMBCTQ_M zj?MqgM;v^ppZL-7mC}bNXF?nd5RH};AqK|OB>;Rxatt4^&cf?AgD_^tS;dAoLVGe& zCQXrY@{@e43e{yoRa#m@uttocP;#1Cy%{XeHli|$59a3?~jaUblDVcBeQ1hC7d zl`%ieY!3194IzAaBgMxb;nI-ODH4>1NhejGjxD`?0?lmE1G~{M``UqFjp&qdA?&)q z5J>fISR5jG7EKbNXp+P^+NonY>obnd905$mNKd%fr6GN$e+YfdBLtQYYg7;{&CU-N z0YR(!jxBY1z)33aBVbOs4^if>UDGuJ&^0_91kH~I@?}Q@1vnZgW;@!cW1_h07~*nQ zpe}b?q{{Z`xwZ%V`Jw{`9fm%BjtVh;$P zWn8lN%0x?vbd(HL*aE@us{Q=4^m$`axOwU_Fo&-I^W>GlhpqyC;u_!s*Mg|uq__8} z#DR#E@+%`{sKRFZ`KRr3bLS4==KNbmfO+`zmGT^R=KkKsG*ZP>7cR$Tb<*7h=`Uou6Sbq$}%6kL6P zy^cDyjp@yPSC~x(U^e;#vpxXW^?_D;T}T&uJ7#H=flZ1HwU;UV%af!TmnMs#qIi;c z%TcGcF|+e)j!7L0%#Lxuq>Kki*tKI@sq=*) z;)?U3BG^Gx=jz(h`$vlOzL7xh9R>8BFA-m@P;JXke%OjSP;SeF z>g#YeL_CK8JJk4WtNL_o=|i91q7DrOI(rzBUNzlsxy4l03QYIkfy(k$iS~ZdefdiWaDcGe zM+~;tt8bqmT!RSetuhnY6ebstneOXzvHwpHi6HTm3 z24c6#+{7alpTTzda{beM`N7-9G0nB?oHAzwoDpzFKq~@DJ{D87Is?L)C&3^%Kh6j^ zBjAjHGXl;CXhZ-!a$kXN7hIrkK?~@9{%!EM-Wc%x4r1gH5NF*5Mmg6KD<@+vbT}8m zwY?S&Hl9qw)!!<@eZR@OAMp|foJf%So!%$8<)4=Oo;fP@Em+3)%IlzP1|q@L5^D*S zjFzji(IQDk>qX=!lf+o)qvRI<)(zV&#(%!IgXER9NBs0)1#+lX(K83cK}SFwcoby! zV={88+f{YtT8L3%Pa#G=W5#?i!otT`Z*eh_5ddCN_5O|)4C@=q6Sj=Pym6)Ay%U75 z(lK|u8^n=&K>U0!h$AvU9G(f{(5wQ-{cy41hWX^HOtcKuh>}yvr$I~5z4&w7j$HB@ zKl!If%rz5y&{{z58F<46;Qcm%!a?&Bwt_Hz8wg`lWPbF{Xvh64V>U|mBBNvyIcl&W zN|uO7IgK$w3oZTUDKp0<`tmW0NpsW^Fi*q$`PAi@Lr(^N%8!8OdXPsC`5E}2{~Tt0 zR=3nzTe+7^k`U0+{vz)sF+SdnpEIAc<=kg4K+Yba{~`p1Gi_y3d+gyao;LMM&S@n<`ll@DTE?yAkljv)AOa zCb@D=x$k4cxP<9uE@1|6-yszKVG;5VDhIJ(mdwtdy9O36#A=qheQrkxqmYL%-9}DA z#hnOQz8x+lUc~d&%}ecCR8n+P3~aEpz=CB*`s4cNrEY$`sw zY3<$~YLrglJKhKvZ{7@-;Km~mi%KSQZ60dYuSX<@^jjfzsIQjL-@Nh+Bv4OR8(+j47z zjqI8bV1Et;8+T*R-~2R1L=I=9)*9xxBzJSvVo$9(Rfb$neifHv<8-bducH8EOI4lv zw(J)F3>)9GApjTzaz4PW3j%hnf{BNy)xnzg4U-VJm|Zwy6(}i$8a|gNOL+)*43lcE z8>+!ojbb{*r-a$&1I#u(Fk2B@d=Y-YZ1NMCjfS|?RPRTgVU+zc+r~9#*9I5j^}58Y z3DV4;o<$xPIjo|KwmK!HR_P%wP7?0bxS^+DYKo>cbGRdnVTmzea?BJyM+lQN-@+Um2I-a6hLu+B==FARlukP9myNeaM$7oY`I*X9o1{(ZKE=UCL#6zoYtxYr`6uPPx02Ck8G?eyNZ; z>M0`MC1Q=&C2H4~tC;O$J+H4fRDYk(g_=M9EmSHyhx;U!y2i*S zRexVqy_{ga{m~%d%7gkurAF~l919f5+yJ(Zs$bu>qM&aZ;#}V%@*MK6$h}f$k$XMU zAIO6KH>rHLj!)x1cO2C;Cy>w1!972QDqa@(+U(q5O7lPEY1UG8mD*6Es7E4I)Jv}7 zY>~I^4P;?&lc})RC{?ev_JBV$%l7BjWCsW`0&0NykUt;xyx+x$%iVetzjwVw{@xYH z%iVyy)E&s;?iQlB`}fNEYTNt%K)UMzgOGO6Ul6m9i?+dlEdu2T-UgKCWe2d2aQC(O zuFJf_i&CW>qlnT@V8b=!udlriRLT1nxjWsfYb3OM?e`OV?>7jADwmysd)0=(9rP95 zw0t}d8J?*G`akAAGRg(;D`4j7p?^xM{b)F$US~$ z-{-Ni!4{wBrA2vkHE%p>v;mt z5t-_J`!y{e&r_yc1FS7+Sy|p9#q?JTFqO9iTMa;YtE=Q+Egrk}>3Va49S`qV4*z0XVYB3Sb0ROAbAbQ&0OS^o9ZMZ+#;S5%+ z^RB?TJ*hstEk{?=IxkX=`)q)92YpOTlOz-4dXZpUBy6u%vM!+{{KHjQTiIWlo?nLd z%~3qZ>2yC~AKp_5X?oTx)%(TNgg)(=mAe1RN|&~{@8O7K6X%j^VqJG(e+0zqURLgn tU3&WMR0Gpu|9Ei8jfYpBb`7V#GXl;CI3wVUfHMNl2sk6)jKG5k{0~Ee%>)1d diff --git a/web/src/assets/logo.tsx b/web/src/assets/logo.tsx index 1f9dd232..8237d266 100644 --- a/web/src/assets/logo.tsx +++ b/web/src/assets/logo.tsx @@ -36,7 +36,7 @@ export function Logo({ className, ...props }: SVGProps) { className={cn('size-6', className)} {...props} > - New API + LFAPI ) diff --git a/web/src/components/layout/components/authenticated-layout.tsx b/web/src/components/layout/components/authenticated-layout.tsx index 237031a2..295cda20 100644 --- a/web/src/components/layout/components/authenticated-layout.tsx +++ b/web/src/components/layout/components/authenticated-layout.tsx @@ -37,7 +37,7 @@ export function AuthenticatedLayout(props: AuthenticatedLayoutProps) { return ( - +
diff --git a/web/src/components/layout/components/footer.tsx b/web/src/components/layout/components/footer.tsx index 438fc6cf..3cc73c6b 100644 --- a/web/src/components/layout/components/footer.tsx +++ b/web/src/components/layout/components/footer.tsx @@ -42,12 +42,6 @@ interface FooterProps { className?: string } -const NEW_API_FOOTER_ATTRIBUTION_KEY = [ - 'footer', - 'new' + 'api', - 'projectAttributionSuffix', -].join('.') - function FooterLinkItem(props: { link: FooterLink }) { const { t } = useTranslation() const isExternal = props.link.href.startsWith('http') @@ -129,14 +123,11 @@ function ProjectAttribution(props: { currentYear: number; inline?: boolean }) { © {props.currentYear}{' '} - {t('New API')} + LFAPI 由 NewAPI 二次开发而成 - . {t(NEW_API_FOOTER_ATTRIBUTION_KEY)} ) if (props.inline) { @@ -158,8 +149,8 @@ export function Footer(props: FooterProps) { demoSiteEnabled, } = useSystemConfig() - const displayLogo = systemLogo || props.logo || '/logo.png' - const displayName = systemName || props.name || 'New API' + const displayLogo = systemLogo || props.logo || '/lfapi-logo.svg' + const displayName = systemName || props.name || 'LFAPI' const isDemoSiteMode = Boolean(demoSiteEnabled) const currentYear = new Date().getFullYear() @@ -170,15 +161,15 @@ export function Footer(props: FooterProps) { links: [ { text: t('footer.columns.about.links.aboutProject'), - href: 'https://docs.newapi.pro/wiki/project-introduction/', + href: '/docs/zh/docs/guide/wiki/basic-concepts/project-introduction', }, { text: t('footer.columns.about.links.contact'), - href: 'https://docs.newapi.pro/support/community-interaction/', + href: '/docs/zh/docs/support/community-interaction', }, { text: t('footer.columns.about.links.features'), - href: 'https://docs.newapi.pro/wiki/features-introduction/', + href: '/docs/zh/docs/guide/wiki/features-introduction', }, ], }, @@ -187,15 +178,15 @@ export function Footer(props: FooterProps) { links: [ { text: t('footer.columns.docs.links.quickStart'), - href: 'https://docs.newapi.pro/getting-started/', + href: '/docs/zh/docs/getting-started', }, { text: t('footer.columns.docs.links.installation'), - href: 'https://docs.newapi.pro/installation/', + href: '/docs/zh/docs/installation', }, { text: t('footer.columns.docs.links.apiDocs'), - href: 'https://docs.newapi.pro/api/', + href: '/docs/zh/docs/api', }, ], }, diff --git a/web/src/components/layout/components/header-logo.tsx b/web/src/components/layout/components/header-logo.tsx index 2ef2b84a..03b48ed4 100644 --- a/web/src/components/layout/components/header-logo.tsx +++ b/web/src/components/layout/components/header-logo.tsx @@ -42,7 +42,7 @@ export function HeaderLogo({ src={src} alt={alt} className={cn( - 'h-6 w-6 rounded-full transition-opacity duration-200', + 'h-6 w-6 rounded-lg transition-opacity duration-200', !loading && logoLoaded ? 'opacity-100' : 'opacity-0', className )} diff --git a/web/src/components/layout/components/public-layout.tsx b/web/src/components/layout/components/public-layout.tsx index bcb65dbe..b8fbad37 100644 --- a/web/src/components/layout/components/public-layout.tsx +++ b/web/src/components/layout/components/public-layout.tsx @@ -34,7 +34,7 @@ type PublicLayoutProps = { export function PublicLayout(props: PublicLayoutProps) { return ( -
+
-
+
{t('Logo')}
{name} @@ -89,7 +89,7 @@ export function SystemBrand(props: SystemBrandProps) { {t('Logo')}
diff --git a/web/src/features/about/index.tsx b/web/src/features/about/index.tsx index 22834305..8aa1b660 100644 --- a/web/src/features/about/index.tsx +++ b/web/src/features/about/index.tsx @@ -47,62 +47,21 @@ function EmptyAboutState() {

- {t('New API Project Repository:')}{' '} - - {t('https://github.com/QuantumNous/new-api')} + LFAPI 源码与许可证:{' '} + + /source

- - {t('NewAPI')} - {' '} - © {currentYear}{' '} - - {t('QuantumNous')} - {' '} - {t('| Based on')}{' '} - - {t('One API')} - {' '} - © 2023{' '} - - {t('JustSong')} - + LFAPI 由 NewAPI 二次开发而成。© {currentYear}

{t('This project must be used in compliance with the')}{' '} - {t('AGPL v3.0 License')} + AGPL v3.0 License .

diff --git a/web/src/features/auth/auth-layout.tsx b/web/src/features/auth/auth-layout.tsx index ba3a5bf9..50d0e857 100644 --- a/web/src/features/auth/auth-layout.tsx +++ b/web/src/features/auth/auth-layout.tsx @@ -31,7 +31,7 @@ export function AuthLayout({ children }: AuthLayoutProps) { const { systemName, logo, loading } = useSystemConfig() return ( -
+
)}
diff --git a/web/src/features/channels/api.ts b/web/src/features/channels/api.ts index fa13a186..b898a405 100644 --- a/web/src/features/channels/api.ts +++ b/web/src/features/channels/api.ts @@ -301,18 +301,17 @@ export async function deleteDisabledChannels(): Promise<{ } /** - * Get channel key (requires 2FA verification) + * Get channel key (available to the Root administrator) */ -export async function getChannelKey( - id: number, - proofToken?: string -): Promise<{ success: boolean; message?: string; data?: { key: string } }> { +export async function getChannelKey(id: number): Promise<{ + success: boolean + message?: string + data?: { key: string } +}> { const res = await api.post( `/api/channel/${id}/key`, undefined, - channelActionConfig({ - headers: proofToken ? { 'X-Security-Proof': proofToken } : undefined, - }) + channelActionConfig() ) return res.data } diff --git a/web/src/features/channels/components/drawers/channel-mutate-drawer.tsx b/web/src/features/channels/components/drawers/channel-mutate-drawer.tsx index 93f6a0a1..8f5e859c 100644 --- a/web/src/features/channels/components/drawers/channel-mutate-drawer.tsx +++ b/web/src/features/channels/components/drawers/channel-mutate-drawer.tsx @@ -107,10 +107,6 @@ import { TooltipContent, TooltipTrigger, } from '@/components/ui/tooltip' -import { - SecureVerificationDialog, - useSecureVerification, -} from '@/features/auth/secure-verification' import { useCopyToClipboard } from '@/hooks/use-copy-to-clipboard' import { useHiddenClickUnlock } from '@/hooks/use-hidden-click-unlock' import { @@ -695,17 +691,6 @@ export function ChannelMutateDrawer({ const { copyToClipboard } = useCopyToClipboard() - const { - open: verificationOpen, - methods: verificationMethods, - state: verificationState, - executeVerification, - withVerification, - cancel: cancelVerification, - setCode: setVerificationCode, - switchMethod: switchVerificationMethod, - } = useSecureVerification() - useEffect(() => { if (!open) { setChannelKey(null) @@ -1373,14 +1358,14 @@ export function ChannelMutateDrawer({ } const fetchChannelKey = useCallback( - async (proofToken?: string) => { + async () => { if (!channelId) { throw new Error('Channel is not selected') } setIsChannelKeyLoading(true) try { - const res = await getChannelKey(channelId, proofToken) + const res = await getChannelKey(channelId) if (!res.success) { throw new Error(res.message || t('Failed to fetch channel key')) } @@ -1400,20 +1385,13 @@ export function ChannelMutateDrawer({ if (!channelId) return try { - await withVerification(fetchChannelKey, { - scope: 'channel.key.read', - preferredMethod: 'passkey', - title: t('Verify to view channel key'), - description: t( - 'Use Passkey or 2FA to confirm your identity before revealing this channel key.' - ), - }) + await fetchChannelKey() } catch (error) { if (error instanceof Error) { toast.error(error.message) } } - }, [channelId, withVerification, fetchChannelKey, t]) + }, [channelId, fetchChannelKey]) const handleRefreshCodexCredential = useCallback(async () => { if (!channelId) return @@ -3119,9 +3097,7 @@ export function ChannelMutateDrawer({ {t('Current key')}

- {t( - 'Verification required to reveal the saved key.' - )} + {t('Display and copy the saved key.')}

@@ -3130,13 +3106,9 @@ export function ChannelMutateDrawer({ variant='outline' size='sm' onClick={handleRevealKey} - disabled={ - isChannelKeyLoading || - verificationState.loading - } + disabled={isChannelKeyLoading} > - {isChannelKeyLoading || - verificationState.loading ? ( + {isChannelKeyLoading ? ( ) : ( @@ -3165,7 +3137,7 @@ export function ChannelMutateDrawer({ readOnly value={channelKey ?? ''} placeholder={t( - 'Hidden — verify to reveal' + 'Hidden — select reveal to display' )} className='font-mono' /> @@ -4931,23 +4903,6 @@ export function ChannelMutateDrawer({ existingModelsOverride={currentModelsArray} /> - { - if (!open) { - cancelVerification() - } - }} - methods={verificationMethods} - state={verificationState} - onVerify={async (method, code) => { - await executeVerification(method, code) - }} - onCancel={cancelVerification} - onCodeChange={setVerificationCode} - onMethodChange={switchVerificationMethod} - /> - {/* Missing Models Confirmation Dialog */} +
{/* Gradient mesh background */}
+

diff --git a/web/src/features/home/components/sections/hero.tsx b/web/src/features/home/components/sections/hero.tsx index 4a08151a..59aab528 100644 --- a/web/src/features/home/components/sections/hero.tsx +++ b/web/src/features/home/components/sections/hero.tsx @@ -49,7 +49,7 @@ export function Hero(props: HeroProps) { const { t } = useTranslation() const { status } = useStatus() const docsUrl = - (status?.docs_link as string | undefined) || 'https://docs.newapi.pro' + (status?.docs_link as string | undefined) || '/docs' const renderDocsButton = () => { const isExternal = docsUrl.startsWith('http') @@ -180,7 +180,7 @@ export function Hero(props: HeroProps) {

{t( - 'Supports one-click configuration and perfectly adapts to NewAPI multi-protocol configuration.' + 'Supports one-click configuration and multi-protocol configuration.' )}

diff --git a/web/src/features/home/components/sections/how-it-works.tsx b/web/src/features/home/components/sections/how-it-works.tsx index 2959fd87..fa8150c3 100644 --- a/web/src/features/home/components/sections/how-it-works.tsx +++ b/web/src/features/home/components/sections/how-it-works.tsx @@ -50,7 +50,7 @@ export function HowItWorks() { ] return ( -
+

diff --git a/web/src/features/home/components/sections/stats.tsx b/web/src/features/home/components/sections/stats.tsx index c3a5bc1d..7639a2a2 100644 --- a/web/src/features/home/components/sections/stats.tsx +++ b/web/src/features/home/components/sections/stats.tsx @@ -105,7 +105,7 @@ export function Stats(_props: StatsProps) { ] return ( -

+
{stats.map((s) => ( diff --git a/web/src/features/system-settings/auth/passkey-section.tsx b/web/src/features/system-settings/auth/passkey-section.tsx index c2296196..5858a0c1 100644 --- a/web/src/features/system-settings/auth/passkey-section.tsx +++ b/web/src/features/system-settings/auth/passkey-section.tsx @@ -225,7 +225,7 @@ export function PasskeySection(props: PasskeySectionProps) { {t('Relying Party Display Name')} field.onChange(event.target.value)} name={field.name} diff --git a/web/src/features/system-settings/general/system-info-section.tsx b/web/src/features/system-settings/general/system-info-section.tsx index 3758b369..18d3c48b 100644 --- a/web/src/features/system-settings/general/system-info-section.tsx +++ b/web/src/features/system-settings/general/system-info-section.tsx @@ -154,7 +154,7 @@ export function SystemInfoSection({ defaultValues }: SystemInfoSectionProps) { {t('System Name')} - + {t('The name displayed across the application')} @@ -282,7 +282,7 @@ export function SystemInfoSection({ defaultValues }: SystemInfoSectionProps) { {t('Home Page Content')}