dns-worker 1.1.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/serverfull.mjs +73 -69
- package/dist/serverfull.mjs.map +4 -4
- package/package.json +3 -1
- package/static/assets/AccountView-p5jSjMAE.js +4 -0
- package/static/assets/{AnalyticsView-C_g_jz14.js → AnalyticsView-BywwDzah.js} +2 -2
- package/static/assets/AuthView-qoUKd5PS.js +2 -0
- package/static/assets/{DestinationMap-jSW7gimP.js → DestinationMap-9Yc54Mdj.js} +1 -1
- package/static/assets/FilteringView-Bs3__NpV.js +1 -0
- package/static/assets/LogsView-B-U9oaxB.js +5 -0
- package/static/assets/{QRCodeCanvas-Cu_-aNyM.js → QRCodeCanvas-DQ-xNuwF.js} +2 -2
- package/static/assets/{RulesView-CfVeQv0-.js → RulesView-B2kL1QhI.js} +1 -1
- package/static/assets/SettingsView-DTGI6eSd.js +1 -0
- package/static/assets/SetupView-DE9MM-32.js +1 -0
- package/static/assets/{SwipeableDrawer-BrmEzhuP.js → SwipeableDrawer-B81ANpsc.js} +1 -1
- package/static/assets/{TrendChart-Dc5yJndv.js → TrendChart-CCR1W3fC.js} +3 -3
- package/static/assets/browser-Dc5iKjY4.js +1 -0
- package/static/assets/date-CpvuBM37.js +1 -0
- package/static/assets/{de-DE-CA3VPcoz.js → de-DE-kDnumQOF.js} +1 -1
- package/static/assets/{es-ES-CHvRWwd-.js → es-ES-CqKS7vHl.js} +1 -1
- package/static/assets/{fr-FR-CqGOuepx.js → fr-FR-BRcdpT35.js} +1 -1
- package/static/assets/getFlagEmoji-DRubsb7D.js +1 -0
- package/static/assets/index-Bheo8y3N.css +2 -0
- package/static/assets/index-dXN_pYn1.js +16 -0
- package/static/assets/{ja-JP-BJSbUSmh.js → ja-JP-C5jk6SuH.js} +1 -1
- package/static/assets/{ko-KR-Chzg6jwO.js → ko-KR-z38NtMFa.js} +1 -1
- package/static/assets/{ru-RU-CSyCGGPn.js → ru-RU-Bicx52lz.js} +1 -1
- package/static/assets/services-BVnEJBDq.js +1 -0
- package/static/assets/vendor-i18next-BKUzkAKP.js +1 -0
- package/static/assets/vendor-react-BmoHsW1x.js +11 -0
- package/static/assets/{vendor-ui-core-sfZn2C08.js → vendor-ui-core-CY_WyMIf.js} +1 -1
- package/static/assets/{vendor-utils-CnB7BG7m.js → vendor-utils-BWSB0jGn.js} +1 -1
- package/static/assets/{vi-VN-D7rcA1IX.js → vi-VN-CvS_mTAu.js} +1 -1
- package/static/assets/{zh-CN-CSPdaOkF.js → zh-CN-B0nRgJTD.js} +1 -1
- package/static/assets/{zh-TW-DETA1X3X.js → zh-TW-lc_SSoVI.js} +1 -1
- package/static/index.html +6 -6
- package/static/sw.js +1 -1
- package/static/assets/AccountView-CGRwz6ae.js +0 -4
- package/static/assets/AuthView-BQzmEyvO.js +0 -2
- package/static/assets/FilteringView-CQ7sX3Rp.js +0 -1
- package/static/assets/LogsView-eLfZMRVo.js +0 -5
- package/static/assets/SettingsView-agJiYEt5.js +0 -1
- package/static/assets/SetupView-CTgCUAgk.js +0 -1
- package/static/assets/browser-DPi2BX_1.js +0 -1
- package/static/assets/date-IKj2stuv.js +0 -1
- package/static/assets/getFlagEmoji-_Wxhq0lT.js +0 -1
- package/static/assets/index-919BqnYI.css +0 -2
- package/static/assets/index-CbTjGMTZ.js +0 -16
- package/static/assets/services-Cwvmit1q.js +0 -1
- package/static/assets/vendor-i18next-cO7FDf_e.js +0 -1
- package/static/assets/vendor-react-CHk5ngkq.js +0 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dns-worker",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Privacy-first DNS & DoH Resolver with modern Web Dashboard, built for Cloudflare Workers & Node.js",
|
|
6
6
|
"main": "./dist/serverfull.mjs",
|
|
@@ -42,6 +42,8 @@
|
|
|
42
42
|
"test": "tsx test/test_legacy_compat.ts",
|
|
43
43
|
"test:compat": "tsx test/test_legacy_compat.ts",
|
|
44
44
|
"test:serverfull": "tsx test/test_serverfull.ts",
|
|
45
|
+
"test:reset": "tsx test/test_serverfull_reset.ts",
|
|
46
|
+
"test:dbsize": "tsx test/test_db_size.ts",
|
|
45
47
|
"lint": "eslint . --ext .ts,.tsx",
|
|
46
48
|
"ui:dev": "cd web && npm run dev",
|
|
47
49
|
"ui:build": "cd web && npm run build",
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/date-CpvuBM37.js","assets/index-dXN_pYn1.js","assets/vendor-icons-other-Bme3ywH9.js","assets/vendor-icons-16-BgwRBCeU.js","assets/rolldown-runtime-C4Xdq4VV.js","assets/vendor-icons-20-X5NPN60g.js","assets/vendor-react-BmoHsW1x.js","assets/vendor-ui-core-CY_WyMIf.js","assets/vendor-utils-BWSB0jGn.js","assets/vendor-i18next-BKUzkAKP.js","assets/index-Bheo8y3N.css"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{i as e}from"./rolldown-runtime-C4Xdq4VV.js";import{$ as t,A as n,B as r,C as i,D as a,E as o,Et as s,J as c,M as l,Q as u,Qt as d,R as f,S as p,W as m,X as h,Y as g,b as _,ft as v,gt as y,ht as b,it as x,j as S,k as C,lt as w,rt as T,st as E,x as D,y as O,z as k}from"./vendor-react-BmoHsW1x.js";import{S as A,b as j,x as M}from"./vendor-icons-other-Bme3ywH9.js";import{r as ee}from"./vendor-i18next-BKUzkAKP.js";import{B as N,C as P,D as F,F as te,H as I,L,M as R,N as z,O as B,P as ne,R as V,S as H,T as re,V as U,_ as W,d as ie,f as G,h as ae,j as K,p as q,r as J,t as oe,u as se,v as ce,x as Y,z as X}from"./vendor-ui-core-CY_WyMIf.js";import{_t as le}from"./vendor-utils-BWSB0jGn.js";import{At as ue,Bt as de,Ct as fe,Dt as pe,Et as me,F as he,Gt as ge,Ht as _e,I as ve,It as ye,Jt as be,Kt as xe,Lt as Se,M as Ce,Mt as we,N as Te,Nt as Ee,Ot as De,P as Oe,Pt as ke,Rt as Ae,St as je,Tt as Me,Ut as Ne,Vt as Pe,Wt as Fe,Xt as Ie,Yt as Le,Zt as Re,d as ze,f as Be,i as Ve,j as Z,jt as He,kt as Ue,l as We,ln as Ge,m as Ke,nn as qe,o as Je,p as Ye,qt as Xe,s as Ze,v as Qe,w as $e,wt as et,zt as tt}from"./index-dXN_pYn1.js";import{t as nt}from"./QRCodeCanvas-DQ-xNuwF.js";var Q=e(A(),1),$=e(j(),1);const rt=({recoveryKeys:e,copied:t,onCopy:r,onDone:i})=>{let{t:a}=d();return(0,$.jsxs)(`div`,{className:`p-4 bg-gray-50 dark:bg-gray-900/50 rounded-lg border border-gray-200 dark:border-gray-800`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2 mb-4`,children:[(0,$.jsx)(n,{size:20,className:`text-green-500`}),(0,$.jsx)(K,{style:{margin:0},children:a(`account.totp.recoveryKeysTitle`,`Save Your Recovery Keys`)})]}),(0,$.jsx)(H,{intent:U.WARNING,className:`mb-4`,children:a(`account.totp.recoveryKeysWarning`,`Store these keys safely. Each key can only be used once.`)}),(0,$.jsx)(`div`,{className:e.length===1?`space-y-2 mb-4`:`grid grid-cols-2 gap-2 mb-4`,children:e.map((e,t)=>(0,$.jsx)(`code`,{className:`block font-mono text-sm sm:text-base font-semibold bg-gray-100 dark:bg-gray-800 text-blue-600 dark:text-blue-400 px-4 py-3 rounded-xl text-center tracking-widest break-all select-all border border-gray-200 dark:border-gray-700`,children:e},t))}),(0,$.jsxs)(`div`,{className:`flex gap-2`,children:[(0,$.jsx)(z,{fill:!0,icon:(0,$.jsx)(w,{size:14}),text:t?a(`account.totp.copied`,`Copied!`):a(`account.totp.copyKeys`,`Copy All Keys`),intent:t?U.SUCCESS:U.NONE,onClick:r}),(0,$.jsx)(z,{fill:!0,intent:U.PRIMARY,text:a(`account.totp.done`,`Done, I've saved them`),onClick:i})]})]})},it=({onRefresh:e,toasterRef:t})=>{let{t:n}=d(),[r,i]=(0,Q.useState)([]),[a,o]=(0,Q.useState)(!0),[s,c]=(0,Q.useState)(!0),[l,u]=(0,Q.useState)(null),[f,p]=(0,Q.useState)(!1),[m,h]=(0,Q.useState)(null),[g,_]=(0,Q.useState)(!1),[v,y]=(0,Q.useState)(``),[b,x]=(0,Q.useState)(!1),[S,C]=(0,Q.useState)(!1),[w,T]=(0,Q.useState)(``),[E,D]=(0,Q.useState)(null),[O,k]=(0,Q.useState)(``),[A,j]=(0,Q.useState)(!1),[M,ee]=(0,Q.useState)(!1),[N,P]=(0,Q.useState)(``),[F,te]=(0,Q.useState)(null),[I,L]=(0,Q.useState)(!1),[R,z]=(0,Q.useState)(null),B=(0,Q.useCallback)(async()=>{o(!0);try{i(await Ee()||[])}catch{}finally{o(!1)}},[]);return(0,Q.useEffect)(()=>{c(Le()),B()},[B]),{passkeys:r,loading:a,supported:s,recoveryKeys:l,setRecoveryKeys:u,copiedKeys:f,handleCopyRecoveryKeys:()=>{l&&navigator.clipboard.writeText(l.join(`
|
|
3
|
+
`)).then(()=>{p(!0),setTimeout(()=>p(!1),2e3)})},isAddOpen:g,setIsAddOpen:_,passkeyName:v,setPasskeyName:y,nameFocused:b,setNameFocused:x,registering:S,addError:w,setAddError:T,handleOpenAdd:()=>{y(``),T(``),x(!1),_(!0)},handleRegister:async t=>{t.preventDefault();let r=v.trim();if(!Qe(r)){T(n(`account.passkey.formatTip`,`1-30 characters, letters, numbers, hyphens and underscores allowed`));return}C(!0),T(``);try{let t=await be({name:r,credential:await Re(await we())}),n=t?.passkey?.id||t?.id;if(n&&Z.isUnlocked())try{await Z.wrapCurrentKeyForPasskey(n)}catch(e){console.warn(`[Passkeys] Failed to wrap existing E2EE key for new passkey:`,e)}_(!1),y(``),await B(),e?.(),t?.recovery_keys&&t.recovery_keys.length>0&&u(t.recovery_keys)}catch(e){console.error(`Passkey registration failed:`,e),T(e instanceof Error?e.message:n(`account.passkey.regFailed`,`Registration failed`))}finally{C(!1)}},editingPasskey:E,setEditingPasskey:D,editName:O,setEditName:k,renameFocused:A,setRenameFocused:j,renaming:M,renameError:N,setRenameError:P,handleOpenRename:e=>{D(e),k(e.name),P(``),j(!1)},handleRenameSubmit:async e=>{e.preventDefault();let t=O.trim();if(!(!E||!t)){if(!Qe(t)){P(n(`account.passkey.formatTip`,`1-30 characters, letters, numbers, hyphens and underscores allowed`));return}ee(!0),P(``);try{await ye(E.id,t),D(null),await B()}catch(e){P(e instanceof Error?e.message:n(`common.errorNetwork`))}finally{ee(!1)}}},deletingId:F,deleteConfirmOpen:I,setDeleteConfirmOpen:L,targetToDelete:R,handleOpenDelete:e=>{z(e),L(!0)},handleDeleteSubmit:async()=>{if(R){te(R.id);try{await me(R.id),L(!1),z(null),await B(),e?.()}catch(e){let t=e instanceof Error?e.message:n(`common.errorNetwork`);alert(t)}finally{te(null)}}},testingId:m,handleTestPasskey:async e=>{h(e?e.id:`all`);try{let r=await _e(e?.id);r.success&&(t?.current?.show({message:n(`account.passkey.testSuccess`,{name:r.passkey?.name||e?.name||``,defaultValue:`Passkey verified successfully: ${r.passkey?.name||e?.name||``}`}),intent:U.SUCCESS,icon:`tick-circle`}),await B())}catch(e){let r=e instanceof Error?e.message:String(e);r.includes(`cancelled`)||r.includes(`NotAllowedError`)||r.includes(`timed out`)||r.includes(`abort`)?t?.current?.show({message:n(`account.passkey.testCancelled`,`Passkey verification cancelled`),intent:U.WARNING,icon:`warning-sign`}):t?.current?.show({message:r||n(`account.passkey.testFailed`,`Passkey verification failed`),intent:U.DANGER,icon:`error`})}finally{h(null)}},fetchPasskeys:B}},at=({passkeys:e,loading:a,deletingId:o,testingId:s,onTestPasskey:c,onOpenRename:l,onOpenDelete:u})=>{let{t:f}=d();return a?(0,$.jsx)(`div`,{className:`py-6 text-center`,children:(0,$.jsx)(ne,{size:24})}):e.length===0?(0,$.jsxs)(`div`,{className:`py-6 text-center text-sm text-gray-500 dark:text-gray-400 border border-dashed border-gray-200 dark:border-gray-800 rounded-lg`,children:[(0,$.jsx)(t,{size:28,className:`mx-auto mb-2 opacity-40`}),(0,$.jsx)(`p`,{children:f(`account.passkey.empty`,`No passkeys added yet.`)})]}):(0,$.jsx)(`div`,{className:`divide-y divide-gray-100 dark:divide-gray-800 border border-gray-200 dark:border-gray-800 rounded-lg overflow-hidden`,children:e.map(e=>(0,$.jsxs)(`div`,{className:`p-3 sm:p-4 flex items-center justify-between gap-3 hover:bg-gray-50 dark:hover:bg-gray-900/40 transition-colors`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-3 min-w-0`,children:[(0,$.jsx)(`div`,{className:`p-2 bg-purple-50 dark:bg-purple-950/40 text-purple-600 dark:text-purple-400 rounded-lg shrink-0`,children:(0,$.jsx)(t,{size:18})}),(0,$.jsxs)(`div`,{className:`min-w-0`,children:[(0,$.jsx)(`div`,{className:`font-semibold text-sm truncate text-gray-900 dark:text-gray-100`,children:e.name}),(0,$.jsxs)(`div`,{className:`text-xs text-gray-500 dark:text-gray-400 flex flex-wrap gap-x-3 gap-y-1 mt-0.5`,children:[(0,$.jsxs)(`span`,{children:[f(`account.passkey.created`,`Added`),`:`,` `,$e(new Date(e.created_at*1e3))]}),e.last_used_at?(0,$.jsxs)(`span`,{children:[f(`account.passkey.lastUsed`,`Last used`),`:`,` `,$e(new Date(e.last_used_at*1e3))]}):(0,$.jsx)(`span`,{children:f(`account.passkey.neverUsed`,`Never used`)})]})]})]}),(0,$.jsxs)(`div`,{className:`flex items-center gap-1 shrink-0`,children:[(0,$.jsx)(z,{minimal:!0,small:!0,intent:U.PRIMARY,icon:(0,$.jsx)(n,{size:14}),title:f(`account.passkey.testThis`,`Test this passkey`),loading:s===e.id,onClick:()=>c?.(e)}),(0,$.jsx)(z,{minimal:!0,small:!0,icon:(0,$.jsx)(r,{size:14}),title:f(`common.rename`,`Rename`),onClick:()=>l(e)}),(0,$.jsx)(z,{minimal:!0,small:!0,intent:U.DANGER,icon:(0,$.jsx)(i,{size:14}),title:f(`common.delete`,`Delete`),loading:o===e.id,onClick:()=>u(e)})]})]},e.id))})},ot=({isOpen:e,onClose:t,passkeyName:n,setPasskeyName:r,nameFocused:i,setNameFocused:a,registering:o,addError:s,setAddError:c,onSubmit:l})=>{let{t:u}=d();return(0,$.jsx)(B,{isOpen:e,onClose:()=>!o&&t(),title:u(`account.passkey.addTitle`,`Add New Passkey`),className:`max-w-md`,children:(0,$.jsxs)(`form`,{onSubmit:l,children:[(0,$.jsxs)(`div`,{className:L,children:[s&&(0,$.jsx)(H,{intent:U.DANGER,className:`mb-4`,children:s}),(0,$.jsx)(q,{label:u(`account.passkey.nameLabel`,`Passkey Name`),labelFor:`passkey-name-input`,helperText:u(`account.passkey.formatTip`,`1-30 characters, letters, numbers, hyphens and underscores allowed`),children:(0,$.jsx)(ce,{content:u(`account.passkey.formatTip`,`1-30 characters, letters, numbers, hyphens and underscores allowed`),isOpen:i,position:N.TOP,intent:U.PRIMARY,className:`w-full`,children:(0,$.jsx)(`div`,{className:`w-full block`,children:(0,$.jsx)(G,{id:`passkey-name-input`,autoFocus:!0,placeholder:u(`account.passkey.namePlaceholder`,`e.g. my_passkey`),value:n,onChange:e=>{r(e.target.value),s&&c(``)},onFocus:()=>a(!0),onBlur:()=>a(!1),disabled:o})})})}),(0,$.jsx)(`p`,{className:`text-xs text-gray-500 dark:text-gray-400`,children:u(`account.passkey.promptNotice`,`After clicking continue, your browser will prompt you to authenticate via Key, face scan, PIN, or hardware key.`)})]}),(0,$.jsx)(`div`,{className:V,children:(0,$.jsxs)(`div`,{className:X,children:[(0,$.jsx)(z,{text:u(`common.cancel`,`Cancel`),onClick:t,disabled:o}),(0,$.jsx)(z,{intent:U.PRIMARY,type:`submit`,text:u(`account.passkey.continue`,`Continue`),loading:o,disabled:!Qe(n.trim())||o})]})})]})})},st=({isOpen:e,onClose:t,editName:n,setEditName:r,renameFocused:i,setRenameFocused:a,renaming:o,renameError:s,setRenameError:c,onSubmit:l})=>{let{t:u}=d();return(0,$.jsx)(B,{isOpen:e,onClose:()=>!o&&t(),title:u(`account.passkey.renameTitle`,`Rename Passkey`),className:`max-w-md`,children:(0,$.jsxs)(`form`,{onSubmit:l,children:[(0,$.jsxs)(`div`,{className:L,children:[s&&(0,$.jsx)(H,{intent:U.DANGER,className:`mb-4`,children:s}),(0,$.jsx)(q,{label:u(`account.passkey.appNameLabel`,`Application (Domain)`),children:(0,$.jsx)(G,{readOnly:!0,disabled:!0,leftIcon:`globe`,value:window.location.hostname})}),(0,$.jsx)(q,{label:u(`account.passkey.nameLabel`,`Passkey Name`),helperText:u(`account.passkey.formatTip`,`1-30 characters, letters, numbers, hyphens and underscores allowed`),children:(0,$.jsx)(ce,{content:u(`account.passkey.formatTip`,`1-30 characters, letters, numbers, hyphens and underscores allowed`),isOpen:i,position:N.TOP,intent:U.PRIMARY,className:`w-full`,children:(0,$.jsx)(`div`,{className:`w-full block`,children:(0,$.jsx)(G,{autoFocus:!0,placeholder:u(`account.passkey.namePlaceholder`,`e.g. my_passkey`),value:n,onChange:e=>{r(e.target.value),s&&c(``)},onFocus:()=>a(!0),onBlur:()=>a(!1),disabled:o})})})})]}),(0,$.jsx)(`div`,{className:V,children:(0,$.jsxs)(`div`,{className:X,children:[(0,$.jsx)(z,{text:u(`common.cancel`,`Cancel`),onClick:t,disabled:o}),(0,$.jsx)(z,{intent:U.PRIMARY,type:`submit`,text:u(`common.save`,`Save`),loading:o,disabled:!Qe(n.trim())||o})]})})]})})},ct=({isOpen:e,onClose:t,targetToDelete:n,deleting:r,onConfirm:i})=>{let{t:a}=d();return(0,$.jsxs)(B,{isOpen:e,onClose:()=>!r&&t(),title:a(`account.passkey.deleteTitle`,`Delete Passkey`),className:`max-w-md`,children:[(0,$.jsx)(`div`,{className:L,children:(0,$.jsx)(`p`,{children:a(`account.passkey.deleteConfirm`,`Are you sure you want to delete passkey "{{name}}"? You will no longer be able to use this passkey for MFA.`,{name:n?.name})})}),(0,$.jsx)(`div`,{className:V,children:(0,$.jsxs)(`div`,{className:X,children:[(0,$.jsx)(z,{text:a(`common.cancel`,`Cancel`),onClick:t,disabled:r}),(0,$.jsx)(z,{intent:U.DANGER,text:a(`common.delete`,`Delete`),onClick:i,loading:r})]})})]})},lt=({onRefresh:e})=>{let{t}=d(),r=(0,Q.useRef)(null),{passkeys:i,loading:a,supported:o,recoveryKeys:s,setRecoveryKeys:c,copiedKeys:l,handleCopyRecoveryKeys:f,isAddOpen:p,setIsAddOpen:m,passkeyName:h,setPasskeyName:g,nameFocused:_,setNameFocused:v,registering:y,addError:b,setAddError:x,handleOpenAdd:C,handleRegister:w,editingPasskey:T,setEditingPasskey:E,editName:D,setEditName:O,renameFocused:A,setRenameFocused:j,renaming:M,renameError:ee,setRenameError:N,handleOpenRename:P,handleRenameSubmit:F,deletingId:te,deleteConfirmOpen:I,setDeleteConfirmOpen:L,targetToDelete:R,handleOpenDelete:B,handleDeleteSubmit:ne,testingId:V,handleTestPasskey:re}=it({onRefresh:e,toasterRef:r});return s?(0,$.jsx)(rt,{recoveryKeys:s,copied:l,onCopy:f,onDone:()=>c(null)}):(0,$.jsxs)(`div`,{className:`space-y-4`,children:[(0,$.jsx)(oe,{ref:r}),(0,$.jsxs)(`div`,{className:`flex items-center justify-between mb-4`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(u,{size:20,className:`text-purple-500`}),(0,$.jsx)(K,{style:{margin:0},children:t(`account.passkey.title`,`Passkeys`)}),(0,$.jsx)(J,{intent:i.length>0?U.SUCCESS:U.NONE,minimal:!0,round:!0,children:i.length>0?t(`account.passkey.count`,{count:i.length,defaultValue:`${i.length} configured`}):t(`account.passkey.none`,`None configured`)})]}),(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[o&&i.length>0&&(0,$.jsx)(z,{intent:U.NONE,outlined:!0,icon:(0,$.jsx)(n,{size:16}),text:t(`account.passkey.testBtn`,`Test Passkey`),onClick:()=>re(),loading:V===`all`}),o&&(0,$.jsx)(z,{intent:U.PRIMARY,icon:(0,$.jsx)(k,{size:16}),text:t(`account.passkey.addBtn`,`Add Passkey`),onClick:C})]})]}),(0,$.jsx)(`p`,{className:`text-sm text-gray-600 dark:text-gray-400 mb-4`,children:t(`account.passkey.desc`,`Authenticate securely with biometrics (Touch ID, Face ID, Windows Hello) or a hardware security key (YubiKey) as an MFA factor.`)}),!o&&(0,$.jsx)(H,{intent:U.WARNING,icon:(0,$.jsx)(S,{size:16}),className:`mb-4`,children:t(`account.passkey.notSupported`,`Your browser or device does not support Passkeys (WebAuthn).`)}),(0,$.jsx)(at,{passkeys:i,loading:a,deletingId:te,testingId:V,onTestPasskey:re,onOpenRename:P,onOpenDelete:B}),(0,$.jsx)(ot,{isOpen:p,onClose:()=>m(!1),passkeyName:h,setPasskeyName:g,nameFocused:_,setNameFocused:v,registering:y,addError:b,setAddError:x,onSubmit:w}),(0,$.jsx)(st,{isOpen:!!T,onClose:()=>E(null),editName:D,setEditName:O,renameFocused:A,setRenameFocused:j,renaming:M,renameError:ee,setRenameError:N,onSubmit:F}),(0,$.jsx)(ct,{isOpen:I,onClose:()=>L(!1),targetToDelete:R,deleting:!!te,onConfirm:ne})]})},ut=({isOpen:e,onClose:n})=>{let{t:r}=d(),[i,a]=(0,Q.useState)(``),[o,s]=(0,Q.useState)(!1),[c,l]=(0,Q.useState)(``),[u,f]=(0,Q.useState)(!1);(0,Q.useEffect)(()=>{e&&(a(``),l(``),f(!1),s(!1))},[e]);let p=async e=>{let t=(e??i).trim().replace(/\s/g,``);if(t.length!==6){l(r(`account.totp.invalidCode`,`Please enter a 6-digit code`));return}s(!0),l(``),f(!1);try{await Ne(t),f(!0)}catch(e){l((e instanceof Error?e.message:String(e))||r(`account.totp.testFailed`,`Invalid verification code`))}finally{s(!1)}};return(0,$.jsx)(B,{isOpen:e,onClose:n,title:r(`account.totp.testTitle`,`Test Authenticator App (TOTP)`),icon:(0,$.jsx)(t,{size:18}),children:(0,$.jsxs)(`div`,{className:`p-6 space-y-4`,children:[(0,$.jsx)(`p`,{className:`text-sm text-gray-600 dark:text-gray-400`,children:r(`account.totp.testDesc`,`Enter the 6-digit verification code from your authenticator app to verify that it is generating valid codes.`)}),u&&(0,$.jsx)(H,{intent:U.SUCCESS,icon:(0,$.jsx)(v,{size:16}),children:r(`account.totp.testSuccess`,`Verification successful! Your authenticator app is configured properly.`)}),c&&(0,$.jsx)(H,{intent:U.DANGER,children:c}),(0,$.jsxs)(`form`,{onSubmit:e=>{e.preventDefault(),p()},className:`space-y-4`,children:[(0,$.jsx)(q,{label:r(`account.totp.verificationCode`,`6-Digit Verification Code`),labelFor:`test-totp-input`,children:(0,$.jsx)(G,{id:`test-totp-input`,value:i,onChange:e=>{let t=e.target.value.replace(/\D/g,``).slice(0,6);a(t),l(``),f(!1),t.length===6&&p(t)},placeholder:`123456`,maxLength:6,autoFocus:!0,inputMode:`numeric`,autoComplete:`one-time-code`,className:`font-mono text-lg tracking-widest`,disabled:o})}),(0,$.jsxs)(`div`,{className:`flex justify-end gap-2`,children:[(0,$.jsx)(z,{text:u?r(`common.close`,`Close`):r(`common.cancel`,`Cancel`),onClick:n}),!u&&(0,$.jsx)(z,{intent:U.PRIMARY,text:r(`account.totp.verifyBtn`,`Verify`),type:`submit`,loading:o,disabled:i.length!==6})]})]})]})})},dt=({user:e,disableDialogOpen:n,setDisableDialogOpen:r,disablePassword:i,setDisablePassword:a,disableError:s,setDisableError:c,disableLoading:l,onDisable:u})=>{let{t:f}=d(),[p,m]=Q.useState(!1),[h,g]=Q.useState(!1);return(0,$.jsxs)(`div`,{className:`space-y-4`,children:[(0,$.jsxs)(`div`,{className:`flex items-center justify-between gap-2 mb-4`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(o,{size:20,className:`text-blue-500`}),(0,$.jsx)(K,{style:{margin:0},children:f(`account.totp.title`,`Authenticator App (TOTP)`)}),(0,$.jsx)(J,{intent:U.SUCCESS,minimal:!0,round:!0,children:f(`account.totp.enabled`,`Enabled`)})]}),(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(z,{outlined:!0,icon:(0,$.jsx)(t,{size:14}),text:f(`account.totp.testBtn`,`Test Code`),onClick:()=>g(!0)}),(0,$.jsx)(z,{intent:U.DANGER,outlined:!0,icon:(0,$.jsx)(C,{size:14}),text:f(`account.totp.disable`,`Disable Authenticator App (TOTP)`),onClick:()=>r(!0)})]})]}),(0,$.jsx)(`div`,{className:`space-y-4`,children:(0,$.jsx)(`p`,{className:`text-sm text-gray-600 dark:text-gray-400`,children:f(`account.totp.activeDesc`,`Authenticator app (TOTP) is active and generating 6-digit verification codes for your account.`)})}),(0,$.jsx)(B,{isOpen:n,onClose:()=>{r(!1),a(``),c(``),m(!1)},title:f(`account.totp.disableTitle`,`Disable Authenticator App (TOTP)`),icon:`shield`,children:(0,$.jsxs)(`div`,{className:`p-6 space-y-4`,children:[(0,$.jsx)(H,{intent:U.WARNING,children:f(`account.totp.disableWarning`,`After disabling TOTP, if no Passkeys are configured, your account will only be protected by password.`)}),s&&(0,$.jsx)(H,{intent:U.DANGER,children:s}),!e.totp_skip_password&&(0,$.jsxs)(`form`,{onSubmit:u,className:`space-y-4`,children:[(0,$.jsx)(q,{label:f(`account.currentPassword`),children:(0,$.jsx)(G,{type:p?`text`:`password`,leftIcon:`lock`,value:i,onChange:e=>a(e.target.value),rightElement:(0,$.jsx)(z,{minimal:!0,icon:p?`eye-open`:`eye-off`,onClick:()=>m(!p),title:p?f(`auth.hidePassword`,`Hide password`):f(`auth.showPassword`,`Show password`)}),required:!0})}),(0,$.jsxs)(`div`,{className:`flex justify-end gap-2`,children:[(0,$.jsx)(z,{text:f(`account.cancel`),onClick:()=>r(!1)}),(0,$.jsx)(z,{intent:U.DANGER,text:f(`account.totp.confirmDisable`,`Disable TOTP`),type:`submit`,loading:l})]})]}),e.totp_skip_password&&(0,$.jsxs)(`div`,{className:`flex justify-end gap-2`,children:[(0,$.jsx)(z,{text:f(`account.cancel`),onClick:()=>r(!1)}),(0,$.jsx)(z,{intent:U.DANGER,text:f(`account.totp.confirmDisable`,`Disable TOTP`),loading:l,onClick:u})]})]})}),(0,$.jsx)(ut,{isOpen:h,onClose:()=>g(!1)})]})},ft=({setupData:e,setupToken:t,setSetupToken:n,setupError:r,setupLoading:i,onStartSetup:s,onConfirmSetup:c,onCancel:l})=>{let{t:u}=d();return(0,$.jsxs)(`div`,{className:`space-y-4`,children:[(0,$.jsxs)(`div`,{className:`flex items-center justify-between gap-2 mb-4`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(o,{size:20,className:`text-blue-500`}),(0,$.jsx)(K,{style:{margin:0},children:u(`account.totp.title`,`Authenticator App (TOTP)`)}),(0,$.jsx)(J,{minimal:!0,round:!0,intent:U.NONE,children:u(`account.totp.disabled`,`Disabled`)})]}),!e&&(0,$.jsx)(z,{intent:U.PRIMARY,icon:(0,$.jsx)(a,{size:14}),text:u(`account.totp.setupBtn`,`Set Up Authenticator App (TOTP)`),loading:i,onClick:s})]}),e?(0,$.jsxs)(`div`,{className:`space-y-4`,children:[(0,$.jsx)(`p`,{className:`text-sm font-medium`,children:u(`account.totp.scanQR`,`Scan this QR code with your authenticator app:`)}),(0,$.jsxs)(`div`,{className:`flex flex-col items-center gap-3`,children:[(0,$.jsx)(nt,{uri:e.uri}),(0,$.jsxs)(`div`,{className:`text-center`,children:[(0,$.jsx)(`p`,{className:`text-xs text-gray-500 mb-1`,children:u(`account.totp.orEnterManually`,`Or enter the key manually:`)}),(0,$.jsx)(`code`,{className:`text-xs font-mono bg-gray-100 dark:bg-gray-800 px-2 py-1 rounded select-all`,children:e.secret})]})]}),(0,$.jsx)(W,{}),r&&(0,$.jsx)(H,{intent:U.DANGER,children:r}),(0,$.jsxs)(`form`,{onSubmit:c,className:`space-y-3`,children:[(0,$.jsx)(q,{label:u(`account.totp.enterCode`,`Enter the 6-digit code to confirm:`),helperText:u(`account.totp.enterCodeHint`,`This verifies the key was scanned correctly.`),children:(0,$.jsx)(Ve,{length:6,value:t,onChange:n,disabled:i})}),(0,$.jsxs)(`div`,{className:`flex gap-2`,children:[(0,$.jsx)(z,{text:u(`account.cancel`),onClick:l}),(0,$.jsx)(z,{intent:U.SUCCESS,type:`submit`,loading:i,text:u(`account.totp.activate`,`Activate`),disabled:t.length<6})]})]})]}):(0,$.jsxs)(`div`,{className:`space-y-3`,children:[(0,$.jsx)(`p`,{className:`text-sm text-gray-600 dark:text-gray-400`,children:u(`account.totp.setupDesc`,`Add an extra layer of security. Use Google Authenticator, Authy, or any TOTP app.`)}),r&&(0,$.jsx)(H,{intent:U.DANGER,children:r})]})]})},pt=({user:e,onRefresh:t})=>{let{t:n}=d(),[r,i]=(0,Q.useState)(null),[a,o]=(0,Q.useState)(``),[s,c]=(0,Q.useState)(null),[l,u]=(0,Q.useState)(!1),[f,p]=(0,Q.useState)(``),[m,h]=(0,Q.useState)(!1),[g,_]=(0,Q.useState)(!1),[v,y]=(0,Q.useState)(``),[b,x]=(0,Q.useState)(!1),[S,C]=(0,Q.useState)(``),[w,T]=(0,Q.useState)(!1);return s?(0,$.jsx)(rt,{recoveryKeys:s,copied:m,onCopy:()=>{s&&navigator.clipboard.writeText(s.join(`
|
|
4
|
+
`)).then(()=>{h(!0),setTimeout(()=>h(!1),2e3)})},onDone:()=>c(null)}):e.totp_enabled?(0,$.jsx)(dt,{user:e,settingsLoading:w,onToggleSkipPassword:async e=>{T(!0);try{await Xe(e),t()}catch{}finally{T(!1)}},disableDialogOpen:g,setDisableDialogOpen:_,disablePassword:v,setDisablePassword:y,disableError:S,setDisableError:C,disableLoading:b,onDisable:async r=>{r.preventDefault(),x(!0),C(``);try{let n=v;e.password_version===2&&(n=await Be(v,e.username)),await pe(n),_(!1),y(``),t()}catch(e){C(e.message||n(`common.errorNetwork`))}finally{x(!1)}}}):(0,$.jsx)(ft,{setupData:r,setupToken:a,setSetupToken:o,setupError:f,setupLoading:l,onStartSetup:async()=>{u(!0),p(``);try{i(await Pe())}catch(e){p(e.message||n(`common.errorNetwork`))}finally{u(!1)}},onConfirmSetup:async e=>{if(e.preventDefault(),r){u(!0),p(``);try{let e=a.replace(/\s/g,``),n=crypto.randomUUID(),s=new TextEncoder().encode(e+n),l=await crypto.subtle.digest(`SHA-256`,s),u=Array.from(new Uint8Array(l)).map(e=>e.toString(16).padStart(2,`0`)).join(``);c((await et({secret:r.secret,totpTokenHash:u,salt:n})).recovery_keys),i(null),o(``),t()}catch(e){p(e.message||n(`common.errorNetwork`))}finally{u(!1)}}},onCancel:()=>{i(null),o(``),p(``)}})},mt=({method:e,onSelectMethod:t,hasPasskey:r,hasRecoveryKey:i,hasTotp:a,hasPassword:o})=>{let{t:s}=d();return(0,$.jsx)(`div`,{className:`flex justify-center mb-5 isolate`,style:{isolation:`isolate`},children:(0,$.jsx)(`div`,{className:`w-full bg-gray-100/70 dark:bg-gray-800/70 p-1 rounded-lg`,children:(0,$.jsxs)(P,{fill:!0,variant:`minimal`,style:{isolation:`isolate`},children:[r&&(0,$.jsx)(z,{small:!0,active:e===`passkey`,intent:e===`passkey`?U.PRIMARY:U.NONE,icon:(0,$.jsx)(u,{size:14}),text:s(`account.mfa.passkey`,`Passkey`),onClick:()=>t(`passkey`)}),i&&(0,$.jsx)(z,{small:!0,active:e===`recovery_key`,intent:e===`recovery_key`?U.PRIMARY:U.NONE,icon:(0,$.jsx)(u,{size:14}),text:s(`account.recoveryKey.verifyBtn`,`Recovery Key`),onClick:()=>t(`recovery_key`)}),a&&(0,$.jsx)(z,{small:!0,active:e===`totp`,intent:e===`totp`?U.PRIMARY:U.NONE,icon:(0,$.jsx)(n,{size:14}),text:s(`account.mfa.totp`,`TOTP`),onClick:()=>t(`totp`)}),o&&(0,$.jsx)(z,{small:!0,active:e===`password`,intent:e===`password`?U.PRIMARY:U.NONE,icon:(0,$.jsx)(h,{size:14}),text:s(`account.mfa.password`,`Password`),onClick:()=>t(`password`)})]})})})},ht=({loading:e,onVerify:t})=>{let{t:n}=d();return(0,$.jsxs)(`div`,{className:`text-center py-4 space-y-4`,children:[(0,$.jsx)(`div`,{className:`flex justify-center`,children:(0,$.jsx)(`div`,{className:`p-4 rounded-full bg-blue-50 dark:bg-blue-900/30 text-blue-500`,children:(0,$.jsx)(u,{size:48})})}),(0,$.jsx)(`p`,{className:`text-sm text-gray-600 dark:text-gray-300`,children:n(`account.passkey.verifyPrompt`,`Authenticate using your device's biometric sensor (Face ID, Touch ID, Windows Hello) or security key.`)}),(0,$.jsx)(z,{fill:!0,large:!0,intent:U.PRIMARY,loading:e,onClick:t,icon:(0,$.jsx)(u,{size:16}),text:n(`account.usePasskeyInstead`,`Authenticate with Passkey`)})]})},gt=({totpCode:e,setTotpCode:t,loading:n,onVerify:r})=>{let{t:i}=d();return(0,$.jsxs)(`div`,{className:`py-2 space-y-4`,children:[(0,$.jsx)(q,{label:i(`account.totpCode`,`Authenticator Code`),children:(0,$.jsx)(Ve,{length:6,value:e,onChange:e=>{t(e),e.length===6&&r(e)},disabled:n})}),(0,$.jsx)(z,{fill:!0,intent:U.PRIMARY,loading:n,disabled:e.length!==6,onClick:()=>r(),text:i(`common.confirm`,`Confirm`)})]})},_t=({password:e,setPassword:t,showPassword:n,setShowPassword:r,loading:i,onSubmit:a})=>{let{t:o}=d();return(0,$.jsxs)(`form`,{onSubmit:a,className:`py-2 space-y-4`,children:[(0,$.jsx)(q,{label:o(`account.currentPassword`,`Current Password`),children:(0,$.jsx)(G,{leftIcon:`lock`,type:n?`text`:`password`,value:e,onChange:e=>t(e.target.value),autoFocus:!0,rightElement:(0,$.jsx)(z,{minimal:!0,icon:n?`eye-open`:`eye-off`,onClick:()=>r(!n)})})}),(0,$.jsx)(z,{fill:!0,intent:U.PRIMARY,type:`submit`,loading:i,text:o(`common.confirm`,`Confirm`)})]})},vt=({recoveryKey:e,setRecoveryKey:t,loading:n,onSubmit:r})=>{let{t:i}=d();return(0,$.jsxs)(`form`,{onSubmit:r,autoComplete:`off`,className:`py-2 space-y-4`,children:[(0,$.jsx)(q,{label:i(`account.recoveryKey.verifyPromptLabel`,`原恢复密钥 (Original Recovery Key)`),children:(0,$.jsx)(G,{leftIcon:`key`,type:`text`,id:`verify-recovery-key-input`,name:`verify_recovery_key_input`,autoComplete:`off`,autoCorrect:`off`,autoCapitalize:`off`,spellCheck:!1,"data-1p-ignore":`true`,"data-lpignore":`true`,"data-bwignore":`true`,placeholder:`123456-789012-345678-901234-567890`,value:e,onChange:e=>t(e.target.value),autoFocus:!0,className:`font-mono text-xs`})}),(0,$.jsx)(z,{fill:!0,intent:U.PRIMARY,type:`submit`,loading:n,disabled:!e.trim(),text:i(`common.confirm`,`Confirm`)})]})};var yt=(e,t)=>{let n=t||[`passkey`,`totp`,`password`];return n.includes(`passkey`)&&e?.passkeys_count&&e.passkeys_count>0?`passkey`:n.includes(`recovery_key`)?`recovery_key`:n.includes(`totp`)&&e?.totp_enabled?`totp`:n.includes(`password`)?`password`:n[0]||`password`};const bt=({isOpen:e,onClose:t,user:n,title:r,onVerify:i,allowedMethods:a})=>{let{t:o}=d(),s=a||[`passkey`,`totp`,`password`],c=!!(n?.passkeys_count&&n.passkeys_count>0)&&s.includes(`passkey`),l=!!n?.totp_enabled&&s.includes(`totp`),u=s.includes(`password`),f=s.includes(`recovery_key`),p=yt(n,a),[m,h]=(0,Q.useState)(p),[g,_]=(0,Q.useState)(``),[v,y]=(0,Q.useState)(!1),[b,x]=(0,Q.useState)(``),[S,C]=(0,Q.useState)(``),[w,T]=(0,Q.useState)(!1),[E,D]=(0,Q.useState)(``),[O,k]=(0,Q.useState)(e);!O&&e?(k(!0),h(p),_(``),y(!1),x(``),C(``),D(``)):O&&!e&&k(!1),(0,Q.useEffect)(()=>{m===`passkey`&&!c?h(f?`recovery_key`:l?`totp`:`password`):m===`totp`&&!l?h(c?`passkey`:f?`recovery_key`:`password`):m===`recovery_key`&&!f&&h(c?`passkey`:l?`totp`:`password`)},[c,l,f,m]);let A=async e=>{if(e&&e.preventDefault(),!g){D(o(`auth.passwordRequired`,`Password is required`));return}T(!0),D(``);try{let e=g;n?.password_version===2&&n?.username&&(e=await Be(g,n.username)),await i({password:e}),t()}catch(e){D(ze(e,o))}finally{T(!1)}},j=async()=>{T(!0),D(``);try{await i({passkeyAssertion:await Ie(await He())}),t()}catch(e){D(ze(e,o))}finally{T(!1)}},M=async e=>{let n=e||b;if(n.length!==6){D(o(`account.totp.invalidCode`,`Please enter a 6-digit code`));return}T(!0),D(``);try{let e=crypto.randomUUID(),r=new TextEncoder().encode(n+e),a=await crypto.subtle.digest(`SHA-256`,r);await i({totpTokenHash:Array.from(new Uint8Array(a)).map(e=>e.toString(16).padStart(2,`0`)).join(``),totpSalt:e}),t()}catch(e){D(ze(e,o))}finally{T(!1)}},ee=async e=>{e&&e.preventDefault();let n=S.trim();if(!n){D(o(`account.recoveryKey.keyRequired`,`Recovery key is required`));return}T(!0),D(``);try{await i({recoveryKey:n}),t()}catch(e){D(ze(e,o))}finally{T(!1)}},N=(c?1:0)+(f?1:0)+(l?1:0)+(u?1:0);return(0,$.jsx)(B,{isOpen:e,onClose:t,title:r||o(`account.verifyIdentity`,`Security Verification`),icon:`shield`,className:`max-w-md w-full`,children:(0,$.jsxs)(`div`,{className:L,children:[(0,$.jsx)(`p`,{className:`text-sm text-gray-600 dark:text-gray-400 mb-4`,children:o(`account.verifyIdentityDesc`,`To protect your account security, please verify your identity before proceeding.`)}),N>1&&(0,$.jsx)(mt,{method:m,onSelectMethod:e=>{h(e),D(``)},hasPasskey:c,hasRecoveryKey:f,hasTotp:l,hasPassword:u}),E&&(0,$.jsx)(H,{intent:U.DANGER,className:`mb-4`,children:E}),m===`recovery_key`&&(0,$.jsx)(vt,{recoveryKey:S,setRecoveryKey:C,loading:w,onSubmit:ee}),m===`passkey`&&(0,$.jsx)(ht,{loading:w,onVerify:j}),m===`totp`&&(0,$.jsx)(gt,{totpCode:b,setTotpCode:x,loading:w,onVerify:M}),m===`password`&&(0,$.jsx)(_t,{password:g,setPassword:_,showPassword:v,setShowPassword:y,loading:w,onSubmit:A})]})})},xt=({user:e,onRefresh:t})=>{let{t:r}=d(),[i,a]=(0,Q.useState)(!1),[o,s]=(0,Q.useState)(!1),[c,l]=(0,Q.useState)(null),[p,m]=(0,Q.useState)(!1),[g,_]=(0,Q.useState)(!1),[v,b]=(0,Q.useState)(null),C=!!(e.has_recovery_keys||e.recovery_keys_encrypted),E=()=>{b(null),s(!0)},D=()=>{s(!1),a(!0)},O=async e=>{let n=await tt(e);l(n.recovery_key),m(!1);let i=!1;if(Z.isUnlocked())try{await Z.wrapCurrentKeyForRecovery(n.recovery_key),i=!0}catch(e){console.warn(`[RecoveryKey] Failed to wrap E2EE key with new recovery key:`,e)}else if(e.recoveryKey)try{await Z.unlockWithRecoveryKey(e.recoveryKey),await Z.wrapCurrentKeyForRecovery(n.recovery_key),i=!0}catch(e){console.warn(`[RecoveryKey] Failed to unlock and re-wrap with new recovery key:`,e)}else if(e.passkeyAssertion)try{await Z.unlockUser(),await Z.wrapCurrentKeyForRecovery(n.recovery_key),i=!0}catch(e){console.warn(`[RecoveryKey] Failed to unlock via Passkey and re-wrap:`,e)}try{if((await Z.getUserStatus()).hasKeys&&!i){b({text:r(`account.recoveryKey.rotateSuccessE2eeWarning`,`恢复密钥已成功轮换!注意:由于端到端加密此前处于锁定状态且未能解密,旧 E2EE 密文仍需使用轮换前的旧恢复密钥解锁,或可在下方端到端加密卡片中点击「重置密钥对」。`),intent:U.WARNING}),t();return}}catch{}b({text:r(`account.recoveryKey.rotateSuccess`,`恢复密钥已成功轮换!请立即妥善离线保存新密钥,旧密钥已失效。`),intent:U.SUCCESS}),t()},k=e=>{navigator.clipboard.writeText(e),_(!0),setTimeout(()=>_(!1),2e3)};return(0,$.jsxs)(`div`,{className:`space-y-4`,children:[(0,$.jsxs)(`div`,{className:`flex flex-col sm:flex-row sm:items-center justify-between gap-3`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,$.jsx)(u,{size:18,className:`text-amber-500`}),(0,$.jsx)(K,{style:{margin:0},children:r(`account.recoveryKey.title`,`紧急恢复密钥`)}),(0,$.jsx)(J,{intent:C?U.SUCCESS:U.NONE,minimal:!0,round:!0,children:C?r(`account.recoveryKey.configured`,`已配置`):r(`account.recoveryKey.notConfigured`,`未配置`)}),(0,$.jsx)(ce,{content:r(`account.recoveryKey.oneWayTooltip`,`采用 SHA-256 单向密码学散列保护,服务端不存储明文且不可解密,仅支持身份轮换验证。`),position:N.TOP,children:(0,$.jsx)(J,{intent:U.PRIMARY,minimal:!0,round:!0,icon:(0,$.jsx)(n,{size:12,style:{display:`inline-flex`,alignItems:`center`,marginRight:`4px`}}),children:r(`account.recoveryKey.oneWayHash`,`单向不可逆散列`)})})]}),(0,$.jsx)(`div`,{className:`flex items-center gap-2`,children:(0,$.jsx)(z,{small:!0,intent:U.WARNING,icon:(0,$.jsx)(f,{size:14}),text:r(`account.recoveryKey.rotateBtn`,`轮换恢复密钥`),onClick:E})})]}),(0,$.jsx)(`p`,{className:`text-sm text-gray-600 dark:text-gray-400`,children:r(`account.recoveryKey.descOneWay`,`紧急恢复密钥是在您丢失所有通行密钥 (Passkey) 或身份验证器时,恢复账号访问及端到端解密数据的唯一凭据。为确保零知识安全,恢复密钥采用单向不可逆散列存储,无法在网页端查看明文,仅支持通过原恢复密钥或现有 Passkey 进行轮换。密钥一旦被使用将立即自动轮换。`)}),v&&(0,$.jsx)(H,{intent:v.intent,className:`my-2`,children:v.text}),c&&(0,$.jsxs)(Y,{elevation:I.ZERO,className:`bg-amber-50/50 dark:bg-amber-950/20 border border-amber-300 dark:border-amber-800 p-4 space-y-3`,children:[(0,$.jsxs)(`div`,{className:`flex flex-col sm:flex-row sm:items-center justify-between gap-2`,children:[(0,$.jsxs)(`span`,{className:`text-xs font-semibold text-amber-800 dark:text-amber-300 uppercase tracking-wider flex items-center gap-1.5`,children:[(0,$.jsx)(S,{size:14}),r(`account.recoveryKey.newKeyGenerated`,`已生成全新 30 位恢复密钥(请立即保存)`)]}),(0,$.jsxs)(`div`,{className:`flex items-center gap-1.5 flex-wrap`,children:[(0,$.jsx)(z,{minimal:!0,small:!0,icon:p?(0,$.jsx)(T,{size:14}):(0,$.jsx)(x,{size:14}),onClick:()=>m(!p),title:p?r(`auth.showPassword`,`显示`):r(`auth.hidePassword`,`隐藏`)}),(0,$.jsx)(z,{minimal:!0,small:!0,icon:g?(0,$.jsx)(y,{size:14,className:`text-green-500`}):(0,$.jsx)(w,{size:14}),onClick:()=>k(c),title:r(`common.copy`,`复制`),text:g?r(`common.copied`,`已复制`):r(`common.copy`,`复制`)}),(0,$.jsx)(z,{minimal:!0,small:!0,icon:`cross`,onClick:()=>l(null),title:r(`common.close`,`关闭`)})]})]}),(0,$.jsx)(`div`,{className:`p-3 bg-white dark:bg-gray-900 rounded border border-amber-200 dark:border-amber-800/80 font-mono text-center text-lg sm:text-xl font-bold tracking-widest select-all text-gray-900 dark:text-gray-100`,children:p?`••••••-••••••-••••••-••••••-••••••`:c}),(0,$.jsxs)(`p`,{className:`text-xs text-amber-700 dark:text-amber-400 flex items-center gap-1`,children:[(0,$.jsx)(h,{size:14,className:`shrink-0`}),r(`account.recoveryKey.oneWayWarning`,`注意:此密钥仅在此显示一次,关闭后将无法再次查看!服务端仅保存不可逆散列,请务必将其妥善复制并离线安全保存。`)]})]}),(0,$.jsx)(F,{isOpen:o,onConfirm:D,onCancel:()=>s(!1),cancelButtonText:r(`common.cancel`,`取消`),confirmButtonText:r(`account.recoveryKey.confirmRotateBtn`,`确认进入轮换验证`),intent:U.DANGER,icon:`warning-sign`,children:(0,$.jsx)(`p`,{children:r(`account.recoveryKey.rotateConfirm`,`轮换恢复密钥将立即使原恢复密钥失效,并重新派生信封加密密钥。仅允许通过现有通行密钥 (Passkey) 或原恢复密钥完成轮换验证。是否继续?`)})}),(0,$.jsx)(bt,{isOpen:i,onClose:()=>a(!1),user:e,allowedMethods:[`passkey`,`recovery_key`],title:r(`account.recoveryKey.rotateVerifyTitle`,`验证身份以轮换恢复密钥`),onVerify:O})]})},St=({user:e,onRefresh:r})=>{let{t:i}=d(),[a,o]=(0,Q.useState)(!1),s=!!(e.mfa_enabled??(e.totp_enabled||e.passkeys_count&&e.passkeys_count>0)),c=async e=>{o(!0);try{await ge(e),r()}catch(e){alert(e.message||i(`common.errorNetwork`,`Network error`))}finally{o(!1)}};return(0,$.jsxs)(Y,{elevation:I.ONE,className:`space-y-6`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`div`,{className:`flex items-center justify-between mb-3`,children:(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(n,{size:20,className:s?`text-green-500`:`text-gray-400`}),(0,$.jsx)(K,{style:{margin:0},children:i(`account.mfa.title`,`Multi-Factor Authentication (MFA)`)}),(0,$.jsx)(J,{intent:s?U.SUCCESS:U.NONE,minimal:!0,round:!0,children:s?i(`account.mfa.enabled`,`Configured`):i(`account.mfa.notConfigured`,`Not Configured`)})]})}),(0,$.jsx)(`p`,{className:`text-sm text-gray-600 dark:text-gray-400 mb-4`,children:i(`account.mfa.desc`,`Passkeys and Authenticator Apps (TOTP) both serve as MFA authentication methods. Configuring at least one factor protects your account and enables passwordless login and self-service password recovery.`)}),s?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(W,{className:`my-3`}),(0,$.jsxs)(`div`,{className:`flex flex-col sm:flex-row sm:items-center justify-between gap-2 py-1`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`div`,{className:`font-medium text-sm text-gray-900 dark:text-gray-100`,children:i(`account.mfa.passwordlessTitle`,`Passwordless Login`)}),(0,$.jsx)(`div`,{className:`text-xs text-gray-500 dark:text-gray-400`,children:i(`account.mfa.passwordlessDesc`,`When enabled, logging in will skip the password requirement and verify your identity directly via Passkey or TOTP.`)})]}),(0,$.jsx)(ae,{checked:!!e.totp_skip_password,onChange:e=>c(e.currentTarget.checked),disabled:a,className:`mb-0 shrink-0`})]})]}):(0,$.jsx)(H,{intent:U.PRIMARY,icon:(0,$.jsx)(t,{size:16,style:{display:`inline-flex`,alignItems:`center`,marginRight:`8px`}}),children:i(`account.mfa.unconfiguredHint`,`No MFA method configured yet. Set up either a Passkey or Authenticator App below to safeguard your account and unlock passwordless login and account recovery.`)})]}),(0,$.jsx)(W,{}),(0,$.jsx)(lt,{onRefresh:r}),(0,$.jsx)(W,{}),(0,$.jsx)(pt,{user:e,onRefresh:r}),(0,$.jsx)(W,{}),(0,$.jsx)(xt,{user:e,onRefresh:r})]})},Ct={signup:{label:`account.activity.signup`,icon:(0,$.jsx)(D,{size:14}),intent:U.SUCCESS},login_success:{label:`account.activity.loginSuccess`,icon:(0,$.jsx)(g,{size:14}),intent:U.SUCCESS},login_fail:{label:`account.activity.loginFail`,icon:(0,$.jsx)(p,{size:14}),intent:U.DANGER},logout:{label:`account.activity.logout`,icon:(0,$.jsx)(c,{size:14}),intent:U.NONE},password_change_success:{label:`account.activity.pwChangeSuccess`,icon:(0,$.jsx)(u,{size:14}),intent:U.SUCCESS},password_change_fail:{label:`account.activity.pwChangeFail`,icon:(0,$.jsx)(p,{size:14}),intent:U.DANGER},totp_verify_success:{label:`account.activity.totpVerifySuccess`,icon:(0,$.jsx)(n,{size:14}),intent:U.SUCCESS},totp_verify_fail:{label:`account.activity.totpVerifyFail`,icon:(0,$.jsx)(p,{size:14}),intent:U.DANGER},totp_setup:{label:`account.activity.totpSetup`,icon:(0,$.jsx)(a,{size:14}),intent:U.PRIMARY},totp_removed:{label:`account.activity.totpRemoved`,icon:(0,$.jsx)(C,{size:14}),intent:U.WARNING},recovery_key_used:{label:`account.activity.recoveryKeyUsed`,icon:(0,$.jsx)(u,{size:14}),intent:U.WARNING},recovery_key_rotated:{label:`account.activity.recoveryKeyRotated`,icon:(0,$.jsx)(u,{size:14}),intent:U.WARNING},session_revoked:{label:`account.activity.sessionRevoked`,icon:(0,$.jsx)(c,{size:14}),intent:U.WARNING},passkey_registered:{label:`account.activity.passkeyRegistered`,icon:(0,$.jsx)(u,{size:14}),intent:U.PRIMARY},passkey_deleted:{label:`account.activity.passkeyDeleted`,icon:(0,$.jsx)(C,{size:14}),intent:U.WARNING},passkey_verify_success:{label:`account.activity.passkeyVerifySuccess`,icon:(0,$.jsx)(n,{size:14}),intent:U.SUCCESS},passkey_verify_fail:{label:`account.activity.passkeyVerifyFail`,icon:(0,$.jsx)(p,{size:14}),intent:U.DANGER}},wt=e=>{if(!e)return`desktop`;let t=e.toLowerCase();return t.includes(`mobile`)||t.includes(`android`)||t.includes(`iphone`)||t.includes(`tablet`)||t.includes(`ipad`)?`mobile-phone`:`desktop`},Tt=(e,t)=>{if(!e)return t;let n=e;return n.includes(`Edg/`)?`Edge`:n.includes(`Chrome/`)&&!n.includes(`Edg/`)?`Chrome`:n.includes(`Firefox/`)?`Firefox`:n.includes(`Safari/`)&&!n.includes(`Chrome/`)?`Safari`:t},Et=({userAgent:e})=>{let{t}=d();if(!e)return(0,$.jsx)(`span`,{className:`text-gray-500`,children:`—`});let n=Tt(e,t(`account.sessions.unknownDevice`,`Unknown Device`));return(0,$.jsxs)(`div`,{children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(te,{icon:wt(e),className:`text-gray-400`}),(0,$.jsx)(`span`,{children:n})]}),(0,$.jsx)(`div`,{className:`text-xs text-gray-400 mt-1 max-w-xs truncate`,title:e,children:e})]})},Dt=({hoveredSessionId:e,setHoveredSessionId:t})=>{let{t:n}=d(),[r,i]=(0,Q.useState)([]),[a,o]=(0,Q.useState)(!0),[c,l]=(0,Q.useState)(!0),[u,p]=(0,Q.useState)(!1),m=(0,Q.useCallback)(async e=>{o(!0);try{let t=new URLSearchParams({limit:`20`});e&&t.set(`before`,String(e));let n=await De(t.toString());i(e?e=>[...e,...n]:n),l(n.length===20)}catch{}finally{o(!1)}},[]);(0,Q.useEffect)(()=>{m()},[m]);let h=()=>{let e=r[r.length-1];e&&m(e.timestamp)},g=e=>Ct[e]??{label:e,icon:(0,$.jsx)(s,{size:14}),intent:U.NONE};return(0,$.jsxs)(Y,{elevation:I.ONE,children:[(0,$.jsxs)(`div`,{className:`flex items-center justify-between cursor-pointer`,onClick:()=>p(!u),children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(s,{size:20,className:`text-purple-500`}),(0,$.jsx)(K,{style:{margin:0},children:n(`account.activity.title`,`Account Activity`)}),r.length>0&&(0,$.jsxs)(J,{minimal:!0,round:!0,intent:U.NONE,children:[r.length,c?`+`:``]})]}),(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(z,{minimal:!0,icon:(0,$.jsx)(f,{size:14}),onClick:e=>{e.stopPropagation(),m()}}),(0,$.jsx)(b,{size:16,className:`text-gray-400 transition-transform ${u?`rotate-180`:``}`})]})]}),u&&(0,$.jsx)(`div`,{className:`mt-4`,children:a&&r.length===0?(0,$.jsx)(`div`,{className:`flex justify-center py-8`,children:(0,$.jsx)(ne,{size:24})}):r.length===0?(0,$.jsx)(`p`,{className:`text-sm text-gray-500 text-center py-6`,children:n(`account.activity.empty`,`No activity recorded yet.`)}):(0,$.jsxs)(`div`,{className:`overflow-x-auto`,children:[(0,$.jsxs)(se,{interactive:!0,striped:!0,className:`w-full text-sm`,children:[(0,$.jsx)(`thead`,{children:(0,$.jsxs)(`tr`,{children:[(0,$.jsx)(`th`,{children:n(`account.activity.action`,`Action`)}),(0,$.jsx)(`th`,{children:n(`account.activity.time`,`Time`)}),(0,$.jsx)(`th`,{children:n(`account.activity.session`,`Session`)}),(0,$.jsx)(`th`,{children:n(`account.activity.ip`,`IP Address`)}),(0,$.jsx)(`th`,{children:n(`account.activity.device`,`Device`)})]})}),(0,$.jsx)(`tbody`,{children:r.map(r=>{let i=g(r.action),a=``,o=r.session_id_hash||``;if(r.extra)try{let e=JSON.parse(r.extra);if(e.reason){let t=`account.activity.reasons.${e.reason}`,r=n(t);a=r&&r!==t?r:e.reason.replace(/[_-]+/g,` `).replace(/\b\w/g,e=>e.toUpperCase())}}catch{}return(0,$.jsxs)(`tr`,{onMouseEnter:()=>{o&&t?.(o)},onMouseLeave:()=>{o&&t?.(null)},className:e&&e===o?`bg-gray-100/80 dark:bg-slate-800/80`:``,children:[(0,$.jsx)(`td`,{className:`align-middle`,children:(0,$.jsxs)(`div`,{className:`flex flex-col items-start gap-1`,children:[(0,$.jsx)(J,{minimal:!0,intent:i.intent,icon:i.icon,children:n(i.label,r.action)}),a&&(0,$.jsx)(`span`,{className:`text-xs text-gray-500 italic ml-1`,children:a})]})}),(0,$.jsx)(`td`,{className:`text-xs text-gray-500 whitespace-nowrap align-middle`,children:$e(new Date(r.timestamp*1e3))}),(0,$.jsx)(`td`,{className:`font-mono text-xs text-gray-500 align-middle`,children:o?o.slice(0,8):`—`}),(0,$.jsx)(`td`,{className:`font-mono text-xs text-gray-500 align-middle`,children:r.ip_address||`—`}),(0,$.jsx)(`td`,{className:`align-middle`,children:(0,$.jsx)(Et,{userAgent:r.user_agent||null})})]},r.id)})})]}),c&&(0,$.jsx)(`div`,{className:`flex justify-center mt-3`,children:(0,$.jsx)(z,{minimal:!0,loading:a,text:n(`account.activity.loadMore`,`Load More`),onClick:h})})]})})]})},Ot=({hoveredSessionId:e,setHoveredSessionId:t})=>{let{t:n}=d(),[r,i]=(0,Q.useState)([]),[a,o]=(0,Q.useState)(!0),[s,l]=(0,Q.useState)(null),[u,p]=(0,Q.useState)(!1),[h,g]=(0,Q.useState)(!1),_=r.filter(e=>!e.is_current).length,v=(0,Q.useCallback)(async()=>{o(!0);try{let e=await ke(),t=Date.now();i((e||[]).filter(e=>e.expires_at*1e3>t))}catch{}finally{o(!1)}},[]);(0,Q.useEffect)(()=>{v()},[v]);let y=async e=>{l(e);try{(await Ae(e)).is_current?window.location.reload():i(t=>t.filter(t=>t.id!==e))}catch(e){alert(e.message||n(`account.sessions.revokeFailed`,`Failed to revoke session.`))}finally{l(null)}};return(0,$.jsxs)(Y,{elevation:I.ONE,children:[(0,$.jsxs)(`div`,{className:`flex items-center justify-between mb-4`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(m,{size:20,className:`text-green-500`}),(0,$.jsx)(K,{style:{margin:0},children:n(`account.sessions.title`,`Active Sessions`)})]}),(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[_>0&&(0,$.jsx)(z,{small:!0,minimal:!0,intent:U.DANGER,icon:(0,$.jsx)(c,{size:14}),text:n(`account.sessions.revokeOthers`,`Revoke Other Sessions`),loading:u,onClick:()=>g(!0)}),(0,$.jsx)(z,{minimal:!0,icon:(0,$.jsx)(f,{size:14}),onClick:()=>v()})]})]}),a?(0,$.jsx)(`div`,{className:`flex justify-center py-4`,children:(0,$.jsx)(ne,{size:24})}):r.length===0?(0,$.jsx)(`p`,{className:`text-sm text-gray-500 text-center py-4`,children:n(`account.sessions.empty`,`No active sessions found.`)}):(0,$.jsx)(`div`,{className:`overflow-x-auto`,children:(0,$.jsxs)(se,{interactive:!0,striped:!0,className:`w-full text-sm`,children:[(0,$.jsx)(`thead`,{children:(0,$.jsxs)(`tr`,{children:[(0,$.jsx)(`th`,{children:n(`account.sessions.device`,`Device`)}),(0,$.jsx)(`th`,{children:n(`account.sessions.session`,`Session`)}),(0,$.jsx)(`th`,{children:n(`account.sessions.ip`,`IP Address`)}),(0,$.jsx)(`th`,{children:n(`account.sessions.loginTime`,`Login Time`)}),(0,$.jsx)(`th`,{children:n(`account.sessions.expires`,`Expires`)}),(0,$.jsx)(`th`,{children:n(`account.sessions.action`,`Action`)})]})}),(0,$.jsx)(`tbody`,{children:r.map(r=>(0,$.jsxs)(`tr`,{onMouseEnter:()=>t?.(r.id),onMouseLeave:()=>t?.(null),className:e===r.id?`bg-gray-100/80 dark:bg-slate-800/80`:``,children:[(0,$.jsx)(`td`,{children:(0,$.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,$.jsx)(Et,{userAgent:r.user_agent}),r.is_current&&(0,$.jsx)(J,{minimal:!0,intent:U.SUCCESS,className:`mt-0.5`,children:n(`account.sessions.current`,`Current`)})]})}),(0,$.jsx)(`td`,{className:`font-mono text-xs text-gray-500 align-middle`,children:r.id?r.id.slice(0,8):`—`}),(0,$.jsx)(`td`,{className:`font-mono text-xs text-gray-500 align-middle`,children:r.ip_address||`—`}),(0,$.jsx)(`td`,{className:`text-xs text-gray-500 align-middle`,children:r.created_at?$e(new Date(r.created_at*1e3)):`—`}),(0,$.jsx)(`td`,{className:`text-xs text-gray-500 align-middle`,children:$e(new Date(r.expires_at*1e3))}),(0,$.jsx)(`td`,{className:`align-middle`,children:(0,$.jsx)(z,{small:!0,minimal:!0,intent:U.DANGER,disabled:r.is_current,icon:(0,$.jsx)(c,{size:14}),text:n(`account.sessions.revoke`,`Revoke`),loading:s===r.id,onClick:()=>y(r.id)})})]},r.id))})]})}),(0,$.jsx)(F,{isOpen:h,cancelButtonText:n(`common.cancel`,`Cancel`),confirmButtonText:n(`account.sessions.confirmRevokeOthers`,`Revoke Other Sessions`),intent:U.DANGER,icon:`log-out`,onCancel:()=>g(!1),onConfirm:async()=>{p(!0);try{await Se(),i(e=>e.filter(e=>e.is_current)),g(!1)}catch(e){alert(e.message||n(`account.sessions.revokeFailed`,`Failed to revoke session.`))}finally{p(!1)}},loading:u,children:(0,$.jsx)(`p`,{children:n(`account.sessions.revokeOthersConfirmText`,`Are you sure you want to revoke all other active sessions? All other logged-in devices will be signed out immediately.`)})})]})},kt=({users:e,currentUserId:t,onRefresh:r,registrationEnabled:a=!0,onRefreshSettings:o})=>{let{t:s}=d(),[c,l]=(0,Q.useState)(!1),[u,f]=(0,Q.useState)(``),[p,m]=(0,Q.useState)(``),[h,g]=(0,Q.useState)(`user`),[_,v]=(0,Q.useState)(!1),[y,b]=(0,Q.useState)(!1),[x,S]=(0,Q.useState)(a),[C,w]=(0,Q.useState)(!1);(0,Q.useEffect)(()=>{S(a)},[a]);let T=async e=>{S(e),w(!0);try{await ve({registration_enabled:String(e)}),o?.()}catch(t){console.error(t),S(!e),alert(t.message||s(`common.errorNetwork`,`Network error`))}finally{w(!1)}},E=async()=>{if(!We.test(u)){alert(s(`account.formatTipUsername`));return}if(!Je.test(p)){alert(s(`account.formatTipPassword`));return}v(!0);try{await Ce({username:u,password:await Be(p,u),role:h}),l(!1),f(``),m(``),b(!1),r()}catch(e){console.error(e),alert(e.message||s(`common.errorNetwork`))}finally{v(!1)}},O=async e=>{if(confirm(s(`account.confirmDeleteUser`)))try{await Te(e),r()}catch(e){console.error(e)}};return(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(`div`,{className:`flex flex-col sm:flex-row sm:items-center justify-between gap-3`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(n,{size:20,className:`text-red-500`}),(0,$.jsx)(K,{style:{margin:0},children:s(`account.userManagement`)})]}),(0,$.jsxs)(`div`,{className:`flex items-center gap-4 flex-wrap`,children:[(0,$.jsx)(ae,{label:s(`account.enableRegistration`,`开放新用户注册`),checked:x,disabled:C,onChange:e=>T(e.currentTarget.checked),className:`mb-0`}),(0,$.jsx)(z,{className:`whitespace-nowrap`,icon:(0,$.jsx)(D,{size:16}),intent:U.SUCCESS,text:s(`account.createUser`),onClick:()=>l(!0)})]})]}),(0,$.jsx)(Y,{elevation:I.ONE,className:`p-0 overflow-hidden overflow-x-auto`,children:(0,$.jsxs)(se,{interactive:!0,striped:!0,className:`w-full`,children:[(0,$.jsx)(`thead`,{children:(0,$.jsxs)(`tr`,{children:[(0,$.jsx)(`th`,{children:s(`account.username`)}),(0,$.jsx)(`th`,{children:s(`account.role`)}),(0,$.jsx)(`th`,{children:`MFA`}),(0,$.jsx)(`th`,{children:`ID`}),(0,$.jsx)(`th`,{children:s(`account.createdAt`)}),(0,$.jsx)(`th`,{children:s(`account.lastActive`)}),(0,$.jsx)(`th`,{children:s(`account.lastResolve`)}),(0,$.jsx)(`th`,{className:`text-right`,children:s(`account.actions`)})]})}),(0,$.jsx)(`tbody`,{children:e.map(e=>(0,$.jsxs)(`tr`,{children:[(0,$.jsx)(`td`,{className:`font-bold`,children:e.username}),(0,$.jsx)(`td`,{children:(0,$.jsx)(J,{minimal:!0,intent:e.role===`admin`?U.DANGER:U.NONE,children:e.role===`admin`?s(`account.roleAdmin`):s(`account.roleUser`)})}),(0,$.jsx)(`td`,{children:(0,$.jsxs)(`div`,{className:`flex flex-wrap gap-1`,children:[!!e.totp_enabled&&(0,$.jsx)(J,{minimal:!0,intent:U.SUCCESS,children:`TOTP`}),!!(e.passkeys_count&&e.passkeys_count>0)&&(0,$.jsx)(J,{minimal:!0,intent:U.PRIMARY,children:`Passkey`}),!e.totp_enabled&&!(e.passkeys_count&&e.passkeys_count>0)&&(0,$.jsx)(J,{minimal:!0,intent:U.NONE,style:{color:`#8a9ba8`},children:s(`account.mfaNone`,`无`)})]})}),(0,$.jsx)(`td`,{children:(0,$.jsx)(`code`,{className:`text-xs`,children:e.id})}),(0,$.jsx)(`td`,{className:`text-xs text-gray-500`,children:e.created_at?$e(new Date(e.created_at*1e3)):`-`}),(0,$.jsx)(`td`,{className:`text-xs text-gray-500`,children:e.last_active_at?$e(new Date(e.last_active_at*1e3)):`-`}),(0,$.jsx)(`td`,{className:`text-xs text-gray-500`,children:e.last_resolve_at?$e(new Date(e.last_resolve_at*1e3)):`-`}),(0,$.jsx)(`td`,{className:`text-right`,children:(0,$.jsx)(`div`,{className:`inline-flex items-center gap-1`,children:(0,$.jsx)(z,{minimal:!0,intent:U.DANGER,icon:(0,$.jsx)(i,{size:14}),disabled:e.id===t,onClick:()=>O(e.id)})})})]},e.id))})]})}),(0,$.jsx)(B,{isOpen:c,onClose:()=>{l(!1),b(!1)},title:s(`account.createNewUser`),icon:`user`,children:(0,$.jsxs)(`div`,{className:`p-6 space-y-4`,children:[(0,$.jsx)(q,{label:s(`account.username`),children:(0,$.jsx)(G,{value:u,onChange:e=>f(e.target.value),placeholder:s(`auth.usernamePlaceholder`)})}),(0,$.jsx)(q,{label:s(`account.initialPassword`),children:(0,$.jsx)(G,{type:y?`text`:`password`,value:p,onChange:e=>m(e.target.value),placeholder:s(`auth.passwordPlaceholder`),rightElement:(0,$.jsx)(z,{minimal:!0,icon:y?`eye-open`:`eye-off`,onClick:()=>b(!y),title:y?s(`auth.hidePassword`,`Hide password`):s(`auth.showPassword`,`Show password`)})})}),(0,$.jsx)(q,{label:s(`account.userRole`),children:(0,$.jsx)(ie,{fill:!0,value:h,onChange:e=>g(e.target.value),options:[{label:s(`account.roleUser`),value:`user`},{label:s(`account.roleAdmin`),value:`admin`}]})}),(0,$.jsxs)(`div`,{className:`flex justify-end gap-2 mt-6`,children:[(0,$.jsx)(z,{text:s(`account.cancel`),onClick:()=>l(!1)}),(0,$.jsx)(z,{intent:U.PRIMARY,text:s(`account.createNow`),loading:_,onClick:E})]})]})})]})},At=({initialSettings:e,onRefresh:t})=>{let{t:n}=d(),[r,i]=(0,Q.useState)(e),[a,o]=(0,Q.useState)(!1),[s,c]=(0,Q.useState)(!1);return Q.useEffect(()=>{i(e)},[e]),(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(l,{size:20,className:`text-gray-500`}),(0,$.jsx)(K,{style:{margin:0},children:n(`account.systemSettings`,`System Settings`)})]}),(0,$.jsxs)(Y,{elevation:I.ONE,children:[(0,$.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-x-8 gap-y-4`,children:[(0,$.jsxs)(`div`,{className:`space-y-4`,children:[(0,$.jsx)(K,{className:`text-sm font-bold opacity-70 text-blue-500`,children:`Cloudflare Turnstile`}),(0,$.jsx)(q,{label:`Site Key`,children:(0,$.jsx)(G,{value:r.turnstile_site_key||``,onChange:e=>i({...r,turnstile_site_key:e.target.value}),placeholder:`0x000...`})}),(0,$.jsx)(q,{label:`Secret Key`,children:(0,$.jsx)(G,{type:s?`text`:`password`,value:r.turnstile_secret_key||``,onChange:e=>i({...r,turnstile_secret_key:e.target.value}),placeholder:`0x000...`,rightElement:(0,$.jsx)(z,{minimal:!0,icon:s?`eye-open`:`eye-off`,onClick:()=>c(!s),title:s?n(`auth.hidePassword`,`Hide password`):n(`auth.showPassword`,`Show password`)})})})]}),(0,$.jsxs)(`div`,{className:`space-y-4`,children:[(0,$.jsx)(K,{className:`text-sm font-bold opacity-70 text-green-500`,children:n(`account.featureToggle`,`Feature Toggle`)}),(0,$.jsx)(ae,{label:n(`account.enableTurnstileSignup`,`Enable verification on Signup`),checked:r.turnstile_enabled_signup===`true`,onChange:e=>i({...r,turnstile_enabled_signup:String(e.currentTarget.checked)})}),(0,$.jsx)(ae,{label:n(`account.enableTurnstileLogin`,`Enable verification on Login`),checked:r.turnstile_enabled_login===`true`,onChange:e=>i({...r,turnstile_enabled_login:String(e.currentTarget.checked)})})]})]}),(0,$.jsx)(W,{className:`my-4`}),(0,$.jsx)(`div`,{className:`flex justify-end`,children:(0,$.jsx)(z,{intent:U.PRIMARY,icon:`floppy-disk`,text:n(`common.save`,`Save`),loading:a,onClick:async()=>{o(!0);try{await ve({turnstile_site_key:r.turnstile_site_key||``,turnstile_secret_key:r.turnstile_secret_key||``,turnstile_enabled_signup:r.turnstile_enabled_signup||`false`,turnstile_enabled_login:r.turnstile_enabled_login||`false`}),alert(n(`common.saveSuccess`,`Settings saved`)),t()}catch(e){console.error(e)}finally{o(!1)}}})})]})]})},jt=({isAdmin:e})=>{let{t}=d(),[n,r]=(0,Q.useState)(null),[a,o]=(0,Q.useState)(!0),[s,c]=(0,Q.useState)(!1),l=(0,Q.useCallback)(async()=>{o(!0);try{r(await Ue())}catch(e){console.error(`Failed to fetch database size:`,e)}finally{o(!1)}},[]);return(0,Q.useEffect)(()=>{l()},[l]),(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(K,{className:`text-red-500 flex items-center gap-2`,children:[(0,$.jsx)(i,{size:20}),` `,t(`account.dangerZone`)]}),(0,$.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-6`,children:[(0,$.jsxs)(Y,{elevation:I.ONE,className:`flex flex-col justify-between`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(K,{children:t(`account.clearLogs`)}),(0,$.jsx)(`p`,{className:`text-xs opacity-60 mb-3`,children:t(`account.clearLogsDesc`)}),(0,$.jsxs)(`div`,{className:`flex items-center justify-between p-2.5 mb-4 bg-gray-50 dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2 text-xs`,children:[(0,$.jsx)(E,{size:15,className:`text-gray-500 flex-shrink-0`}),(0,$.jsxs)(`span`,{className:`text-gray-700 dark:text-gray-300 font-medium`,children:[t(`account.currentDbSize`),`:`]}),a?(0,$.jsx)(ne,{size:14}):(0,$.jsx)(J,{minimal:!0,round:!0,intent:U.PRIMARY,className:`font-mono font-semibold`,children:n?.formatted||`0 B`})]}),(0,$.jsx)(z,{minimal:!0,small:!0,icon:`refresh`,loading:a,onClick:l,title:t(`common.refresh`)||`Refresh`})]})]}),(0,$.jsx)(z,{fill:!0,intent:U.DANGER,text:t(`account.clearLogsBtn`),icon:`trash`,loading:s,onClick:async()=>{if(confirm(t(`account.confirmClearLogs`))){c(!0);try{await je(),alert(t(`account.clearLogsSuccess`)),await l()}catch(e){console.error(e)}finally{c(!1)}}}})]}),!e&&(0,$.jsxs)(Y,{elevation:I.ONE,className:`flex flex-col justify-between`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(K,{children:t(`account.deleteAccount`)}),(0,$.jsx)(`p`,{className:`text-xs opacity-60 mb-4`,children:t(`account.deleteAccountDesc`)})]}),(0,$.jsx)(z,{fill:!0,intent:U.DANGER,text:t(`account.deleteAccountBtn`),icon:`delete`,onClick:async()=>{if(confirm(t(`account.confirmDeleteAccount`)))try{await Me(),window.location.href=`/`}catch(e){console.error(e),alert(e.message||t(`common.errorNetwork`))}}})]})]}),(0,$.jsx)(H,{intent:U.WARNING,icon:`info-sign`,title:t(`account.inactivityPolicy`),children:(0,$.jsx)(`p`,{className:`text-sm`,children:t(`account.inactivityDesc`)})})]})},Mt=[{label:ee(`account.timezoneAuto`,`Auto (Browser Default)`),value:``},{label:`Pacific/Midway (Midway Island) (Standard: UTC-11)`,value:`Pacific/Midway`},{label:`Pacific/Honolulu (Honolulu, Hawaii) (Standard: UTC-10)`,value:`Pacific/Honolulu`},{label:`America/Anchorage (Anchorage, Alaska) (Standard: UTC-9 / DST: UTC-8)`,value:`America/Anchorage`},{label:`America/Los_Angeles (Pacific Time) (Standard: UTC-8 / DST: UTC-7)`,value:`America/Los_Angeles`},{label:`America/Denver (Mountain Time) (Standard: UTC-7 / DST: UTC-6)`,value:`America/Denver`},{label:`America/Chicago (Central Time) (Standard: UTC-6 / DST: UTC-5)`,value:`America/Chicago`},{label:`America/New_York (Eastern Time) (Standard: UTC-5 / DST: UTC-4)`,value:`America/New_York`},{label:`America/Halifax (Atlantic Time) (Standard: UTC-4 / DST: UTC-3)`,value:`America/Halifax`},{label:`America/Argentina/Buenos_Aires (Buenos Aires) (Standard: UTC-3)`,value:`America/Argentina/Buenos_Aires`},{label:`America/Noronha (Fernando de Noronha) (Standard: UTC-2)`,value:`America/Noronha`},{label:`Atlantic/Azores (Azores) (Standard: UTC-1 / DST: UTC+0)`,value:`Atlantic/Azores`},{label:`UTC (Coordinated Universal Time) (Standard: UTC+0)`,value:`UTC`},{label:`Europe/London (London) (Standard: UTC+0 / DST: UTC+1)`,value:`Europe/London`},{label:`Europe/Paris (Paris, Berlin, Rome) (Standard: UTC+1 / DST: UTC+2)`,value:`Europe/Paris`},{label:`Europe/Kyiv (Kyiv, Helsinki, Cairo) (Standard: UTC+2 / DST: UTC+3)`,value:`Europe/Kyiv`},{label:`Europe/Moscow (Moscow) (Standard: UTC+3)`,value:`Europe/Moscow`},{label:`Asia/Dubai (Dubai, Baku) (Standard: UTC+4)`,value:`Asia/Dubai`},{label:`Asia/Karachi (Karachi, Tashkent) (Standard: UTC+5)`,value:`Asia/Karachi`},{label:`Asia/Dhaka (Dhaka, Almaty) (Standard: UTC+6)`,value:`Asia/Dhaka`},{label:`Asia/Bangkok (Bangkok, Jakarta) (Standard: UTC+7)`,value:`Asia/Bangkok`},{label:`Asia/Singapore (Beijing, Shanghai, Singapore, Taipei) (Standard: UTC+8)`,value:`Asia/Singapore`},{label:`Asia/Tokyo (Tokyo, Seoul) (Standard: UTC+9)`,value:`Asia/Tokyo`},{label:`Australia/Sydney (Sydney, Melbourne) (Standard: UTC+10 / DST: UTC+11)`,value:`Australia/Sydney`},{label:`Pacific/Noumea (Nouméa) (Standard: UTC+11)`,value:`Pacific/Noumea`},{label:`Pacific/Auckland (Auckland, Suva) (Standard: UTC+12 / DST: UTC+13)`,value:`Pacific/Auckland`}],Nt=({me:e,isEditingUsername:t,setIsEditingUsername:n,editUsername:i,setEditUsername:a,usernameLoading:o,usernameFocused:s,setUsernameFocused:c,onUpdateUsername:l,onUpdateTimezone:u})=>{let{t:f}=d();return(0,$.jsxs)(Y,{elevation:I.ONE,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2 mb-4`,children:[(0,$.jsx)(_,{size:20,className:`text-blue-500`}),(0,$.jsx)(K,{style:{margin:0},children:f(`account.personalInfo`)})]}),(0,$.jsxs)(`div`,{className:`space-y-4`,children:[(0,$.jsx)(q,{label:f(`account.username`),children:(0,$.jsx)(`div`,{className:`flex gap-2`,children:t?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(ce,{content:f(`account.formatTipUsername`),isOpen:s,position:N.TOP,intent:U.PRIMARY,className:`w-full`,children:(0,$.jsx)(`div`,{className:`w-full block`,children:(0,$.jsx)(G,{fill:!0,value:i,onChange:e=>a(e.target.value),onFocus:()=>c(!0),onBlur:()=>c(!1),autoFocus:!0})})}),(0,$.jsxs)(P,{children:[(0,$.jsx)(z,{icon:(0,$.jsx)(y,{size:16}),intent:U.SUCCESS,loading:o,onClick:l}),(0,$.jsx)(z,{icon:(0,$.jsx)(O,{size:16}),onClick:()=>{n(!1),a(e?.username||``)}})]})]}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(G,{fill:!0,value:e?.username,readOnly:!0}),(0,$.jsx)(z,{icon:(0,$.jsx)(r,{size:16}),onClick:()=>n(!0)})]})})}),(0,$.jsx)(q,{label:f(`account.userId`),children:(0,$.jsx)(G,{leftIcon:`id-number`,value:e?.id,disabled:!0})}),(0,$.jsx)(q,{label:f(`account.timezone`,`Timezone`),children:(0,$.jsx)(ie,{fill:!0,value:e?.timezone||``,onChange:e=>u?.(e.target.value||null),options:Mt})})]})]})},Pt=({me:e,onRefresh:t})=>{let{t:r}=d(),i=!!(e?.passkeys_count&&e.passkeys_count>0),a=!!e?.totp_enabled,[o,s]=(0,Q.useState)(`password`),[c,l]=(0,Q.useState)(``),[f,p]=(0,Q.useState)(!1),[m,g]=(0,Q.useState)(``),[_,v]=(0,Q.useState)(``),[y,b]=(0,Q.useState)(!1),[x,S]=(0,Q.useState)(!1),[C,w]=(0,Q.useState)(!1),[T,E]=(0,Q.useState)(null);return(0,Q.useEffect)(()=>{o===`passkey`&&!i?s(a?`totp`:`password`):o===`totp`&&!a&&s(i?`passkey`:`password`)},[i,a,o]),(0,$.jsxs)(Y,{elevation:I.ONE,className:`isolate`,style:{isolation:`isolate`},children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2 mb-4`,children:[(0,$.jsx)(u,{size:20,className:`text-orange-500`}),(0,$.jsx)(K,{style:{margin:0},children:r(`account.changePassword`,`Change Password`)})]}),(i||a)&&(0,$.jsx)(`div`,{className:`mb-4 isolate`,style:{isolation:`isolate`},children:(0,$.jsx)(`div`,{className:`w-full bg-gray-100/70 dark:bg-gray-800/70 p-1 rounded-lg`,children:(0,$.jsxs)(P,{fill:!0,variant:`minimal`,style:{isolation:`isolate`},children:[(0,$.jsx)(z,{small:!0,active:o===`password`,intent:o===`password`?U.PRIMARY:U.NONE,icon:(0,$.jsx)(h,{size:14}),text:r(`account.mfa.password`,`Password`),onClick:()=>{s(`password`),E(null)}}),i&&(0,$.jsx)(z,{small:!0,active:o===`passkey`,intent:o===`passkey`?U.PRIMARY:U.NONE,icon:(0,$.jsx)(u,{size:14}),text:r(`account.mfa.passkey`,`Passkey`),onClick:()=>{s(`passkey`),E(null)}}),a&&(0,$.jsx)(z,{small:!0,active:o===`totp`,intent:o===`totp`?U.PRIMARY:U.NONE,icon:(0,$.jsx)(n,{size:14}),text:r(`account.mfa.totp`,`TOTP`),onClick:()=>{s(`totp`),E(null)}})]})})}),T&&(0,$.jsx)(H,{intent:T.intent,className:`mb-4`,children:T.text}),(0,$.jsxs)(`form`,{onSubmit:async n=>{if(n.preventDefault(),!Je.test(_)){E({text:r(`account.formatTipPassword`,`Password must be 12-100 characters and contain letters, numbers, and symbols.`),intent:U.DANGER});return}if(!e?.username){E({text:r(`auth.sessionExpired`,`Session expired. Please log in again.`),intent:U.DANGER});return}w(!0),E(null);try{let n=await Be(_,e.username);if(o===`passkey`)await xe({passkeyAssertion:await Ie(await He()),newPassword:n});else if(o===`totp`){if(m.length!==6){E({text:r(`account.totp.invalidCode`,`Please enter a 6-digit code`),intent:U.DANGER}),w(!1);return}let e=crypto.randomUUID(),t=new TextEncoder().encode(m+e),i=await crypto.subtle.digest(`SHA-256`,t);await xe({totpTokenHash:Array.from(new Uint8Array(i)).map(e=>e.toString(16).padStart(2,`0`)).join(``),totpSalt:e,newPassword:n})}else{if(!c){E({text:r(`auth.passwordRequired`,`Current password is required`),intent:U.DANGER}),w(!1);return}let t=c;(e.password_version??1)===2&&(t=await Be(c,e.username)),await xe({oldPassword:t,newPassword:n})}E({text:r(`account.passwordSuccess`,`Password updated successfully!`),intent:U.SUCCESS}),l(``),g(``),v(``),t&&t()}catch(e){E({text:ze(e,r),intent:U.DANGER})}finally{w(!1)}},className:`space-y-4`,children:[o===`password`&&(0,$.jsx)(q,{label:r(`account.currentPassword`,`Current Password`),children:(0,$.jsx)(G,{leftIcon:`lock`,type:f?`text`:`password`,value:c,onChange:e=>l(e.target.value),rightElement:(0,$.jsx)(z,{minimal:!0,icon:f?`eye-open`:`eye-off`,onClick:()=>p(!f),title:r(f?`auth.hidePassword`:`auth.showPassword`)}),required:!0})}),o===`totp`&&(0,$.jsx)(q,{label:r(`account.totpCode`,`Authenticator Code`),children:(0,$.jsx)(Ve,{length:6,value:m,onChange:g,disabled:C})}),o===`passkey`&&(0,$.jsx)(H,{intent:U.PRIMARY,children:(0,$.jsx)(`span`,{className:`text-xs`,children:r(`account.passkey.changePwNotice`,`You will be prompted to verify via biometric authentication or your security key when submitting.`)})}),(0,$.jsx)(q,{label:r(`account.newPassword`,`New Password`),children:(0,$.jsx)(ce,{content:r(`account.formatTipPassword`,`Password must be 12-100 characters and contain letters, numbers, and symbols.`),isOpen:x,position:N.TOP,intent:U.PRIMARY,className:`w-full`,children:(0,$.jsx)(`div`,{className:`w-full block`,children:(0,$.jsx)(G,{leftIcon:`lock`,type:y?`text`:`password`,value:_,onChange:e=>v(e.target.value),onFocus:()=>S(!0),onBlur:()=>S(!1),rightElement:(0,$.jsx)(z,{minimal:!0,icon:y?`eye-open`:`eye-off`,onClick:()=>b(!y),title:r(y?`auth.hidePassword`:`auth.showPassword`)}),required:!0})})})}),(0,$.jsx)(z,{fill:!0,intent:o===`passkey`?U.PRIMARY:U.WARNING,type:`submit`,loading:C,icon:o===`passkey`?(0,$.jsx)(u,{size:16}):void 0,text:o===`passkey`?r(`account.changePasswordWithPasskey`,`Verify with Passkey & Update`):r(`account.updatePassword`,`Update Password`)})]})]})},Ft=({isOpen:e,onClose:t,user:r,onSuccess:i})=>{let{t:a}=d(),o=!!(r?.passkeys_count&&r.passkeys_count>0),s=!!r?.totp_enabled,[c,l]=(0,Q.useState)(`password`),[f,p]=(0,Q.useState)(``),[m,g]=(0,Q.useState)(``),[_,v]=(0,Q.useState)(``),[y,b]=(0,Q.useState)(!1),[x,S]=(0,Q.useState)(``),[C,w]=(0,Q.useState)(!1),[T,E]=(0,Q.useState)(``),D=(0,Q.useRef)(null),O=(0,Q.useRef)(null);(0,Q.useEffect)(()=>{c===`passkey`&&!o?l(s?`totp`:`password`):c===`totp`&&!s&&l(o?`passkey`:`password`)},[o,s,c]);let k=async(e,t)=>{if(e&&e.preventDefault(),f.length!==4||!Ze.test(f)){E(a(`auth.pinFormatTip`,`PIN must be exactly 4 digits`));return}if(f!==m){E(a(`auth.pinMatchTip`,`PINs do not match`));return}w(!0),E(``);try{let e=r?.id||sessionStorage.getItem(`dns_worker_user_id`);if(!e){E(a(`auth.sessionExpired`,`Session expired. Logging out...`)),setTimeout(()=>{A()},1500);return}let n=await Ye(f,e),o={};if(c===`passkey`)o.passkeyAssertion=await Ie(await He());else if(c===`totp`){let e=(t||x).replace(/\s/g,``);if(e.length!==6){E(a(`account.totp.invalidCode`,`Please enter a 6-digit code`)),w(!1);return}let n=crypto.randomUUID();o.totpTokenHash=await Ke(e,n),o.totpSalt=n}else{if(!_){E(a(`auth.passwordRequired`,`Password is required for verification`)),w(!1);return}let e=_;r?.password_version===2&&r?.username&&(e=await Be(_,r.username)),o.password=e}await de(n,o),p(``),g(``),v(``),S(``),i()}catch(e){E(ze(e,a))}finally{w(!1)}},A=()=>{E(``),p(``),g(``),v(``),b(!1),S(``),l(`password`),t()};return(0,$.jsx)(B,{isOpen:e,onClose:A,title:r?.pin_enabled?a(`auth.changePin`,`Change PIN`):a(`auth.configurePin`,`Configure PIN`),icon:`key`,className:`pb-0`,style:{width:`420px`},children:(0,$.jsxs)(`form`,{onSubmit:k,children:[(0,$.jsxs)(`div`,{className:L,children:[T&&(0,$.jsx)(H,{intent:U.DANGER,className:`mb-4`,children:T}),(0,$.jsx)(q,{label:a(`auth.newPin`,`New 4-Digit PIN`),labelFor:`new-pin-input`,helperText:a(`auth.pinHelper`,`Digits only, e.g., 1234`),children:(0,$.jsx)(Ve,{length:4,value:f,onChange:p,type:`password`,disabled:C,autoFocus:!0,onComplete:()=>D.current?.focus()})}),(0,$.jsx)(q,{label:a(`auth.confirmPin`,`Confirm New PIN`),labelFor:`confirm-pin-input`,children:(0,$.jsx)(Ve,{ref:D,length:4,value:m,onChange:g,type:`password`,disabled:C,onComplete:()=>{c===`totp`?O.current?.focus():c===`password`&&document.getElementById(`verify-pw-input`)?.focus()}})}),(0,$.jsx)(W,{className:`my-4`}),(0,$.jsxs)(`div`,{className:`mb-3 space-y-2`,children:[(0,$.jsx)(`span`,{className:`font-semibold text-sm block`,children:a(`auth.verifyIdentity`,`Verify Identity`)}),(o||s)&&(0,$.jsx)(`div`,{className:`w-full bg-gray-100/70 dark:bg-gray-800/70 p-1 rounded-lg isolate`,style:{isolation:`isolate`},children:(0,$.jsxs)(P,{fill:!0,variant:`minimal`,style:{isolation:`isolate`},children:[(0,$.jsx)(z,{small:!0,active:c===`password`,intent:c===`password`?U.PRIMARY:U.NONE,icon:(0,$.jsx)(h,{size:14}),text:a(`account.mfa.password`,`Password`),onClick:()=>{l(`password`),E(``)}}),o&&(0,$.jsx)(z,{small:!0,active:c===`passkey`,intent:c===`passkey`?U.PRIMARY:U.NONE,icon:(0,$.jsx)(u,{size:14}),text:a(`account.mfa.passkey`,`Passkey`),onClick:()=>{l(`passkey`),E(``)}}),s&&(0,$.jsx)(z,{small:!0,active:c===`totp`,intent:c===`totp`?U.PRIMARY:U.NONE,icon:(0,$.jsx)(n,{size:14}),text:a(`account.mfa.totp`,`TOTP`),onClick:()=>{l(`totp`),E(``)}})]})})]}),c===`password`&&(0,$.jsx)(q,{label:a(`auth.currentPassword`,`Current Password`),labelFor:`verify-pw-input`,children:(0,$.jsx)(G,{id:`verify-pw-input`,type:y?`text`:`password`,placeholder:a(`auth.passwordPlaceholder`,`Enter current password`),value:_,onChange:e=>v(e.target.value),leftIcon:`lock`,rightElement:(0,$.jsx)(z,{minimal:!0,icon:y?`eye-open`:`eye-off`,onClick:()=>b(!y),title:y?a(`auth.hidePassword`,`Hide password`):a(`auth.showPassword`,`Show password`)}),required:!0})}),c===`totp`&&(0,$.jsx)(q,{label:a(`auth.totpCode`,`TOTP Code`),labelFor:`verify-totp-input`,children:(0,$.jsx)(Ve,{ref:O,length:6,value:x,onChange:S,disabled:C,onComplete:e=>k(void 0,e),autoFocus:!0})}),c===`passkey`&&(0,$.jsx)(H,{intent:U.PRIMARY,icon:(0,$.jsx)(u,{size:16}),children:(0,$.jsx)(`span`,{className:`text-xs`,children:a(`account.passkey.submitNotice`,a(`account.passkey.changePwNotice`,`You will be prompted to verify via biometric authentication or your security key when submitting.`))})})]}),(0,$.jsx)(`div`,{className:V,children:(0,$.jsxs)(`div`,{className:X,children:[(0,$.jsx)(z,{onClick:A,children:a(`common.cancel`,`Cancel`)}),(0,$.jsx)(z,{type:`submit`,intent:U.PRIMARY,loading:C,children:a(`common.save`,`Save`)})]})})]})})},It=({isOpen:e,onClose:t,user:r,onSuccess:i})=>{let{t:a}=d(),o=!!(r?.passkeys_count&&r.passkeys_count>0),s=!!r?.totp_enabled,[c,l]=(0,Q.useState)(`password`),[f,p]=(0,Q.useState)(``),[m,g]=(0,Q.useState)(!1),[_,v]=(0,Q.useState)(``),[y,b]=(0,Q.useState)(!1),[x,C]=(0,Q.useState)(``);(0,Q.useEffect)(()=>{c===`passkey`&&!o?l(s?`totp`:`password`):c===`totp`&&!s&&l(o?`passkey`:`password`)},[o,s,c]);let w=async(e,t)=>{e&&e.preventDefault(),b(!0),C(``);try{let e={};if(c===`passkey`)e.passkeyAssertion=await Ie(await He());else if(c===`totp`){let n=(t||_).replace(/\s/g,``);if(n.length!==6){C(a(`account.totp.invalidCode`,`Please enter a 6-digit code`)),b(!1);return}let r=crypto.randomUUID();e.totpTokenHash=await Ke(n,r),e.totpSalt=r}else{if(!f){C(a(`auth.passwordRequired`,`Password is required for verification`)),b(!1);return}let t=f;r?.password_version===2&&r?.username&&(t=await Be(f,r.username)),e.password=t}await fe(e),p(``),v(``),i()}catch(e){C(ze(e,a))}finally{b(!1)}},T=()=>{C(``),p(``),g(!1),v(``),l(`password`),t()};return(0,$.jsx)(B,{isOpen:e,onClose:T,title:a(`auth.disablePin`,`Disable Session Lock`),icon:`trash`,className:`pb-0`,style:{width:`420px`},children:(0,$.jsxs)(`form`,{onSubmit:w,children:[(0,$.jsxs)(`div`,{className:L,children:[x&&(0,$.jsx)(H,{intent:U.DANGER,className:`mb-4`,children:x}),(0,$.jsx)(H,{intent:U.WARNING,className:`mb-4`,icon:(0,$.jsx)(S,{size:20}),children:a(`auth.disablePinWarning`,`Disabling the PIN will disable the inactivity session locking feature completely.`)}),(0,$.jsxs)(`div`,{className:`mb-3 space-y-2`,children:[(0,$.jsx)(`span`,{className:`font-semibold text-sm block`,children:a(`auth.verifyIdentity`,`Verify Identity`)}),(o||s)&&(0,$.jsx)(`div`,{className:`w-full bg-gray-100/70 dark:bg-gray-800/70 p-1 rounded-lg isolate`,style:{isolation:`isolate`},children:(0,$.jsxs)(P,{fill:!0,variant:`minimal`,style:{isolation:`isolate`},children:[(0,$.jsx)(z,{small:!0,active:c===`password`,intent:c===`password`?U.PRIMARY:U.NONE,icon:(0,$.jsx)(h,{size:14}),text:a(`account.mfa.password`,`Password`),onClick:()=>{l(`password`),C(``)}}),o&&(0,$.jsx)(z,{small:!0,active:c===`passkey`,intent:c===`passkey`?U.PRIMARY:U.NONE,icon:(0,$.jsx)(u,{size:14}),text:a(`account.mfa.passkey`,`Passkey`),onClick:()=>{l(`passkey`),C(``)}}),s&&(0,$.jsx)(z,{small:!0,active:c===`totp`,intent:c===`totp`?U.PRIMARY:U.NONE,icon:(0,$.jsx)(n,{size:14}),text:a(`account.mfa.totp`,`TOTP`),onClick:()=>{l(`totp`),C(``)}})]})})]}),c===`password`&&(0,$.jsx)(q,{label:a(`auth.currentPassword`,`Current Password`),labelFor:`disable-pw-input`,children:(0,$.jsx)(G,{id:`disable-pw-input`,type:m?`text`:`password`,placeholder:a(`auth.passwordPlaceholder`,`Enter current password`),value:f,onChange:e=>p(e.target.value),leftIcon:`lock`,rightElement:(0,$.jsx)(z,{minimal:!0,icon:m?`eye-open`:`eye-off`,onClick:()=>g(!m),title:m?a(`auth.hidePassword`,`Hide password`):a(`auth.showPassword`,`Show password`)}),required:!0})}),c===`totp`&&(0,$.jsx)(q,{label:a(`auth.totpCode`,`TOTP Code`),labelFor:`disable-totp-input`,children:(0,$.jsx)(Ve,{length:6,value:_,onChange:v,disabled:y,onComplete:e=>w(void 0,e),autoFocus:!0})}),c===`passkey`&&(0,$.jsx)(H,{intent:U.PRIMARY,icon:(0,$.jsx)(u,{size:16}),children:(0,$.jsx)(`span`,{className:`text-xs`,children:a(`account.passkey.submitNotice`,a(`account.passkey.changePwNotice`,`You will be prompted to verify via biometric authentication or your security key when submitting.`))})})]}),(0,$.jsx)(`div`,{className:V,children:(0,$.jsxs)(`div`,{className:X,children:[(0,$.jsx)(z,{onClick:T,children:a(`common.cancel`,`Cancel`)}),(0,$.jsx)(z,{type:`submit`,intent:U.DANGER,loading:y,children:a(`common.disable`,`Disable`)})]})})]})})},Lt=({user:e,onRefresh:t})=>{let{t:r}=d(),[i,a]=(0,Q.useState)(!1),[o,s]=(0,Q.useState)(!1),[c,l]=(0,Q.useState)(!1),u=!!e?.pin_enabled,f=e?.session_lock_timeout||15,p=async e=>{let n=Number(e.currentTarget.value);a(!0);try{await Fe({session_lock_timeout:n}),t()}catch(e){console.error(`Failed to change session lock timeout`,e)}finally{a(!1)}},m=()=>{s(!0)};return(0,$.jsxs)(Y,{elevation:I.ONE,children:[(0,$.jsxs)(`div`,{className:`flex items-center justify-between mb-4`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(n,{size:20,className:`text-indigo-600`}),(0,$.jsx)(K,{className:`m-0!`,children:r(`auth.sessionLockTitle`,`Idle Session Lock`)})]}),!u&&(0,$.jsx)(z,{icon:`key`,intent:U.PRIMARY,onClick:m,disabled:i,children:r(`auth.configurePin`,`Configure 4-Digit PIN`)})]}),(0,$.jsx)(`p`,{className:`text-gray-500 text-sm mb-4`,children:r(`auth.sessionLockDesc`,`Lock the interface with a 4-digit PIN when the application is idle to protect active sessions from unauthorized physical access.`)}),(0,$.jsx)(`div`,{className:`flex flex-col gap-4 mb-4`,children:(0,$.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,$.jsx)(`span`,{children:r(`auth.inactivityTimeout`,`Inactivity Timeout`)}),(0,$.jsx)(ie,{value:f,onChange:p,disabled:!u||i,options:[{label:r(`auth.timeout1m`,`1 Minute`),value:1},{label:r(`auth.timeout2m`,`2 Minutes`),value:2},{label:r(`auth.timeout5m`,`5 Minutes`),value:5},{label:r(`auth.timeout15m`,`15 Minutes`),value:15},{label:r(`auth.timeout30m`,`30 Minutes`),value:30},{label:r(`auth.timeout60m`,`60 Minutes`),value:60}]})]})}),u&&(0,$.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,$.jsx)(z,{icon:`edit`,onClick:m,disabled:i,children:r(`auth.changePin`,`Change PIN`)}),(0,$.jsx)(z,{icon:`trash`,intent:U.DANGER,onClick:()=>{l(!0)},disabled:i,children:r(`auth.disablePin`,`Disable PIN & Lock`)}),(0,$.jsx)(z,{icon:`lock`,intent:U.WARNING,onClick:async()=>{a(!0);try{await qe(),window.dispatchEvent(new Event(`session_paused`))}catch(e){console.error(`Failed to lock session immediately`,e)}finally{a(!1)}},disabled:i,children:r(`auth.lockNow`,`Lock Now`)})]}),(0,$.jsx)(Ft,{isOpen:o,onClose:()=>s(!1),user:e,onSuccess:()=>{s(!1),t()}}),(0,$.jsx)(It,{isOpen:c,onClose:()=>l(!1),user:e,onSuccess:()=>{l(!1),t()}})]})};function Rt({user:e,onRefresh:t,toasterRef:n}){let{t:r}=d(),[i,a]=(0,Q.useState)(null),[o,s]=(0,Q.useState)(!0),[c,l]=(0,Q.useState)(!1),[u,f]=(0,Q.useState)(!1),[p,m]=(0,Q.useState)(!1),[h,g]=(0,Q.useState)(!1),[_,v]=(0,Q.useState)(``),[y,b]=(0,Q.useState)(``),[x,S]=(0,Q.useState)(!1),[C,w]=(0,Q.useState)(``),[T,E]=(0,Q.useState)(``),[D,O]=(0,Q.useState)(null),[k,A]=(0,Q.useState)(!1),j=(0,Q.useCallback)(async()=>{s(!0);try{a(await Z.getUserStatus()),m(Z.isUnlocked())}catch(e){console.error(`[useE2eeCardState] Failed to fetch E2EE status:`,e)}finally{s(!1)}},[]);(0,Q.useEffect)(()=>{j()},[j]);let M=e.passkeys_count&&e.passkeys_count>0||(i?.userPasskeyCount||0)>0,ee=!!i?.enabled,N=(0,Q.useMemo)(()=>{if(!i?.publicKey)return!1;try{let e=JSON.parse(i.publicKey);return e.alg===`P256-MLKEM768`||!!e.pqc_pk}catch{return!1}},[i?.publicKey]),P=async e=>{if(e){l(!0);try{await Z.enableUserE2ee(),n.current?.show({message:r(`account.e2ee.enableSuccess`),intent:U.SUCCESS,icon:`lock`}),await j(),t?.()}catch(e){console.error(`[useE2eeCardState] Failed to enable E2EE:`,e),n.current?.show({message:e.message||r(`account.e2ee.enableError`),intent:U.DANGER,icon:`error`})}finally{l(!1)}}else f(!0)},F=async()=>{l(!0);try{await Z.disableUserE2ee(),n.current?.show({message:r(`account.e2ee.disableSuccess`),intent:U.WARNING,icon:`unlock`}),await j(),t?.()}catch(e){console.error(`[useE2eeCardState] Failed to disable E2EE:`,e),n.current?.show({message:e.message||r(`account.e2ee.disableError`),intent:U.DANGER,icon:`error`})}finally{l(!1),f(!1)}},te=async()=>{l(!0);try{await Z.unlockUser()&&(m(!0),n.current?.show({message:r(`account.e2ee.unlockSuccess`),intent:U.SUCCESS,icon:`tick`}))}catch(e){console.error(`[useE2eeCardState] Failed to unlock private key:`,e),n.current?.show({message:e.message||r(`account.e2ee.unlockError`),intent:U.DANGER,icon:`error`})}finally{l(!1)}},I=async e=>{e.preventDefault();let i=_.trim();if(i){l(!0),b(``);try{await Z.unlockWithRecoveryKey(i);try{let e=await tt({recoveryKey:i});await Z.wrapCurrentKeyForRecovery(e.recovery_key),O(e.recovery_key)}catch(e){console.warn(`[useE2eeCardState] Recovery key auto-rotation failed:`,e)}m(!0),g(!1),v(``),n.current?.show({message:r(`account.e2ee.unlockSuccess`),intent:U.SUCCESS,icon:`tick`}),await j(),t?.()}catch(e){console.error(`[useE2eeCardState] Recovery unlock failed:`,e),b(e.message||r(`account.e2ee.recoveryUnlockFailed`))}finally{l(!1)}}},L=async()=>{l(!0);try{await Z.enableUserE2ee(),n.current?.show({message:r(`account.e2ee.keypairGenSuccess`),intent:U.SUCCESS,icon:`tick`}),await j(),t?.()}catch(e){console.error(`[useE2eeCardState] Generate key with Passkey failed:`,e),n.current?.show({message:e.message||r(`account.e2ee.keypairGenError`),intent:U.DANGER,icon:`error`})}finally{l(!1)}},R=async()=>{l(!0);try{await Z.rotateUserE2eeKey(),n.current?.show({message:r(`account.e2ee.upgradePqcSuccess`,`已成功升级到后量子混合加密 (P256-MLKEM768)`),intent:U.SUCCESS,icon:`tick`}),await j(),t?.()}catch(e){console.error(`[useE2eeCardState] Upgrade to PQC failed:`,e),n.current?.show({message:e.message||r(`account.e2ee.upgradePqcError`,`升级到后量子加密失败`),intent:U.DANGER,icon:`error`})}finally{l(!1)}},z=async e=>{e.preventDefault();let i=C.trim();if(i){l(!0),E(``);try{await Z.initUserE2eeWithRecoveryKey(i);try{let e=await tt({recoveryKey:i});await Z.wrapCurrentKeyForRecovery(e.recovery_key),O(e.recovery_key)}catch(e){console.warn(`[useE2eeCardState] Recovery key auto-rotation failed:`,e)}S(!1),w(``),m(!0),n.current?.show({message:r(`account.e2ee.keypairGenSuccess`),intent:U.SUCCESS,icon:`tick`}),await j(),t?.()}catch(e){console.error(`[useE2eeCardState] Init keypair with recovery key failed:`,e),E(e.message||r(`account.e2ee.initFailed`))}finally{l(!1)}}},B=()=>{Z.clearStorage(),m(!1),n.current?.show({message:r(`account.e2ee.lockSuccess`,`已锁定,私钥已从本地清除`),intent:U.NONE})},[ne,V]=(0,Q.useState)(!1);return{status:i,loading:o,processing:c,isUnlocked:p,isPqc:N,isLogsE2eeEnabled:ee,hasPasskey:M,isDisableAlertOpen:u,setIsDisableAlertOpen:f,isRecoveryDialogOpen:h,setIsRecoveryDialogOpen:g,recoveryKeyInput:_,setRecoveryKeyInput:v,recoveryUnlockError:y,setRecoveryUnlockError:b,initRecoveryDialogOpen:x,setInitRecoveryDialogOpen:S,initRecoveryKeyInput:C,setInitRecoveryKeyInput:w,initRecoveryError:T,setInitRecoveryError:E,rotatedKey:D,setRotatedKey:O,copiedKey:k,handleToggleLogs:P,handleConfirmDisable:F,handleUnlock:te,handleUnlockWithRecoveryKey:I,handleGenerateKeyWithPasskey:L,handleUpgradeToPqc:R,handleInitWithRecoveryKey:z,handleLockDevice:B,handleCopyRotatedKey:e=>{navigator.clipboard.writeText(e),A(!0),setTimeout(()=>A(!1),2e3)},isResetAlertOpen:ne,setIsResetAlertOpen:V,handleResetAndReinit:async()=>{l(!0);try{await fetch(`/api/account/e2ee?purge=true`,{method:`DELETE`}),Z.clearStorage(),M?(await Z.enableUserE2ee(),n.current?.show({message:r(`account.e2ee.resetAndInitPasskeySuccess`,`密钥对已成功重置并使用通行密钥重新加密!`),intent:U.SUCCESS,icon:`tick`})):(n.current?.show({message:r(`account.e2ee.resetSuccessEnterRecovery`,`旧密钥已清除,请使用恢复密钥初始化新密钥对。`),intent:U.WARNING,icon:`refresh`}),S(!0)),await j(),t?.()}catch(e){console.error(`[useE2eeCardState] Reset keypair failed:`,e),n.current?.show({message:e.message||r(`account.e2ee.resetFailed`,`重置密钥对失败`),intent:U.DANGER,icon:`error`})}finally{l(!1),V(!1)}},handleEnrollPasskey:async()=>{l(!0);try{let e=await Ee(),i=e.length>0?e[0].id:`primary`;if(await Z.wrapCurrentKeyForPasskey(i))n.current?.show({message:r(`account.e2ee.enrollPasskeySuccess`,`已成功将通行密钥关联至端到端加密!`),intent:U.SUCCESS,icon:`tick`}),await j(),t?.();else throw Error(r(`account.e2ee.enrollPasskeyFailed`,`关联通行密钥失败`))}catch(e){console.error(`[useE2eeCardState] Enroll passkey failed:`,e),n.current?.show({message:e.message||r(`account.e2ee.enrollPasskeyFailed`,`关联通行密钥失败`),intent:U.DANGER,icon:`error`})}finally{l(!1)}}}}const zt=({isLogsE2eeEnabled:e})=>{let{t}=d();return(0,$.jsxs)(`div`,{className:`flex items-center justify-between mb-3`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(h,{size:20,className:e?`text-emerald-500`:`text-gray-400`}),(0,$.jsx)(K,{style:{margin:0},children:t(`account.e2ee.title`,`E2EE`)}),(0,$.jsx)(J,{intent:e?U.SUCCESS:U.NONE,minimal:!0,round:!0,children:t(e?`account.e2ee.enabled`:`account.e2ee.disabled`)})]}),(0,$.jsx)(re,{placement:`bottom-end`,usePortal:!0,content:(0,$.jsxs)(`div`,{className:`p-4 max-w-sm`,children:[(0,$.jsx)(R,{children:t(`account.e2ee.trustBoundaryTitle`)}),(0,$.jsx)(`p`,{className:`text-sm text-gray-700 dark:text-gray-300 m-0`,children:t(`account.e2ee.trustBoundaryDesc`,`All DNS query traffic inevitably passes through the hosting server (Cloudflare Workers edge nodes or self-hosted server runtime) during resolution, where queries are processed in memory before being encrypted and saved. This feature strictly protects data at rest in the cloud database (D1 / persistent storage) from data leaks or offline analysis; it does not conceal active network traffic from the hosting server processing the request.`)})]}),children:(0,$.jsx)(z,{icon:`help`,variant:`minimal`,intent:U.NONE})})]})},Bt=({hasPasskey:e,processing:n,onGenerateKeyWithPasskey:r,onOpenInitRecoveryDialog:i})=>{let{t:a}=d();return(0,$.jsx)(H,{intent:U.PRIMARY,icon:`shield`,className:`my-3 text-xs`,children:(0,$.jsxs)(`div`,{className:`space-y-3`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`h5`,{className:`font-semibold text-sm mb-1 text-blue-900 dark:text-blue-100`,children:a(`account.e2ee.noKeypairTitle`)}),(0,$.jsx)(`p`,{className:`text-xs text-blue-800 dark:text-blue-200 m-0`,children:a(`account.e2ee.noKeypairDesc`)})]}),(0,$.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap pt-1`,children:[e?(0,$.jsx)(z,{intent:U.PRIMARY,small:!0,icon:(0,$.jsx)(t,{size:14}),text:a(`account.e2ee.initPasskeyBtn`),loading:n,onClick:r}):(0,$.jsx)(z,{intent:U.PRIMARY,small:!0,icon:(0,$.jsx)(u,{size:14}),text:a(`account.e2ee.addPasskeyBtn`),onClick:()=>{document.getElementById(`passkeys-section`)?.scrollIntoView({behavior:`smooth`})}}),(0,$.jsx)(z,{intent:U.NONE,small:!0,icon:(0,$.jsx)(u,{size:14}),text:a(`account.e2ee.initRecoveryBtn`),onClick:i})]})]})})},Vt=({status:e,isLogsE2eeEnabled:r,isUnlocked:i,isPqc:a,hasPasskey:o,processing:s,loading:c,onToggleLogs:l,onUpgradeToPqc:u,onLockDevice:p,onUnlockPasskey:m,onOpenRecoveryUnlockDialog:h,onEnrollPasskey:g,onOpenResetAlert:_})=>{let{t:v}=d();return(0,$.jsxs)(`div`,{className:`space-y-4`,children:[(0,$.jsx)(W,{className:`my-2`}),(0,$.jsxs)(`div`,{className:`flex flex-col sm:flex-row sm:items-center justify-between gap-4 p-4 rounded-lg border border-gray-200 dark:border-gray-800 bg-gray-50/70 dark:bg-gray-900/50`,children:[(0,$.jsxs)(`div`,{className:`space-y-1`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(`span`,{className:`font-semibold text-sm text-gray-900 dark:text-gray-100`,children:v(`account.e2ee.enableSwitch`)}),(0,$.jsx)(J,{intent:r?U.SUCCESS:U.NONE,minimal:!0,round:!0,children:v(r?`account.e2ee.enabled`:`account.e2ee.disabled`)})]}),(0,$.jsx)(`p`,{className:`text-xs text-gray-500 dark:text-gray-400 m-0`,children:v(`account.e2ee.enableSwitchDesc`)})]}),(0,$.jsx)(`div`,{className:`shrink-0 flex items-center`,children:(0,$.jsx)(ae,{checked:r,disabled:s||c,onChange:e=>l(e.currentTarget.checked),large:!0,className:`mb-0`})})]}),(0,$.jsxs)(`div`,{className:`pt-2 border-t border-gray-100 dark:border-gray-800/80 space-y-2 text-xs`,children:[(0,$.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,$.jsxs)(`span`,{className:`opacity-70 flex items-center gap-1.5`,children:[(0,$.jsx)(t,{size:13}),v(`account.e2ee.keyType`),`:`]}),(0,$.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,$.jsx)(`span`,{className:`font-mono`,children:a?`P256-MLKEM768 + AES-256-GCM`:`ECDH P-256 + AES-256-GCM`}),a?(0,$.jsx)(J,{minimal:!0,intent:U.PRIMARY,className:`text-[10px]`,children:v(`account.e2ee.pqcTag`,`PQC / NIST FIPS 203`)}):(0,$.jsx)(z,{small:!0,intent:U.PRIMARY,minimal:!0,icon:(0,$.jsx)(f,{size:12}),text:v(`account.e2ee.upgradePqcBtn`,`升级到后量子 (PQC)`),loading:s,onClick:u})]})]}),(0,$.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,$.jsxs)(`span`,{className:`opacity-70 flex items-center gap-1.5`,children:[(0,$.jsx)(n,{size:13}),v(`account.e2ee.deviceState`),`:`]}),i?(0,$.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap justify-end`,children:[(0,$.jsx)(J,{minimal:!0,intent:U.SUCCESS,className:`text-[10px]`,children:v(`account.e2ee.unlocked`)}),o&&(e?.wrappedPasskeys?.length||0)===0&&g&&(0,$.jsx)(z,{small:!0,intent:U.PRIMARY,icon:(0,$.jsx)(t,{size:12}),text:v(`account.e2ee.enrollPasskeyBtn`,`关联当前通行密钥`),loading:s,onClick:g}),(0,$.jsx)(z,{small:!0,minimal:!0,intent:U.NONE,icon:`lock`,text:v(`account.e2ee.lockDevice`,`锁定此设备`),onClick:p})]}):(0,$.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap justify-end`,children:[o&&(e?.wrappedPasskeys?.length||0)>0&&(0,$.jsx)(z,{small:!0,minimal:!0,intent:U.PRIMARY,icon:(0,$.jsx)(f,{size:12}),text:v(`account.e2ee.unlockButton`),loading:s,onClick:m}),(0,$.jsx)(z,{small:!0,minimal:!0,intent:U.NONE,icon:(0,$.jsx)(t,{size:12}),text:v(`account.e2ee.unlockRecoveryButton`),onClick:h}),_&&(0,$.jsx)(z,{small:!0,minimal:!0,intent:U.DANGER,icon:`reset`,text:v(`account.e2ee.resetKeypairBtn`,`重置密钥对`),onClick:_})]})]}),(0,$.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,$.jsxs)(`span`,{className:`opacity-70`,children:[v(`account.e2ee.protectedPasskeys`),`:`]}),(0,$.jsxs)(`span`,{className:`font-mono`,children:[e?.wrappedPasskeys?.length||0,` `,v(`account.e2ee.devicesUnit`)]})]})]})]})},Ht=({isOpen:e,processing:t,onConfirm:n,onCancel:r})=>{let{t:i}=d();return(0,$.jsx)(F,{isOpen:e,confirmButtonText:i(`common.confirmDisable`),cancelButtonText:i(`common.cancel`),intent:U.DANGER,icon:`unlock`,onConfirm:n,onCancel:r,loading:t,children:(0,$.jsx)(`p`,{children:i(`account.e2ee.disableConfirm`)})})},Ut=({isOpen:e,onClose:t,recoveryKeyInput:n,setRecoveryKeyInput:r,recoveryUnlockError:i,processing:a,onSubmit:o})=>{let{t:s}=d();return(0,$.jsx)(B,{isOpen:e,onClose:t,title:s(`account.e2ee.unlockWithRecoveryTitle`),icon:`key`,className:`dark:bg-gray-900`,children:(0,$.jsxs)(`form`,{onSubmit:o,autoComplete:`off`,children:[(0,$.jsxs)(`div`,{className:L,children:[(0,$.jsx)(`p`,{className:`text-xs text-gray-500 dark:text-gray-400 mb-3`,children:s(`account.e2ee.unlockWithRecoveryDesc`)}),i&&(0,$.jsx)(H,{intent:U.DANGER,className:`mb-3 text-xs`,children:i}),(0,$.jsx)(q,{label:s(`account.e2ee.recoveryKeyInputLabel`),labelFor:`recovery-key-input`,children:(0,$.jsx)(G,{id:`recovery-key-input`,name:`recovery_key_input`,autoComplete:`off`,autoCorrect:`off`,autoCapitalize:`off`,spellCheck:!1,"data-1p-ignore":`true`,"data-lpignore":`true`,"data-bwignore":`true`,placeholder:`123456-789012-345678-901234-567890`,value:n,onChange:e=>r(e.target.value),leftIcon:`key`,className:`font-mono text-xs`,autoFocus:!0})})]}),(0,$.jsx)(`div`,{className:V,children:(0,$.jsxs)(`div`,{className:X,children:[(0,$.jsx)(z,{onClick:t,text:s(`common.cancel`)}),(0,$.jsx)(z,{type:`submit`,intent:U.PRIMARY,loading:a,disabled:!n.trim(),text:s(`account.e2ee.unlockConfirm`)})]})})]})})},Wt=({isOpen:e,onClose:t,initRecoveryKeyInput:n,setInitRecoveryKeyInput:r,initRecoveryError:i,processing:a,onSubmit:o})=>{let{t:s}=d();return(0,$.jsx)(B,{isOpen:e,onClose:t,title:s(`account.e2ee.initWithRecoveryTitle`),icon:`key`,className:`dark:bg-gray-900`,children:(0,$.jsxs)(`form`,{onSubmit:o,autoComplete:`off`,children:[(0,$.jsxs)(`div`,{className:L,children:[(0,$.jsx)(`p`,{className:`text-xs text-gray-500 dark:text-gray-400 mb-3`,children:s(`account.e2ee.initWithRecoveryDesc`)}),i&&(0,$.jsx)(H,{intent:U.DANGER,className:`mb-3 text-xs`,children:i}),(0,$.jsx)(q,{label:s(`account.e2ee.recoveryKeyInputLabel`),labelFor:`init-recovery-key-input`,children:(0,$.jsx)(G,{id:`init-recovery-key-input`,name:`init_recovery_key_input`,autoComplete:`off`,autoCorrect:`off`,autoCapitalize:`off`,spellCheck:!1,"data-1p-ignore":`true`,"data-lpignore":`true`,"data-bwignore":`true`,placeholder:`123456-789012-345678-901234-567890`,value:n,onChange:e=>r(e.target.value),leftIcon:`key`,className:`font-mono text-xs`,autoFocus:!0})})]}),(0,$.jsx)(`div`,{className:V,children:(0,$.jsxs)(`div`,{className:X,children:[(0,$.jsx)(z,{onClick:t,text:s(`common.cancel`)}),(0,$.jsx)(z,{type:`submit`,intent:U.PRIMARY,loading:a,disabled:!n.trim(),text:s(`account.e2ee.generateKeypairBtn`)})]})})]})})},Gt=({rotatedKey:e,onClose:t,copiedKey:n,onCopyKey:r})=>{let{t:i}=d();return(0,$.jsxs)(B,{isOpen:!!e,onClose:t,title:i(`account.recoveryKey.autoRotatedTitle`),icon:`warning-sign`,isCloseButtonShown:!1,canOutsideClickClose:!1,className:`dark:bg-gray-900`,children:[(0,$.jsxs)(`div`,{className:L,children:[(0,$.jsx)(H,{intent:U.WARNING,icon:(0,$.jsx)(S,{size:16}),className:`mb-4 text-xs`,children:i(`account.recoveryKey.autoRotatedNotice`)}),e&&(0,$.jsxs)(`div`,{className:`space-y-3`,children:[(0,$.jsx)(`div`,{className:`p-3 bg-gray-100 dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700 font-mono text-center text-lg font-bold tracking-widest select-all text-gray-900 dark:text-gray-100`,children:e}),(0,$.jsx)(`div`,{className:`flex justify-center`,children:(0,$.jsx)(z,{intent:U.PRIMARY,icon:n?(0,$.jsx)(y,{size:14,className:`text-green-400`}):(0,$.jsx)(w,{size:14}),text:i(n?`common.copied`:`common.copyKey`),onClick:()=>r(e)})})]})]}),(0,$.jsx)(`div`,{className:V,children:(0,$.jsx)(`div`,{className:X,children:(0,$.jsx)(z,{intent:U.SUCCESS,onClick:t,text:i(`account.recoveryKey.savedAndClose`)})})})]})},Kt=({isOpen:e,processing:t,hasPasskey:n,onConfirm:r,onCancel:i})=>{let{t:a}=d();return(0,$.jsx)(F,{isOpen:e,confirmButtonText:a(`account.e2ee.confirmResetBtn`,`确认重置并重新生成`),cancelButtonText:a(`common.cancel`,`取消`),intent:U.DANGER,icon:`reset`,onConfirm:r,onCancel:i,loading:t,children:(0,$.jsxs)(`div`,{className:`space-y-2 text-xs`,children:[(0,$.jsx)(`p`,{className:`font-semibold text-gray-900 dark:text-gray-100`,children:a(`account.e2ee.resetKeypairTitle`,`重置端到端加密密钥对`)}),(0,$.jsx)(`p`,{children:a(`account.e2ee.resetKeypairDesc`,`如果您的恢复密钥不匹配或无法解密,且未关联通行密钥,重置密钥对将从服务端清除旧密钥,并为您重新生成全新的后量子 (P256-MLKEM768) 密钥对。`)}),(0,$.jsx)(`p`,{className:`text-gray-500 dark:text-gray-400`,children:n?a(`account.e2ee.resetKeypairPasskeyNotice`,`确认后将立即调用您当前已配置的通行密钥 (Passkey) 完成新密钥对的加密与授权。`):a(`account.e2ee.resetKeypairRecoveryNotice`,`确认后将引导您输入当前恢复密钥以完成新密钥对的生成与加密。`)})]})})},qt=({user:e,onRefresh:t})=>{let{t:n}=d(),r=(0,Q.useRef)(null),{status:i,loading:a,processing:o,isUnlocked:s,isPqc:c,isLogsE2eeEnabled:l,hasPasskey:u,isDisableAlertOpen:f,setIsDisableAlertOpen:p,isRecoveryDialogOpen:m,setIsRecoveryDialogOpen:h,recoveryKeyInput:g,setRecoveryKeyInput:_,recoveryUnlockError:v,initRecoveryDialogOpen:y,setInitRecoveryDialogOpen:b,initRecoveryKeyInput:x,setInitRecoveryKeyInput:S,initRecoveryError:C,setInitRecoveryError:w,rotatedKey:T,setRotatedKey:E,copiedKey:D,handleToggleLogs:O,handleConfirmDisable:k,handleUnlock:A,handleUnlockWithRecoveryKey:j,handleGenerateKeyWithPasskey:M,handleUpgradeToPqc:ee,handleInitWithRecoveryKey:N,handleLockDevice:P,handleCopyRotatedKey:F,isResetAlertOpen:te,setIsResetAlertOpen:L,handleResetAndReinit:R,handleEnrollPasskey:z}=Rt({user:e,onRefresh:t,toasterRef:r});return(0,$.jsxs)(Y,{elevation:I.ONE,className:`space-y-6`,children:[(0,$.jsx)(oe,{ref:r}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(zt,{isLogsE2eeEnabled:l}),(0,$.jsx)(`p`,{className:`text-sm text-gray-600 dark:text-gray-400 mb-3`,children:n(`account.e2ee.desc`)}),a?(0,$.jsx)(`div`,{className:`flex items-center justify-center p-6`,children:(0,$.jsx)(ne,{size:20})}):i?.hasKeys?(0,$.jsx)(Vt,{status:i,isLogsE2eeEnabled:l,isUnlocked:s,isPqc:c,hasPasskey:u,processing:o,loading:a,onToggleLogs:O,onUpgradeToPqc:ee,onLockDevice:P,onUnlockPasskey:A,onOpenRecoveryUnlockDialog:()=>{_(``),h(!0)},onEnrollPasskey:z,onOpenResetAlert:()=>L(!0)}):(0,$.jsx)(Bt,{hasPasskey:u,processing:o,onGenerateKeyWithPasskey:M,onOpenInitRecoveryDialog:()=>{w(``),S(``),b(!0)}})]}),(0,$.jsx)(Ht,{isOpen:f,processing:o,onConfirm:k,onCancel:()=>p(!1)}),(0,$.jsx)(Kt,{isOpen:te,processing:o,hasPasskey:u,onConfirm:R,onCancel:()=>L(!1)}),(0,$.jsx)(Ut,{isOpen:m,onClose:()=>h(!1),recoveryKeyInput:g,setRecoveryKeyInput:_,recoveryUnlockError:v,processing:o,onSubmit:j}),(0,$.jsx)(Wt,{isOpen:y,onClose:()=>b(!1),initRecoveryKeyInput:x,setInitRecoveryKeyInput:S,initRecoveryError:C,processing:o,onSubmit:N}),(0,$.jsx)(Gt,{rotatedKey:T,onClose:()=>E(null),copiedKey:D,onCopyKey:F})]})},Jt=()=>{let[e,t]=(0,Q.useState)(null),[r,i]=(0,Q.useState)([]),[a,o]=(0,Q.useState)(!0),[s,c]=(0,Q.useState)(null),{t:l,i18n:u}=d(),f=Ge(),[m,h]=(0,Q.useState)(!1),[g,_]=(0,Q.useState)(``),[v,y]=(0,Q.useState)(!1),[b,x]=(0,Q.useState)(!1),[S,C]=(0,Q.useState)({}),w=async()=>{try{i(await he())}catch(e){console.error(e)}},T=async()=>{try{C(await Oe())}catch(e){console.error(e)}},E=(0,Q.useCallback)(async()=>{try{let e=await ue();if(t(e),_(e.username),window.dispatchEvent(new Event(`user_updated`)),e.timezone){let{setSystemTimeZone:t}=await M(async()=>{let{setSystemTimeZone:e}=await import(`./date-CpvuBM37.js`);return{setSystemTimeZone:e}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10]));t(e.timezone)}if(e.locale){let{setSystemLocale:t}=await M(async()=>{let{setSystemLocale:e}=await import(`./date-CpvuBM37.js`);return{setSystemLocale:e}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10]));t(e.locale),u.changeLanguage(e.locale)}e.role===`admin`&&(w(),T())}catch(e){console.error(e)}finally{o(!1)}},[]);return(0,Q.useEffect)(()=>{E()},[E]),a?(0,$.jsx)(`div`,{className:`p-8 text-center`,children:l(`common.loading`)}):(0,$.jsxs)(`div`,{className:le(`max-w-5xl mx-auto space-y-8`,f?`p-0`:`px-8`),children:[(0,$.jsxs)(`div`,{className:`flex justify-between items-end`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`h2`,{className:`bp6-heading`,children:l(`account.title`)}),(0,$.jsx)(`p`,{className:`bp6-text-muted`,children:l(`account.subtitle`)})]}),e&&(0,$.jsx)(J,{large:!0,round:!0,intent:e.role===`admin`?U.DANGER:U.PRIMARY,icon:(0,$.jsx)(n,{size:16}),children:e.role===`admin`?l(`account.roleAdmin`):l(`account.roleUser`)})]}),e?.role===`admin`&&e?.jwt_secret_warning&&(0,$.jsx)(H,{intent:U.WARNING,icon:(0,$.jsx)(p,{size:18}),title:l(`account.jwtSecretWarningTitle`),children:(0,$.jsx)(`div`,{className:`text-sm leading-relaxed mt-1`,children:l(`account.jwtSecretWarningDesc`)})}),(0,$.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-6`,children:[(0,$.jsx)(Nt,{me:e,isEditingUsername:m,setIsEditingUsername:h,editUsername:g,setEditUsername:_,usernameLoading:v,usernameFocused:b,setUsernameFocused:x,onUpdateUsername:async()=>{if(g===e?.username){h(!1);return}if(!We.test(g)){alert(l(`account.formatTipUsername`));return}y(!0);try{await Fe({username:g}),t(e=>e?{...e,username:g}:null),h(!1)}catch(e){console.error(e),alert(e.message||l(`common.errorNetwork`))}finally{y(!1)}},onUpdateTimezone:async e=>{try{await Fe({timezone:e||``}),t(t=>t?{...t,timezone:e}:null);let{setSystemTimeZone:n}=await M(async()=>{let{setSystemTimeZone:e}=await import(`./date-CpvuBM37.js`);return{setSystemTimeZone:e}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10]));n(e||``)}catch(e){console.error(e),alert(e.message||l(`common.errorNetwork`))}}}),(0,$.jsx)(Pt,{me:e,onRefresh:E})]}),e&&(0,$.jsx)(St,{user:e,onRefresh:E}),e&&(0,$.jsx)(qt,{user:e,onRefresh:E}),e&&(0,$.jsx)(Lt,{user:e,onRefresh:E}),e&&(0,$.jsx)(Ot,{hoveredSessionId:s,setHoveredSessionId:c}),e&&(0,$.jsx)(Dt,{hoveredSessionId:s,setHoveredSessionId:c}),e?.role===`admin`&&(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(W,{}),(0,$.jsx)(`div`,{className:`space-y-4`,children:(0,$.jsx)(kt,{users:r,currentUserId:e.id,onRefresh:w,registrationEnabled:S.registration_enabled!==`false`,onRefreshSettings:T})}),(0,$.jsx)(W,{}),(0,$.jsx)(`div`,{className:`space-y-4`,children:(0,$.jsx)(At,{initialSettings:S,onRefresh:T})})]}),(0,$.jsx)(W,{}),(0,$.jsx)(`div`,{className:`space-y-4`,children:(0,$.jsx)(jt,{isAdmin:e?.role===`admin`})})]})};export{Jt as AccountView};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/TrendChart-
|
|
2
|
-
import{i as e}from"./rolldown-runtime-C4Xdq4VV.js";import{D as t,L as n,Zt as r,_t as i,j as a,q as o,tt as s,v as c}from"./vendor-react-CHk5ngkq.js";import{S as l,b as u,x as d}from"./vendor-icons-other-Bme3ywH9.js";import{C as f,H as p,M as m,N as h,P as g,T as _,V as v,d as y,f as b,o as x,p as S,r as C,u as w,x as T}from"./vendor-ui-core-sfZn2C08.js";import{_t as E}from"./vendor-utils-CnB7BG7m.js";import{ct as D,j as O,k,lt as A,on as j,ut as M}from"./index-CbTjGMTZ.js";import{t as N}from"./getFlagEmoji-_Wxhq0lT.js";var P=e(l(),1);function F(e,t,n){if(!e)return[];let r={},i=Math.floor(Date.now()/1e3),a,o;switch(t){case`10m`:o=60,a=i-600;break;case`1h`:o=60,a=i-3600;break;case`24h`:o=3600,a=i-24*3600;break;case`7d`:o=86400,a=i-7*86400;break;case`30d`:o=86400,a=i-30*86400;break;case`custom`:if(o=3600,n.start&&n.end)a=Math.floor(new Date(n.start).getTime()/1e3),i=Math.floor(new Date(n.end).getTime()/1e3);else{let t=e.trend.map(e=>e.timestamp);a=t.length?Math.min(...t):i-86400,i=t.length?Math.max(...t):i}break;default:o=3600,a=i-24*3600}a=Math.floor(a/o)*o,i=Math.floor(i/o)*o;for(let e=a;e<=i;e+=o)r[e]={timestamp:e,allowed:0,blocked:0,redirected:0};return e.trend.forEach(e=>{let t=Math.floor(e.timestamp/o)*o;r[t]||(r[t]={timestamp:t,allowed:0,blocked:0,redirected:0}),e.action===`PASS`?r[t].allowed+=e.count:e.action===`BLOCK`?r[t].blocked+=e.count:e.action===`REDIRECT`&&(r[t].redirected+=e.count)}),Object.keys(r).sort((e,t)=>Number(e)-Number(t)).map(e=>r[Number(e)])}var I=e(u(),1);const L=({title:e,data:t,intent:n})=>{let{t:i}=r(),a=[{key:`rank`,cellClassName:`w-8 opacity-30 font-mono text-xs`,render:(e,t)=>t+1},{key:`domain`,cellClassName:`font-medium text-sm truncate max-w-50`,render:e=>e.domain},{key:`count`,cellClassName:`text-right`,render:e=>(0,I.jsx)(C,{minimal:!0,intent:n,className:`font-bold`,children:e.count})}];return(0,I.jsxs)(T,{elevation:p.ZERO,className:`dark:bg-gray-900 dark:border-gray-800 border border-gray-100 shadow-sm`,children:[(0,I.jsx)(m,{className:`mb-4 font-bold`,children:e}),(0,I.jsx)(w,{striped:!0,className:`w-full`,children:(0,I.jsxs)(`tbody`,{children:[t.map((e,t)=>(0,I.jsx)(`tr`,{children:a.map(n=>(0,I.jsx)(`td`,{className:n.cellClassName,children:n.render(e,t)},n.key))},t)),t.length===0&&(0,I.jsx)(`tr`,{children:(0,I.jsx)(`td`,{colSpan:a.length,className:`text-center py-8 opacity-50`,children:i(`analytics.noData`)})})]})})]})};function R(e){let[t,n]=(0,P.useState)(null),[r,i]=(0,P.useState)(!0),[a,o]=(0,P.useState)(`24h`),[s,c]=(0,P.useState)({start:``,end:``}),[l,u]=(0,P.useState)(null),[d,f]=(0,P.useState)([]),[p,m]=(0,P.useState)(30);(0,P.useEffect)(()=>{D(e).then(e=>f(e)).catch(e=>console.error(`[useAnalyticsData] Failed to load access points:`,e))},[e]),(0,P.useEffect)(()=>{M(e).then(e=>{try{let t=JSON.parse(e.settings||`{}`);m(t.log_retention_days===void 0?30:Number(t.log_retention_days))}catch(e){console.error(`[useAnalyticsData] Failed to parse settings:`,e)}}).catch(e=>console.error(`[useAnalyticsData] Failed to fetch profile settings:`,e))},[e]);let h=(0,P.useCallback)(async(t,r,a,o)=>{i(!0);let s=Math.floor(Date.now()/1e3),c,l=s,u;if(t===`custom`&&r&&a){c=Math.floor(new Date(r).getTime()/1e3),l=Math.floor(new Date(a).getTime()/1e3);let e=l-c;u=e<=7200?60:e<=172800?3600:86400}else switch(t){case`10m`:c=s-600,u=60;break;case`1h`:c=s-3600,u=60;break;case`24h`:c=s-86400,u=3600;break;case`7d`:c=s-604800,u=86400;break;case`30d`:c=s-2592e3,u=86400;break;default:c=s-86400,u=3600;break}try{O.isUnlocked()&&await k.reDecryptLocalLogs(e)}catch{}try{if(await k.init()){let t=await k.queryAnalytics({profileId:e,since:c,until:l,bucketSec:u,accessPointId:o||void 0});t.summary.some(e=>e.count>0)&&(n(t),i(!1))}}catch(e){console.warn(`[useAnalyticsData] Local SQLite preview failed:`,e)}try{let i=`?range=${t}`;t===`custom`&&r&&a&&(i+=`&start=${c}&end=${l}`),o&&(i+=`&access_point_id=${o}`);let s=null;try{s=await A(e,``,i)}catch{let[t,n,r,a,o,c]=await Promise.all([A(e,`summary`,i),A(e,`trend`,i),A(e,`top_allowed`,i),A(e,`top_blocked`,i),A(e,`clients`,i),A(e,`destinations`,i)]);s={summary:t,trend:n,top_allowed:r,top_blocked:a,clients:o,destinations:c}}s&&n(e=>{let t=e&&(e.top_allowed.some(e=>e.domain&&e.domain!==`[Encrypted]`&&e.domain!==`[Decryption Failed]`)||e.destinations&&e.destinations.length>0);return{...s,trend:s.trend||[],summary:s.summary||[],top_allowed:t&&e?.top_allowed.length?e.top_allowed:s.top_allowed||[],top_blocked:t&&e?.top_blocked.length?e.top_blocked:s.top_blocked||[],clients:t&&e?.clients.length?e.clients:s.clients||[],destinations:(t||(s.destinations||[]).length===0)&&e?.destinations?.length?e.destinations:s.destinations||[]}})}catch(e){console.error(`[useAnalyticsData] Failed to fetch server analytics:`,e)}finally{i(!1)}try{k.syncProfileLogs(e,void 0,c).then(async t=>{if(t>0)try{let t=await k.queryAnalytics({profileId:e,since:c,until:l,bucketSec:u,accessPointId:o||void 0});(t.destinations?.length>0||t.top_allowed?.length>0)&&n(e=>e?{...e,destinations:t.destinations.length>0?t.destinations:e.destinations,top_allowed:t.top_allowed.length>0?t.top_allowed:e.top_allowed,top_blocked:t.top_blocked.length>0?t.top_blocked:e.top_blocked,clients:t.clients.length>0?t.clients:e.clients}:t)}catch{}}).catch(e=>{console.warn(`[useAnalyticsData] Background sync error:`,e)})}catch{}},[e]);return(0,P.useEffect)(()=>{a!==`custom`&&h(a,void 0,void 0,l)},[a,l,h]),{data:t,loading:r,range:a,setRange:o,customRange:s,setCustomRange:c,accessPointIdFilter:l,setAccessPointIdFilter:u,accessPoints:d,logRetentionDays:p,fetchData:h}}var z=[{key:`10m`,days:.007},{key:`1h`,days:.0416},{key:`24h`,days:1},{key:`7d`,days:7},{key:`30d`,days:30}];const B=({range:e,setRange:t,customRange:n,setCustomRange:a,logRetentionDays:o,accessPoints:s,accessPointIdFilter:c,setAccessPointIdFilter:l,loading:u,onApplyCustom:d})=>{let{t:p}=r(),x=new Date().toLocaleString(`sv-SE`).replace(` `,`T`).slice(0,16);return(0,I.jsxs)(`div`,{className:`flex justify-between items-center bg-white dark:bg-gray-900 p-2 rounded-lg shadow-sm border border-gray-100 dark:border-gray-800`,children:[(0,I.jsxs)(f,{variant:`minimal`,children:[z.filter(e=>e.days<=o).map(e=>e.key).map(n=>(0,I.jsx)(h,{active:e===n,onClick:()=>t(n),text:n.toUpperCase()},n)),(0,I.jsx)(_,{content:(0,I.jsxs)(`div`,{className:`p-4 space-y-4 w-64`,children:[(0,I.jsx)(m,{children:p(`analytics.customRange`)}),(0,I.jsx)(S,{label:p(`analytics.startTime`),children:(0,I.jsx)(b,{type:`datetime-local`,max:n.end||x,value:n.start,onChange:e=>a({...n,start:e.target.value})})}),(0,I.jsx)(S,{label:p(`analytics.endTime`),children:(0,I.jsx)(b,{type:`datetime-local`,min:n.start,max:x,value:n.end,onChange:e=>a({...n,end:e.target.value})})}),(0,I.jsx)(h,{fill:!0,intent:v.PRIMARY,text:p(`analytics.apply`),onClick:d})]}),children:(0,I.jsx)(h,{active:e===`custom`,icon:(0,I.jsx)(i,{size:14,className:`mr-1`}),text:p(`analytics.custom`)})})]}),(0,I.jsxs)(`div`,{className:`flex items-center gap-4`,children:[s.length>0&&(0,I.jsx)(y,{value:c||``,onChange:e=>l(e.target.value||null),options:[{label:`${p(`logs.allAccessPoint`)}`,value:``},...s.map(e=>({label:e.name,value:e.id}))],minimal:!0}),u&&(0,I.jsx)(g,{size:16})]})]})},V=({title:e,value:t,icon:n})=>(0,I.jsxs)(T,{elevation:p.ZERO,className:`flex items-center gap-4 p-4 dark:bg-gray-900 dark:border-gray-800 border border-gray-100 shadow-sm`,children:[(0,I.jsx)(`div`,{className:`p-3 bg-gray-50 dark:bg-gray-800 rounded-lg`,children:n}),(0,I.jsxs)(`div`,{children:[(0,I.jsx)(`div`,{className:`text-xs text-gray-500 font-medium uppercase tracking-wider`,children:e}),(0,I.jsx)(`div`,{className:`text-xl font-bold dark:text-white`,children:t})]})]}),H=({data:e})=>{let{t:i}=r(),o=e?.summary.reduce((e,t)=>e+t.count,0)||0,l=e?.summary.find(e=>e.action===`BLOCK`)?.count||0,u=e?.summary.find(e=>e.action===`REDIRECT`)?.count||0,d=o>0?(l/o*100).toFixed(1):`0.0`;return(0,I.jsx)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 gap-2 lg:gap-4`,children:[{title:i(`analytics.totalQueries`),value:o.toLocaleString(),icon:(0,I.jsx)(c,{className:`text-blue-500`,size:20})},{title:i(`analytics.blocked`),value:l.toLocaleString(),icon:(0,I.jsx)(a,{className:`text-red-500`,size:20})},{title:i(`analytics.redirected`),value:u.toLocaleString(),icon:(0,I.jsx)(n,{className:`text-amber-500`,size:20})},{title:i(`analytics.blockRate`),value:`${d}%`,icon:(0,I.jsx)(t,{className:`text-green-500`,size:20})},{title:i(`analytics.activeIPs`),value:e?.clients.length.toString()||`0`,icon:(0,I.jsx)(s,{className:`text-purple-500`,size:20})}].map((e,t)=>(0,I.jsx)(V,{title:e.title,value:e.value,icon:e.icon},t))})},U=({clients:e})=>{let{t}=r();return(0,I.jsx)(x,{title:t(`analytics.clientActivity`),icon:(0,I.jsx)(s,{size:16}),children:(0,I.jsxs)(w,{striped:!0,className:`w-full mt-2`,children:[(0,I.jsx)(`thead`,{children:(0,I.jsxs)(`tr`,{children:[(0,I.jsx)(`th`,{className:`text-xs uppercase opacity-60`,children:t(`analytics.ipAddress`)}),(0,I.jsx)(`th`,{className:`text-xs uppercase opacity-60`,children:t(`analytics.location`)}),(0,I.jsx)(`th`,{className:`text-xs uppercase opacity-60 text-right`,children:t(`analytics.queries`)})]})}),(0,I.jsxs)(`tbody`,{children:[e?.map((e,t)=>(0,I.jsxs)(`tr`,{children:[(0,I.jsx)(`td`,{className:`font-mono text-xs`,children:e.client_ip||`-`}),(0,I.jsx)(`td`,{children:(0,I.jsx)(C,{minimal:!0,children:N(e.geo_country)})}),(0,I.jsx)(`td`,{className:`text-right font-bold`,children:e.count})]},t)),(!e||e.length===0)&&(0,I.jsx)(`tr`,{children:(0,I.jsx)(`td`,{colSpan:3,className:`text-center py-8 opacity-50`,children:t(`analytics.noData`)})})]})]})})};var W=(0,P.lazy)(()=>d(()=>import(`./TrendChart-Dc5yJndv.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10])).then(e=>({default:e.TrendChart}))),G=(0,P.lazy)(()=>d(()=>import(`./DestinationMap-jSW7gimP.js`),__vite__mapDeps([11,1,2,3,4,5,6,7,8,9,10,12,13])).then(e=>({default:e.DestinationMap}))),K=()=>(0,I.jsx)(`div`,{className:`h-64 flex items-center justify-center`,children:(0,I.jsx)(g,{size:30})});const q=({profileId:e})=>{let{t}=r(),n=j(),{data:i,loading:a,range:s,setRange:c,customRange:l,setCustomRange:u,accessPointIdFilter:d,setAccessPointIdFilter:f,accessPoints:h,logRetentionDays:_,fetchData:y}=R(e);if(a&&!i)return(0,I.jsx)(`div`,{className:`p-20 flex justify-center`,children:(0,I.jsx)(g,{size:50})});let b=F(i,s,l);return(0,I.jsxs)(`div`,{className:E(`max-w-7xl mx-auto space-y-6`,n?`p-0`:`p-6`),children:[(0,I.jsx)(B,{range:s,setRange:c,customRange:l,setCustomRange:u,logRetentionDays:_,accessPoints:h,accessPointIdFilter:d,setAccessPointIdFilter:f,loading:a,onApplyCustom:()=>{c(`custom`),y(`custom`,l.start,l.end,d)}}),(0,I.jsx)(H,{data:i}),(0,I.jsxs)(T,{elevation:p.ONE,className:`dark:bg-gray-900 dark:border-gray-800 relative`,children:[(0,I.jsxs)(m,{className:`mb-4 font-bold flex items-center gap-2`,children:[t(`analytics.queryTrend`),(0,I.jsx)(C,{minimal:!0,round:!0,children:s===`custom`?t(`analytics.custom`):s.toUpperCase()})]}),(0,I.jsx)(P.Suspense,{fallback:(0,I.jsx)(K,{}),children:(0,I.jsx)(W,{chartData:b,range:s})})]}),(0,I.jsxs)(`div`,{className:`grid grid-cols-1 lg:grid-cols-2 gap-6`,children:[(0,I.jsx)(L,{title:t(`analytics.topAllowed`),data:i?.top_allowed||[],intent:v.SUCCESS}),(0,I.jsx)(L,{title:t(`analytics.topBlocked`),data:i?.top_blocked||[],intent:v.DANGER})]}),(0,I.jsxs)(`div`,{className:`grid gap-6 grid-cols-1`,children:[(0,I.jsx)(x,{title:t(`analytics.destinationDistribution`),icon:(0,I.jsx)(o,{size:16}),children:(0,I.jsx)(P.Suspense,{fallback:(0,I.jsx)(K,{}),children:(0,I.jsx)(G,{destinations:i?.destinations||[],profileId:e||``,range:s,customRange:l,accessPointId:d||void 0})})}),(0,I.jsx)(U,{clients:i?.clients})]})]})};export{q as AnalyticsView};
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/TrendChart-CCR1W3fC.js","assets/index-dXN_pYn1.js","assets/vendor-icons-other-Bme3ywH9.js","assets/vendor-icons-16-BgwRBCeU.js","assets/rolldown-runtime-C4Xdq4VV.js","assets/vendor-icons-20-X5NPN60g.js","assets/vendor-react-BmoHsW1x.js","assets/vendor-ui-core-CY_WyMIf.js","assets/vendor-utils-BWSB0jGn.js","assets/vendor-i18next-BKUzkAKP.js","assets/index-Bheo8y3N.css","assets/DestinationMap-9Yc54Mdj.js","assets/formatCountryName-CSBD8pP8.js","assets/getFlagEmoji-DRubsb7D.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{i as e}from"./rolldown-runtime-C4Xdq4VV.js";import{D as t,L as n,Qt as r,j as i,q as a,tt as o,v as s,vt as c}from"./vendor-react-BmoHsW1x.js";import{S as l,b as u,x as d}from"./vendor-icons-other-Bme3ywH9.js";import{C as f,H as p,M as m,N as h,P as g,T as _,V as v,d as y,f as b,o as x,p as S,r as C,u as w,x as T}from"./vendor-ui-core-CY_WyMIf.js";import{_t as E}from"./vendor-utils-BWSB0jGn.js";import{at as D,j as O,k,ln as A,ot as j,st as M}from"./index-dXN_pYn1.js";import{t as N}from"./getFlagEmoji-DRubsb7D.js";var P=e(l(),1);function F(e,t,n){if(!e)return[];let r={},i=Math.floor(Date.now()/1e3),a,o;switch(t){case`10m`:o=60,a=i-600;break;case`1h`:o=60,a=i-3600;break;case`24h`:o=3600,a=i-24*3600;break;case`7d`:o=86400,a=i-7*86400;break;case`30d`:o=86400,a=i-30*86400;break;case`custom`:if(o=3600,n.start&&n.end)a=Math.floor(new Date(n.start).getTime()/1e3),i=Math.floor(new Date(n.end).getTime()/1e3);else{let t=e.trend.map(e=>e.timestamp);a=t.length?Math.min(...t):i-86400,i=t.length?Math.max(...t):i}break;default:o=3600,a=i-24*3600}a=Math.floor(a/o)*o,i=Math.floor(i/o)*o;for(let e=a;e<=i;e+=o)r[e]={timestamp:e,allowed:0,blocked:0,redirected:0};return e.trend.forEach(e=>{let t=Math.floor(e.timestamp/o)*o;r[t]||(r[t]={timestamp:t,allowed:0,blocked:0,redirected:0}),e.action===`PASS`?r[t].allowed+=e.count:e.action===`BLOCK`?r[t].blocked+=e.count:e.action===`REDIRECT`&&(r[t].redirected+=e.count)}),Object.keys(r).sort((e,t)=>Number(e)-Number(t)).map(e=>r[Number(e)])}var I=e(u(),1);const L=({title:e,data:t,intent:n})=>{let{t:i}=r(),a=[{key:`rank`,cellClassName:`w-8 opacity-30 font-mono text-xs`,render:(e,t)=>t+1},{key:`domain`,cellClassName:`font-medium text-sm truncate max-w-50`,render:e=>e.domain},{key:`count`,cellClassName:`text-right`,render:e=>(0,I.jsx)(C,{minimal:!0,intent:n,className:`font-bold`,children:e.count})}];return(0,I.jsxs)(T,{elevation:p.ZERO,className:`dark:bg-gray-900 dark:border-gray-800 border border-gray-100 shadow-sm`,children:[(0,I.jsx)(m,{className:`mb-4 font-bold`,children:e}),(0,I.jsx)(w,{striped:!0,className:`w-full`,children:(0,I.jsxs)(`tbody`,{children:[t.map((e,t)=>(0,I.jsx)(`tr`,{children:a.map(n=>(0,I.jsx)(`td`,{className:n.cellClassName,children:n.render(e,t)},n.key))},t)),t.length===0&&(0,I.jsx)(`tr`,{children:(0,I.jsx)(`td`,{colSpan:a.length,className:`text-center py-8 opacity-50`,children:i(`analytics.noData`)})})]})})]})};function R(e){let[t,n]=(0,P.useState)(null),[r,i]=(0,P.useState)(!0),[a,o]=(0,P.useState)(`24h`),[s,c]=(0,P.useState)({start:``,end:``}),[l,u]=(0,P.useState)(null),[d,f]=(0,P.useState)([]),[p,m]=(0,P.useState)(30);(0,P.useEffect)(()=>{D(e).then(e=>f(e)).catch(e=>console.error(`[useAnalyticsData] Failed to load access points:`,e))},[e]),(0,P.useEffect)(()=>{M(e).then(e=>{try{let t=JSON.parse(e.settings||`{}`);m(t.log_retention_days===void 0?30:Number(t.log_retention_days))}catch(e){console.error(`[useAnalyticsData] Failed to parse settings:`,e)}}).catch(e=>console.error(`[useAnalyticsData] Failed to fetch profile settings:`,e))},[e]);let h=(0,P.useCallback)(async(t,r,a,o)=>{i(!0);let s=Math.floor(Date.now()/1e3),c,l=s,u;if(t===`custom`&&r&&a){c=Math.floor(new Date(r).getTime()/1e3),l=Math.floor(new Date(a).getTime()/1e3);let e=l-c;u=e<=7200?60:e<=172800?3600:86400}else switch(t){case`10m`:c=s-600,u=60;break;case`1h`:c=s-3600,u=60;break;case`24h`:c=s-86400,u=3600;break;case`7d`:c=s-604800,u=86400;break;case`30d`:c=s-2592e3,u=86400;break;default:c=s-86400,u=3600;break}try{O.isUnlocked()&&await k.reDecryptLocalLogs(e)}catch{}try{if(await k.init()){let t=await k.queryAnalytics({profileId:e,since:c,until:l,bucketSec:u,accessPointId:o||void 0});t.summary.some(e=>e.count>0)&&(n(t),i(!1))}}catch(e){console.warn(`[useAnalyticsData] Local SQLite preview failed:`,e)}try{let i=`?range=${t}`;t===`custom`&&r&&a&&(i+=`&start=${c}&end=${l}`),o&&(i+=`&access_point_id=${o}`);let s=null;try{s=await j(e,``,i)}catch{let[t,n,r,a,o,c]=await Promise.all([j(e,`summary`,i),j(e,`trend`,i),j(e,`top_allowed`,i),j(e,`top_blocked`,i),j(e,`clients`,i),j(e,`destinations`,i)]);s={summary:t,trend:n,top_allowed:r,top_blocked:a,clients:o,destinations:c}}s&&n(e=>{let t=e&&(e.top_allowed.some(e=>e.domain&&e.domain!==`[Encrypted]`&&e.domain!==`[Decryption Failed]`)||e.destinations&&e.destinations.length>0);return{...s,trend:s.trend||[],summary:s.summary||[],top_allowed:t&&e?.top_allowed.length?e.top_allowed:s.top_allowed||[],top_blocked:t&&e?.top_blocked.length?e.top_blocked:s.top_blocked||[],clients:t&&e?.clients.length?e.clients:s.clients||[],destinations:(t||(s.destinations||[]).length===0)&&e?.destinations?.length?e.destinations:s.destinations||[]}})}catch(e){console.error(`[useAnalyticsData] Failed to fetch server analytics:`,e)}finally{i(!1)}try{k.syncProfileLogs(e,void 0,c).then(async t=>{if(t>0)try{let t=await k.queryAnalytics({profileId:e,since:c,until:l,bucketSec:u,accessPointId:o||void 0});(t.destinations?.length>0||t.top_allowed?.length>0)&&n(e=>e?{...e,destinations:t.destinations.length>0?t.destinations:e.destinations,top_allowed:t.top_allowed.length>0?t.top_allowed:e.top_allowed,top_blocked:t.top_blocked.length>0?t.top_blocked:e.top_blocked,clients:t.clients.length>0?t.clients:e.clients}:t)}catch{}}).catch(e=>{console.warn(`[useAnalyticsData] Background sync error:`,e)})}catch{}},[e]);return(0,P.useEffect)(()=>{a!==`custom`&&h(a,void 0,void 0,l)},[a,l,h]),{data:t,loading:r,range:a,setRange:o,customRange:s,setCustomRange:c,accessPointIdFilter:l,setAccessPointIdFilter:u,accessPoints:d,logRetentionDays:p,fetchData:h}}var z=[{key:`10m`,days:.007},{key:`1h`,days:.0416},{key:`24h`,days:1},{key:`7d`,days:7},{key:`30d`,days:30}];const B=({range:e,setRange:t,customRange:n,setCustomRange:i,logRetentionDays:a,accessPoints:o,accessPointIdFilter:s,setAccessPointIdFilter:l,loading:u,onApplyCustom:d})=>{let{t:p}=r(),x=new Date().toLocaleString(`sv-SE`).replace(` `,`T`).slice(0,16);return(0,I.jsxs)(`div`,{className:`flex justify-between items-center bg-white dark:bg-gray-900 p-2 rounded-lg shadow-sm border border-gray-100 dark:border-gray-800`,children:[(0,I.jsxs)(f,{variant:`minimal`,children:[z.filter(e=>e.days<=a).map(e=>e.key).map(n=>(0,I.jsx)(h,{active:e===n,onClick:()=>t(n),text:n.toUpperCase()},n)),(0,I.jsx)(_,{content:(0,I.jsxs)(`div`,{className:`p-4 space-y-4 w-64`,children:[(0,I.jsx)(m,{children:p(`analytics.customRange`)}),(0,I.jsx)(S,{label:p(`analytics.startTime`),children:(0,I.jsx)(b,{type:`datetime-local`,max:n.end||x,value:n.start,onChange:e=>i({...n,start:e.target.value})})}),(0,I.jsx)(S,{label:p(`analytics.endTime`),children:(0,I.jsx)(b,{type:`datetime-local`,min:n.start,max:x,value:n.end,onChange:e=>i({...n,end:e.target.value})})}),(0,I.jsx)(h,{fill:!0,intent:v.PRIMARY,text:p(`analytics.apply`),onClick:d})]}),children:(0,I.jsx)(h,{active:e===`custom`,icon:(0,I.jsx)(c,{size:14,className:`mr-1`}),text:p(`analytics.custom`)})})]}),(0,I.jsxs)(`div`,{className:`flex items-center gap-4`,children:[o.length>0&&(0,I.jsx)(y,{value:s||``,onChange:e=>l(e.target.value||null),options:[{label:`${p(`logs.allAccessPoint`)}`,value:``},...o.map(e=>({label:e.name,value:e.id}))],minimal:!0}),u&&(0,I.jsx)(g,{size:16})]})]})},V=({title:e,value:t,icon:n})=>(0,I.jsxs)(T,{elevation:p.ZERO,className:`flex items-center gap-4 p-4 dark:bg-gray-900 dark:border-gray-800 border border-gray-100 shadow-sm`,children:[(0,I.jsx)(`div`,{className:`p-3 bg-gray-50 dark:bg-gray-800 rounded-lg`,children:n}),(0,I.jsxs)(`div`,{children:[(0,I.jsx)(`div`,{className:`text-xs text-gray-500 font-medium uppercase tracking-wider`,children:e}),(0,I.jsx)(`div`,{className:`text-xl font-bold dark:text-white`,children:t})]})]}),H=({data:e})=>{let{t:a}=r(),c=e?.summary.reduce((e,t)=>e+t.count,0)||0,l=e?.summary.find(e=>e.action===`BLOCK`)?.count||0,u=e?.summary.find(e=>e.action===`REDIRECT`)?.count||0,d=c>0?(l/c*100).toFixed(1):`0.0`;return(0,I.jsx)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 gap-2 lg:gap-4`,children:[{title:a(`analytics.totalQueries`),value:c.toLocaleString(),icon:(0,I.jsx)(s,{className:`text-blue-500`,size:20})},{title:a(`analytics.blocked`),value:l.toLocaleString(),icon:(0,I.jsx)(i,{className:`text-red-500`,size:20})},{title:a(`analytics.redirected`),value:u.toLocaleString(),icon:(0,I.jsx)(n,{className:`text-amber-500`,size:20})},{title:a(`analytics.blockRate`),value:`${d}%`,icon:(0,I.jsx)(t,{className:`text-green-500`,size:20})},{title:a(`analytics.activeIPs`),value:e?.clients.length.toString()||`0`,icon:(0,I.jsx)(o,{className:`text-purple-500`,size:20})}].map((e,t)=>(0,I.jsx)(V,{title:e.title,value:e.value,icon:e.icon},t))})},U=({clients:e})=>{let{t}=r();return(0,I.jsx)(x,{title:t(`analytics.clientActivity`),icon:(0,I.jsx)(o,{size:16}),children:(0,I.jsxs)(w,{striped:!0,className:`w-full mt-2`,children:[(0,I.jsx)(`thead`,{children:(0,I.jsxs)(`tr`,{children:[(0,I.jsx)(`th`,{className:`text-xs uppercase opacity-60`,children:t(`analytics.ipAddress`)}),(0,I.jsx)(`th`,{className:`text-xs uppercase opacity-60`,children:t(`analytics.location`)}),(0,I.jsx)(`th`,{className:`text-xs uppercase opacity-60 text-right`,children:t(`analytics.queries`)})]})}),(0,I.jsxs)(`tbody`,{children:[e?.map((e,t)=>(0,I.jsxs)(`tr`,{children:[(0,I.jsx)(`td`,{className:`font-mono text-xs`,children:e.client_ip||`-`}),(0,I.jsx)(`td`,{children:(0,I.jsx)(C,{minimal:!0,children:N(e.geo_country)})}),(0,I.jsx)(`td`,{className:`text-right font-bold`,children:e.count})]},t)),(!e||e.length===0)&&(0,I.jsx)(`tr`,{children:(0,I.jsx)(`td`,{colSpan:3,className:`text-center py-8 opacity-50`,children:t(`analytics.noData`)})})]})]})})};var W=(0,P.lazy)(()=>d(()=>import(`./TrendChart-CCR1W3fC.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10])).then(e=>({default:e.TrendChart}))),G=(0,P.lazy)(()=>d(()=>import(`./DestinationMap-9Yc54Mdj.js`),__vite__mapDeps([11,1,2,3,4,5,6,7,8,9,10,12,13])).then(e=>({default:e.DestinationMap}))),K=()=>(0,I.jsx)(`div`,{className:`h-64 flex items-center justify-center`,children:(0,I.jsx)(g,{size:30})});const q=({profileId:e})=>{let{t}=r(),n=A(),{data:i,loading:o,range:s,setRange:c,customRange:l,setCustomRange:u,accessPointIdFilter:d,setAccessPointIdFilter:f,accessPoints:h,logRetentionDays:_,fetchData:y}=R(e);if(o&&!i)return(0,I.jsx)(`div`,{className:`p-20 flex justify-center`,children:(0,I.jsx)(g,{size:50})});let b=F(i,s,l);return(0,I.jsxs)(`div`,{className:E(`max-w-7xl mx-auto space-y-6`,n?`p-0`:`p-6`),children:[(0,I.jsx)(B,{range:s,setRange:c,customRange:l,setCustomRange:u,logRetentionDays:_,accessPoints:h,accessPointIdFilter:d,setAccessPointIdFilter:f,loading:o,onApplyCustom:()=>{c(`custom`),y(`custom`,l.start,l.end,d)}}),(0,I.jsx)(H,{data:i}),(0,I.jsxs)(T,{elevation:p.ONE,className:`dark:bg-gray-900 dark:border-gray-800 relative`,children:[(0,I.jsxs)(m,{className:`mb-4 font-bold flex items-center gap-2`,children:[t(`analytics.queryTrend`),(0,I.jsx)(C,{minimal:!0,round:!0,children:s===`custom`?t(`analytics.custom`):s.toUpperCase()})]}),(0,I.jsx)(P.Suspense,{fallback:(0,I.jsx)(K,{}),children:(0,I.jsx)(W,{chartData:b,range:s})})]}),(0,I.jsxs)(`div`,{className:`grid grid-cols-1 lg:grid-cols-2 gap-6`,children:[(0,I.jsx)(L,{title:t(`analytics.topAllowed`),data:i?.top_allowed||[],intent:v.SUCCESS}),(0,I.jsx)(L,{title:t(`analytics.topBlocked`),data:i?.top_blocked||[],intent:v.DANGER})]}),(0,I.jsxs)(`div`,{className:`grid gap-6 grid-cols-1`,children:[(0,I.jsx)(x,{title:t(`analytics.destinationDistribution`),icon:(0,I.jsx)(a,{size:16}),children:(0,I.jsx)(P.Suspense,{fallback:(0,I.jsx)(K,{}),children:(0,I.jsx)(G,{destinations:i?.destinations||[],profileId:e||``,range:s,customRange:l,accessPointId:d||void 0})})}),(0,I.jsx)(U,{clients:i?.clients})]})]})};export{q as AnalyticsView};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{i as e}from"./rolldown-runtime-C4Xdq4VV.js";import{$ as t,Ct as n,E as r,Q as i,Qt as a,gt as o,j as s,lt as c}from"./vendor-react-BmoHsW1x.js";import{S as l,b as u}from"./vendor-icons-other-Bme3ywH9.js";import"./vendor-i18next-BKUzkAKP.js";import{A as d,B as f,H as p,L as m,N as h,O as g,R as _,S as v,V as y,f as b,m as x,p as S,r as C,v as w,x as T,z as E}from"./vendor-ui-core-CY_WyMIf.js";import{_t as D}from"./vendor-utils-BWSB0jGn.js";import{$t as O,C as k,Ft as A,Jt as ee,Mt as j,O as M,Qt as N,S as P,Vt as F,Xt as I,Zt as te,_ as L,an as R,b as z,d as B,en as V,f as H,g as ne,h as U,i as W,j as G,m as K,r as q,rn as J,sn as re,u as Y,wt as ie,x as ae,y as oe}from"./index-dXN_pYn1.js";import{t as X}from"./QRCodeCanvas-DQ-xNuwF.js";var Z=e(l(),1),Q=e(u(),1);const $=({username:e,setUsername:t,isTurnstileEnabled:n,turnstileRef:r,loading:i,turnstileStatus:o,onSubmit:s})=>{let{t:c}=a();return(0,Q.jsxs)(`form`,{onSubmit:s,className:`space-y-4`,children:[(0,Q.jsx)(S,{label:c(`auth.username`),labelFor:`username`,children:(0,Q.jsx)(b,{id:`username`,leftIcon:`user`,placeholder:c(`auth.usernamePlaceholder`),size:`large`,className:`rounded-xl w-full`,value:e,onChange:e=>t(e.target.value),autoFocus:!0,required:!0})}),n&&(0,Q.jsx)(`div`,{className:`py-2 flex justify-center min-h-16.25`,children:(0,Q.jsx)(`div`,{ref:r})}),(0,Q.jsx)(h,{fill:!0,size:`large`,intent:y.PRIMARY,type:`submit`,loading:i||o===`verifying`,disabled:!!n&&o!==`success`,className:`mt-6 font-bold py-6 rounded-xl shadow-lg shadow-blue-500/20`,children:o===`verifying`?c(`auth.verifying`):c(`auth.next`,`Next`)})]})},se=({password:e,setPassword:t,hasMfa:n,onSwitchToMfa:r,loading:i,onSubmit:o,keepLoggedIn:s,setKeepLoggedIn:c,optionalSessionExpirationDays:l})=>{let[u,d]=Z.useState(!1),{t:f}=a();return(0,Q.jsxs)(`form`,{onSubmit:o,className:`space-y-4`,children:[(0,Q.jsx)(S,{label:f(`auth.password`),labelFor:`password`,children:(0,Q.jsx)(b,{id:`password`,leftIcon:`lock`,placeholder:f(`auth.passwordPlaceholder`),type:u?`text`:`password`,size:`large`,className:`rounded-xl`,value:e,onChange:e=>t(e.target.value),rightElement:(()=>(0,Q.jsxs)(`div`,{className:`flex items-center`,children:[e&&(0,Q.jsx)(h,{minimal:!0,icon:`cross`,onClick:()=>t(``)}),(0,Q.jsx)(h,{minimal:!0,icon:u?`eye-open`:`eye-off`,onClick:()=>d(!u),title:u?f(`auth.hidePassword`,`Hide password`):f(`auth.showPassword`,`Show password`)})]}))(),autoFocus:!0,required:!0})}),(0,Q.jsx)(x,{checked:s,onChange:e=>c(e.currentTarget.checked),label:f(`auth.keepLoggedIn`,`Keep me logged in for {{days}} days`,{days:l}),className:`mt-4 text-left`}),(0,Q.jsxs)(`div`,{className:`pt-2 space-y-3`,children:[(0,Q.jsx)(h,{fill:!0,size:`large`,intent:y.PRIMARY,type:`submit`,loading:i,className:`font-bold py-6 rounded-xl shadow-lg shadow-blue-500/20`,children:n?f(`auth.next`,`Next`):f(`auth.loginBtn`,`Login`)}),n&&r&&(0,Q.jsx)(h,{fill:!0,minimal:!0,size:`large`,type:`button`,disabled:i,onClick:r,className:`font-medium text-blue-600 dark:text-blue-400 py-2.5 rounded-xl transition-colors hover:bg-blue-50 dark:hover:bg-blue-950/30`,children:f(`auth.otherOptions`,`其他选项`)})]})]})},ce=({value:e,onChange:t,disabled:n=!1,autoFocus:r=!0,className:i=``})=>{let{t:o}=a(),s=(0,Z.useRef)([]),c=(e=>{let t=e.replace(/\D/g,``).slice(0,30),n=[];for(let e=0;e<5;e++)n.push(t.slice(e*6,(e+1)*6));return n})(e);(0,Z.useEffect)(()=>{r&&s.current[0]&&s.current[0].focus()},[r]);let l=(e,n)=>{let r=n.replace(/\D/g,``).slice(0,6),i=[...c];i[e]=r,t(i.join(`-`)),r.length===6&&e<4&&s.current[e+1]?.focus()},u=(e,t)=>{if(t.key===`Backspace`&&c[e].length===0&&e>0){t.preventDefault();let n=s.current[e-1];n&&n.focus()}else t.key===`ArrowLeft`&&(t.currentTarget.selectionStart??0)===0&&e>0?(t.preventDefault(),s.current[e-1]?.focus()):t.key===`ArrowRight`&&(t.currentTarget.selectionStart??0)===c[e].length&&e<4&&(t.preventDefault(),s.current[e+1]?.focus())},d=(e,n)=>{let r=n.clipboardData.getData(`text`).replace(/\D/g,``);if(r.length>6){n.preventDefault();let i=[...c],a=0;for(let t=e;t<5&&a<r.length;t++){let e=r.slice(a,a+6);i[t]=e,a+=e.length}t(i.join(`-`));let o=Math.min(4,e+Math.ceil(r.length/6)-1);s.current[o]?.focus()}},f=c.map((e,t)=>e.length===6&&!z(e)?t:-1).filter(e=>e!==-1);return(0,Q.jsxs)(`div`,{className:`space-y-2 ${i}`,children:[(0,Q.jsx)(`div`,{className:`flex items-center justify-between gap-1 sm:gap-2`,children:c.map((e,t)=>{let r=e.length===6,i=r&&!z(e),a=r&&!i,c=`border-gray-300 dark:border-gray-600 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20`;return i?c=`border-red-500 ring-2 ring-red-500/30 bg-red-50/40 dark:bg-red-950/20 text-red-600 dark:text-red-400`:a&&(c=`border-green-500/80 dark:border-green-500/60 bg-green-50/20 dark:bg-green-950/10 text-gray-900 dark:text-gray-100`),(0,Q.jsxs)(Z.Fragment,{children:[(0,Q.jsx)(`input`,{ref:e=>{s.current[t]=e},type:`text`,inputMode:`numeric`,pattern:`[0-9]*`,maxLength:6,value:e,disabled:n,autoComplete:`off`,autoCorrect:`off`,autoCapitalize:`off`,spellCheck:!1,"data-1p-ignore":`true`,"data-lpignore":`true`,"data-bwignore":`true`,onChange:e=>l(t,e.target.value),onKeyDown:e=>u(t,e),onPaste:e=>d(t,e),className:`w-full min-w-0 text-center font-mono text-xs sm:text-sm tracking-wider py-2 sm:py-2.5 px-1 rounded-lg border transition-all duration-150 outline-none ${c}`,title:i?o(`auth.recoveryChecksumError`,{defaultValue:`校验码错误:该组 6 位数无法被 11 整除`,group:t+1}):void 0}),t<4&&(0,Q.jsx)(`span`,{className:`text-gray-400 dark:text-gray-500 font-bold select-none text-xs`,children:`-`})]},t)})}),f.length>0&&(0,Q.jsx)(`p`,{className:`text-xs text-red-500 dark:text-red-400 text-center font-medium mt-1`,children:o(`auth.recoveryChecksumErrorDesc`,{defaultValue:`第 {{groups}} 组校验码错误,请核对后重试`,groups:f.map(e=>e+1).join(`、`)})})]})},le=({hasPasskey:e,requiresTotp:n,mfaMethod:r,setMfaMethod:o,passkeyLoading:s,onPasskeyLogin:c,totpToken:l,setTotpToken:u,recoveryKey:d,setRecoveryKey:f,loading:p,onClearError:m,onSubmit:g,keepLoggedIn:_,setKeepLoggedIn:v,optionalSessionExpirationDays:b})=>{let{t:C}=a(),w=e=>{o(e),m()};return(0,Q.jsxs)(`form`,{onSubmit:e=>{if(e.preventDefault(),r===`passkey`){c();return}g(e)},className:`space-y-4`,children:[r===`passkey`&&(0,Q.jsxs)(`div`,{className:`space-y-5 text-center py-2`,children:[(0,Q.jsx)(`div`,{className:`mx-auto w-16 h-16 rounded-2xl bg-blue-50 dark:bg-blue-950/40 flex items-center justify-center text-blue-600 dark:text-blue-400`,children:(0,Q.jsx)(i,{size:36})}),(0,Q.jsxs)(`div`,{className:`space-y-1`,children:[(0,Q.jsx)(`h4`,{className:`text-base font-semibold text-gray-900 dark:text-gray-100 m-0`,children:C(`auth.passkeyVerification`,`Passkey Verification`)}),(0,Q.jsx)(`p`,{className:`text-xs text-gray-500 dark:text-gray-400 max-w-xs mx-auto leading-relaxed`,children:C(`auth.passkeyPromptDesc`,`Use your registered device's biometric or hardware security key to verify`)})]}),(0,Q.jsx)(x,{checked:_,onChange:e=>v(e.currentTarget.checked),label:C(`auth.keepLoggedIn`,`Keep me logged in for {{days}} days`,{days:b}),className:`text-left inline-block mt-2`}),(0,Q.jsxs)(`div`,{className:`pt-2 space-y-3`,children:[(0,Q.jsxs)(h,{fill:!0,size:`large`,intent:y.PRIMARY,type:`button`,loading:s,disabled:p,onClick:c,className:`font-semibold py-6 rounded-xl shadow-lg shadow-blue-500/20 flex items-center justify-center space-x-2`,children:[(0,Q.jsx)(i,{size:20,className:`inline mr-1.5`}),(0,Q.jsx)(`span`,{children:C(`auth.verifyWithPasskey`,`Verify with Passkey`)})]}),n&&(0,Q.jsx)(h,{fill:!0,minimal:!0,size:`large`,type:`button`,disabled:s||p,onClick:()=>w(`totp`),className:`font-medium text-blue-600 dark:text-blue-400 py-2.5 rounded-xl transition-colors hover:bg-blue-50 dark:hover:bg-blue-950/30`,children:C(`auth.otherOptions`,`Other Options`)}),(0,Q.jsx)(`div`,{className:`pt-1`,children:(0,Q.jsxs)(`button`,{type:`button`,onClick:()=>w(`recovery`),className:`text-xs text-gray-500 hover:text-blue-600 dark:hover:text-blue-400 hover:underline bg-transparent border-none cursor-pointer p-0 font-normal inline-flex items-center gap-1`,children:[(0,Q.jsx)(t,{size:12}),(0,Q.jsx)(`span`,{children:C(`auth.totpUseRecovery`,`Use Recovery Key`)})]})})]})]}),r===`totp`&&(0,Q.jsxs)(`div`,{className:`space-y-4`,children:[(0,Q.jsx)(S,{label:C(`account.totp.title`,`Time-based One-time Password (TOTP)`),helperText:C(`auth.totpPrompt`,`Please enter the 6-digit code from your authentication app`),children:(0,Q.jsx)(`div`,{className:`pt-2`,children:(0,Q.jsx)(W,{length:6,value:l,onChange:u,disabled:p,autoFocus:!0})})}),(0,Q.jsx)(x,{checked:_,onChange:e=>v(e.currentTarget.checked),label:C(`auth.keepLoggedIn`,`Keep me logged in for {{days}} days`,{days:b}),className:`mt-4 text-left`}),(0,Q.jsxs)(`div`,{className:`pt-2 space-y-3`,children:[(0,Q.jsx)(h,{fill:!0,size:`large`,intent:y.PRIMARY,type:`submit`,loading:p,className:`font-bold py-6 rounded-xl shadow-lg shadow-blue-500/20`,children:C(`auth.loginBtn`,`Login`)}),e&&(0,Q.jsx)(h,{fill:!0,minimal:!0,size:`large`,type:`button`,disabled:p,onClick:()=>w(`passkey`),className:`font-medium text-blue-600 dark:text-blue-400 py-2.5 rounded-xl transition-colors hover:bg-blue-50 dark:hover:bg-blue-950/30`,children:C(`auth.otherOptions`,`Other Options`)}),(0,Q.jsx)(`div`,{className:`text-center pt-1`,children:(0,Q.jsxs)(`button`,{type:`button`,onClick:()=>w(`recovery`),className:`text-xs text-gray-500 hover:text-blue-600 dark:hover:text-blue-400 hover:underline bg-transparent border-none cursor-pointer p-0 font-normal inline-flex items-center gap-1`,children:[(0,Q.jsx)(t,{size:12}),(0,Q.jsx)(`span`,{children:C(`auth.totpUseRecovery`,`Use Recovery Key`)})]})})]})]}),r===`recovery`&&(0,Q.jsxs)(`div`,{className:`space-y-4`,children:[(0,Q.jsx)(S,{label:C(`account.totp.recoveryKeysTitle`,`Recovery Keys`),helperText:C(`auth.recoveryPrompt`,`Please enter your 30-character recovery key (5 groups of 6 digits)`),children:(0,Q.jsx)(`div`,{className:`pt-2`,children:(0,Q.jsx)(ce,{value:d,onChange:f,disabled:p,autoFocus:!0})})}),(0,Q.jsx)(x,{checked:_,onChange:e=>v(e.currentTarget.checked),label:C(`auth.keepLoggedIn`,`Keep me logged in for {{days}} days`,{days:b}),className:`mt-4 text-left`}),(0,Q.jsxs)(`div`,{className:`pt-2 space-y-3`,children:[(0,Q.jsx)(h,{fill:!0,size:`large`,intent:y.PRIMARY,type:`submit`,loading:p,className:`font-bold py-6 rounded-xl shadow-lg shadow-blue-500/20`,children:C(`auth.loginBtn`,`Login`)}),(0,Q.jsx)(`div`,{className:`text-center pt-1`,children:(0,Q.jsx)(`button`,{type:`button`,onClick:()=>w(e?`passkey`:`totp`),className:`text-xs text-blue-600 dark:text-blue-400 hover:underline bg-transparent border-none cursor-pointer p-0 font-normal`,children:e?C(`auth.backToPasskey`,`Back to Passkey Verification`):C(`auth.totpUseApp`,`Use Authentication App`)})})]})]})]})};function ue({siteKey:e,enabled:t,turnstileReady:n,isActive:r,onError:i,onClearError:o}){let[s,c]=(0,Z.useState)(null),[l,u]=(0,Z.useState)(`idle`),d=(0,Z.useRef)(null),f=(0,Z.useRef)(null),{t:p}=a();return(0,Z.useEffect)(()=>{if(r&&t&&e&&(n||window.turnstile)&&d.current)try{f.current&&window.turnstile&&(window.turnstile.remove(f.current),f.current=null),u(`verifying`),d.current.innerHTML=``,f.current=window.turnstile.render(d.current,{sitekey:e,callback:e=>{c(e),u(`success`),o()},"expired-callback":()=>{c(null),u(`idle`)},"error-callback":e=>{console.error(`Turnstile error:`,e),u(`error`),i(p(`auth.turnstileError`,`Verification service failed to load. Please reload and try again.`)),c(null)}})}catch(e){console.error(`Turnstile render error:`,e),u(`error`)}return()=>{f.current&&window.turnstile&&(window.turnstile.remove(f.current),f.current=null)}},[r,t,e,n,p,i,o]),{turnstileToken:s,setTurnstileToken:c,turnstileStatus:l,turnstileRef:d,resetTurnstile:()=>{window.turnstile&&f.current&&window.turnstile.reset(f.current),c(null),u(`idle`)}}}function de({username:e,password:t,passwordVersion:n,nonce:r,serverSalt:i,keepLoggedIn:o,onSuccess:s}){let[c,l]=(0,Z.useState)(!1),[u,d]=(0,Z.useState)(``),[f,p]=(0,Z.useState)(null),{t:m}=a();return{loading:c,error:u,setError:d,rotatedRecoveryKey:f,setRotatedRecoveryKey:p,executeLogin:async a=>{l(!0),d(``);try{let c={keepLoggedIn:o,passkeyAssertion:a.passkeyAssertion,totpTokenHash:a.totpTokenHash,totpSalt:a.totpSalt,recoveryKey:a.recoveryKey};if(a.useEnteredPassword&&t)if(n===2){if(!r||!i)throw Error(m(`auth.sessionExpired`,`Session expired, please start over`));c.password=await U(await Y(await H(t,e),i),r)}else c.password=t;let l=await J(c);if(l.accessToken&&M(l.accessToken),l.needsMigration&&t&&await A(await H(t,e),t),l.rotatedRecoveryKey&&a.recoveryKey){try{await G.unlockWithRecoveryKey(a.recoveryKey),await G.wrapCurrentKeyForRecovery(l.rotatedRecoveryKey)}catch(e){console.warn(`[Login] Could not auto re-wrap E2EE key with rotated recovery key:`,e)}p(l.rotatedRecoveryKey);return}s()}catch(e){e instanceof N&&ne({status:e.status},e.bodyText)?d(m(`auth.passwordLeaked`)):d(B(e,m))}finally{l(!1)}}}}function fe({hasPasswordEntered:e,passkeyOptions:t,executeLogin:n,onError:r}){let[i,o]=(0,Z.useState)(`passkey`),[s,c]=(0,Z.useState)(``),[l,u]=(0,Z.useState)(``),[d,f]=(0,Z.useState)(!1),{t:p}=a();return{mfaMethod:i,setMfaMethod:o,totpToken:s,setTotpToken:c,recoveryKey:l,setRecoveryKey:u,passkeyLoading:d,setPasskeyLoading:f,handlePasskeyLogin:async()=>{if(t){f(!0),r(``);try{await n({useEnteredPassword:e,passkeyAssertion:await I(t)})}catch(e){console.error(`Passkey authentication error:`,e),r(B(e,p))}finally{f(!1)}}},handleStep3Submit:async t=>{if(t.preventDefault(),i===`totp`){let t=s.replace(/\s/g,``);if(t.length!==6){r(p(`auth.totpFormatError`,`Please enter a valid 6-digit code`));return}let i=crypto.randomUUID();await n({useEnteredPassword:e,totpTokenHash:await K(t,i),totpSalt:i})}else if(i===`recovery`){let t=l.replace(/[-\s]/g,``);if(!t){r(p(`auth.recoveryKeyRequired`,`Please enter your recovery key`));return}await n({useEnteredPassword:e,recoveryKey:t})}},resetMfaFields:()=>{c(``),u(``),f(!1),o(`passkey`)}}}const pe=({authConfig:e,turnstileReady:t,onSuccess:n})=>{let{t:r}=a(),[i,o]=(0,Z.useState)(1),[s,c]=(0,Z.useState)(``),[l,u]=(0,Z.useState)(``),[d,f]=(0,Z.useState)(!1),[p,m]=(0,Z.useState)(1),[h,g]=(0,Z.useState)(void 0),[_,v]=(0,Z.useState)(void 0),[y,b]=(0,Z.useState)(!0),[x,S]=(0,Z.useState)(!1),[C,w]=(0,Z.useState)(!1),[T,E]=(0,Z.useState)(null),{loading:D,error:O,setError:k,rotatedRecoveryKey:A,setRotatedRecoveryKey:ee,executeLogin:j}=de({username:s,password:l,passwordVersion:p,nonce:h,serverSalt:_,keepLoggedIn:d,onSuccess:n}),[M,N]=(0,Z.useState)(!1),P=D||M,F=e?.turnstile_enabled_login,{turnstileToken:I,turnstileStatus:te,turnstileRef:L,resetTurnstile:z}=ue({siteKey:e?.turnstile_site_key,enabled:F,turnstileReady:t,isActive:i===1,onError:k,onClearError:()=>k(``)}),{mfaMethod:V,setMfaMethod:H,totpToken:ne,setTotpToken:U,recoveryKey:W,setRecoveryKey:G,passkeyLoading:K,handlePasskeyLogin:q,handleStep3Submit:J,resetMfaFields:re}=fe({hasPasswordEntered:!!l,passkeyOptions:T,executeLogin:j,onError:k}),Y=async t=>{if(t.preventDefault(),!ae(s)){k(r(`auth.formatTipUsername`));return}if(F&&e?.turnstile_site_key&&!I){k(r(`auth.turnstileRequired`));return}N(!0),k(``);try{let e=await R({username:s,turnstileToken:I});b(e.requires_password),S(e.requires_totp),w(!!e.has_passkey),E(e.passkey_options||null),m(e.password_version??1),g(e.nonce),v(e.serverSalt),H(e.has_passkey?`passkey`:`totp`),e.requires_password?o(2):o(3)}catch(e){k(B(e,r)),z()}finally{N(!1)}},ie=async e=>{if(e.preventDefault(),!l){k(r(`auth.passwordRequiredFirst`,`Please enter your password first`));return}C||x?(k(``),o(3),H(C?`passkey`:`totp`)):await j({useEnteredPassword:!0})},oe=()=>{u(``),k(``),o(3),H(C?`passkey`:`totp`)},X=()=>{o(1),u(``),k(``),g(void 0),v(void 0),w(!1),E(null),re(),z()};return{loginStep:i,username:s,setUsername:c,password:l,setPassword:u,totpToken:ne,setTotpToken:U,recoveryKey:W,setRecoveryKey:G,requiresPassword:y,requiresTotp:x,hasPasskey:C,mfaMethod:V,setMfaMethod:H,passkeyLoading:K,loading:P,error:O,setError:k,turnstileStatus:te,turnstileRef:L,isTurnstileEnabled:F,keepLoggedIn:d,setKeepLoggedIn:f,handleStep1Submit:Y,handleStep2Submit:ie,handleStep3Submit:J,handleSwitchToMfa:oe,handlePasskeyLogin:q,handleBack:()=>{k(``),i===2?X():i===3&&(y?o(2):X())},resetToStep1:X,rotatedRecoveryKey:A,handleAcknowledgeRotatedKey:()=>{ee(null),n()}}},me=({authConfig:e,turnstileReady:t,onSuccess:r,onToggleMode:i})=>{let{t:l}=a(),{loginStep:u,username:f,setUsername:p,password:b,setPassword:x,totpToken:S,setTotpToken:C,recoveryKey:w,setRecoveryKey:T,requiresTotp:D,hasPasskey:O,mfaMethod:k,setMfaMethod:A,passkeyLoading:ee,loading:j,error:M,setError:N,turnstileStatus:F,turnstileRef:I,isTurnstileEnabled:te,keepLoggedIn:L,setKeepLoggedIn:R,handleStep1Submit:z,handleStep2Submit:B,handleStep3Submit:V,handleSwitchToMfa:H,handlePasskeyLogin:ne,handleBack:U,rotatedRecoveryKey:W,handleAcknowledgeRotatedKey:G}=pe({authConfig:e,turnstileReady:t,onSuccess:r}),[K,q]=(0,Z.useState)(!1),J=e=>{navigator.clipboard.writeText(e),q(!0),setTimeout(()=>q(!1),2e3)};return(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsxs)(`div`,{className:`flex flex-col items-center mb-8 relative`,children:[u!==1&&(0,Q.jsx)(`button`,{type:`button`,onClick:U,className:`absolute left-0 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 bg-transparent border-none cursor-pointer p-1 rounded-lg transition-colors`,title:l(`common.back`,`返回`),children:(0,Q.jsx)(n,{size:24})}),(0,Q.jsx)(`img`,{src:P,alt:`DNS Worker Logo`,className:`w-20 h-20 object-contain`}),(0,Q.jsx)(d,{className:`font-bold tracking-tight text-2xl mt-4`,children:(()=>{switch(u){case 1:return l(`auth.login`);case 2:return l(`auth.password`);case 3:return l(`auth.mfaVerification`,`多因素认证`)}})()}),(0,Q.jsx)(`p`,{className:`text-gray-500 mt-2 text-center text-sm leading-relaxed`,children:u===1?l(`auth.protectInternet`):f})]}),e?.has_users===!1&&(0,Q.jsx)(v,{intent:y.PRIMARY,icon:`info-sign`,className:`mb-6 rounded-xl`,children:(0,Q.jsxs)(`div`,{className:`flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3`,children:[(0,Q.jsx)(`span`,{className:`text-sm font-medium`,children:l(`auth.noUsersRegistered`,`系统尚无账号,请注册成为管理员。`)}),(0,Q.jsx)(`button`,{type:`button`,onClick:i,className:`text-xs bg-blue-600 hover:bg-blue-700 text-white font-semibold py-1.5 px-3 rounded-lg border-none cursor-pointer whitespace-nowrap transition-colors`,children:l(`auth.goToRegisterAdmin`,`注册管理员`)})]})}),M&&(0,Q.jsx)(v,{intent:y.DANGER,className:`mb-6 rounded-xl`,title:l(`auth.error`),children:M}),u===1&&(0,Q.jsx)($,{username:f,setUsername:p,isTurnstileEnabled:te,turnstileRef:I,loading:j,turnstileStatus:F,onSubmit:z}),u===2&&(0,Q.jsx)(se,{password:b,setPassword:x,hasMfa:O||D,onSwitchToMfa:H,loading:j,onSubmit:B,keepLoggedIn:L,setKeepLoggedIn:R,optionalSessionExpirationDays:e?.optional_session_expiration_days??7}),u===3&&(0,Q.jsx)(le,{hasPasskey:O,requiresTotp:D,mfaMethod:k,setMfaMethod:A,passkeyLoading:ee,onPasskeyLogin:ne,totpToken:S,setTotpToken:C,recoveryKey:w,setRecoveryKey:T,loading:j,onClearError:()=>N(``),onSubmit:V,keepLoggedIn:L,setKeepLoggedIn:R,optionalSessionExpirationDays:e?.optional_session_expiration_days??7}),u===1&&(e?.has_users===!1||e?.registration_enabled!==!1)&&(0,Q.jsx)(`div`,{className:`mt-8 pt-6 border-t border-gray-100 dark:border-gray-800 flex justify-center items-center text-sm`,children:(0,Q.jsx)(`button`,{onClick:i,className:`text-blue-600 dark:text-blue-400 font-semibold hover:underline bg-transparent border-none cursor-pointer`,children:l(`auth.noAccount`)})}),(0,Q.jsxs)(g,{isOpen:!!W,onClose:G,title:l(`account.recoveryKey.autoRotatedTitle`,`恢复密钥已自动轮换`),icon:`warning-sign`,isCloseButtonShown:!1,canOutsideClickClose:!1,className:`dark:bg-gray-900`,children:[(0,Q.jsxs)(`div`,{className:m,children:[(0,Q.jsx)(v,{intent:y.WARNING,icon:(0,Q.jsx)(s,{size:16}),className:`mb-4 text-xs`,children:l(`account.recoveryKey.autoRotatedNotice`,`根据恢复密钥单次使用规则,您的原恢复密钥已失效,系统已为您生成全新 30 位紧急恢复密钥。请务必立即复制并妥善离线保存,关闭后将无法再次查看!`)}),W&&(0,Q.jsxs)(`div`,{className:`space-y-3`,children:[(0,Q.jsx)(`div`,{className:`p-3 bg-gray-100 dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700 font-mono text-center text-lg font-bold tracking-widest select-all text-gray-900 dark:text-gray-100`,children:W}),(0,Q.jsx)(`div`,{className:`flex justify-center`,children:(0,Q.jsx)(h,{intent:y.PRIMARY,icon:K?(0,Q.jsx)(o,{size:14,className:`text-green-400`}):(0,Q.jsx)(c,{size:14}),text:K?l(`common.copied`,`已复制`):l(`common.copyKey`,`复制新恢复密钥`),onClick:()=>J(W)})})]})]}),(0,Q.jsx)(`div`,{className:_,children:(0,Q.jsx)(`div`,{className:E,children:(0,Q.jsx)(h,{intent:y.SUCCESS,onClick:G,text:l(`account.recoveryKey.savedAndContinue`,`我已妥善保存并进入控制台`)})})})]})]})},he=({username:e,setUsername:t,usernameFocused:n,setUsernameFocused:r,checkUsernameDuplicate:i,loading:o,onSubmit:s,onClearError:c})=>{let{t:l}=a();return(0,Q.jsxs)(`form`,{onSubmit:s,className:`space-y-4`,children:[(0,Q.jsx)(S,{label:l(`auth.username`),labelFor:`username`,children:(0,Q.jsx)(w,{content:l(`auth.formatTipUsername`),isOpen:n,position:f.TOP,intent:y.PRIMARY,className:`w-full`,children:(0,Q.jsx)(`div`,{className:`w-full block`,children:(0,Q.jsx)(b,{id:`username`,leftIcon:`user`,placeholder:l(`auth.usernamePlaceholder`),size:`large`,className:`rounded-xl w-full`,value:e,onChange:e=>{t(e.target.value),c()},onFocus:()=>r(!0),onBlur:()=>{r(!1),i(e)},autoFocus:!0,required:!0})})})}),(0,Q.jsx)(h,{fill:!0,size:`large`,intent:y.PRIMARY,type:`submit`,loading:o,className:`mt-6 font-bold py-6 rounded-xl shadow-lg shadow-blue-500/20`,children:l(`auth.next`,`Next`)})]})},ge=({password:e,setPassword:t,passwordFocused:n,setPasswordFocused:r,loading:i,onSubmit:o,isTurnstileEnabled:s,turnstileRef:c,turnstileStatus:l})=>{let[u,d]=Z.useState(!1),{t:p}=a();return(0,Q.jsxs)(`form`,{onSubmit:o,className:`space-y-4`,children:[(0,Q.jsx)(S,{label:p(`auth.password`),labelFor:`password`,children:(0,Q.jsx)(w,{content:p(`auth.formatTipPassword`),isOpen:n,position:f.TOP,intent:y.PRIMARY,className:`w-full`,children:(0,Q.jsx)(`div`,{className:`w-full block`,children:(0,Q.jsx)(b,{id:`password`,leftIcon:`lock`,placeholder:p(`auth.passwordPlaceholder`),type:u?`text`:`password`,size:`large`,className:`rounded-xl w-full`,value:e,onChange:e=>t(e.target.value),onFocus:()=>r(!0),onBlur:()=>r(!1),rightElement:(()=>(0,Q.jsxs)(`div`,{className:`flex items-center`,children:[e&&(0,Q.jsx)(h,{minimal:!0,icon:`cross`,onClick:()=>t(``)}),(0,Q.jsx)(h,{minimal:!0,icon:u?`eye-open`:`eye-off`,onClick:()=>d(!u),title:u?p(`auth.hidePassword`,`Hide password`):p(`auth.showPassword`,`Show password`)})]}))(),required:!0,autoFocus:!0})})})}),s&&(0,Q.jsx)(`div`,{className:`py-2 flex justify-center min-h-16.25`,children:(0,Q.jsx)(`div`,{ref:c})}),(0,Q.jsx)(h,{fill:!0,size:`large`,intent:y.PRIMARY,type:`submit`,loading:i||l===`verifying`,disabled:!!s&&l!==`success`,className:`mt-6 font-bold py-6 rounded-xl shadow-lg shadow-blue-500/20`,children:p(l===`verifying`?`auth.verifying`:`auth.signupBtn`)})]})},_e=({mfaChoice:e,setMfaChoice:t,onRegisterPasskey:o,passkeyRegLoading:s,passkeyRegError:c,onStartTotp:l,totpSetupData:u,totpSetupToken:d,setTotpSetupToken:f,totpSetupError:m,totpSetupLoading:g,onTotpSubmit:_,onSkip:b})=>{let{t:x}=a();return e===`choose`?(0,Q.jsxs)(`div`,{className:`space-y-4`,children:[c&&(0,Q.jsx)(v,{intent:y.DANGER,className:`rounded-xl`,children:c}),(0,Q.jsxs)(`div`,{className:`space-y-3`,children:[(0,Q.jsxs)(T,{elevation:p.ONE,className:`p-4 rounded-xl border border-blue-100 dark:border-blue-900/40 hover:border-blue-300 dark:hover:border-blue-700 transition-colors cursor-pointer`,onClick:s?void 0:o,children:[(0,Q.jsx)(`div`,{className:`flex items-start justify-between`,children:(0,Q.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,Q.jsx)(`div`,{className:`p-2.5 bg-blue-50 dark:bg-blue-950/40 text-blue-600 dark:text-blue-400 rounded-xl`,children:(0,Q.jsx)(i,{size:24})}),(0,Q.jsxs)(`div`,{children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(`h4`,{className:`text-sm font-bold text-gray-800 dark:text-gray-100 m-0`,children:x(`account.passkey.title`,`通行密钥 (Passkey)`)}),(0,Q.jsx)(C,{intent:y.PRIMARY,minimal:!0,round:!0,children:x(`auth.mfaRecommended`,`推荐 · 无密码`)})]}),(0,Q.jsx)(`div`,{className:`text-xs text-blue-600 dark:text-blue-400 font-mono mt-0.5`,children:window.location.hostname}),(0,Q.jsx)(`p`,{className:`text-xs text-gray-500 dark:text-gray-400 mt-1 mb-0 leading-relaxed`,children:x(`auth.passkeySignupDesc`,`使用本设备生物识别 (Touch ID / Face ID / Windows Hello) 或硬件密钥 (YubiKey),一键快捷且防钓鱼。`)})]})]})}),(0,Q.jsx)(`div`,{className:`mt-3 text-right`,children:(0,Q.jsx)(h,{intent:y.PRIMARY,loading:s,text:x(`auth.bindPasskeyNow`,`绑定通行密钥`),className:`rounded-lg font-medium`})})]}),(0,Q.jsxs)(T,{elevation:p.ONE,className:`p-4 rounded-xl border border-gray-100 dark:border-gray-800 hover:border-gray-300 dark:hover:border-gray-700 transition-colors cursor-pointer`,onClick:l,children:[(0,Q.jsx)(`div`,{className:`flex items-start justify-between`,children:(0,Q.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,Q.jsx)(`div`,{className:`p-2.5 bg-purple-50 dark:bg-purple-950/40 text-purple-600 dark:text-purple-400 rounded-xl`,children:(0,Q.jsx)(r,{size:24})}),(0,Q.jsxs)(`div`,{children:[(0,Q.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Q.jsx)(`h4`,{className:`text-sm font-bold text-gray-800 dark:text-gray-100 m-0`,children:x(`auth.mfaMethodTotp`,`数字验证器 (TOTP)`)}),(0,Q.jsx)(C,{intent:y.NONE,minimal:!0,round:!0,children:x(`auth.mfaUniversal`,`通用应用`)})]}),(0,Q.jsx)(`p`,{className:`text-xs text-gray-500 dark:text-gray-400 mt-1 mb-0 leading-relaxed`,children:x(`account.totp.setupDesc`,`使用 Google Authenticator、1Password 等验证器应用扫码绑定 6 位动态验证码。`)})]})]})}),(0,Q.jsx)(`div`,{className:`mt-3 text-right`,children:(0,Q.jsx)(h,{minimal:!0,text:x(`auth.setupTotpBtn`,`扫码配置验证器`),className:`rounded-lg font-medium text-gray-700 dark:text-gray-200`})})]})]}),(0,Q.jsx)(`div`,{className:`text-center pt-2`,children:(0,Q.jsx)(h,{minimal:!0,text:x(`auth.skipMfaSetup`,`跳过多因素认证配置,直接进入系统`),onClick:b,className:`text-xs text-gray-400 hover:text-gray-600 dark:hover:text-gray-200`})})]}):(0,Q.jsxs)(`div`,{className:`space-y-4`,children:[(0,Q.jsx)(`div`,{className:`flex items-center justify-between`,children:(0,Q.jsxs)(`button`,{type:`button`,onClick:()=>t(`choose`),className:`text-xs text-blue-600 hover:underline flex items-center gap-1 bg-transparent border-none cursor-pointer p-0`,children:[(0,Q.jsx)(n,{size:14}),(0,Q.jsx)(`span`,{children:x(`auth.backToMfaOptions`,`选择其他认证方式`)})]})}),u&&(0,Q.jsxs)(`div`,{className:`flex flex-col items-center gap-3`,children:[(0,Q.jsx)(X,{uri:u.uri}),(0,Q.jsxs)(`div`,{className:`text-center`,children:[(0,Q.jsx)(`p`,{className:`text-xs text-gray-500 mb-1`,children:x(`account.totp.orEnterManually`,`Or enter the key manually:`)}),(0,Q.jsx)(`code`,{className:`text-xs font-mono bg-gray-100 dark:bg-gray-800 px-2 py-1 rounded select-all`,children:u.secret})]})]}),m&&(0,Q.jsx)(v,{intent:y.DANGER,className:`rounded-xl`,children:m}),(0,Q.jsxs)(`form`,{onSubmit:_,className:`space-y-4`,children:[(0,Q.jsx)(S,{label:x(`account.totp.enterCode`,`Enter the 6-digit code:`),helperText:x(`account.totp.enterCodeHint`,`Enter the 6-digit code to confirm.`),children:(0,Q.jsx)(W,{length:6,value:d,onChange:f,disabled:g,autoFocus:!0})}),(0,Q.jsx)(h,{fill:!0,size:`large`,intent:y.PRIMARY,type:`submit`,loading:g,disabled:d.length!==6,className:`rounded-xl font-bold py-3`,children:x(`account.totp.activate`,`Activate`)})]})]})},ve=({totpRecoveryKeys:e,copiedRecovery:t,onCopy:n,onSuccess:r})=>{let{t:i}=a();return Z.useEffect(()=>{let e=e=>{e.key===`Enter`&&r()};return window.addEventListener(`keydown`,e),()=>{window.removeEventListener(`keydown`,e)}},[r]),(0,Q.jsxs)(`div`,{className:`space-y-4`,children:[(0,Q.jsx)(`div`,{className:e.length===1?`space-y-2 mb-4`:`grid grid-cols-2 gap-2 mb-4`,children:e.map((e,t)=>(0,Q.jsx)(`code`,{className:`block font-mono text-sm sm:text-base font-semibold bg-gray-100 dark:bg-gray-800 text-blue-600 dark:text-blue-400 px-4 py-3 rounded-xl text-center tracking-widest break-all select-all border border-gray-200 dark:border-gray-700`,children:e},t))}),(0,Q.jsxs)(`div`,{className:`flex gap-2`,children:[(0,Q.jsx)(h,{fill:!0,icon:(0,Q.jsx)(c,{size:14}),text:t?i(`account.totp.copied`,`Copied!`):i(`account.totp.copyKeys`,`Copy All Keys`),intent:t?y.SUCCESS:y.NONE,onClick:n}),(0,Q.jsx)(h,{fill:!0,intent:y.PRIMARY,text:i(`account.totp.done`,`Done`),onClick:r})]})]})},ye=({authConfig:e,turnstileReady:t,onSuccess:n})=>{let[r,i]=(0,Z.useState)(`username`),[o,s]=(0,Z.useState)(``),[c,l]=(0,Z.useState)(``),[u,d]=(0,Z.useState)(``),[f,p]=(0,Z.useState)(null),[m,h]=(0,Z.useState)(null),[g,_]=(0,Z.useState)(!1),[v,y]=(0,Z.useState)(``),[b,x]=(0,Z.useState)(!1),[S,C]=(0,Z.useState)(!1),[w,T]=(0,Z.useState)(!1),[E,D]=(0,Z.useState)(!1),[k,A]=(0,Z.useState)(``),[P,I]=(0,Z.useState)(`choose`),[L,R]=(0,Z.useState)(!1),[z,V]=(0,Z.useState)(``),[U,W]=(0,Z.useState)(null),[q,J]=(0,Z.useState)(`idle`),Y=(0,Z.useRef)(null),X=(0,Z.useRef)(null),{t:Q}=a(),$=e?.turnstile_enabled_signup;(0,Z.useEffect)(()=>{if(r===`password`&&$&&e?.turnstile_site_key&&(t||window.turnstile)&&Y.current)try{X.current&&window.turnstile&&(window.turnstile.remove(X.current),X.current=null),J(`verifying`),Y.current.innerHTML=``,X.current=window.turnstile.render(Y.current,{sitekey:e.turnstile_site_key,callback:e=>{W(e),J(`success`),y(``)},"expired-callback":()=>{W(null),J(`idle`)},"error-callback":e=>{console.error(`Turnstile error:`,e),J(`error`),y(Q(`auth.turnstileError`,`Verification service failed to load. Please reload and try again.`)),W(null)}})}catch(e){console.error(`Turnstile render error:`,e),J(`error`)}return()=>{X.current&&window.turnstile&&(window.turnstile.remove(X.current),X.current=null)}},[$,e,r,t,Q]);let se=async e=>{if(!(!e||!ae(e)))try{await O(e)?y(Q(`auth.usernameExists`)):y(e=>e===Q(`auth.usernameExists`)?``:e)}catch(e){console.error(`Failed to check username duplicate`,e)}},ce=async e=>{if(e.preventDefault(),!ae(o)){y(Q(`auth.formatTipUsername`));return}_(!0),y(``);try{await O(o)?y(Q(`auth.usernameExists`)):i(`password`)}catch{y(Q(`auth.networkError`))}finally{_(!1)}},le=async()=>{D(!0),A(``);try{p(await F()),i(`totp`)}catch(e){console.error(`Network error during signup TOTP setup:`,e),n()}finally{D(!1)}};return{signupStep:r,setSignupStep:i,username:o,setUsername:s,password:c,setPassword:l,mfaChoice:P,setMfaChoice:I,passkeyRegLoading:L,passkeyRegError:z,handleRegisterPasskey:async()=>{R(!0),V(``);try{let e=await ee({name:`primary_passkey`,credential:await te(await j())}),t=e?.passkey?.id||e?.id;if(t&&G.isUnlocked())try{await G.wrapCurrentKeyForPasskey(t)}catch(e){console.warn(`Failed to wrap key for new passkey:`,e)}e.recovery_keys&&e.recovery_keys.length>0&&h(e.recovery_keys),i(`recovery`)}catch(e){console.error(`Passkey registration failed:`,e),V(B(e,Q))}finally{R(!1)}},handleChooseTotp:async()=>{I(`totp`),await le()},totpSetupToken:u,setTotpSetupToken:d,totpSetupData:f,setTotpSetupData:p,totpRecoveryKeys:m,setTotpRecoveryKeys:h,loading:g,error:v,setError:y,usernameFocused:b,setUsernameFocused:x,passwordFocused:S,setPasswordFocused:C,copiedRecovery:w,totpSetupLoading:E,totpSetupError:k,turnstileStatus:q,turnstileRef:Y,isTurnstileEnabled:$,checkUsernameDuplicate:se,handleSignupUsernameSubmit:ce,handleSignupTotpConfirm:async e=>{if(e.preventDefault(),f){D(!0),A(``);try{let e=u.replace(/\s/g,``),t=crypto.randomUUID(),n=await K(e,t),r=await ie({secret:f.secret,totpTokenHash:n,salt:t});r.recovery_keys&&r.recovery_keys.length>0&&h(r.recovery_keys),i(`recovery`)}catch(e){A(e.message||Q(`common.errorNetwork`))}finally{D(!1)}}},handleCopySignupRecoveryKeys:()=>{m&&navigator.clipboard.writeText(m.join(`
|
|
2
|
+
`)).then(()=>{T(!0),setTimeout(()=>T(!1),2e3)})},handleSignupSubmit:async t=>{if(t.preventDefault(),!ae(o)){y(Q(`auth.formatTipUsername`));return}if(!oe(c)){y(Q(`auth.formatTipPassword`));return}if($&&e?.turnstile_site_key&&!U){y(Q(`auth.turnstileRequired`));return}_(!0),y(``);try{let e=await re({username:o,password:await H(c,o),turnstileToken:U});e.accessToken&&M(e.accessToken),e.recoveryKey&&h([e.recoveryKey]),I(`choose`),i(`totp`)}catch(e){e instanceof N&&ne({status:e.status},e.bodyText)?y(Q(`auth.passwordLeaked`)):y(B(e,Q)),window.turnstile&&window.turnstile.reset(),W(null)}finally{_(!1)}}}},be=({authConfig:e,turnstileReady:t,onSuccess:r,onToggleMode:i})=>{let{t:o}=a(),{signupStep:s,setSignupStep:c,username:l,setUsername:u,password:f,setPassword:p,mfaChoice:m,setMfaChoice:h,passkeyRegLoading:g,passkeyRegError:_,handleRegisterPasskey:b,handleChooseTotp:x,totpSetupToken:S,setTotpSetupToken:C,totpSetupData:w,totpRecoveryKeys:T,loading:E,error:D,setError:O,usernameFocused:k,setUsernameFocused:A,passwordFocused:ee,setPasswordFocused:j,copiedRecovery:M,totpSetupLoading:N,totpSetupError:F,turnstileStatus:I,turnstileRef:te,isTurnstileEnabled:L,checkUsernameDuplicate:R,handleSignupUsernameSubmit:z,handleSignupTotpConfirm:B,handleCopySignupRecoveryKeys:V,handleSignupSubmit:H}=ye({authConfig:e,turnstileReady:t,onSuccess:r});return e&&e.has_users!==!1&&e.registration_enabled===!1?(0,Q.jsxs)(`div`,{className:`space-y-6 text-center`,children:[(0,Q.jsxs)(`div`,{className:`flex flex-col items-center`,children:[(0,Q.jsx)(`img`,{src:P,alt:`DNS Worker Logo`,className:`w-20 h-20 object-contain`}),(0,Q.jsx)(d,{className:`font-bold tracking-tight text-2xl mt-4`,children:o(`auth.signup`)})]}),(0,Q.jsx)(v,{intent:y.WARNING,icon:`lock`,title:o(`auth.registrationDisabledTitle`,`注册已停用`),children:o(`auth.registrationDisabledDesc`,`当前系统已暂停开放新用户注册,请联系系统管理员分配账号。`)}),(0,Q.jsx)(`div`,{className:`pt-4 border-t border-gray-100 dark:border-gray-800 flex justify-center items-center text-sm`,children:(0,Q.jsxs)(`button`,{onClick:i,className:`text-blue-600 dark:text-blue-400 font-semibold hover:underline bg-transparent border-none cursor-pointer flex items-center gap-1`,children:[(0,Q.jsx)(n,{size:16}),o(`auth.backToLogin`,`返回登录`)]})})]}):(0,Q.jsxs)(Q.Fragment,{children:[(0,Q.jsxs)(`div`,{className:`flex flex-col items-center mb-8 relative`,children:[s===`password`&&(0,Q.jsx)(`button`,{onClick:()=>{c(`username`),O(``)},className:`absolute left-0 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 bg-transparent border-none cursor-pointer`,title:`Back to username`,children:(0,Q.jsx)(n,{size:24})}),(0,Q.jsx)(`img`,{src:P,alt:`DNS Worker Logo`,className:`w-20 h-20 object-contain`}),(0,Q.jsx)(d,{className:`font-bold tracking-tight text-2xl mt-4`,children:s===`username`||s===`password`?e?.has_users===!1?o(`auth.registerAdminTitle`,`注册管理员账号`):o(`auth.signup`):s===`totp`?o(`auth.mfaSetupTitle`,`配置多因素认证 (MFA)`):o(`account.totp.recoveryKeysTitle`,`Save Recovery Keys`)}),(0,Q.jsx)(`p`,{className:`text-gray-500 mt-2 text-center text-sm leading-relaxed`,children:s===`username`||s===`password`?s===`password`?l:e?.has_users===!1?o(`auth.registerAdminDesc`,`系统尚无账号,首位注册用户将自动成为系统管理员。`):o(`auth.protectInternet`):s===`totp`?o(`auth.mfaSetupDesc`,`任选一种认证方式即可完成配置,保障账号安全。`):o(`account.totp.recoveryKeysWarning`,`Store keys safely.`)})]}),D&&(0,Q.jsx)(v,{intent:y.DANGER,className:`mb-6 rounded-xl`,title:o(`auth.error`),children:D}),s===`username`&&(0,Q.jsx)(he,{username:l,setUsername:u,usernameFocused:k,setUsernameFocused:A,checkUsernameDuplicate:R,loading:E,onSubmit:z,onClearError:()=>O(e=>e===o(`auth.usernameExists`)?``:e)}),s===`password`&&(0,Q.jsx)(ge,{password:f,setPassword:p,passwordFocused:ee,setPasswordFocused:j,loading:E,onSubmit:H,isTurnstileEnabled:L,turnstileRef:te,turnstileStatus:I}),s===`totp`&&(0,Q.jsx)(_e,{mfaChoice:m,setMfaChoice:h,onRegisterPasskey:b,passkeyRegLoading:g,passkeyRegError:_,onStartTotp:x,totpSetupData:w,totpSetupToken:S,setTotpSetupToken:C,totpSetupError:F,totpSetupLoading:N,onTotpSubmit:B,onSkip:()=>{T&&T.length>0?c(`recovery`):r()}}),s===`recovery`&&T&&(0,Q.jsx)(ve,{totpRecoveryKeys:T,copiedRecovery:M,onCopy:V,onSuccess:r}),s===`username`&&(0,Q.jsx)(`div`,{className:`mt-8 pt-6 border-t border-gray-100 dark:border-gray-800 text-center`,children:(0,Q.jsx)(`button`,{onClick:i,className:`text-blue-600 dark:text-blue-400 font-semibold hover:underline bg-transparent border-none cursor-pointer text-sm`,children:o(`auth.haveAccount`)})})]})},xe=({onSuccess:e})=>{let[t,n]=(0,Z.useState)(!0),[r,i]=(0,Z.useState)(!0),[o,s]=(0,Z.useState)(!1),{t:c}=a(),l=()=>{s(!0),setTimeout(()=>{n(e=>!e),s(!1)},300)},[u,d]=(0,Z.useState)(null),[f,m]=(0,Z.useState)(!1);(0,Z.useEffect)(()=>{(async()=>{try{let e=await V();d(e),e&&e.has_users===!1&&n(!1)}catch(e){console.error(`Failed to load auth config`,e)}})()},[]);let g=t?u?.turnstile_enabled_login:u?.turnstile_enabled_signup;return(0,Z.useEffect)(()=>{g&&u?.turnstile_site_key&&L(()=>{m(!0)})},[g,u]),(0,Q.jsxs)(`div`,{className:`flex flex-row min-h-screen bg-white dark:bg-gray-950 overflow-hidden relative`,children:[(0,Q.jsx)(`div`,{className:`hidden lg:block w-1/2 h-screen overflow-hidden border-r border-gray-100 dark:border-gray-900`,children:(0,Q.jsx)(q,{})}),(0,Q.jsx)(`div`,{className:`lg:hidden absolute inset-0 z-0 transition-opacity duration-500 cursor-pointer ${r?`opacity-25`:`opacity-70`}`,onClick:()=>i(!0),children:(0,Q.jsx)(q,{})}),!r&&(0,Q.jsx)(`div`,{className:`lg:hidden fixed bottom-12 left-1/2 -translate-x-1/2 z-50 animate-bounce`,children:(0,Q.jsx)(h,{large:!0,intent:`primary`,icon:`log-in`,text:c(`auth.loginBtn`),onClick:()=>i(!0),className:`shadow-2xl px-8 py-4 rounded-full`})}),(0,Q.jsxs)(`div`,{className:`flex-1 flex items-center justify-center p-4 relative z-10 bg-gray-50/50 dark:bg-gray-900/30 lg:bg-gray-50 lg:dark:bg-gray-900/50 transition-all duration-500 ease-in-out ${r?`translate-x-0 opacity-100`:`max-lg:translate-x-full max-lg:opacity-0 max-lg:pointer-events-none`}`,onClick:e=>{window.innerWidth<1024&&e.target===e.currentTarget&&i(!1)},children:[(0,Q.jsx)(`div`,{className:`absolute top-4 right-4 z-50`,children:(0,Q.jsx)(k,{})}),(0,Q.jsx)(`div`,{className:D(`w-full max-w-md transition-all duration-200 ease-in-out transform-gpu`,o?`blur-lg opacity-20 scale-95`:`blur-0 opacity-100 scale-100`),children:(0,Q.jsx)(T,{elevation:p.FOUR,className:`w-full p-8 rounded-2xl shadow-none! z-10 dark:bg-gray-900 border border-gray-100 dark:border-gray-800`,onClick:e=>e.stopPropagation(),children:t?(0,Q.jsx)(me,{authConfig:u,turnstileReady:f,onSuccess:e,onToggleMode:l}):(0,Q.jsx)(be,{authConfig:u,turnstileReady:f,onSuccess:e,onToggleMode:l})})})]})]})};export{xe as AuthView};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{i as e}from"./rolldown-runtime-C4Xdq4VV.js";import{L as t,Zt as n,_ as r,d as i,f as a,g as o,i as s,m as c,p as l,r as u,u as d,y as f}from"./vendor-react-CHk5ngkq.js";import{S as p,b as m}from"./vendor-icons-other-Bme3ywH9.js";import"./vendor-utils-CnB7BG7m.js";import{H as h,k as g,lt as _}from"./index-CbTjGMTZ.js";import{n as v,t as y}from"./formatCountryName-CSBD8pP8.js";import{t as b}from"./getFlagEmoji-_Wxhq0lT.js";var x=e(p(),1);function S(e){let[t,n]=(0,x.useState)(null);(0,x.useEffect)(()=>{h().then(e=>{if(e&&e.objects){let t={};e.objects.countries&&(t.countries=e.objects.countries),e.objects.land&&(t.land=e.objects.land),e.objects=t}e&&e.objects&&e.objects.countries&&Array.isArray(e.objects.countries.geometries)&&e.objects.countries.geometries.forEach(e=>{e.id!==void 0&&e.id!==null&&(e.id=String(e.id).padStart(3,`0`))}),n(e)}).catch(e=>console.error(`Failed to load map topology`,e))},[]);let r=(0,x.useMemo)(()=>e.reduce((e,t)=>e+t.count,0),[e]),i=(0,x.useMemo)(()=>{if(r<=0)return{maxThreshold:10,step:1};if(r<=1e3)return{maxThreshold:100,step:10};let e=10**Math.floor(Math.log10(r));return{maxThreshold:e,step:e/10}},[r]);return{geographyData:t,destinationMap:(0,x.useMemo)(()=>{let t={};return e.forEach(e=>{if(e.country_code){let n=e.country_code.toUpperCase();t[n]={count:e.count,name:e.country,countryCode:n}}}),t},[e]),scaleConfig:i,getLevel:e=>!e||e<=0?0:Math.min(10,Math.floor(e/i.step)+1),formatNumber:e=>{if(e>=1e6){let t=e/1e6;return Number.isInteger(t)?`${t}M`:`${t.toFixed(1)}M`}if(e>=1e3){let t=e/1e3;return Number.isInteger(t)?`${t}K`:`${t.toFixed(1)}K`}return e.toString()}}}var C=e(m(),1);const w=({onZoomIn:e,onZoomOut:n,onReset:i})=>(0,C.jsxs)(`div`,{className:`absolute top-3 right-3 flex flex-col gap-1.5 bg-white/80 dark:bg-slate-950/80 backdrop-blur-md p-1.5 rounded-lg border border-gray-200/50 dark:border-slate-800/50 shadow-sm z-10`,children:[(0,C.jsx)(`button`,{type:`button`,onClick:e,className:`p-1.5 hover:bg-gray-100 dark:hover:bg-slate-800 rounded text-gray-600 dark:text-gray-300 transition-colors cursor-pointer`,title:`Zoom In`,children:(0,C.jsx)(o,{size:16})}),(0,C.jsx)(`button`,{type:`button`,onClick:n,className:`p-1.5 hover:bg-gray-100 dark:hover:bg-slate-800 rounded text-gray-600 dark:text-gray-300 transition-colors cursor-pointer`,title:`Zoom Out`,children:(0,C.jsx)(r,{size:16})}),(0,C.jsx)(`button`,{type:`button`,onClick:i,className:`p-1.5 hover:bg-gray-100 dark:hover:bg-slate-800 rounded text-gray-600 dark:text-gray-300 transition-colors cursor-pointer`,title:`Reset Zoom`,children:(0,C.jsx)(t,{size:16})})]}),T=({maxThreshold:e,formatNumber:t})=>{let{t:r}=n();return(0,C.jsxs)(`div`,{className:`sm:absolute sm:bottom-3 sm:left-3 relative m-3 sm:m-0 flex flex-col shrink-0 gap-1.5 bg-white/80 dark:bg-slate-950/80 backdrop-blur-md p-2 rounded-lg border border-gray-200/50 dark:border-slate-800/50 shadow-sm z-10 max-w-70`,children:[(0,C.jsx)(`span`,{className:`text-[9px] font-bold text-gray-500 dark:text-gray-400 uppercase tracking-wider`,children:r(`analytics.queries`)}),(0,C.jsx)(`div`,{className:`flex items-center gap-0.5`,children:Array.from({length:11}).map((e,t)=>(0,C.jsx)(`div`,{className:`w-4 h-2.5 rounded-sm border border-black/5 dark:border-white/5`,style:{backgroundColor:`var(--map-color-${t})`}},t))}),(0,C.jsxs)(`div`,{className:`flex justify-between text-[9px] text-gray-500 dark:text-gray-400 font-semibold px-0.5`,children:[(0,C.jsx)(`span`,{children:`0`}),(0,C.jsx)(`span`,{children:t(e/2)}),(0,C.jsxs)(`span`,{children:[t(e),`+`]})]})]})},E=({name:e,count:t,flag:r,x:i,y:a,countryCode:o,profileId:s,range:c,customRange:l,accessPointId:u,ispCache:d,onCacheIsp:p,isPinned:m,onClose:h})=>{let{t:v}=n(),y=(0,x.useRef)(null),[b,S]=(0,x.useState)({left:i,top:a-10,alignBottom:!1}),[w,T]=(0,x.useState)([]),[E,D]=(0,x.useState)(!1),O=(0,x.useRef)(d);O.current=d;let k=(0,x.useRef)(p);return k.current=p,(0,x.useEffect)(()=>{if(!o||!s)return;if(t<=0){T([]),D(!1);return}let e=O.current[o];if(e){T(e),D(!1);return}D(!0);let n=Math.floor(Date.now()/1e3),r,i=n,a=`?country_code=${o}&range=${c}`;if(c===`custom`&&l.start&&l.end)r=Math.floor(new Date(l.start).getTime()/1e3),i=Math.floor(new Date(l.end).getTime()/1e3),a+=`&start=${r}&end=${i}`;else switch(c){case`10m`:r=n-600;break;case`1h`:r=n-3600;break;case`24h`:r=n-86400;break;case`7d`:r=n-604800;break;case`30d`:r=n-2592e3;break;default:r=n-86400;break}u&&(a+=`&access_point_id=${u}`);let d=!0,f=setTimeout(async()=>{try{let e=await g.queryISPs({profileId:s,countryCode:o,since:r,until:i,accessPointId:u||void 0});if(e&&e.length>0){k.current(o,e),d&&(T(e),D(!1));return}}catch(e){console.warn(`[MapTooltip] Local SQLite ISP query failed, falling back to server:`,e)}_(s,`isps`,a).then(e=>{let t=Array.isArray(e)?e:[];k.current(o,t),d&&T(t)}).catch(e=>{console.error(`Failed to fetch ISPs`,e)}).finally(()=>{d&&D(!1)})},200);return()=>{d=!1,clearTimeout(f)}},[o,s,c,l,u,t]),(0,x.useEffect)(()=>{if(!m)return;let e=e=>{if(y.current&&!y.current.contains(e.target)){let t=e.target,n=t.classList.contains(`rsm-geography`)||t.closest(`.rsm-geography`),r=t.classList.contains(`map-marker-circle`)||t.closest(`.map-marker-circle`);!n&&!r&&h()}},t=setTimeout(()=>{document.addEventListener(`click`,e,!0)},0);return()=>{clearTimeout(t),document.removeEventListener(`click`,e,!0)}},[m,h]),(0,x.useLayoutEffect)(()=>{if(!y.current)return;let e=y.current.getBoundingClientRect(),t=y.current.parentElement;if(!t)return;let n=t.getBoundingClientRect(),r=i,o=e.width/2;i-o<4?r=o+4:i+o>n.width-4&&(r=n.width-o-4);let s=a-10,c=!1;a-e.height-15<4&&(s=a+15,c=!0),S({left:r,top:s,alignBottom:c})},[i,a,w]),(0,C.jsxs)(`div`,{ref:y,onMouseLeave:m?h:void 0,className:`absolute bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm px-3 py-2 rounded-lg shadow-xl border border-gray-200/50 dark:border-slate-800/50 text-xs z-50 flex flex-col gap-1 transition-all duration-75 text-gray-900 dark:text-gray-100 ${m?`pointer-events-auto cursor-default`:`pointer-events-none`}`,style:{left:`${b.left}px`,top:`${b.top}px`,transform:b.alignBottom?`translate(-50%, 0)`:`translate(-50%, -100%)`},children:[(0,C.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,C.jsxs)(`div`,{className:`flex flex-col gap-0.5`,children:[(0,C.jsxs)(`div`,{className:`flex items-center gap-1.5 font-semibold whitespace-nowrap`,children:[(0,C.jsx)(`span`,{className:`text-sm`,children:r}),(0,C.jsx)(`span`,{children:e})]}),(0,C.jsxs)(`div`,{className:`text-gray-500 dark:text-gray-400 whitespace-nowrap`,children:[t.toLocaleString(),` `,v(`analytics.queries`)]})]}),m&&(0,C.jsx)(`button`,{onClick:e=>{e.stopPropagation(),h()},className:`flex items-center justify-center p-2 rounded-lg border border-gray-200 dark:border-slate-800 text-gray-500 hover:text-red-500 hover:bg-red-50 dark:hover:bg-red-950/20 hover:border-red-200 dark:hover:border-red-900/50 transition-colors cursor-pointer self-stretch aspect-square`,title:v(`common.close`,`Close`),children:(0,C.jsx)(f,{size:18})})]}),E?(0,C.jsxs)(`div`,{className:`mt-1.5 pt-1.5 border-t border-gray-150 dark:border-slate-850 flex flex-col gap-1 min-w-36`,children:[(0,C.jsx)(`div`,{className:`text-[10px] uppercase font-bold text-gray-400 dark:text-gray-500 tracking-wider`,children:v(`analytics.topIsps`,`Top ISPs`)}),(0,C.jsx)(`div`,{className:`text-[11px] text-gray-400 dark:text-gray-500 italic`,children:v(`analytics.loading`,`Loading...`)})]}):w.length>0&&(0,C.jsxs)(`div`,{className:`mt-1.5 pt-1.5 border-t border-gray-150 dark:border-slate-800 flex flex-col gap-1`,children:[(0,C.jsx)(`div`,{className:`text-[10px] uppercase font-bold text-gray-400 dark:text-gray-500 tracking-wider`,children:v(`analytics.topIsps`,`Top ISPs`)}),(0,C.jsxs)(`div`,{className:`flex flex-col gap-0.5 min-w-36 max-w-48 ${m?`max-h-36 overflow-y-auto pr-1`:``}`,children:[(m?w:w.slice(0,5)).map(e=>(0,C.jsxs)(`div`,{className:`flex justify-between gap-3 text-[11px] text-gray-600 dark:text-gray-300`,children:[(0,C.jsx)(`span`,{className:`truncate`,title:e.name,children:e.name}),(0,C.jsx)(`span`,{className:`font-mono text-gray-400 dark:text-gray-500`,children:e.count.toLocaleString()})]},e.name)),!m&&w.length>5&&(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(`div`,{className:`text-center text-gray-400 dark:text-gray-500 leading-none py-0.5 font-bold`,children:`...`}),(0,C.jsx)(`div`,{className:`text-[10px] text-center text-blue-500 dark:text-blue-400 font-medium whitespace-nowrap mt-0.5`,children:v(`analytics.pressToShowMore`,`Click to show more`)})]})]})]})]})},D=({geographyData:e,destinationMap:t,getLevel:r,containerRef:a,hoveredCountry:o,setHoveredCountry:s})=>{let{i18n:c}=n();return e?(0,C.jsx)(i,{geography:e,children:({geographies:e})=>e.map(e=>{let n=e.id==null?void 0:v[String(e.id)],i=n?t[n]:null,l=i?.count||0,u=r(l);return(0,C.jsx)(d,{geography:e,onMouseEnter:e=>{if(!n||o?.isPinned)return;let t=y(n,c.language)||i?.name||n,r=b(n),u=a.current?.getBoundingClientRect();s({name:t,code:n,count:l,flag:r,x:e.clientX-(u?.left||0),y:e.clientY-(u?.top||0)-15})},onMouseMove:e=>{s(t=>{if(t?.isPinned)return t;let n=a.current?.getBoundingClientRect(),r=e.clientX-(n?.left||0),i=e.clientY-(n?.top||0)-15;return t?{...t,x:r,y:i}:null})},onMouseLeave:()=>{s(e=>e?.isPinned?e:null)},onClick:e=>{if(e.stopPropagation(),!n)return;let t=y(n,c.language)||i?.name||n,r=b(n),o=a.current?.getBoundingClientRect(),u=e.clientX-(o?.left||0),d=e.clientY-(o?.top||0)-15;s(e=>e?.code===n&&e?.isPinned?null:{name:t,code:n,count:l,flag:r,x:u,y:d,isPinned:!0})},style:{default:{fill:`var(--map-color-${u})`,stroke:`var(--map-stroke)`,strokeWidth:.5,outline:`none`,transition:`fill 250ms, stroke 250ms`},hover:{fill:`var(--map-hover)`,stroke:`var(--map-stroke)`,strokeWidth:.5,outline:`none`,cursor:`pointer`},pressed:{fill:`var(--map-hover)`,stroke:`var(--map-stroke)`,strokeWidth:.5,outline:`none`}}},e.rsmKey)})}):null},O={SG:{name:`Singapore`,coordinates:[103.8198,1.3521]},HK:{name:`Hong Kong`,coordinates:[114.1694,22.3193]},MO:{name:`Macau`,coordinates:[113.5439,22.1987]},VA:{name:`Vatican City`,coordinates:[12.4534,41.9029]},MC:{name:`Monaco`,coordinates:[7.4246,43.7384]},SM:{name:`San Marino`,coordinates:[12.4578,43.9424]},LI:{name:`Liechtenstein`,coordinates:[9.5209,47.141]},AD:{name:`Andorra`,coordinates:[1.5218,42.5063]},MT:{name:`Malta`,coordinates:[14.3754,35.9375]},GI:{name:`Gibraltar`,coordinates:[-5.3536,36.1408]},BM:{name:`Bermuda`,coordinates:[-64.7505,32.3078]},MV:{name:`Maldives`,coordinates:[73.5089,4.1755]},MU:{name:`Mauritius`,coordinates:[57.5522,-20.3484]}},k=({destinationMap:e,getLevel:t,containerRef:r,hoveredCountry:i,setHoveredCountry:a})=>{let{i18n:o}=n();return(0,C.jsx)(C.Fragment,{children:Object.entries(O).map(([n,s])=>{let l=e[n],d=l?.count||0,f=t(d),p=d>0,m=p?4:1.5;return(0,C.jsx)(u,{coordinates:c(s.coordinates[0],s.coordinates[1]),onMouseEnter:e=>{if(i?.isPinned)return;let t=y(n,o.language)||l?.name||n,s=b(n),c=r.current?.getBoundingClientRect();a({name:t,code:n,count:d,flag:s,x:e.clientX-(c?.left||0),y:e.clientY-(c?.top||0)-15})},onMouseMove:e=>{a(t=>{if(t?.isPinned)return t;let n=r.current?.getBoundingClientRect(),i=e.clientX-(n?.left||0),a=e.clientY-(n?.top||0)-15;return t?{...t,x:i,y:a}:null})},onMouseLeave:()=>{a(e=>e?.isPinned?e:null)},onClick:e=>{e.stopPropagation();let t=y(n,o.language)||l?.name||n,i=b(n),s=r.current?.getBoundingClientRect(),c=e.clientX-(s?.left||0),u=e.clientY-(s?.top||0)-15;a(e=>e?.code===n&&e?.isPinned?null:{name:t,code:n,count:d,flag:i,x:c,y:u,isPinned:!0})},children:p?(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(`circle`,{r:m+3,fill:`var(--map-color-${f})`,opacity:.4,className:`animate-ping map-marker-circle`}),(0,C.jsx)(`circle`,{r:m,fill:`var(--map-color-${f})`,stroke:`var(--map-stroke)`,strokeWidth:.75,style:{cursor:`pointer`},className:`map-marker-circle`})]}):(0,C.jsx)(`circle`,{r:m,fill:`var(--text-color)`,opacity:.25,style:{pointerEvents:`none`}})},n)})})},A=({destinations:e,profileId:t,range:n,customRange:r,accessPointId:i})=>{let{geographyData:o,destinationMap:u,scaleConfig:d,getLevel:f,formatNumber:p}=S(e),[m,h]=(0,x.useState)({coordinates:c(0,0),zoom:1.2}),[g,_]=(0,x.useState)(null),[v,y]=(0,x.useState)(null),[b,O]=(0,x.useState)({}),A=(0,x.useRef)(null);A.current=g,(0,x.useEffect)(()=>{if(!g){y(null);return}if(g.isPinned){y(g);return}if(v&&v.code===g.code)return;let e=setTimeout(()=>{A.current&&A.current.code===g.code&&y(A.current)},100);return()=>clearTimeout(e)},[g?.code,g?.isPinned,v?.code]),(0,x.useEffect)(()=>{g&&v&&g.code===v.code&&(g.x!==v.x||g.y!==v.y||g.isPinned!==v.isPinned)&&y(g)},[g?.x,g?.y,g?.isPinned,v]);let j=(0,x.useRef)(null);x.useEffect(()=>{O({})},[t,n,r,i]);let M=x.useCallback((e,t)=>{O(n=>({...n,[e]:t}))},[]),N=x.useMemo(()=>l(c(-100,-50),c(900,600)),[]);return(0,C.jsxs)(`div`,{className:`relative w-full min-h-85 max-h-120 aspect-800/566 bg-gray-50 dark:bg-slate-950 rounded-xl overflow-hidden border border-gray-100 dark:border-slate-800 flex flex-col justify-between shadow-sm`,children:[(0,C.jsxs)(`div`,{ref:j,className:`relative w-full flex-1 min-h-0 overflow-hidden select-none cursor-grab active:cursor-grabbing`,onClick:e=>{(e.target===e.currentTarget||e.target.tagName===`svg`)&&_(null)},children:[(0,C.jsx)(a,{projection:`geoEqualEarth`,width:800,height:566,style:{width:`100%`,height:`100%`},children:(0,C.jsxs)(s,{zoom:m.zoom,center:m.coordinates,onMoveEnd:e=>h({coordinates:c(e.coordinates[0],e.coordinates[1]),zoom:e.zoom}),maxZoom:8,minZoom:1,enablePan:!0,translateExtent:N,children:[(0,C.jsx)(D,{geographyData:o,destinationMap:u,getLevel:f,containerRef:j,hoveredCountry:g,setHoveredCountry:_}),(0,C.jsx)(k,{destinationMap:u,getLevel:f,containerRef:j,hoveredCountry:g,setHoveredCountry:_})]})}),v&&(0,C.jsx)(E,{name:v.name,count:v.count,flag:v.flag,x:v.x,y:v.y,countryCode:v.code,profileId:t,range:n,customRange:r,accessPointId:i,ispCache:b,onCacheIsp:M,isPinned:v.isPinned||!1,onClose:()=>_(null)})]}),(0,C.jsx)(w,{onZoomIn:()=>{m.zoom>=8||h(e=>({...e,zoom:e.zoom*1.5}))},onZoomOut:()=>{m.zoom<=1||h(e=>({...e,zoom:e.zoom/1.5}))},onReset:()=>{h({coordinates:c(0,0),zoom:1.2})}}),(0,C.jsx)(T,{maxThreshold:d.maxThreshold,formatNumber:p})]})};export{A as DestinationMap};
|
|
1
|
+
import{i as e}from"./rolldown-runtime-C4Xdq4VV.js";import{L as t,Qt as n,_ as r,d as i,f as a,g as o,i as s,m as c,p as l,r as u,u as d,y as f}from"./vendor-react-BmoHsW1x.js";import{S as p,b as m}from"./vendor-icons-other-Bme3ywH9.js";import"./vendor-utils-BWSB0jGn.js";import{k as h,ot as g,z as _}from"./index-dXN_pYn1.js";import{n as v,t as y}from"./formatCountryName-CSBD8pP8.js";import{t as b}from"./getFlagEmoji-DRubsb7D.js";var x=e(p(),1);function S(e){let[t,n]=(0,x.useState)(null);(0,x.useEffect)(()=>{_().then(e=>{if(e&&e.objects){let t={};e.objects.countries&&(t.countries=e.objects.countries),e.objects.land&&(t.land=e.objects.land),e.objects=t}e&&e.objects&&e.objects.countries&&Array.isArray(e.objects.countries.geometries)&&e.objects.countries.geometries.forEach(e=>{e.id!==void 0&&e.id!==null&&(e.id=String(e.id).padStart(3,`0`))}),n(e)}).catch(e=>console.error(`Failed to load map topology`,e))},[]);let r=(0,x.useMemo)(()=>e.reduce((e,t)=>e+t.count,0),[e]),i=(0,x.useMemo)(()=>{if(r<=0)return{maxThreshold:10,step:1};if(r<=1e3)return{maxThreshold:100,step:10};let e=10**Math.floor(Math.log10(r));return{maxThreshold:e,step:e/10}},[r]);return{geographyData:t,destinationMap:(0,x.useMemo)(()=>{let t={};return e.forEach(e=>{if(e.country_code){let n=e.country_code.toUpperCase();t[n]={count:e.count,name:e.country,countryCode:n}}}),t},[e]),scaleConfig:i,getLevel:e=>!e||e<=0?0:Math.min(10,Math.floor(e/i.step)+1),formatNumber:e=>{if(e>=1e6){let t=e/1e6;return Number.isInteger(t)?`${t}M`:`${t.toFixed(1)}M`}if(e>=1e3){let t=e/1e3;return Number.isInteger(t)?`${t}K`:`${t.toFixed(1)}K`}return e.toString()}}}var C=e(m(),1);const w=({onZoomIn:e,onZoomOut:n,onReset:i})=>(0,C.jsxs)(`div`,{className:`absolute top-3 right-3 flex flex-col gap-1.5 bg-white/80 dark:bg-slate-950/80 backdrop-blur-md p-1.5 rounded-lg border border-gray-200/50 dark:border-slate-800/50 shadow-sm z-10`,children:[(0,C.jsx)(`button`,{type:`button`,onClick:e,className:`p-1.5 hover:bg-gray-100 dark:hover:bg-slate-800 rounded text-gray-600 dark:text-gray-300 transition-colors cursor-pointer`,title:`Zoom In`,children:(0,C.jsx)(r,{size:16})}),(0,C.jsx)(`button`,{type:`button`,onClick:n,className:`p-1.5 hover:bg-gray-100 dark:hover:bg-slate-800 rounded text-gray-600 dark:text-gray-300 transition-colors cursor-pointer`,title:`Zoom Out`,children:(0,C.jsx)(o,{size:16})}),(0,C.jsx)(`button`,{type:`button`,onClick:i,className:`p-1.5 hover:bg-gray-100 dark:hover:bg-slate-800 rounded text-gray-600 dark:text-gray-300 transition-colors cursor-pointer`,title:`Reset Zoom`,children:(0,C.jsx)(t,{size:16})})]}),T=({maxThreshold:e,formatNumber:t})=>{let{t:r}=n();return(0,C.jsxs)(`div`,{className:`sm:absolute sm:bottom-3 sm:left-3 relative m-3 sm:m-0 flex flex-col shrink-0 gap-1.5 bg-white/80 dark:bg-slate-950/80 backdrop-blur-md p-2 rounded-lg border border-gray-200/50 dark:border-slate-800/50 shadow-sm z-10 max-w-70`,children:[(0,C.jsx)(`span`,{className:`text-[9px] font-bold text-gray-500 dark:text-gray-400 uppercase tracking-wider`,children:r(`analytics.queries`)}),(0,C.jsx)(`div`,{className:`flex items-center gap-0.5`,children:Array.from({length:11}).map((e,t)=>(0,C.jsx)(`div`,{className:`w-4 h-2.5 rounded-sm border border-black/5 dark:border-white/5`,style:{backgroundColor:`var(--map-color-${t})`}},t))}),(0,C.jsxs)(`div`,{className:`flex justify-between text-[9px] text-gray-500 dark:text-gray-400 font-semibold px-0.5`,children:[(0,C.jsx)(`span`,{children:`0`}),(0,C.jsx)(`span`,{children:t(e/2)}),(0,C.jsxs)(`span`,{children:[t(e),`+`]})]})]})},E=({name:e,count:t,flag:r,x:i,y:a,countryCode:o,profileId:s,range:c,customRange:l,accessPointId:u,ispCache:d,onCacheIsp:p,isPinned:m,onClose:_})=>{let{t:v}=n(),y=(0,x.useRef)(null),[b,S]=(0,x.useState)({left:i,top:a-10,alignBottom:!1}),[w,T]=(0,x.useState)([]),[E,D]=(0,x.useState)(!1),O=(0,x.useRef)(d);O.current=d;let k=(0,x.useRef)(p);return k.current=p,(0,x.useEffect)(()=>{if(!o||!s)return;if(t<=0){T([]),D(!1);return}let e=O.current[o];if(e){T(e),D(!1);return}D(!0);let n=Math.floor(Date.now()/1e3),r,i=n,a=`?country_code=${o}&range=${c}`;if(c===`custom`&&l.start&&l.end)r=Math.floor(new Date(l.start).getTime()/1e3),i=Math.floor(new Date(l.end).getTime()/1e3),a+=`&start=${r}&end=${i}`;else switch(c){case`10m`:r=n-600;break;case`1h`:r=n-3600;break;case`24h`:r=n-86400;break;case`7d`:r=n-604800;break;case`30d`:r=n-2592e3;break;default:r=n-86400;break}u&&(a+=`&access_point_id=${u}`);let d=!0,f=setTimeout(async()=>{try{let e=await h.queryISPs({profileId:s,countryCode:o,since:r,until:i,accessPointId:u||void 0});if(e&&e.length>0){k.current(o,e),d&&(T(e),D(!1));return}}catch(e){console.warn(`[MapTooltip] Local SQLite ISP query failed, falling back to server:`,e)}g(s,`isps`,a).then(e=>{let t=Array.isArray(e)?e:[];k.current(o,t),d&&T(t)}).catch(e=>{console.error(`Failed to fetch ISPs`,e)}).finally(()=>{d&&D(!1)})},200);return()=>{d=!1,clearTimeout(f)}},[o,s,c,l,u,t]),(0,x.useEffect)(()=>{if(!m)return;let e=e=>{if(y.current&&!y.current.contains(e.target)){let t=e.target,n=t.classList.contains(`rsm-geography`)||t.closest(`.rsm-geography`),r=t.classList.contains(`map-marker-circle`)||t.closest(`.map-marker-circle`);!n&&!r&&_()}},t=setTimeout(()=>{document.addEventListener(`click`,e,!0)},0);return()=>{clearTimeout(t),document.removeEventListener(`click`,e,!0)}},[m,_]),(0,x.useLayoutEffect)(()=>{if(!y.current)return;let e=y.current.getBoundingClientRect(),t=y.current.parentElement;if(!t)return;let n=t.getBoundingClientRect(),r=i,o=e.width/2;i-o<4?r=o+4:i+o>n.width-4&&(r=n.width-o-4);let s=a-10,c=!1;a-e.height-15<4&&(s=a+15,c=!0),S({left:r,top:s,alignBottom:c})},[i,a,w]),(0,C.jsxs)(`div`,{ref:y,onMouseLeave:m?_:void 0,className:`absolute bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm px-3 py-2 rounded-lg shadow-xl border border-gray-200/50 dark:border-slate-800/50 text-xs z-50 flex flex-col gap-1 transition-all duration-75 text-gray-900 dark:text-gray-100 ${m?`pointer-events-auto cursor-default`:`pointer-events-none`}`,style:{left:`${b.left}px`,top:`${b.top}px`,transform:b.alignBottom?`translate(-50%, 0)`:`translate(-50%, -100%)`},children:[(0,C.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,C.jsxs)(`div`,{className:`flex flex-col gap-0.5`,children:[(0,C.jsxs)(`div`,{className:`flex items-center gap-1.5 font-semibold whitespace-nowrap`,children:[(0,C.jsx)(`span`,{className:`text-sm`,children:r}),(0,C.jsx)(`span`,{children:e})]}),(0,C.jsxs)(`div`,{className:`text-gray-500 dark:text-gray-400 whitespace-nowrap`,children:[t.toLocaleString(),` `,v(`analytics.queries`)]})]}),m&&(0,C.jsx)(`button`,{onClick:e=>{e.stopPropagation(),_()},className:`flex items-center justify-center p-2 rounded-lg border border-gray-200 dark:border-slate-800 text-gray-500 hover:text-red-500 hover:bg-red-50 dark:hover:bg-red-950/20 hover:border-red-200 dark:hover:border-red-900/50 transition-colors cursor-pointer self-stretch aspect-square`,title:v(`common.close`,`Close`),children:(0,C.jsx)(f,{size:18})})]}),E?(0,C.jsxs)(`div`,{className:`mt-1.5 pt-1.5 border-t border-gray-150 dark:border-slate-850 flex flex-col gap-1 min-w-36`,children:[(0,C.jsx)(`div`,{className:`text-[10px] uppercase font-bold text-gray-400 dark:text-gray-500 tracking-wider`,children:v(`analytics.topIsps`,`Top ISPs`)}),(0,C.jsx)(`div`,{className:`text-[11px] text-gray-400 dark:text-gray-500 italic`,children:v(`analytics.loading`,`Loading...`)})]}):w.length>0&&(0,C.jsxs)(`div`,{className:`mt-1.5 pt-1.5 border-t border-gray-150 dark:border-slate-800 flex flex-col gap-1`,children:[(0,C.jsx)(`div`,{className:`text-[10px] uppercase font-bold text-gray-400 dark:text-gray-500 tracking-wider`,children:v(`analytics.topIsps`,`Top ISPs`)}),(0,C.jsxs)(`div`,{className:`flex flex-col gap-0.5 min-w-36 max-w-48 ${m?`max-h-36 overflow-y-auto pr-1`:``}`,children:[(m?w:w.slice(0,5)).map(e=>(0,C.jsxs)(`div`,{className:`flex justify-between gap-3 text-[11px] text-gray-600 dark:text-gray-300`,children:[(0,C.jsx)(`span`,{className:`truncate`,title:e.name,children:e.name}),(0,C.jsx)(`span`,{className:`font-mono text-gray-400 dark:text-gray-500`,children:e.count.toLocaleString()})]},e.name)),!m&&w.length>5&&(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(`div`,{className:`text-center text-gray-400 dark:text-gray-500 leading-none py-0.5 font-bold`,children:`...`}),(0,C.jsx)(`div`,{className:`text-[10px] text-center text-blue-500 dark:text-blue-400 font-medium whitespace-nowrap mt-0.5`,children:v(`analytics.pressToShowMore`,`Click to show more`)})]})]})]})]})},D=({geographyData:e,destinationMap:t,getLevel:r,containerRef:a,hoveredCountry:o,setHoveredCountry:s})=>{let{i18n:c}=n();return e?(0,C.jsx)(i,{geography:e,children:({geographies:e})=>e.map(e=>{let n=e.id==null?void 0:v[String(e.id)],i=n?t[n]:null,l=i?.count||0,u=r(l);return(0,C.jsx)(d,{geography:e,onMouseEnter:e=>{if(!n||o?.isPinned)return;let t=y(n,c.language)||i?.name||n,r=b(n),u=a.current?.getBoundingClientRect();s({name:t,code:n,count:l,flag:r,x:e.clientX-(u?.left||0),y:e.clientY-(u?.top||0)-15})},onMouseMove:e=>{s(t=>{if(t?.isPinned)return t;let n=a.current?.getBoundingClientRect(),r=e.clientX-(n?.left||0),i=e.clientY-(n?.top||0)-15;return t?{...t,x:r,y:i}:null})},onMouseLeave:()=>{s(e=>e?.isPinned?e:null)},onClick:e=>{if(e.stopPropagation(),!n)return;let t=y(n,c.language)||i?.name||n,r=b(n),o=a.current?.getBoundingClientRect(),u=e.clientX-(o?.left||0),d=e.clientY-(o?.top||0)-15;s(e=>e?.code===n&&e?.isPinned?null:{name:t,code:n,count:l,flag:r,x:u,y:d,isPinned:!0})},style:{default:{fill:`var(--map-color-${u})`,stroke:`var(--map-stroke)`,strokeWidth:.5,outline:`none`,transition:`fill 250ms, stroke 250ms`},hover:{fill:`var(--map-hover)`,stroke:`var(--map-stroke)`,strokeWidth:.5,outline:`none`,cursor:`pointer`},pressed:{fill:`var(--map-hover)`,stroke:`var(--map-stroke)`,strokeWidth:.5,outline:`none`}}},e.rsmKey)})}):null},O={SG:{name:`Singapore`,coordinates:[103.8198,1.3521]},HK:{name:`Hong Kong`,coordinates:[114.1694,22.3193]},MO:{name:`Macau`,coordinates:[113.5439,22.1987]},VA:{name:`Vatican City`,coordinates:[12.4534,41.9029]},MC:{name:`Monaco`,coordinates:[7.4246,43.7384]},SM:{name:`San Marino`,coordinates:[12.4578,43.9424]},LI:{name:`Liechtenstein`,coordinates:[9.5209,47.141]},AD:{name:`Andorra`,coordinates:[1.5218,42.5063]},MT:{name:`Malta`,coordinates:[14.3754,35.9375]},GI:{name:`Gibraltar`,coordinates:[-5.3536,36.1408]},BM:{name:`Bermuda`,coordinates:[-64.7505,32.3078]},MV:{name:`Maldives`,coordinates:[73.5089,4.1755]},MU:{name:`Mauritius`,coordinates:[57.5522,-20.3484]}},k=({destinationMap:e,getLevel:t,containerRef:r,hoveredCountry:i,setHoveredCountry:a})=>{let{i18n:o}=n();return(0,C.jsx)(C.Fragment,{children:Object.entries(O).map(([n,s])=>{let l=e[n],d=l?.count||0,f=t(d),p=d>0,m=p?4:1.5;return(0,C.jsx)(u,{coordinates:c(s.coordinates[0],s.coordinates[1]),onMouseEnter:e=>{if(i?.isPinned)return;let t=y(n,o.language)||l?.name||n,s=b(n),c=r.current?.getBoundingClientRect();a({name:t,code:n,count:d,flag:s,x:e.clientX-(c?.left||0),y:e.clientY-(c?.top||0)-15})},onMouseMove:e=>{a(t=>{if(t?.isPinned)return t;let n=r.current?.getBoundingClientRect(),i=e.clientX-(n?.left||0),a=e.clientY-(n?.top||0)-15;return t?{...t,x:i,y:a}:null})},onMouseLeave:()=>{a(e=>e?.isPinned?e:null)},onClick:e=>{e.stopPropagation();let t=y(n,o.language)||l?.name||n,i=b(n),s=r.current?.getBoundingClientRect(),c=e.clientX-(s?.left||0),u=e.clientY-(s?.top||0)-15;a(e=>e?.code===n&&e?.isPinned?null:{name:t,code:n,count:d,flag:i,x:c,y:u,isPinned:!0})},children:p?(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(`circle`,{r:m+3,fill:`var(--map-color-${f})`,opacity:.4,className:`animate-ping map-marker-circle`}),(0,C.jsx)(`circle`,{r:m,fill:`var(--map-color-${f})`,stroke:`var(--map-stroke)`,strokeWidth:.75,style:{cursor:`pointer`},className:`map-marker-circle`})]}):(0,C.jsx)(`circle`,{r:m,fill:`var(--text-color)`,opacity:.25,style:{pointerEvents:`none`}})},n)})})},A=({destinations:e,profileId:t,range:n,customRange:r,accessPointId:i})=>{let{geographyData:o,destinationMap:u,scaleConfig:d,getLevel:f,formatNumber:p}=S(e),[m,h]=(0,x.useState)({coordinates:c(0,0),zoom:1.2}),[g,_]=(0,x.useState)(null),[v,y]=(0,x.useState)(null),[b,O]=(0,x.useState)({}),A=(0,x.useRef)(null);A.current=g,(0,x.useEffect)(()=>{if(!g){y(null);return}if(g.isPinned){y(g);return}if(v&&v.code===g.code)return;let e=setTimeout(()=>{A.current&&A.current.code===g.code&&y(A.current)},100);return()=>clearTimeout(e)},[g?.code,g?.isPinned,v?.code]),(0,x.useEffect)(()=>{g&&v&&g.code===v.code&&(g.x!==v.x||g.y!==v.y||g.isPinned!==v.isPinned)&&y(g)},[g?.x,g?.y,g?.isPinned,v]);let j=(0,x.useRef)(null);x.useEffect(()=>{O({})},[t,n,r,i]);let M=x.useCallback((e,t)=>{O(n=>({...n,[e]:t}))},[]),N=x.useMemo(()=>l(c(-100,-50),c(900,600)),[]);return(0,C.jsxs)(`div`,{className:`relative w-full min-h-85 max-h-120 aspect-800/566 bg-gray-50 dark:bg-slate-950 rounded-xl overflow-hidden border border-gray-100 dark:border-slate-800 flex flex-col justify-between shadow-sm`,children:[(0,C.jsxs)(`div`,{ref:j,className:`relative w-full flex-1 min-h-0 overflow-hidden select-none cursor-grab active:cursor-grabbing`,onClick:e=>{(e.target===e.currentTarget||e.target.tagName===`svg`)&&_(null)},children:[(0,C.jsx)(a,{projection:`geoEqualEarth`,width:800,height:566,style:{width:`100%`,height:`100%`},children:(0,C.jsxs)(s,{zoom:m.zoom,center:m.coordinates,onMoveEnd:e=>h({coordinates:c(e.coordinates[0],e.coordinates[1]),zoom:e.zoom}),maxZoom:8,minZoom:1,enablePan:!0,translateExtent:N,children:[(0,C.jsx)(D,{geographyData:o,destinationMap:u,getLevel:f,containerRef:j,hoveredCountry:g,setHoveredCountry:_}),(0,C.jsx)(k,{destinationMap:u,getLevel:f,containerRef:j,hoveredCountry:g,setHoveredCountry:_})]})}),v&&(0,C.jsx)(E,{name:v.name,count:v.count,flag:v.flag,x:v.x,y:v.y,countryCode:v.code,profileId:t,range:n,customRange:r,accessPointId:i,ispCache:b,onCacheIsp:M,isPinned:v.isPinned||!1,onClose:()=>_(null)})]}),(0,C.jsx)(w,{onZoomIn:()=>{m.zoom>=8||h(e=>({...e,zoom:e.zoom*1.5}))},onZoomOut:()=>{m.zoom<=1||h(e=>({...e,zoom:e.zoom/1.5}))},onReset:()=>{h({coordinates:c(0,0),zoom:1.2})}}),(0,C.jsx)(T,{maxThreshold:d.maxThreshold,formatNumber:p})]})};export{A as DestinationMap};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{i as e}from"./rolldown-runtime-C4Xdq4VV.js";import{C as t,F as n,Mt as r,Qt as i,R as a,at as o,k as s,lt as c}from"./vendor-react-BmoHsW1x.js";import{S as l,b as u}from"./vendor-icons-other-Bme3ywH9.js";import{C as d,E as f,H as p,N as m,O as h,S as g,T as _,V as v,f as y,h as b,r as x,u as S,w as C,x as w}from"./vendor-ui-core-CY_WyMIf.js";import{_t as T}from"./vendor-utils-BWSB0jGn.js";import{Q as E,V as D,X as O,_t as k,ct as A,et as j,ln as M,q as N,w as P,yt as F}from"./index-dXN_pYn1.js";var I=e(l(),1);const L=()=>{let{t:e}=i(),[t,n]=(0,I.useState)([]);return(0,I.useEffect)(()=>{D().then(t=>{t&&Array.isArray(t)&&n(t.map(t=>({label:e(t.label),url:t.url})))}).catch(e=>console.warn(`Failed to fetch preset filters from API`,e))},[e]),t};var R=e(u(),1);const z=({newUrl:e,setNewUrl:t,onAddList:n,syncing:r,loading:a,lists:o})=>{let{t:s}=i(),c=(0,R.jsx)(f,{className:`min-w-96`,children:L().map((e,t)=>(0,R.jsx)(C,{text:e.label,onClick:()=>n(e.url),disabled:o.some(t=>t.url===e.url),labelElement:(0,R.jsx)(`div`,{className:`flex flex-col items-end text-right`,children:(0,R.jsx)(`span`,{className:`text-[9px] opacity-85 max-w-xl truncate`,title:e.url,children:e.url})})},t))});return(0,R.jsx)(w,{elevation:p.ONE,className:`mb-6`,children:(0,R.jsxs)(`div`,{className:`flex gap-2 flex-col sm:flex-row`,children:[(0,R.jsx)(y,{fill:!0,size:`large`,placeholder:s(`filtering.urlPlaceholder`),value:e,onChange:e=>t(e.target.value),leftIcon:`globe`,rightElement:(0,R.jsx)(_,{content:c,placement:`bottom-end`,animation:`minimal`,arrow:!1,usePortal:!0,children:(0,R.jsx)(m,{variant:`minimal`,icon:`chevron-down`})})}),(0,R.jsx)(m,{intent:v.PRIMARY,size:`large`,icon:`plus`,onClick:()=>n(),className:`shrink-0`,loading:r||a,disabled:r||a,children:s(`filtering.addSubscription`)})]})})},B=({lists:e,onSelect:t})=>{let{t:n}=i(),r=[{key:`url`,header:n(`filtering.tableUrl`),cellClassName:`font-mono text-sm max-w-md truncate`,render:e=>e.url},{key:`lastSync`,header:n(`filtering.tableLastSync`),cellClassName:`text-xs opacity-60`,render:e=>e.last_synced_at?P(new Date(e.last_synced_at*1e3)):n(`filtering.neverSynced`)},{key:`status`,header:n(`filtering.tableStatus`),render:e=>{if(!e.enabled)return(0,R.jsx)(x,{intent:v.NONE,minimal:!0,children:n(`filtering.statusDisabled`,`Disabled`)});let t=!!e.sync_error,r=!!e.last_synced_at,i=n(`filtering.statusNormal`,`Active`),a=v.SUCCESS;return t&&(r?(i=n(`filtering.statusOutdated`,`Outdated`),a=v.WARNING):(i=n(`filtering.statusMissing`,`Missing`),a=v.DANGER)),(0,R.jsx)(x,{intent:a,minimal:!0,children:i})}}];return(0,R.jsx)(`div`,{className:`w-full max-w-full overflow-x-auto pb-4`,children:(0,R.jsxs)(S,{interactive:!0,striped:!0,className:`w-full min-w-max whitespace-nowrap`,children:[(0,R.jsx)(`thead`,{children:(0,R.jsx)(`tr`,{children:r.map(e=>(0,R.jsx)(`th`,{className:e.headerClassName,children:e.header},e.key))})}),(0,R.jsx)(`tbody`,{children:e.map(e=>(0,R.jsx)(`tr`,{onClick:()=>t(e),className:`cursor-pointer`,children:r.map(t=>(0,R.jsx)(`td`,{className:t.cellClassName,children:t.render(e)},t.key))},e.id))})]})})},V=({profileId:e,selectedList:r,onClose:a,onCopy:l,onDelete:u,onToggleEnabled:d,onAllowDomain:f})=>{let{t:p}=i(),[_,S]=(0,I.useState)(``),[C,w]=(0,I.useState)(!1),[T,D]=(0,I.useState)(null),[O,k]=(0,I.useState)(null),[A,j]=(0,I.useState)(!1),[M,N]=(0,I.useState)(!1),[F,L]=(0,I.useState)(!1),z=(0,I.useRef)(0),B=()=>{z.current++,w(!1),S(``),D(null),k(null),N(!1)},V=async()=>{let t=_.trim().toLowerCase();if(!t||!r||(t=t.replace(/^https?:\/\//,``).split(`/`)[0].split(`:`)[0].replace(/\.+$/,``),!t))return;S(t);let n=++z.current,i=r.id;w(!0),k(null),D(null),N(!1);try{let r=await E(e,i,t);z.current===n&&D(r)}catch(e){z.current===n&&k(e instanceof Error?e.message:String(e))}finally{z.current===n&&w(!1)}},H=async e=>{if(r){L(!0);try{await d(r.id,e)}finally{L(!1)}}},U=async()=>{if(T?.matchedEntry){j(!0);try{await f(T.domain),N(!0)}catch(e){k(e instanceof Error?e.message:String(e))}finally{j(!1)}}};return(0,R.jsxs)(h,{isOpen:r!==null,onClose:()=>{B(),a()},title:p(`filtering.listDetails`,`List Details`),icon:`info-sign`,children:[(0,R.jsxs)(`div`,{className:`p-6 space-y-4`,children:[r?.sync_error&&(0,R.jsx)(g,{intent:v.WARNING,title:p(`filtering.syncError`),icon:`warning-sign`,children:r.sync_error}),(0,R.jsx)(`div`,{className:`bg-gray-50 dark:bg-gray-800 p-4 rounded-lg border border-gray-200 dark:border-gray-700 break-all font-mono text-sm`,children:r?.url}),(0,R.jsxs)(`div`,{className:`flex items-center justify-between border border-gray-200 dark:border-gray-700 rounded-lg p-3`,children:[(0,R.jsxs)(`div`,{children:[(0,R.jsx)(`div`,{className:`text-sm font-bold`,children:p(`filtering.listEnabled`,`List active`)}),(0,R.jsx)(`div`,{className:`text-xs opacity-60`,children:p(`filtering.listEnabledHint`,`Disable to stop filtering with this list without deleting it. Its subscription and sync history are kept.`)})]}),(0,R.jsx)(b,{large:!0,checked:!!r?.enabled,disabled:F,onChange:e=>H(e.target.checked)})]}),(0,R.jsxs)(`div`,{className:`border border-gray-200 dark:border-gray-700 rounded-lg p-3 space-y-3`,children:[(0,R.jsxs)(`div`,{children:[(0,R.jsx)(`div`,{className:`text-sm font-bold`,children:p(`filtering.checkDomain`,`Check a domain`)}),(0,R.jsx)(`div`,{className:`text-xs opacity-60`,children:p(`filtering.checkDomainHint`,`Lists are stored as compact filters, so their entries cannot be browsed. You can test any domain against this list instantly.`)})]}),(0,R.jsxs)(`div`,{className:`flex gap-2`,children:[(0,R.jsx)(y,{fill:!0,placeholder:`example.com`,value:_,disabled:C,leftIcon:`globe-network`,onChange:e=>{S(e.target.value),D(null)},onKeyDown:e=>{e.key===`Enter`&&V()}}),(0,R.jsx)(m,{icon:(0,R.jsx)(n,{size:14}),text:p(`filtering.check`,`Check`),loading:C,disabled:!_.trim(),onClick:()=>void V()})]}),O&&(0,R.jsx)(g,{intent:v.DANGER,className:`text-xs`,children:O}),T&&!T.synced&&(0,R.jsx)(g,{intent:v.WARNING,className:`text-xs`,children:p(`filtering.checkNotSynced`,`This list has not finished syncing yet, so there is nothing to check against.`)}),T?.synced&&T.enabled===!1&&(0,R.jsx)(g,{intent:v.NONE,className:`text-xs`,children:p(`filtering.checkListDisabled`,`This list is currently disabled, so it is not filtering anything right now.`)}),T?.synced&&(0,R.jsx)(g,{intent:T.blocked?v.WARNING:v.SUCCESS,className:`text-xs`,icon:T.blocked?`ban-circle`:`tick-circle`,children:T.blocked?(0,R.jsxs)(`div`,{className:`space-y-2`,children:[(0,R.jsxs)(`div`,{children:[p(`filtering.checkBlocked`,`Blocked by this list`),T.matchedEntry&&T.matchedEntry!==T.domain&&(0,R.jsxs)(R.Fragment,{children:[` `,(0,R.jsx)(x,{minimal:!0,className:`font-mono`,children:T.matchedEntry}),` `,p(`filtering.checkViaParent`,`(matched a parent domain)`)]})]}),(0,R.jsx)(`div`,{className:`opacity-75`,children:T.falsePositiveRate?p(`filtering.checkProbabilisticRate`,{defaultValue:`Filters are probabilistic: roughly 1 match in {{odds}} is a false positive. Adding an exception also covers every subdomain of it.`,odds:Math.round(1/T.falsePositiveRate).toLocaleString()}):p(`filtering.checkProbabilistic`,`Filters are probabilistic, so a small share of matches are false positives. Adding an exception also covers every subdomain of it.`)}),M?(0,R.jsx)(x,{intent:v.SUCCESS,minimal:!0,children:p(`filtering.checkAllowed`,`Exception added - this domain now resolves`)}):(0,R.jsx)(m,{small:!0,icon:(0,R.jsx)(s,{size:12}),intent:v.PRIMARY,loading:A,text:p(`filtering.checkAllowAction`,`Allow anyway`),onClick:()=>void U()})]}):p(`filtering.checkNotBlocked`,`Not blocked by this list`)})]}),(0,R.jsxs)(`div`,{className:`flex justify-between items-center`,children:[(0,R.jsxs)(`span`,{className:`text-xs opacity-50`,children:[p(`filtering.tableLastSync`),`:`,` `,r?.last_synced_at?P(new Date(r.last_synced_at*1e3)):`-`]}),(0,R.jsxs)(`div`,{className:`flex gap-2`,children:[(0,R.jsx)(m,{icon:(0,R.jsx)(c,{size:14}),text:p(`setup.copyUrl`,`Copy link`),onClick:()=>{r&&l(r.url)}}),(0,R.jsx)(m,{icon:(0,R.jsx)(o,{size:14}),text:p(`setup.learnMore`,`Open link`),onClick:()=>{r&&window.open(r.url,`_blank`)}})]})]})]}),(0,R.jsxs)(`div`,{className:`p-4 border-t border-gray-100 dark:border-gray-800 flex justify-between`,children:[(0,R.jsx)(m,{icon:(0,R.jsx)(t,{size:14}),intent:v.DANGER,text:p(`rules.delete`,`Delete`),onClick:()=>{if(!r)return;let e=r.id;B(),u(e)}}),(0,R.jsx)(m,{onClick:()=>{B(),a()},text:p(`rules.close`,`Close`)})]})]})},H=({profileId:e,toasterRef:t})=>{let n=r(),o=M(),[s,c]=(0,I.useState)([]),[l,u]=(0,I.useState)(``),[f,p]=(0,I.useState)(!0),[h,_]=(0,I.useState)(!1),{t:y}=i(),[b,x]=(0,I.useState)(null),S=async()=>{p(!0);try{c(await A(e))}catch(e){console.error(`Failed to fetch filters`,e)}finally{p(!1)}},C=e=>{navigator.clipboard.writeText(e),t?.current?.show({message:y(`setup.copied`,`已复制到剪贴板`),intent:v.SUCCESS,icon:`duplicate`})},w=async t=>{let n=new Map(t.map(e=>[e.id,e.last_synced_at])),r=0;for(;r<15;){await new Promise(e=>setTimeout(e,2e3));try{let t=await A(e),r=!0;for(let e of t){if(n.has(e.id)&&e.last_synced_at===n.get(e.id)){r=!1;break}if(!n.has(e.id)&&!e.last_synced_at){r=!1;break}}if(r&&t.length>0)return c(t),!0}catch{}r++}return await S(),!1};return(0,I.useEffect)(()=>{S()},[e]),(0,R.jsxs)(`div`,{className:T(`md:px-8 w-full min-w-0 max-w-5xl mx-auto`,o?`p-1`:`px-8`),children:[(0,R.jsxs)(`div`,{className:`mb-8 flex flex-col md:flex-row justify-between items-start md:items-end gap-4`,children:[(0,R.jsxs)(`div`,{className:`w-full md:w-auto flex-1`,children:[o?(0,R.jsxs)(d,{minimal:!0,fill:o,children:[(0,R.jsx)(m,{active:!1,onClick:()=>n(`/dash/${e}/rules`),text:y(`rules.title`),large:!0}),(0,R.jsx)(m,{active:!0,onClick:()=>n(`/dash/${e}/filter`),text:y(`filtering.title`),large:!0})]}):(0,R.jsx)(`h1`,{className:`bp6-heading`,children:y(`rules.title`)}),(0,R.jsx)(`p`,{className:`bp6-text-muted mt-2!`,children:y(`filtering.subtitle`)})]}),(0,R.jsx)(m,{icon:(0,R.jsx)(a,{size:16}),text:y(`filtering.syncAll`),onClick:async()=>{_(!0);try{await k(e),t?.current?.show({message:y(`filtering.syncTaskStarted`),intent:v.PRIMARY,icon:`cloud-download`}),await w(s)&&t?.current?.show({message:y(`filtering.syncCheckComplete`),intent:v.SUCCESS,icon:`tick`})}catch(e){console.error(e)}finally{_(!1)}},loading:h||f,disabled:h||f||s.length===0,className:o?`w-full`:``})]}),(0,R.jsx)(g,{intent:v.WARNING,icon:`info-sign`,className:`mb-6`,children:(0,R.jsx)(`p`,{children:y(`filtering.formatDisclaimer`,`本系统只支持有限的 AdGuard 格式列表和纯域名列表。仅支持基础的拦截规则(如 ||example.com^),会绕过 "@@" 白名单,暂不支持 "$" 重写规则以及 "*" 省略规则。系统会自动匹配域名的所有子域名。`)})}),(0,R.jsx)(z,{newUrl:l,setNewUrl:u,onAddList:async n=>{let r=n||l;if(r){_(!0);try{await N(e,r),t?.current?.show({message:y(`filtering.addSuccess`),intent:v.SUCCESS,icon:`tick`}),u(``),t?.current?.show({message:y(`filtering.syncTaskStarted`),intent:v.PRIMARY,icon:`cloud-download`}),await w(s)&&t?.current?.show({message:y(`filtering.syncCheckComplete`),intent:v.SUCCESS,icon:`tick`})}catch(e){console.error(e)}finally{_(!1)}}},syncing:h,loading:f,lists:s}),(0,R.jsx)(B,{lists:s,onSelect:x}),(0,R.jsx)(V,{profileId:e,selectedList:b,onClose:()=>x(null),onCopy:C,onDelete:async n=>{try{await j(e,n),t?.current?.show({message:y(`filtering.deleteSuccess`),intent:v.PRIMARY,icon:`trash`}),x(null),await S()}catch(e){console.error(e)}},onToggleEnabled:async(n,r)=>{try{await F(e,n,r),x(e=>e&&e.id===n?{...e,enabled:r}:e),t?.current?.show({message:r?y(`filtering.listEnabledToast`,`List enabled - rebuilding filter`):y(`filtering.listDisabledToast`,`List disabled - rebuilding filter`),intent:v.PRIMARY,icon:r?`tick`:`disable`}),await S()}catch(e){console.error(e),t?.current?.show({message:e instanceof Error?e.message:String(e),intent:v.DANGER,icon:`error`})}},onAllowDomain:async n=>{await O(e,{type:`ALLOW`,pattern:n}),t?.current?.show({message:y(`filtering.allowRuleAdded`,`Exception added for {{domain}}`,{domain:n}),intent:v.SUCCESS,icon:`tick`})}})]})};export{H as FilteringView};
|