dns-worker 1.1.5 → 1.1.6
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/LICENSE +154 -155
- package/README.md +1 -3
- package/dist/serverfull.mjs +49 -49
- package/dist/serverfull.mjs.map +4 -4
- package/package.json +7 -3
- package/static/assets/AccountView-DIeqrGlp.js +4 -0
- package/static/assets/AnalyticsView-BzZ61m0y.js +2 -0
- package/static/assets/{DestinationMap-Bwv9zW4k.js → DestinationMap-DAk0zqdP.js} +1 -1
- package/static/assets/{FilteringView-hYm_mlJ0.js → FilteringView-CkcgGa7_.js} +1 -1
- package/static/assets/LogsView-Bb2JGWSY.js +5 -0
- package/static/assets/{RulesView-DLhxdWLq.js → RulesView-BKZXclmK.js} +1 -1
- package/static/assets/{SettingsView-VR3JolCU.js → SettingsView-BIUiIVIC.js} +1 -1
- package/static/assets/SetupView-MjSOUYm0.js +1 -0
- package/static/assets/{TrendChart-wcrIRt7R.js → TrendChart-CDyqUTCQ.js} +1 -1
- package/static/assets/date-D8IlsmbP.js +1 -0
- package/static/assets/de-DE-BXtoHcnB.js +12 -0
- package/static/assets/es-ES-HzsKZWQV.js +12 -0
- package/static/assets/fr-FR-cS1x6c9J.js +12 -0
- package/static/assets/index-BJJdTKLc.css +2 -0
- package/static/assets/index-C5rHE6WK.js +17 -0
- package/static/assets/ja-JP-Dxk2el-P.js +12 -0
- package/static/assets/ko-KR-Bj56Fs_D.js +12 -0
- package/static/assets/ru-RU-D1z3XQQZ.js +12 -0
- package/static/assets/{services-BYhiWUn8.js → services-B-OKDv75.js} +1 -1
- package/static/assets/useLogsE2ee-Crd_rHKZ.js +1 -0
- package/static/assets/vi-VN-YQQX1woE.js +12 -0
- package/static/assets/zh-CN-B0jDBZPP.js +12 -0
- package/static/assets/zh-TW-DOnIGWL3.js +12 -0
- package/static/index.html +2 -2
- package/static/sw.js +1 -1
- package/static/assets/AccountView-t2HnohwK.js +0 -4
- package/static/assets/AnalyticsView-DDNyezYl.js +0 -2
- package/static/assets/LogsView-BSRCO63V.js +0 -5
- package/static/assets/SetupView-BEaDE8T8.js +0 -1
- package/static/assets/date-DG8jTrEB.js +0 -1
- package/static/assets/de-DE-BiPVfS40.js +0 -12
- package/static/assets/es-ES-CM9mOh6j.js +0 -12
- package/static/assets/fr-FR-_-PAIgSj.js +0 -12
- package/static/assets/index-CrB_HdIL.js +0 -17
- package/static/assets/index-DZNm9qiP.css +0 -2
- package/static/assets/ja-JP-CYATQiqp.js +0 -12
- package/static/assets/ko-KR-DCPI1Twu.js +0 -12
- package/static/assets/ru-RU-D5bj5X0j.js +0 -12
- package/static/assets/vi-VN-D1YSdAMz.js +0 -12
- package/static/assets/zh-CN-Dhtte9ac.js +0 -12
- package/static/assets/zh-TW-CiUsmXXj.js +0 -12
- /package/static/assets/{SwipeableDrawer-DkPacJ1O.js → SwipeableDrawer-BrlOF_Xg.js} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dns-worker",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.6",
|
|
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",
|
|
@@ -48,12 +48,15 @@
|
|
|
48
48
|
"test": "tsx test/test_legacy_compat.ts",
|
|
49
49
|
"test:compat": "tsx test/test_legacy_compat.ts",
|
|
50
50
|
"test:turso": "tsx test/test_turso.ts",
|
|
51
|
+
"test:turnstile": "tsx test/test_turnstile.ts",
|
|
51
52
|
"test:serverfull": "tsx test/test_serverfull.ts",
|
|
52
53
|
"test:reset": "tsx test/test_serverfull_reset.ts",
|
|
53
54
|
"lint": "oxlint",
|
|
54
55
|
"ui:dev": "cd web && npm run dev",
|
|
55
56
|
"ui:build": "cd web && npm run build",
|
|
56
|
-
"ui:install": "cd web && npm install"
|
|
57
|
+
"ui:install": "cd web && npm install",
|
|
58
|
+
"tag-promote": "npm version patch",
|
|
59
|
+
"tag-push": "git push && git push --tags"
|
|
57
60
|
},
|
|
58
61
|
"keywords": [
|
|
59
62
|
"dns",
|
|
@@ -82,7 +85,8 @@
|
|
|
82
85
|
"wrangler": "^4.151.1"
|
|
83
86
|
},
|
|
84
87
|
"overrides": {
|
|
85
|
-
"esbuild": "^0.28.1"
|
|
88
|
+
"esbuild": "^0.28.1",
|
|
89
|
+
"undici": "^7.30.1"
|
|
86
90
|
},
|
|
87
91
|
"dependencies": {
|
|
88
92
|
"@noble/post-quantum": "^0.7.1"
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/date-D8IlsmbP.js","assets/index-C5rHE6WK.js","assets/vendor-icons-other-BTYC6Wvz.js","assets/vendor-icons-16-BgwRBCeU.js","assets/rolldown-runtime-C4Xdq4VV.js","assets/vendor-icons-20-X5NPN60g.js","assets/vendor-react-De1zEwOV.js","assets/vendor-i18next-CevVzhh3.js","assets/vendor-ui-core-ClwQiwMI.js","assets/vendor-utils-rmW6cqPl.js","assets/index-BJJdTKLc.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,N 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,x as E,y as D,z as O}from"./vendor-react-De1zEwOV.js";import{S as k,b as A,x as ee}from"./vendor-icons-other-BTYC6Wvz.js";import{i as te}from"./vendor-i18next-CevVzhh3.js";import{B as j,C as M,D as ne,F as N,H as P,L as F,M as re,N as I,O as L,P as ie,R,S as z,T as ae,V as B,_ as V,d as oe,f as H,h as U,j as W,p as G,r as K,t as se,u as ce,v as le,x as q,z as J}from"./vendor-ui-core-ClwQiwMI.js";import{_t as ue}from"./vendor-utils-rmW6cqPl.js";import{$t as de,At as fe,Bt as pe,C as me,Ct as he,Dt as ge,E as _e,Et as ve,Ft as ye,It as be,Kt as xe,Lt as Se,Mt as Ce,Nt as we,Ot as Te,Pt as Ee,Rt as De,S as Oe,St as ke,T as Ae,Vt as je,_t as Me,bt as Ne,d as Y,f as Pe,gt as Fe,h as X,ht as Ie,i as Le,jt as Re,kt as ze,l as Be,m as Ve,mt as He,o as Ue,p as We,pt as Ge,r as Ke,s as qe,u as Je,vt as Ye,w as Xe,wt as Ze,x as Z,xt as Qe,yt as $e,zt as et}from"./index-C5rHE6WK.js";var Q=e(k(),1),$=e(A(),1);const tt=({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)(W,{style:{margin:0},children:a(`account.totp.recoveryKeysTitle`,`Save Your Recovery Keys`)})]}),(0,$.jsx)(z,{intent:B.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)(I,{fill:!0,icon:(0,$.jsx)(w,{size:14}),text:t?a(`account.totp.copied`,`Copied!`):a(`account.totp.copyKeys`,`Copy All Keys`),intent:t?B.SUCCESS:B.NONE,onClick:r}),(0,$.jsx)(I,{fill:!0,intent:B.PRIMARY,text:a(`account.totp.done`,`Done, I've saved them`),onClick:i})]})]})},nt=({onRefresh:e,toasterRef:t,user:n})=>{let{t:r}=d(),[i,a]=(0,Q.useState)([]),[o,s]=(0,Q.useState)(!0),[c,l]=(0,Q.useState)(!0),[u,f]=(0,Q.useState)(null),[p,m]=(0,Q.useState)(!1),[h,g]=(0,Q.useState)(null),[_,v]=(0,Q.useState)(!1),[y,b]=(0,Q.useState)(``),[x,S]=(0,Q.useState)(!1),[C,w]=(0,Q.useState)(!1),[T,E]=(0,Q.useState)(``),[D,O]=(0,Q.useState)(null),[k,A]=(0,Q.useState)(``),[ee,te]=(0,Q.useState)(!1),[j,M]=(0,Q.useState)(!1),[ne,N]=(0,Q.useState)(``),[P,F]=(0,Q.useState)(null),[re,I]=(0,Q.useState)(!1),[L,ie]=(0,Q.useState)(null),R=(0,Q.useCallback)(async()=>{s(!0);try{a(await he()||[])}catch{}finally{s(!1)}},[]);(0,Q.useEffect)(()=>{l(et()),R()},[R]);let z=()=>{b(``),E(``),S(!1),v(!0)},ae=async t=>{t.preventDefault();let n=y.trim();if(!Ve(n)){E(r(`account.passkey.formatTip`,`1-30 characters, letters, numbers, hyphens and underscores allowed`));return}w(!0),E(``);try{let t=await De({name:n,credential:await je(await ke())}),r=t?.passkey?.id||t?.id;if(r&&Z.isUnlocked())try{await Z.wrapCurrentKeyForPasskey(r)}catch(e){console.warn(`[Passkeys] Failed to wrap existing E2EE key for new passkey:`,e)}v(!1),b(``),await R(),e?.(),t?.recovery_keys&&t.recovery_keys.length>0&&f(t.recovery_keys)}catch(e){console.error(`Passkey registration failed:`,e),E(e instanceof Error?e.message:r(`account.passkey.regFailed`,`Registration failed`))}finally{w(!1)}},V=()=>{u&&navigator.clipboard.writeText(u.join(`
|
|
3
|
+
`)).then(()=>{m(!0),setTimeout(()=>m(!1),2e3)})},oe=e=>{O(e),A(e.name),N(``),te(!1)},H=async e=>{e.preventDefault();let t=k.trim();if(!(!D||!t)){if(!Ve(t)){N(r(`account.passkey.formatTip`,`1-30 characters, letters, numbers, hyphens and underscores allowed`));return}M(!0),N(``);try{await ve(D.id,t),O(null),await R()}catch(e){N(e instanceof Error?e.message:r(`common.errorNetwork`))}finally{M(!1)}}},[U,W]=(0,Q.useState)(``),[G,K]=(0,Q.useState)(``);return{passkeys:i,loading:o,supported:c,recoveryKeys:u,setRecoveryKeys:f,copiedKeys:p,handleCopyRecoveryKeys:V,isAddOpen:_,setIsAddOpen:v,passkeyName:y,setPasskeyName:b,nameFocused:x,setNameFocused:S,registering:C,addError:T,setAddError:E,handleOpenAdd:z,handleRegister:ae,editingPasskey:D,setEditingPasskey:O,editName:k,setEditName:A,renameFocused:ee,setRenameFocused:te,renaming:j,renameError:ne,setRenameError:N,handleOpenRename:oe,handleRenameSubmit:H,deletingId:P,deleteConfirmOpen:re,setDeleteConfirmOpen:I,targetToDelete:L,deletePassword:U,setDeletePassword:W,deleteError:G,setDeleteError:K,handleOpenDelete:e=>{ie(e),W(``),K(``),I(!0)},handleDeleteSubmit:async()=>{if(L){F(L.id),K(``);try{let t=U;n?.password_version===2&&n.username&&(t=await Y(U,n.username)),await Me(L.id,{password:t}),I(!1),ie(null),W(``),await R(),e?.()}catch(e){K(e instanceof Error?e.message:r(`common.errorNetwork`))}finally{F(null)}}},testingId:h,handleTestPasskey:async e=>{g(e?e.id:`all`);try{let n=await Ce(e?.id);n.success&&(t?.current?.show({message:r(`account.passkey.testSuccess`,{name:n.passkey?.name||e?.name||``,defaultValue:`Passkey verified successfully: ${n.passkey?.name||e?.name||``}`}),intent:B.SUCCESS,icon:`tick-circle`}),await R())}catch(e){let n=e instanceof Error?e.message:String(e);n.includes(`cancelled`)||n.includes(`NotAllowedError`)||n.includes(`timed out`)||n.includes(`abort`)?t?.current?.show({message:r(`account.passkey.testCancelled`,`Passkey verification cancelled`),intent:B.WARNING,icon:`warning-sign`}):t?.current?.show({message:n||r(`account.passkey.testFailed`,`Passkey verification failed`),intent:B.DANGER,icon:`error`})}finally{g(null)}},fetchPasskeys:R}},rt=({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)(ie,{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`),`:`,` `,X(new Date(e.created_at*1e3))]}),e.last_used_at?(0,$.jsxs)(`span`,{children:[f(`account.passkey.lastUsed`,`Last used`),`:`,` `,X(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)(I,{minimal:!0,small:!0,intent:B.PRIMARY,icon:(0,$.jsx)(n,{size:14}),title:f(`account.passkey.testThis`,`Test this passkey`),loading:s===e.id,onClick:()=>c?.(e)}),(0,$.jsx)(I,{minimal:!0,small:!0,icon:(0,$.jsx)(r,{size:14}),title:f(`common.rename`,`Rename`),onClick:()=>l(e)}),(0,$.jsx)(I,{minimal:!0,small:!0,intent:B.DANGER,icon:(0,$.jsx)(i,{size:14}),title:f(`common.delete`,`Delete`),loading:o===e.id,onClick:()=>u(e)})]})]},e.id))})},it=({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)(L,{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:F,children:[s&&(0,$.jsx)(z,{intent:B.DANGER,className:`mb-4`,children:s}),(0,$.jsx)(G,{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)(le,{content:u(`account.passkey.formatTip`,`1-30 characters, letters, numbers, hyphens and underscores allowed`),isOpen:i,position:j.TOP,intent:B.PRIMARY,className:`w-full`,children:(0,$.jsx)(`div`,{className:`w-full block`,children:(0,$.jsx)(H,{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:R,children:(0,$.jsxs)(`div`,{className:J,children:[(0,$.jsx)(I,{text:u(`common.cancel`,`Cancel`),onClick:t,disabled:o}),(0,$.jsx)(I,{intent:B.PRIMARY,type:`submit`,text:u(`account.passkey.continue`,`Continue`),loading:o,disabled:!Ve(n.trim())||o})]})})]})})},at=({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)(L,{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:F,children:[s&&(0,$.jsx)(z,{intent:B.DANGER,className:`mb-4`,children:s}),(0,$.jsx)(G,{label:u(`account.passkey.appNameLabel`,`Application (Domain)`),children:(0,$.jsx)(H,{readOnly:!0,disabled:!0,leftIcon:`globe`,value:window.location.hostname})}),(0,$.jsx)(G,{label:u(`account.passkey.nameLabel`,`Passkey Name`),helperText:u(`account.passkey.formatTip`,`1-30 characters, letters, numbers, hyphens and underscores allowed`),children:(0,$.jsx)(le,{content:u(`account.passkey.formatTip`,`1-30 characters, letters, numbers, hyphens and underscores allowed`),isOpen:i,position:j.TOP,intent:B.PRIMARY,className:`w-full`,children:(0,$.jsx)(`div`,{className:`w-full block`,children:(0,$.jsx)(H,{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:R,children:(0,$.jsxs)(`div`,{className:J,children:[(0,$.jsx)(I,{text:u(`common.cancel`,`Cancel`),onClick:t,disabled:o}),(0,$.jsx)(I,{intent:B.PRIMARY,type:`submit`,text:u(`common.save`,`Save`),loading:o,disabled:!Ve(n.trim())||o})]})})]})})},ot=({isOpen:e,onClose:t,targetToDelete:n,deleting:r,onConfirm:i,password:a,setPassword:o,error:s})=>{let{t:c}=d();return(0,$.jsx)(L,{isOpen:e,onClose:()=>!r&&t(),title:c(`account.passkey.deleteTitle`,`Delete Passkey`),className:`max-w-md`,children:(0,$.jsxs)(`form`,{onSubmit:e=>{e.preventDefault(),a&&i()},children:[(0,$.jsxs)(`div`,{className:F,children:[(0,$.jsx)(`p`,{children:c(`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})}),o&&(0,$.jsx)(G,{label:c(`account.totp.enterPassword`,`Enter your password to confirm:`),labelFor:`delete-passkey-password`,className:`mt-3`,children:(0,$.jsx)(H,{id:`delete-passkey-password`,type:`password`,placeholder:c(`account.totp.passwordPlaceholder`,`Account password`),value:a||``,onChange:e=>o(e.target.value),autoFocus:!0})}),s&&(0,$.jsx)(z,{intent:B.DANGER,className:`mt-2 text-xs`,children:s})]}),(0,$.jsx)(`div`,{className:R,children:(0,$.jsxs)(`div`,{className:J,children:[(0,$.jsx)(I,{text:c(`common.cancel`,`Cancel`),onClick:t,disabled:r}),(0,$.jsx)(I,{intent:B.DANGER,text:c(`common.delete`,`Delete`),type:`submit`,loading:r,disabled:r||!(a||``).trim()})]})})]})})},st=({onRefresh:e,user:t})=>{let{t:r}=d(),i=(0,Q.useRef)(null),{passkeys:a,loading:o,supported:s,recoveryKeys:c,setRecoveryKeys:l,copiedKeys:f,handleCopyRecoveryKeys:p,isAddOpen:m,setIsAddOpen:h,passkeyName:g,setPasskeyName:_,nameFocused:v,setNameFocused:y,registering:b,addError:x,setAddError:C,handleOpenAdd:w,handleRegister:T,editingPasskey:E,setEditingPasskey:D,editName:k,setEditName:A,renameFocused:ee,setRenameFocused:te,renaming:j,renameError:M,setRenameError:ne,handleOpenRename:N,handleRenameSubmit:P,deletingId:F,deleteConfirmOpen:re,setDeleteConfirmOpen:L,targetToDelete:ie,deletePassword:R,setDeletePassword:ae,deleteError:V,handleOpenDelete:oe,handleDeleteSubmit:H,testingId:U,handleTestPasskey:G}=nt({onRefresh:e,toasterRef:i,user:t});return c?(0,$.jsx)(tt,{recoveryKeys:c,copied:f,onCopy:p,onDone:()=>l(null)}):(0,$.jsxs)(`div`,{className:`space-y-4`,children:[(0,$.jsx)(se,{ref:i}),(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)(W,{style:{margin:0},children:r(`account.passkey.title`,`Passkeys`)}),(0,$.jsx)(K,{intent:a.length>0?B.SUCCESS:B.NONE,minimal:!0,round:!0,children:a.length>0?r(`account.passkey.count`,{count:a.length,defaultValue:`${a.length} configured`}):r(`account.passkey.none`,`None configured`)})]}),(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[s&&a.length>0&&(0,$.jsx)(I,{intent:B.NONE,outlined:!0,icon:(0,$.jsx)(n,{size:16}),text:r(`account.passkey.testBtn`,`Test Passkey`),onClick:()=>G(),loading:U===`all`}),s&&(0,$.jsx)(I,{intent:B.PRIMARY,icon:(0,$.jsx)(O,{size:16}),text:r(`account.passkey.addBtn`,`Add Passkey`),onClick:w})]})]}),(0,$.jsx)(`p`,{className:`text-sm text-gray-600 dark:text-gray-400 mb-4`,children:r(`account.passkey.desc`,`Authenticate securely with biometrics (Touch ID, Face ID, Windows Hello) or a hardware security key (YubiKey) as an MFA factor.`)}),!s&&(0,$.jsx)(z,{intent:B.WARNING,icon:(0,$.jsx)(S,{size:16}),className:`mb-4`,children:r(`account.passkey.notSupported`,`Your browser or device does not support Passkeys (WebAuthn).`)}),(0,$.jsx)(rt,{passkeys:a,loading:o,deletingId:F,testingId:U,onTestPasskey:G,onOpenRename:N,onOpenDelete:oe}),(0,$.jsx)(it,{isOpen:m,onClose:()=>h(!1),passkeyName:g,setPasskeyName:_,nameFocused:v,setNameFocused:y,registering:b,addError:x,setAddError:C,onSubmit:T}),(0,$.jsx)(at,{isOpen:!!E,onClose:()=>D(null),editName:k,setEditName:A,renameFocused:ee,setRenameFocused:te,renaming:j,renameError:M,setRenameError:ne,onSubmit:P}),(0,$.jsx)(ot,{isOpen:re,onClose:()=>L(!1),targetToDelete:ie,deleting:!!F,onConfirm:H,password:R,setPassword:ae,error:V})]})},ct=({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 we(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)(L,{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)(z,{intent:B.SUCCESS,icon:(0,$.jsx)(v,{size:16}),children:r(`account.totp.testSuccess`,`Verification successful! Your authenticator app is configured properly.`)}),c&&(0,$.jsx)(z,{intent:B.DANGER,children:c}),(0,$.jsxs)(`form`,{onSubmit:e=>{e.preventDefault(),p()},className:`space-y-4`,children:[(0,$.jsx)(G,{label:r(`account.totp.verificationCode`,`6-Digit Verification Code`),labelFor:`test-totp-input`,children:(0,$.jsx)(H,{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)(I,{text:u?r(`common.close`,`Close`):r(`common.cancel`,`Cancel`),onClick:n}),!u&&(0,$.jsx)(I,{intent:B.PRIMARY,text:r(`account.totp.verifyBtn`,`Verify`),type:`submit`,loading:o,disabled:i.length!==6})]})]})]})})},lt=({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)(W,{style:{margin:0},children:f(`account.totp.title`,`Authenticator App (TOTP)`)}),(0,$.jsx)(K,{intent:B.SUCCESS,minimal:!0,round:!0,children:f(`account.totp.enabled`,`Enabled`)})]}),(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(I,{outlined:!0,icon:(0,$.jsx)(t,{size:14}),text:f(`account.totp.testBtn`,`Test Code`),onClick:()=>g(!0)}),(0,$.jsx)(I,{intent:B.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)(L,{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)(z,{intent:B.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)(z,{intent:B.DANGER,children:s}),!e.totp_skip_password&&(0,$.jsxs)(`form`,{onSubmit:u,className:`space-y-4`,children:[(0,$.jsx)(G,{label:f(`account.currentPassword`),children:(0,$.jsx)(H,{type:p?`text`:`password`,leftIcon:`lock`,value:i,onChange:e=>a(e.target.value),rightElement:(0,$.jsx)(I,{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)(I,{text:f(`account.cancel`),onClick:()=>r(!1)}),(0,$.jsx)(I,{intent:B.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)(I,{text:f(`account.cancel`),onClick:()=>r(!1)}),(0,$.jsx)(I,{intent:B.DANGER,text:f(`account.totp.confirmDisable`,`Disable TOTP`),loading:l,onClick:u})]})]})}),(0,$.jsx)(ct,{isOpen:h,onClose:()=>g(!1)})]})},ut=({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)(W,{style:{margin:0},children:u(`account.totp.title`,`Authenticator App (TOTP)`)}),(0,$.jsx)(K,{minimal:!0,round:!0,intent:B.NONE,children:u(`account.totp.disabled`,`Disabled`)})]}),!e&&(0,$.jsx)(I,{intent:B.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)(Ke,{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)(V,{}),r&&(0,$.jsx)(z,{intent:B.DANGER,children:r}),(0,$.jsxs)(`form`,{onSubmit:c,className:`space-y-3`,children:[(0,$.jsx)(G,{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)(Le,{length:6,value:t,onChange:n,disabled:i})}),(0,$.jsxs)(`div`,{className:`flex gap-2`,children:[(0,$.jsx)(I,{text:u(`account.cancel`),onClick:l}),(0,$.jsx)(I,{intent:B.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)(z,{intent:B.DANGER,children:r})]})]})},dt=({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)(tt,{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)(lt,{user:e,settingsLoading:w,onToggleSkipPassword:async e=>{T(!0);try{await Se(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 Y(v,e.username)),await Ye(n),_(!1),y(``),t()}catch(e){C(e.message||n(`common.errorNetwork`))}finally{x(!1)}}}):(0,$.jsx)(ut,{setupData:r,setupToken:a,setSetupToken:o,setupError:f,setupLoading:l,onStartSetup:async()=>{u(!0),p(``);try{i(await Re())}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 Ie({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(``)}})},ft=({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)(M,{fill:!0,variant:`minimal`,style:{isolation:`isolate`},children:[r&&(0,$.jsx)(I,{small:!0,active:e===`passkey`,intent:e===`passkey`?B.PRIMARY:B.NONE,icon:(0,$.jsx)(u,{size:14}),text:s(`account.mfa.passkey`,`Passkey`),onClick:()=>t(`passkey`)}),i&&(0,$.jsx)(I,{small:!0,active:e===`recovery_key`,intent:e===`recovery_key`?B.PRIMARY:B.NONE,icon:(0,$.jsx)(u,{size:14}),text:s(`account.recoveryKey.verifyBtn`,`Recovery Key`),onClick:()=>t(`recovery_key`)}),a&&(0,$.jsx)(I,{small:!0,active:e===`totp`,intent:e===`totp`?B.PRIMARY:B.NONE,icon:(0,$.jsx)(n,{size:14}),text:s(`account.mfa.totp`,`TOTP`),onClick:()=>t(`totp`)}),o&&(0,$.jsx)(I,{small:!0,active:e===`password`,intent:e===`password`?B.PRIMARY:B.NONE,icon:(0,$.jsx)(h,{size:14}),text:s(`account.mfa.password`,`Password`),onClick:()=>t(`password`)})]})})})},pt=({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)(I,{fill:!0,large:!0,intent:B.PRIMARY,loading:e,onClick:t,icon:(0,$.jsx)(u,{size:16}),text:n(`account.usePasskeyInstead`,`Authenticate with Passkey`)})]})},mt=({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)(G,{label:i(`account.totpCode`,`Authenticator Code`),children:(0,$.jsx)(Le,{length:6,value:e,onChange:e=>{t(e),e.length===6&&r(e)},disabled:n})}),(0,$.jsx)(I,{fill:!0,intent:B.PRIMARY,loading:n,disabled:e.length!==6,onClick:()=>r(),text:i(`common.confirm`,`Confirm`)})]})},ht=({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)(G,{label:o(`account.currentPassword`,`Current Password`),children:(0,$.jsx)(H,{leftIcon:`lock`,type:n?`text`:`password`,value:e,onChange:e=>t(e.target.value),autoFocus:!0,rightElement:(0,$.jsx)(I,{minimal:!0,icon:n?`eye-open`:`eye-off`,onClick:()=>r(!n)})})}),(0,$.jsx)(I,{fill:!0,intent:B.PRIMARY,type:`submit`,loading:i,text:o(`common.confirm`,`Confirm`)})]})},gt=({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)(G,{label:i(`account.recoveryKey.verifyPromptLabel`,`原恢复密钥 (Original Recovery Key)`),children:(0,$.jsx)(H,{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)(I,{fill:!0,intent:B.PRIMARY,type:`submit`,loading:n,disabled:!e.trim(),text:i(`common.confirm`,`Confirm`)})]})};var _t=(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 vt=({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=_t(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 Y(g,n.username)),await i({password:e}),t()}catch(e){D(Je(e,o))}finally{T(!1)}},ee=async()=>{T(!0),D(``);try{await i({passkeyAssertion:await pe(await Qe())}),t()}catch(e){D(Je(e,o))}finally{T(!1)}},te=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(Je(e,o))}finally{T(!1)}},j=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(Je(e,o))}finally{T(!1)}},M=(c?1:0)+(f?1:0)+(l?1:0)+(u?1:0);return(0,$.jsx)(L,{isOpen:e,onClose:t,title:r||o(`account.verifyIdentity`,`Security Verification`),icon:`shield`,className:`max-w-md w-full`,children:(0,$.jsxs)(`div`,{className:F,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.`)}),M>1&&(0,$.jsx)(ft,{method:m,onSelectMethod:e=>{h(e),D(``)},hasPasskey:c,hasRecoveryKey:f,hasTotp:l,hasPassword:u}),E&&(0,$.jsx)(z,{intent:B.DANGER,className:`mb-4`,children:E}),m===`recovery_key`&&(0,$.jsx)(gt,{recoveryKey:S,setRecoveryKey:C,loading:w,onSubmit:j}),m===`passkey`&&(0,$.jsx)(pt,{loading:w,onVerify:ee}),m===`totp`&&(0,$.jsx)(mt,{totpCode:b,setTotpCode:x,loading:w,onVerify:te}),m===`password`&&(0,$.jsx)(ht,{password:g,setPassword:_,showPassword:v,setShowPassword:y,loading:w,onSubmit:A})]})})},yt=({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 ze(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:B.WARNING}),t();return}}catch{}b({text:r(`account.recoveryKey.rotateSuccess`,`恢复密钥已成功轮换!请立即妥善离线保存新密钥,旧密钥已失效。`),intent:B.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)(W,{style:{margin:0},children:r(`account.recoveryKey.title`,`紧急恢复密钥`)}),(0,$.jsx)(K,{intent:C?B.SUCCESS:B.NONE,minimal:!0,round:!0,children:C?r(`account.recoveryKey.configured`,`已配置`):r(`account.recoveryKey.notConfigured`,`未配置`)}),(0,$.jsx)(le,{content:r(`account.recoveryKey.oneWayTooltip`,`采用 SHA-256 单向密码学散列保护,服务端不存储明文且不可解密,仅支持身份轮换验证。`),position:j.TOP,children:(0,$.jsx)(K,{intent:B.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)(I,{small:!0,intent:B.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)(z,{intent:v.intent,className:`my-2`,children:v.text}),c&&(0,$.jsxs)(q,{elevation:P.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)(I,{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)(I,{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)(I,{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)(ne,{isOpen:o,onConfirm:D,onCancel:()=>s(!1),cancelButtonText:r(`common.cancel`,`取消`),confirmButtonText:r(`account.recoveryKey.confirmRotateBtn`,`确认进入轮换验证`),intent:B.DANGER,icon:`warning-sign`,children:(0,$.jsx)(`p`,{children:r(`account.recoveryKey.rotateConfirm`,`轮换恢复密钥将立即使原恢复密钥失效,并重新派生信封加密密钥。仅允许通过现有通行密钥 (Passkey) 或原恢复密钥完成轮换验证。是否继续?`)})}),(0,$.jsx)(vt,{isOpen:i,onClose:()=>a(!1),user:e,allowedMethods:[`passkey`,`recovery_key`],title:r(`account.recoveryKey.rotateVerifyTitle`,`验证身份以轮换恢复密钥`),onVerify:O})]})},bt=({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 ye(e),r()}catch(e){alert(e.message||i(`common.errorNetwork`,`Network error`))}finally{o(!1)}};return(0,$.jsxs)(q,{elevation:P.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)(W,{style:{margin:0},children:i(`account.mfa.title`,`Multi-Factor Authentication (MFA)`)}),(0,$.jsx)(K,{intent:s?B.SUCCESS:B.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)(V,{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)(U,{checked:!!e.totp_skip_password,onChange:e=>c(e.currentTarget.checked),disabled:a,className:`mb-0 shrink-0`})]})]}):(0,$.jsx)(z,{intent:B.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)(V,{}),(0,$.jsx)(st,{user:e,onRefresh:r}),(0,$.jsx)(V,{}),(0,$.jsx)(dt,{user:e,onRefresh:r}),(0,$.jsx)(V,{}),(0,$.jsx)(yt,{user:e,onRefresh:r})]})},xt={signup:{label:`account.activity.signup`,icon:(0,$.jsx)(E,{size:14}),intent:B.SUCCESS},login_success:{label:`account.activity.loginSuccess`,icon:(0,$.jsx)(g,{size:14}),intent:B.SUCCESS},login_fail:{label:`account.activity.loginFail`,icon:(0,$.jsx)(p,{size:14}),intent:B.DANGER},logout:{label:`account.activity.logout`,icon:(0,$.jsx)(c,{size:14}),intent:B.NONE},password_change_success:{label:`account.activity.pwChangeSuccess`,icon:(0,$.jsx)(u,{size:14}),intent:B.SUCCESS},password_change_fail:{label:`account.activity.pwChangeFail`,icon:(0,$.jsx)(p,{size:14}),intent:B.DANGER},totp_verify_success:{label:`account.activity.totpVerifySuccess`,icon:(0,$.jsx)(n,{size:14}),intent:B.SUCCESS},totp_verify_fail:{label:`account.activity.totpVerifyFail`,icon:(0,$.jsx)(p,{size:14}),intent:B.DANGER},totp_setup:{label:`account.activity.totpSetup`,icon:(0,$.jsx)(a,{size:14}),intent:B.PRIMARY},totp_removed:{label:`account.activity.totpRemoved`,icon:(0,$.jsx)(C,{size:14}),intent:B.WARNING},recovery_key_used:{label:`account.activity.recoveryKeyUsed`,icon:(0,$.jsx)(u,{size:14}),intent:B.WARNING},recovery_key_rotated:{label:`account.activity.recoveryKeyRotated`,icon:(0,$.jsx)(u,{size:14}),intent:B.WARNING},session_revoked:{label:`account.activity.sessionRevoked`,icon:(0,$.jsx)(c,{size:14}),intent:B.WARNING},passkey_registered:{label:`account.activity.passkeyRegistered`,icon:(0,$.jsx)(u,{size:14}),intent:B.PRIMARY},passkey_deleted:{label:`account.activity.passkeyDeleted`,icon:(0,$.jsx)(C,{size:14}),intent:B.WARNING},passkey_verify_success:{label:`account.activity.passkeyVerifySuccess`,icon:(0,$.jsx)(n,{size:14}),intent:B.SUCCESS},passkey_verify_fail:{label:`account.activity.passkeyVerifyFail`,icon:(0,$.jsx)(p,{size:14}),intent:B.DANGER}},St=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`},Ct=(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},wt=({userAgent:e})=>{let{t}=d();if(!e)return(0,$.jsx)(`span`,{className:`text-gray-500`,children:`—`});let n=Ct(e,t(`account.sessions.unknownDevice`,`Unknown Device`));return(0,$.jsxs)(`div`,{children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(N,{icon:St(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})]})},Tt=({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 $e(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=>xt[e]??{label:e,icon:(0,$.jsx)(s,{size:14}),intent:B.NONE};return(0,$.jsxs)(q,{elevation:P.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)(W,{style:{margin:0},children:n(`account.activity.title`,`Account Activity`)}),r.length>0&&(0,$.jsxs)(K,{minimal:!0,round:!0,intent:B.NONE,children:[r.length,c?`+`:``]})]}),(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,$.jsx)(I,{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)(ie,{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)(ce,{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)(K,{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:X(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)(wt,{userAgent:r.user_agent||null})})]},r.id)})})]}),c&&(0,$.jsx)(`div`,{className:`flex justify-center mt-3`,children:(0,$.jsx)(I,{minimal:!0,loading:a,text:n(`account.activity.loadMore`,`Load More`),onClick:h})})]})})]})},Et=({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 Ze(),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 Te(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)(q,{elevation:P.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)(W,{style:{margin:0},children:n(`account.sessions.title`,`Active Sessions`)})]}),(0,$.jsxs)(`div`,{className:`flex items-center gap-2`,children:[_>0&&(0,$.jsx)(I,{small:!0,minimal:!0,intent:B.DANGER,icon:(0,$.jsx)(c,{size:14}),text:n(`account.sessions.revokeOthers`,`Revoke Other Sessions`),loading:u,onClick:()=>g(!0)}),(0,$.jsx)(I,{minimal:!0,icon:(0,$.jsx)(f,{size:14}),onClick:()=>v()})]})]}),a?(0,$.jsx)(`div`,{className:`flex justify-center py-4`,children:(0,$.jsx)(ie,{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)(ce,{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)(wt,{userAgent:r.user_agent}),r.is_current&&(0,$.jsx)(K,{minimal:!0,intent:B.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?X(new Date(r.created_at*1e3)):`—`}),(0,$.jsx)(`td`,{className:`text-xs text-gray-500 align-middle`,children:X(new Date(r.expires_at*1e3))}),(0,$.jsx)(`td`,{className:`align-middle`,children:(0,$.jsx)(I,{small:!0,minimal:!0,intent:B.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)(ne,{isOpen:h,cancelButtonText:n(`common.cancel`,`Cancel`),confirmButtonText:n(`account.sessions.confirmRevokeOthers`,`Revoke Other Sessions`),intent:B.DANGER,icon:`log-out`,onCancel:()=>g(!1),onConfirm:async()=>{p(!0);try{await ge(),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.`)})})]})},Dt=({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 _e({registration_enabled:String(e)}),o?.()}catch(t){console.error(t),S(!e),alert(t.message||s(`common.errorNetwork`,`Network error`))}finally{w(!1)}},D=async()=>{if(!Be.test(u)){alert(s(`account.formatTipUsername`));return}if(!Ue.test(p)){alert(s(`account.formatTipPassword`));return}v(!0);try{await Oe({username:u,password:await Y(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 me(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)(W,{style:{margin:0},children:s(`account.userManagement`)})]}),(0,$.jsxs)(`div`,{className:`flex items-center gap-4 flex-wrap`,children:[(0,$.jsx)(U,{label:s(`account.enableRegistration`,`开放新用户注册`),checked:x,disabled:C,onChange:e=>T(e.currentTarget.checked),className:`mb-0`}),(0,$.jsx)(I,{className:`whitespace-nowrap`,icon:(0,$.jsx)(E,{size:16}),intent:B.SUCCESS,text:s(`account.createUser`),onClick:()=>l(!0)})]})]}),(0,$.jsx)(q,{elevation:P.ONE,className:`p-0 overflow-hidden overflow-x-auto`,children:(0,$.jsxs)(ce,{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)(K,{minimal:!0,intent:e.role===`admin`?B.DANGER:B.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)(K,{minimal:!0,intent:B.SUCCESS,children:`TOTP`}),!!(e.passkeys_count&&e.passkeys_count>0)&&(0,$.jsx)(K,{minimal:!0,intent:B.PRIMARY,children:`Passkey`}),!e.totp_enabled&&!(e.passkeys_count&&e.passkeys_count>0)&&(0,$.jsx)(K,{minimal:!0,intent:B.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?X(new Date(e.created_at*1e3)):`-`}),(0,$.jsx)(`td`,{className:`text-xs text-gray-500`,children:e.last_active_at?X(new Date(e.last_active_at*1e3)):`-`}),(0,$.jsx)(`td`,{className:`text-xs text-gray-500`,children:e.last_resolve_at?X(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)(I,{minimal:!0,intent:B.DANGER,icon:(0,$.jsx)(i,{size:14}),disabled:e.id===t,onClick:()=>O(e.id)})})})]},e.id))})]})}),(0,$.jsx)(L,{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)(G,{label:s(`account.username`),children:(0,$.jsx)(H,{value:u,onChange:e=>f(e.target.value),placeholder:s(`auth.usernamePlaceholder`)})}),(0,$.jsx)(G,{label:s(`account.initialPassword`),children:(0,$.jsx)(H,{type:y?`text`:`password`,value:p,onChange:e=>m(e.target.value),placeholder:s(`auth.passwordPlaceholder`),rightElement:(0,$.jsx)(I,{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)(G,{label:s(`account.userRole`),children:(0,$.jsx)(oe,{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)(I,{text:s(`account.cancel`),onClick:()=>l(!1)}),(0,$.jsx)(I,{intent:B.PRIMARY,text:s(`account.createNow`),loading:_,onClick:D})]})]})})]})},Ot=({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(0,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)(W,{style:{margin:0},children:n(`account.systemSettings`,`System Settings`)})]}),(0,$.jsxs)(q,{elevation:P.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)(W,{className:`text-sm font-bold opacity-70 text-blue-500`,children:`Cloudflare Turnstile`}),(0,$.jsx)(G,{label:`Site Key`,children:(0,$.jsx)(H,{value:r.turnstile_site_key||``,onChange:e=>i({...r,turnstile_site_key:e.target.value}),placeholder:`0x000...`})}),(0,$.jsx)(G,{label:`Secret Key`,children:(0,$.jsx)(H,{type:s?`text`:`password`,value:r.turnstile_secret_key||``,onChange:e=>i({...r,turnstile_secret_key:e.target.value}),placeholder:`0x000...`,rightElement:(0,$.jsx)(I,{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)(W,{className:`text-sm font-bold opacity-70 text-green-500`,children:n(`account.featureToggle`,`Feature Toggle`)}),(0,$.jsx)(U,{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)(U,{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)(V,{className:`my-4`}),(0,$.jsx)(`div`,{className:`flex justify-end`,children:(0,$.jsx)(I,{intent:B.PRIMARY,icon:`floppy-disk`,text:n(`common.save`,`Save`),loading:a,onClick:async()=>{o(!0);try{await _e({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)}}})})]})]})},kt=({isAdmin:e,onLogsCleared:t,user:n})=>{let{t:r}=d(),[a,o]=(0,Q.useState)(!1),[s,c]=(0,Q.useState)(!1),[l,u]=(0,Q.useState)(``),[f,p]=(0,Q.useState)(!1),[m,h]=(0,Q.useState)(``);return(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(W,{className:`text-red-500 flex items-center gap-2`,children:[(0,$.jsx)(i,{size:20}),` `,r(`account.dangerZone`)]}),(0,$.jsxs)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-6`,children:[(0,$.jsxs)(q,{elevation:P.ONE,className:`flex flex-col justify-between`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(W,{children:r(`account.clearLogs`)}),(0,$.jsx)(`p`,{className:`text-xs opacity-60 mb-3`,children:r(`account.clearLogsDesc`)})]}),(0,$.jsx)(I,{fill:!0,intent:B.DANGER,text:r(`account.clearLogsBtn`),icon:`trash`,loading:a,onClick:async()=>{if(confirm(r(`account.confirmClearLogs`))){o(!0);try{await Ge(),alert(r(`account.clearLogsSuccess`)),t?.()}catch(e){console.error(e)}finally{o(!1)}}}})]}),!e&&(0,$.jsxs)(q,{elevation:P.ONE,className:`flex flex-col justify-between`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(W,{children:r(`account.deleteAccount`)}),(0,$.jsx)(`p`,{className:`text-xs opacity-60 mb-4`,children:r(`account.deleteAccountDesc`)})]}),(0,$.jsx)(I,{fill:!0,intent:B.DANGER,text:r(`account.deleteAccountBtn`),icon:`delete`,onClick:()=>{u(``),h(``),c(!0)}})]})]}),(0,$.jsx)(z,{intent:B.WARNING,icon:`info-sign`,title:r(`account.inactivityPolicy`),children:(0,$.jsx)(`p`,{className:`text-sm`,children:r(`account.inactivityDesc`)})}),(0,$.jsx)(L,{isOpen:s,onClose:()=>!f&&c(!1),title:r(`account.deleteAccount`),className:`max-w-md`,children:(0,$.jsxs)(`form`,{onSubmit:async e=>{if(e.preventDefault(),l){p(!0),h(``);try{let e=l;n?.password_version===2&&n.username&&(e=await Y(l,n.username)),await Fe({password:e}),window.location.href=`/`}catch(e){h(e.message||r(`common.errorNetwork`))}finally{p(!1)}}},children:[(0,$.jsxs)(`div`,{className:F,children:[(0,$.jsx)(`p`,{className:`text-sm opacity-80 mb-3 text-red-500 font-medium`,children:r(`account.confirmDeleteAccount`)}),(0,$.jsx)(G,{label:r(`account.totp.enterPassword`,`Enter your password to confirm:`),labelFor:`delete-account-password`,children:(0,$.jsx)(H,{id:`delete-account-password`,type:`password`,placeholder:r(`account.totp.passwordPlaceholder`,`Account password`),value:l,onChange:e=>u(e.target.value),autoFocus:!0})}),m&&(0,$.jsx)(z,{intent:B.DANGER,className:`mt-2 text-xs`,children:m})]}),(0,$.jsx)(`div`,{className:R,children:(0,$.jsxs)(`div`,{className:J,children:[(0,$.jsx)(I,{text:r(`common.cancel`,`Cancel`),onClick:()=>c(!1),disabled:f}),(0,$.jsx)(I,{intent:B.DANGER,text:r(`account.deleteAccountBtn`,`Delete Account`),type:`submit`,loading:f,disabled:f||!l.trim()})]})})]})})]})},At=[{label:te(`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`}],jt=({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)(q,{elevation:P.ONE,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2 mb-4`,children:[(0,$.jsx)(_,{size:20,className:`text-blue-500`}),(0,$.jsx)(W,{style:{margin:0},children:f(`account.personalInfo`)})]}),(0,$.jsxs)(`div`,{className:`space-y-4`,children:[(0,$.jsx)(G,{label:f(`account.username`),children:(0,$.jsx)(`div`,{className:`flex gap-2`,children:t?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(le,{content:f(`account.formatTipUsername`),isOpen:s,position:j.TOP,intent:B.PRIMARY,className:`w-full`,children:(0,$.jsx)(`div`,{className:`w-full block`,children:(0,$.jsx)(H,{fill:!0,value:i,onChange:e=>a(e.target.value),onFocus:()=>c(!0),onBlur:()=>c(!1),autoFocus:!0})})}),(0,$.jsxs)(M,{children:[(0,$.jsx)(I,{icon:(0,$.jsx)(y,{size:16}),intent:B.SUCCESS,loading:o,onClick:l}),(0,$.jsx)(I,{icon:(0,$.jsx)(D,{size:16}),onClick:()=>{n(!1),a(e?.username||``)}})]})]}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(H,{fill:!0,value:e?.username,readOnly:!0}),(0,$.jsx)(I,{icon:(0,$.jsx)(r,{size:16}),onClick:()=>n(!0)})]})})}),(0,$.jsx)(G,{label:f(`account.userId`),children:(0,$.jsx)(H,{leftIcon:`id-number`,value:e?.id,disabled:!0})}),(0,$.jsx)(G,{label:f(`account.timezone`,`Timezone`),children:(0,$.jsx)(oe,{fill:!0,value:e?.timezone||``,onChange:e=>u?.(e.target.value||null),options:At})})]})]})},Mt=({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)(q,{elevation:P.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)(W,{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)(M,{fill:!0,variant:`minimal`,style:{isolation:`isolate`},children:[(0,$.jsx)(I,{small:!0,active:o===`password`,intent:o===`password`?B.PRIMARY:B.NONE,icon:(0,$.jsx)(h,{size:14}),text:r(`account.mfa.password`,`Password`),onClick:()=>{s(`password`),E(null)}}),i&&(0,$.jsx)(I,{small:!0,active:o===`passkey`,intent:o===`passkey`?B.PRIMARY:B.NONE,icon:(0,$.jsx)(u,{size:14}),text:r(`account.mfa.passkey`,`Passkey`),onClick:()=>{s(`passkey`),E(null)}}),a&&(0,$.jsx)(I,{small:!0,active:o===`totp`,intent:o===`totp`?B.PRIMARY:B.NONE,icon:(0,$.jsx)(n,{size:14}),text:r(`account.mfa.totp`,`TOTP`),onClick:()=>{s(`totp`),E(null)}})]})})}),T&&(0,$.jsx)(z,{intent:T.intent,className:`mb-4`,children:T.text}),(0,$.jsxs)(`form`,{onSubmit:async n=>{if(n.preventDefault(),!Ue.test(_)){E({text:r(`account.formatTipPassword`,`Password must be 12-100 characters and contain letters, numbers, and symbols.`),intent:B.DANGER});return}if(!e?.username){E({text:r(`auth.sessionExpired`,`Session expired. Please log in again.`),intent:B.DANGER});return}w(!0),E(null);try{let n=await Y(_,e.username);if(o===`passkey`)await be({passkeyAssertion:await pe(await Qe()),newPassword:n});else if(o===`totp`){if(m.length!==6){E({text:r(`account.totp.invalidCode`,`Please enter a 6-digit code`),intent:B.DANGER}),w(!1);return}let e=crypto.randomUUID(),t=new TextEncoder().encode(m+e),i=await crypto.subtle.digest(`SHA-256`,t);await be({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:B.DANGER}),w(!1);return}let t=c;(e.password_version??1)===2&&(t=await Y(c,e.username)),await be({oldPassword:t,newPassword:n})}E({text:r(`account.passwordSuccess`,`Password updated successfully!`),intent:B.SUCCESS}),l(``),g(``),v(``),t&&t()}catch(e){E({text:Je(e,r),intent:B.DANGER})}finally{w(!1)}},className:`space-y-4`,children:[o===`password`&&(0,$.jsx)(G,{label:r(`account.currentPassword`,`Current Password`),children:(0,$.jsx)(H,{leftIcon:`lock`,type:f?`text`:`password`,value:c,onChange:e=>l(e.target.value),rightElement:(0,$.jsx)(I,{minimal:!0,icon:f?`eye-open`:`eye-off`,onClick:()=>p(!f),title:r(f?`auth.hidePassword`:`auth.showPassword`)}),required:!0})}),o===`totp`&&(0,$.jsx)(G,{label:r(`account.totpCode`,`Authenticator Code`),children:(0,$.jsx)(Le,{length:6,value:m,onChange:g,disabled:C})}),o===`passkey`&&(0,$.jsx)(z,{intent:B.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)(G,{label:r(`account.newPassword`,`New Password`),children:(0,$.jsx)(le,{content:r(`account.formatTipPassword`,`Password must be 12-100 characters and contain letters, numbers, and symbols.`),isOpen:x,position:j.TOP,intent:B.PRIMARY,className:`w-full`,children:(0,$.jsx)(`div`,{className:`w-full block`,children:(0,$.jsx)(H,{leftIcon:`lock`,type:y?`text`:`password`,value:_,onChange:e=>v(e.target.value),onFocus:()=>S(!0),onBlur:()=>S(!1),rightElement:(0,$.jsx)(I,{minimal:!0,icon:y?`eye-open`:`eye-off`,onClick:()=>b(!y),title:r(y?`auth.hidePassword`:`auth.showPassword`)}),required:!0})})})}),(0,$.jsx)(I,{fill:!0,intent:o===`passkey`?B.PRIMARY:B.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`)})]})]})},Nt=({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||!qe.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(`obex_user_id`)||localStorage.getItem(`obex_user_id`);if(!e){E(a(`auth.sessionExpired`,`Session expired. Logging out...`)),setTimeout(()=>{A()},1500);return}let n=await Pe(f,e),o={};if(c===`passkey`)o.passkeyAssertion=await pe(await Qe());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 We(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 Y(_,r.username)),o.password=e}await fe(n,o),p(``),g(``),v(``),S(``),i()}catch(e){E(Je(e,a))}finally{w(!1)}},A=()=>{E(``),p(``),g(``),v(``),b(!1),S(``),l(`password`),t()};return(0,$.jsx)(L,{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:F,children:[T&&(0,$.jsx)(z,{intent:B.DANGER,className:`mb-4`,children:T}),(0,$.jsx)(G,{label:a(`auth.newPin`,`New 4-Digit PIN`),labelFor:`new-pin-input`,helperText:a(`auth.pinHelper`,`Digits only, e.g., 1234`),children:(0,$.jsx)(Le,{length:4,value:f,onChange:p,type:`password`,disabled:C,autoFocus:!0,onComplete:()=>D.current?.focus()})}),(0,$.jsx)(G,{label:a(`auth.confirmPin`,`Confirm New PIN`),labelFor:`confirm-pin-input`,children:(0,$.jsx)(Le,{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)(V,{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)(M,{fill:!0,variant:`minimal`,style:{isolation:`isolate`},children:[(0,$.jsx)(I,{small:!0,active:c===`password`,intent:c===`password`?B.PRIMARY:B.NONE,icon:(0,$.jsx)(h,{size:14}),text:a(`account.mfa.password`,`Password`),onClick:()=>{l(`password`),E(``)}}),o&&(0,$.jsx)(I,{small:!0,active:c===`passkey`,intent:c===`passkey`?B.PRIMARY:B.NONE,icon:(0,$.jsx)(u,{size:14}),text:a(`account.mfa.passkey`,`Passkey`),onClick:()=>{l(`passkey`),E(``)}}),s&&(0,$.jsx)(I,{small:!0,active:c===`totp`,intent:c===`totp`?B.PRIMARY:B.NONE,icon:(0,$.jsx)(n,{size:14}),text:a(`account.mfa.totp`,`TOTP`),onClick:()=>{l(`totp`),E(``)}})]})})]}),c===`password`&&(0,$.jsx)(G,{label:a(`auth.currentPassword`,`Current Password`),labelFor:`verify-pw-input`,children:(0,$.jsx)(H,{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)(I,{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)(G,{label:a(`auth.totpCode`,`TOTP Code`),labelFor:`verify-totp-input`,children:(0,$.jsx)(Le,{ref:O,length:6,value:x,onChange:S,disabled:C,onComplete:e=>k(void 0,e),autoFocus:!0})}),c===`passkey`&&(0,$.jsx)(z,{intent:B.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:R,children:(0,$.jsxs)(`div`,{className:J,children:[(0,$.jsx)(I,{onClick:A,children:a(`common.cancel`,`Cancel`)}),(0,$.jsx)(I,{type:`submit`,intent:B.PRIMARY,loading:C,children:a(`common.save`,`Save`)})]})})]})})},Pt=({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 pe(await Qe());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 We(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 Y(f,r.username)),e.password=t}await He(e),p(``),v(``),i()}catch(e){C(Je(e,a))}finally{b(!1)}},T=()=>{C(``),p(``),g(!1),v(``),l(`password`),t()};return(0,$.jsx)(L,{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:F,children:[x&&(0,$.jsx)(z,{intent:B.DANGER,className:`mb-4`,children:x}),(0,$.jsx)(z,{intent:B.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)(M,{fill:!0,variant:`minimal`,style:{isolation:`isolate`},children:[(0,$.jsx)(I,{small:!0,active:c===`password`,intent:c===`password`?B.PRIMARY:B.NONE,icon:(0,$.jsx)(h,{size:14}),text:a(`account.mfa.password`,`Password`),onClick:()=>{l(`password`),C(``)}}),o&&(0,$.jsx)(I,{small:!0,active:c===`passkey`,intent:c===`passkey`?B.PRIMARY:B.NONE,icon:(0,$.jsx)(u,{size:14}),text:a(`account.mfa.passkey`,`Passkey`),onClick:()=>{l(`passkey`),C(``)}}),s&&(0,$.jsx)(I,{small:!0,active:c===`totp`,intent:c===`totp`?B.PRIMARY:B.NONE,icon:(0,$.jsx)(n,{size:14}),text:a(`account.mfa.totp`,`TOTP`),onClick:()=>{l(`totp`),C(``)}})]})})]}),c===`password`&&(0,$.jsx)(G,{label:a(`auth.currentPassword`,`Current Password`),labelFor:`disable-pw-input`,children:(0,$.jsx)(H,{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)(I,{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)(G,{label:a(`auth.totpCode`,`TOTP Code`),labelFor:`disable-totp-input`,children:(0,$.jsx)(Le,{length:6,value:_,onChange:v,disabled:y,onComplete:e=>w(void 0,e),autoFocus:!0})}),c===`passkey`&&(0,$.jsx)(z,{intent:B.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:R,children:(0,$.jsxs)(`div`,{className:J,children:[(0,$.jsx)(I,{onClick:T,children:a(`common.cancel`,`Cancel`)}),(0,$.jsx)(I,{type:`submit`,intent:B.DANGER,loading:y,children:a(`common.disable`,`Disable`)})]})})]})})},Ft=({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 Ee({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)(q,{elevation:P.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)(W,{className:`m-0!`,children:r(`auth.sessionLockTitle`,`Idle Session Lock`)})]}),!u&&(0,$.jsx)(I,{icon:`key`,intent:B.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)(oe,{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)(I,{icon:`edit`,onClick:m,disabled:i,children:r(`auth.changePin`,`Change PIN`)}),(0,$.jsx)(I,{icon:`trash`,intent:B.DANGER,onClick:()=>{l(!0)},disabled:i,children:r(`auth.disablePin`,`Disable PIN & Lock`)}),(0,$.jsx)(I,{icon:`lock`,intent:B.WARNING,onClick:async()=>{a(!0);try{await xe(),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)(Nt,{isOpen:o,onClose:()=>s(!1),user:e,onSuccess:()=>{s(!1),t()}}),(0,$.jsx)(Pt,{isOpen:c,onClose:()=>l(!1),user:e,onSuccess:()=>{l(!1),t()}})]})};function It({user:e,onRefresh:t,toasterRef:n,setProcessing:r}){let{t:i}=d(),[a,o]=(0,Q.useState)(null),[s,c]=(0,Q.useState)(!0),[l,u]=(0,Q.useState)(!1),[f,p]=(0,Q.useState)(!1),m=(0,Q.useCallback)(async()=>{c(!0);try{o(await Z.getUserStatus()),u(Z.isUnlocked())}catch(e){console.error(`[useE2eeStatus] Failed to fetch E2EE status:`,e)}finally{c(!1)}},[]);(0,Q.useEffect)(()=>{m()},[m]);let h=e.passkeys_count&&e.passkeys_count>0||(a?.userPasskeyCount||0)>0,g=!!a?.enabled;return{status:a,loading:s,isUnlocked:l,setIsUnlocked:u,isPqc:(0,Q.useMemo)(()=>{if(!a?.publicKey)return!1;try{let e=JSON.parse(a.publicKey);return e.alg===`P256-MLKEM768`||!!e.pqc_pk}catch{return!1}},[a?.publicKey]),isLogsE2eeEnabled:g,hasPasskey:h,loadStatus:m,isDisableAlertOpen:f,setIsDisableAlertOpen:p,handleToggleLogs:async e=>{if(e){r(!0);try{await Z.enableUserE2ee(),n.current?.show({message:i(`account.e2ee.enableSuccess`),intent:B.SUCCESS,icon:`lock`}),await m(),t?.()}catch(e){console.error(`[useE2eeStatus] Failed to enable E2EE:`,e),n.current?.show({message:e.message||i(`account.e2ee.enableError`),intent:B.DANGER,icon:`error`})}finally{r(!1)}}else p(!0)},handleConfirmDisable:async()=>{r(!0);try{await Z.disableUserE2ee(),n.current?.show({message:i(`account.e2ee.disableSuccess`),intent:B.WARNING,icon:`unlock`}),await m(),t?.()}catch(e){console.error(`[useE2eeStatus] Failed to disable E2EE:`,e),n.current?.show({message:e.message||i(`account.e2ee.disableError`),intent:B.DANGER,icon:`error`})}finally{r(!1),p(!1)}},handleLockDevice:()=>{Z.clearStorage(),u(!1),n.current?.show({message:i(`account.e2ee.lockSuccess`,`已锁定,私钥已从本地清除`),intent:B.NONE})}}}function Lt({onRefresh:e,loadStatus:t,setIsUnlocked:n,toasterRef:r,setProcessing:i}){let{t:a}=d(),[o,s]=(0,Q.useState)(!1),[c,l]=(0,Q.useState)(``),[u,f]=(0,Q.useState)(``),[p,m]=(0,Q.useState)(!1),[h,g]=(0,Q.useState)(``),[_,v]=(0,Q.useState)(``),[y,b]=(0,Q.useState)(null),[x,S]=(0,Q.useState)(!1);return{isRecoveryDialogOpen:o,setIsRecoveryDialogOpen:s,recoveryKeyInput:c,setRecoveryKeyInput:l,recoveryUnlockError:u,setRecoveryUnlockError:f,initRecoveryDialogOpen:p,setInitRecoveryDialogOpen:m,initRecoveryKeyInput:h,setInitRecoveryKeyInput:g,initRecoveryError:_,setInitRecoveryError:v,rotatedKey:y,setRotatedKey:b,copiedKey:x,handleUnlockWithRecoveryKey:async o=>{o.preventDefault();let u=c.trim();if(u){i(!0),f(``);try{await Z.unlockWithRecoveryKey(u);try{let e=await ze({recoveryKey:u});await Z.wrapCurrentKeyForRecovery(e.recovery_key),b(e.recovery_key)}catch(e){console.warn(`[useE2eeRecoveryDialogs] Recovery key auto-rotation failed:`,e)}n(!0),s(!1),l(``),r.current?.show({message:a(`account.e2ee.unlockSuccess`),intent:B.SUCCESS,icon:`tick`}),await t(),e?.()}catch(e){console.error(`[useE2eeRecoveryDialogs] Recovery unlock failed:`,e),f(e.message||a(`account.e2ee.recoveryUnlockFailed`))}finally{i(!1)}}},handleInitWithRecoveryKey:async o=>{o.preventDefault();let s=h.trim();if(s){i(!0),v(``);try{await Z.initUserE2eeWithRecoveryKey(s);try{let e=await ze({recoveryKey:s});await Z.wrapCurrentKeyForRecovery(e.recovery_key),b(e.recovery_key)}catch(e){console.warn(`[useE2eeRecoveryDialogs] Recovery key auto-rotation failed:`,e)}m(!1),g(``),n(!0),r.current?.show({message:a(`account.e2ee.keypairGenSuccess`),intent:B.SUCCESS,icon:`tick`}),await t(),e?.()}catch(e){console.error(`[useE2eeRecoveryDialogs] Init keypair with recovery key failed:`,e),v(e.message||a(`account.e2ee.initFailed`))}finally{i(!1)}}},handleCopyRotatedKey:e=>{navigator.clipboard.writeText(e),S(!0),setTimeout(()=>S(!1),2e3)}}}function Rt({hasPasskey:e,onRefresh:t,loadStatus:n,setIsUnlocked:r,setInitRecoveryDialogOpen:i,toasterRef:a,setProcessing:o}){let{t:s}=d(),[c,l]=(0,Q.useState)(!1);return{handleUnlock:async()=>{o(!0);try{await Z.unlockUser()&&(r(!0),a.current?.show({message:s(`account.e2ee.unlockSuccess`),intent:B.SUCCESS,icon:`tick`}))}catch(e){console.error(`[useE2eeActions] Failed to unlock private key:`,e),a.current?.show({message:e.message||s(`account.e2ee.unlockError`),intent:B.DANGER,icon:`error`})}finally{o(!1)}},handleGenerateKeyWithPasskey:async()=>{o(!0);try{await Z.enableUserE2ee(),a.current?.show({message:s(`account.e2ee.keypairGenSuccess`),intent:B.SUCCESS,icon:`tick`}),await n(),t?.()}catch(e){console.error(`[useE2eeActions] Generate key with Passkey failed:`,e),a.current?.show({message:e.message||s(`account.e2ee.keypairGenError`),intent:B.DANGER,icon:`error`})}finally{o(!1)}},handleUpgradeToPqc:async()=>{o(!0);try{await Z.rotateUserE2eeKey(),a.current?.show({message:s(`account.e2ee.upgradePqcSuccess`,`已成功升级到后量子混合加密 (P256-MLKEM768)`),intent:B.SUCCESS,icon:`tick`}),await n(),t?.()}catch(e){console.error(`[useE2eeActions] Upgrade to PQC failed:`,e),a.current?.show({message:e.message||s(`account.e2ee.upgradePqcError`,`升级到后量子加密失败`),intent:B.DANGER,icon:`error`})}finally{o(!1)}},handleEnrollPasskey:async()=>{o(!0);try{let e=await he(),r=e.length>0?e[0].id:`primary`;if(await Z.wrapCurrentKeyForPasskey(r))a.current?.show({message:s(`account.e2ee.enrollPasskeySuccess`,`已成功将通行密钥关联至端到端加密!`),intent:B.SUCCESS,icon:`tick`}),await n(),t?.();else throw Error(s(`account.e2ee.enrollPasskeyFailed`,`关联通行密钥失败`))}catch(e){console.error(`[useE2eeActions] Enroll passkey failed:`,e),a.current?.show({message:e.message||s(`account.e2ee.enrollPasskeyFailed`,`关联通行密钥失败`),intent:B.DANGER,icon:`error`})}finally{o(!1)}},isResetAlertOpen:c,setIsResetAlertOpen:l,handleResetAndReinit:async()=>{o(!0);try{await fetch(`/api/account/e2ee?purge=true`,{method:`DELETE`}),Z.clearStorage(),e?(await Z.enableUserE2ee(),a.current?.show({message:s(`account.e2ee.resetAndInitPasskeySuccess`,`密钥对已成功重置并使用通行密钥重新加密!`),intent:B.SUCCESS,icon:`tick`})):(a.current?.show({message:s(`account.e2ee.resetSuccessEnterRecovery`,`旧密钥已清除,请使用恢复密钥初始化新密钥对。`),intent:B.WARNING,icon:`refresh`}),i(!0)),await n(),t?.()}catch(e){console.error(`[useE2eeActions] Reset keypair failed:`,e),a.current?.show({message:e.message||s(`account.e2ee.resetFailed`,`重置密钥对失败`),intent:B.DANGER,icon:`error`})}finally{o(!1),l(!1)}}}}function zt({user:e,onRefresh:t,toasterRef:n}){let[r,i]=(0,Q.useState)(!1),a=It({user:e,onRefresh:t,toasterRef:n,setProcessing:i}),o=Lt({onRefresh:t,loadStatus:a.loadStatus,setIsUnlocked:a.setIsUnlocked,toasterRef:n,setProcessing:i}),s=Rt({hasPasskey:a.hasPasskey,onRefresh:t,loadStatus:a.loadStatus,setIsUnlocked:a.setIsUnlocked,setInitRecoveryDialogOpen:o.setInitRecoveryDialogOpen,toasterRef:n,setProcessing:i});return{status:a.status,loading:a.loading,processing:r,isUnlocked:a.isUnlocked,isPqc:a.isPqc,isLogsE2eeEnabled:a.isLogsE2eeEnabled,hasPasskey:a.hasPasskey,isDisableAlertOpen:a.isDisableAlertOpen,setIsDisableAlertOpen:a.setIsDisableAlertOpen,isRecoveryDialogOpen:o.isRecoveryDialogOpen,setIsRecoveryDialogOpen:o.setIsRecoveryDialogOpen,recoveryKeyInput:o.recoveryKeyInput,setRecoveryKeyInput:o.setRecoveryKeyInput,recoveryUnlockError:o.recoveryUnlockError,setRecoveryUnlockError:o.setRecoveryUnlockError,initRecoveryDialogOpen:o.initRecoveryDialogOpen,setInitRecoveryDialogOpen:o.setInitRecoveryDialogOpen,initRecoveryKeyInput:o.initRecoveryKeyInput,setInitRecoveryKeyInput:o.setInitRecoveryKeyInput,initRecoveryError:o.initRecoveryError,setInitRecoveryError:o.setInitRecoveryError,rotatedKey:o.rotatedKey,setRotatedKey:o.setRotatedKey,copiedKey:o.copiedKey,handleToggleLogs:a.handleToggleLogs,handleConfirmDisable:a.handleConfirmDisable,handleUnlock:s.handleUnlock,handleUnlockWithRecoveryKey:o.handleUnlockWithRecoveryKey,handleGenerateKeyWithPasskey:s.handleGenerateKeyWithPasskey,handleUpgradeToPqc:s.handleUpgradeToPqc,handleInitWithRecoveryKey:o.handleInitWithRecoveryKey,handleLockDevice:a.handleLockDevice,handleCopyRotatedKey:o.handleCopyRotatedKey,isResetAlertOpen:s.isResetAlertOpen,setIsResetAlertOpen:s.setIsResetAlertOpen,handleResetAndReinit:s.handleResetAndReinit,handleEnrollPasskey:s.handleEnrollPasskey}}const Bt=({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)(W,{style:{margin:0},children:t(`account.e2ee.title`,`E2EE`)}),(0,$.jsx)(K,{intent:e?B.SUCCESS:B.NONE,minimal:!0,round:!0,children:t(e?`account.e2ee.enabled`:`account.e2ee.disabled`)})]}),(0,$.jsx)(ae,{placement:`bottom-end`,usePortal:!0,content:(0,$.jsxs)(`div`,{className:`p-4 max-w-sm`,children:[(0,$.jsx)(re,{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)(I,{icon:`help`,variant:`minimal`,intent:B.NONE})})]})},Vt=({hasPasskey:e,processing:n,onGenerateKeyWithPasskey:r,onOpenInitRecoveryDialog:i})=>{let{t:a}=d();return(0,$.jsx)(z,{intent:B.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)(I,{intent:B.PRIMARY,small:!0,icon:(0,$.jsx)(t,{size:14}),text:a(`account.e2ee.initPasskeyBtn`),loading:n,onClick:r}):(0,$.jsx)(I,{intent:B.PRIMARY,small:!0,icon:(0,$.jsx)(u,{size:14}),text:a(`account.e2ee.addPasskeyBtn`),onClick:()=>{document.getElementById(`passkeys-section`)?.scrollIntoView({behavior:`smooth`})}}),(0,$.jsx)(I,{intent:B.NONE,small:!0,icon:(0,$.jsx)(u,{size:14}),text:a(`account.e2ee.initRecoveryBtn`),onClick:i})]})]})})},Ht=({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)(V,{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)(K,{intent:r?B.SUCCESS:B.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)(U,{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)(K,{minimal:!0,intent:B.PRIMARY,className:`text-[10px]`,children:v(`account.e2ee.pqcTag`,`PQC / NIST FIPS 203`)}):(0,$.jsx)(I,{small:!0,intent:B.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)(K,{minimal:!0,intent:B.SUCCESS,className:`text-[10px]`,children:v(`account.e2ee.unlocked`)}),o&&(e?.wrappedPasskeys?.length||0)===0&&g&&(0,$.jsx)(I,{small:!0,intent:B.PRIMARY,icon:(0,$.jsx)(t,{size:12}),text:v(`account.e2ee.enrollPasskeyBtn`,`关联当前通行密钥`),loading:s,onClick:g}),(0,$.jsx)(I,{small:!0,minimal:!0,intent:B.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)(I,{small:!0,minimal:!0,intent:B.PRIMARY,icon:(0,$.jsx)(f,{size:12}),text:v(`account.e2ee.unlockButton`),loading:s,onClick:m}),(0,$.jsx)(I,{small:!0,minimal:!0,intent:B.NONE,icon:(0,$.jsx)(t,{size:12}),text:v(`account.e2ee.unlockRecoveryButton`),onClick:h}),_&&(0,$.jsx)(I,{small:!0,minimal:!0,intent:B.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`)]})]})]})]})},Ut=({isOpen:e,processing:t,onConfirm:n,onCancel:r})=>{let{t:i}=d();return(0,$.jsx)(ne,{isOpen:e,confirmButtonText:i(`common.confirmDisable`),cancelButtonText:i(`common.cancel`),intent:B.DANGER,icon:`unlock`,onConfirm:n,onCancel:r,loading:t,children:(0,$.jsx)(`p`,{children:i(`account.e2ee.disableConfirm`)})})},Wt=({isOpen:e,onClose:t,recoveryKeyInput:n,setRecoveryKeyInput:r,recoveryUnlockError:i,processing:a,onSubmit:o})=>{let{t:s}=d();return(0,$.jsx)(L,{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:F,children:[(0,$.jsx)(`p`,{className:`text-xs text-gray-500 dark:text-gray-400 mb-3`,children:s(`account.e2ee.unlockWithRecoveryDesc`)}),i&&(0,$.jsx)(z,{intent:B.DANGER,className:`mb-3 text-xs`,children:i}),(0,$.jsx)(G,{label:s(`account.e2ee.recoveryKeyInputLabel`),labelFor:`recovery-key-input`,children:(0,$.jsx)(H,{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:R,children:(0,$.jsxs)(`div`,{className:J,children:[(0,$.jsx)(I,{onClick:t,text:s(`common.cancel`)}),(0,$.jsx)(I,{type:`submit`,intent:B.PRIMARY,loading:a,disabled:!n.trim(),text:s(`account.e2ee.unlockConfirm`)})]})})]})})},Gt=({isOpen:e,onClose:t,initRecoveryKeyInput:n,setInitRecoveryKeyInput:r,initRecoveryError:i,processing:a,onSubmit:o})=>{let{t:s}=d();return(0,$.jsx)(L,{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:F,children:[(0,$.jsx)(`p`,{className:`text-xs text-gray-500 dark:text-gray-400 mb-3`,children:s(`account.e2ee.initWithRecoveryDesc`)}),i&&(0,$.jsx)(z,{intent:B.DANGER,className:`mb-3 text-xs`,children:i}),(0,$.jsx)(G,{label:s(`account.e2ee.recoveryKeyInputLabel`),labelFor:`init-recovery-key-input`,children:(0,$.jsx)(H,{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:R,children:(0,$.jsxs)(`div`,{className:J,children:[(0,$.jsx)(I,{onClick:t,text:s(`common.cancel`)}),(0,$.jsx)(I,{type:`submit`,intent:B.PRIMARY,loading:a,disabled:!n.trim(),text:s(`account.e2ee.generateKeypairBtn`)})]})})]})})},Kt=({rotatedKey:e,onClose:t,copiedKey:n,onCopyKey:r})=>{let{t:i}=d();return(0,$.jsxs)(L,{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:F,children:[(0,$.jsx)(z,{intent:B.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)(I,{intent:B.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:R,children:(0,$.jsx)(`div`,{className:J,children:(0,$.jsx)(I,{intent:B.SUCCESS,onClick:t,text:i(`account.recoveryKey.savedAndClose`)})})})]})},qt=({isOpen:e,processing:t,hasPasskey:n,onConfirm:r,onCancel:i})=>{let{t:a}=d();return(0,$.jsx)(ne,{isOpen:e,confirmButtonText:a(`account.e2ee.confirmResetBtn`,`确认重置并重新生成`),cancelButtonText:a(`common.cancel`,`取消`),intent:B.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`,`确认后将引导您输入当前恢复密钥以完成新密钥对的生成与加密。`)})]})})},Jt=({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:ee,handleGenerateKeyWithPasskey:te,handleUpgradeToPqc:j,handleInitWithRecoveryKey:M,handleLockDevice:ne,handleCopyRotatedKey:N,isResetAlertOpen:F,setIsResetAlertOpen:re,handleResetAndReinit:I,handleEnrollPasskey:L}=zt({user:e,onRefresh:t,toasterRef:r});return(0,$.jsxs)(q,{elevation:P.ONE,className:`space-y-6`,children:[(0,$.jsx)(se,{ref:r}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(Bt,{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)(ie,{size:20})}):i?.hasKeys?(0,$.jsx)(Ht,{status:i,isLogsE2eeEnabled:l,isUnlocked:s,isPqc:c,hasPasskey:u,processing:o,loading:a,onToggleLogs:O,onUpgradeToPqc:j,onLockDevice:ne,onUnlockPasskey:A,onOpenRecoveryUnlockDialog:()=>{_(``),h(!0)},onEnrollPasskey:L,onOpenResetAlert:()=>re(!0)}):(0,$.jsx)(Vt,{hasPasskey:u,processing:o,onGenerateKeyWithPasskey:te,onOpenInitRecoveryDialog:()=>{w(``),S(``),b(!0)}})]}),(0,$.jsx)(Ut,{isOpen:f,processing:o,onConfirm:k,onCancel:()=>p(!1)}),(0,$.jsx)(qt,{isOpen:F,processing:o,hasPasskey:u,onConfirm:I,onCancel:()=>re(!1)}),(0,$.jsx)(Wt,{isOpen:m,onClose:()=>h(!1),recoveryKeyInput:g,setRecoveryKeyInput:_,recoveryUnlockError:v,processing:o,onSubmit:ee}),(0,$.jsx)(Gt,{isOpen:y,onClose:()=>b(!1),initRecoveryKeyInput:x,setInitRecoveryKeyInput:S,initRecoveryError:C,processing:o,onSubmit:M}),(0,$.jsx)(Kt,{rotatedKey:T,onClose:()=>E(null),copiedKey:D,onCopyKey:N})]})},Yt=()=>{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=de(),[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 Ae())}catch(e){console.error(e)}},T=async()=>{try{C(await Xe())}catch(e){console.error(e)}},E=(0,Q.useCallback)(async()=>{try{let e=await Ne();if(t(e),_(e.username),window.dispatchEvent(new Event(`user_updated`)),e.timezone){let{setSystemTimeZone:t}=await ee(async()=>{let{setSystemTimeZone:e}=await import(`./date-D8IlsmbP.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 ee(async()=>{let{setSystemLocale:e}=await import(`./date-D8IlsmbP.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:ue(`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)(K,{large:!0,round:!0,intent:e.role===`admin`?B.DANGER:B.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)(z,{intent:B.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)(jt,{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(!Be.test(g)){alert(l(`account.formatTipUsername`));return}y(!0);try{await Ee({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 Ee({timezone:e||``}),t(t=>t?{...t,timezone:e}:null);let{setSystemTimeZone:n}=await ee(async()=>{let{setSystemTimeZone:e}=await import(`./date-D8IlsmbP.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)(Mt,{me:e,onRefresh:E})]}),e&&(0,$.jsx)(bt,{user:e,onRefresh:E}),e&&(0,$.jsx)(Jt,{user:e,onRefresh:E}),e&&(0,$.jsx)(Ft,{user:e,onRefresh:E}),e&&(0,$.jsx)(Et,{hoveredSessionId:s,setHoveredSessionId:c}),e&&(0,$.jsx)(Tt,{hoveredSessionId:s,setHoveredSessionId:c}),e?.role===`admin`&&(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(V,{}),(0,$.jsx)(`div`,{className:`space-y-4`,children:(0,$.jsx)(Dt,{users:r,currentUserId:e.id,onRefresh:w,registrationEnabled:S.registration_enabled!==`false`,onRefreshSettings:T})}),(0,$.jsx)(V,{}),(0,$.jsx)(`div`,{className:`space-y-4`,children:(0,$.jsx)(Ot,{initialSettings:S,onRefresh:T})})]}),(0,$.jsx)(V,{}),(0,$.jsx)(`div`,{className:`space-y-4`,children:(0,$.jsx)(kt,{isAdmin:e?.role===`admin`,user:e})})]})};export{Yt as AccountView};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/TrendChart-CDyqUTCQ.js","assets/index-C5rHE6WK.js","assets/vendor-icons-other-BTYC6Wvz.js","assets/vendor-icons-16-BgwRBCeU.js","assets/rolldown-runtime-C4Xdq4VV.js","assets/vendor-icons-20-X5NPN60g.js","assets/vendor-react-De1zEwOV.js","assets/vendor-i18next-CevVzhh3.js","assets/vendor-ui-core-ClwQiwMI.js","assets/vendor-utils-rmW6cqPl.js","assets/index-BJJdTKLc.css","assets/DestinationMap-DAk0zqdP.js","assets/formatCountryName-JTcoEopY.js","assets/getFlagEmoji-DiZiGyWX.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,X as i,j as a,q as o,tt as s,v as c,vt as l}from"./vendor-react-De1zEwOV.js";import{S as u,b as d,x as f}from"./vendor-icons-other-BTYC6Wvz.js";import"./vendor-i18next-CevVzhh3.js";import{C as p,H as m,M as h,N as g,P as _,T as v,V as y,d as b,f as x,o as S,p as C,r as w,u as T,x as E}from"./vendor-ui-core-ClwQiwMI.js";import{_t as D}from"./vendor-utils-rmW6cqPl.js";import{$t as O,Q as k,X as A,Z as j,x as M,y as N}from"./index-C5rHE6WK.js";import{t as P}from"./getFlagEmoji-DiZiGyWX.js";import{i as F,n as I,r as L,t as R}from"./useLogsE2ee-Crd_rHKZ.js";var z=e(u(),1);function B(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 V=e(d(),1);const H=({title:e,data:t,intent:n})=>{let{t:a}=r(),o=[{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===`[Encrypted]`?(0,V.jsxs)(`span`,{className:`inline-flex items-center gap-1.5 text-gray-400 dark:text-gray-500 italic font-normal`,children:[(0,V.jsx)(i,{size:14,className:`text-amber-500 shrink-0`}),(0,V.jsx)(`span`,{children:a(`logs.encryptedRecord`,`[加密记录]`)})]}):e.domain===`[Decryption Failed]`?(0,V.jsxs)(`span`,{className:`inline-flex items-center gap-1.5 text-red-400 dark:text-red-500 italic font-normal`,children:[(0,V.jsx)(i,{size:14,className:`text-red-500 shrink-0`}),(0,V.jsx)(`span`,{children:a(`logs.decryptionFailed`,`[解密失败]`)})]}):e.domain},{key:`count`,cellClassName:`text-right`,render:e=>(0,V.jsx)(w,{minimal:!0,intent:n,className:`font-bold`,children:e.count})}];return(0,V.jsxs)(E,{elevation:m.ZERO,className:`dark:bg-gray-900 dark:border-gray-800 border border-gray-100 shadow-sm`,children:[(0,V.jsx)(h,{className:`mb-4 font-bold`,children:e}),(0,V.jsx)(T,{striped:!0,className:`w-full`,children:(0,V.jsxs)(`tbody`,{children:[t.map((e,t)=>(0,V.jsx)(`tr`,{children:o.map(n=>(0,V.jsx)(`td`,{className:n.cellClassName,children:n.render(e,t)},n.key))},t)),t.length===0&&(0,V.jsx)(`tr`,{children:(0,V.jsx)(`td`,{colSpan:o.length,className:`text-center py-8 opacity-50`,children:a(`analytics.noData`)})})]})})]})};function U(e){let[t,n]=(0,z.useState)(null),[r,i]=(0,z.useState)(!0),[a,o]=(0,z.useState)(`24h`),[s,c]=(0,z.useState)({start:``,end:``}),[l,u]=(0,z.useState)(null),[d,f]=(0,z.useState)([]),[p,m]=(0,z.useState)(30);(0,z.useEffect)(()=>{A(e).then(e=>f(e)).catch(e=>console.error(`[useAnalyticsData] Failed to load access points:`,e))},[e]),(0,z.useEffect)(()=>{k(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,z.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{(M.isProfileUnlocked(e)||M.isUnlocked())&&await N.reDecryptLocalLogs(e)}catch{}try{if(await N.init()){let t=await N.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.top_blocked?.some(e=>e.domain&&e.domain!==`[Encrypted]`&&e.domain!==`[Decryption Failed]`)||e.clients?.some(e=>e.client_ip&&e.client_ip!==`[Encrypted]`&&e.client_ip!==`[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.some(e=>e.domain!==`[Encrypted]`)?e.top_allowed:s.top_allowed||[],top_blocked:t&&e?.top_blocked?.length&&e.top_blocked.some(e=>e.domain!==`[Encrypted]`)?e.top_blocked:s.top_blocked||[],clients:t&&e?.clients?.length&&e.clients.some(e=>e.client_ip!==`[Encrypted]`)?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{let t=M.isProfileUnlocked(e)||M.isUnlocked();N.syncProfileLogs(e,void 0,c,void 0,t).then(async r=>{if(r>0||t)try{let t=await N.queryAnalytics({profileId:e,since:c,until:l,bucketSec:u,accessPointId:o||void 0});(t.destinations?.length>0||t.top_allowed?.length>0||t.top_blocked?.length>0||t.clients?.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,z.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 W=[{key:`10m`,days:.007},{key:`1h`,days:.0416},{key:`24h`,days:1},{key:`7d`,days:7},{key:`30d`,days:30}];const G=({range:e,setRange:t,customRange:n,setCustomRange:i,logRetentionDays:a,accessPoints:o,accessPointIdFilter:s,setAccessPointIdFilter:c,loading:u,onApplyCustom:d})=>{let{t:f}=r(),m=new Date().toLocaleString(`sv-SE`).replace(` `,`T`).slice(0,16);return(0,V.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,V.jsxs)(p,{variant:`minimal`,children:[W.filter(e=>e.days<=a).map(e=>e.key).map(n=>(0,V.jsx)(g,{active:e===n,onClick:()=>t(n),text:n.toUpperCase()},n)),(0,V.jsx)(v,{content:(0,V.jsxs)(`div`,{className:`p-4 space-y-4 w-64`,children:[(0,V.jsx)(h,{children:f(`analytics.customRange`)}),(0,V.jsx)(C,{label:f(`analytics.startTime`),children:(0,V.jsx)(x,{type:`datetime-local`,max:n.end||m,value:n.start,onChange:e=>i({...n,start:e.target.value})})}),(0,V.jsx)(C,{label:f(`analytics.endTime`),children:(0,V.jsx)(x,{type:`datetime-local`,min:n.start,max:m,value:n.end,onChange:e=>i({...n,end:e.target.value})})}),(0,V.jsx)(g,{fill:!0,intent:y.PRIMARY,text:f(`analytics.apply`),onClick:d})]}),children:(0,V.jsx)(g,{active:e===`custom`,icon:(0,V.jsx)(l,{size:14,className:`mr-1`}),text:f(`analytics.custom`)})})]}),(0,V.jsxs)(`div`,{className:`flex items-center gap-4`,children:[o.length>0&&(0,V.jsx)(b,{value:s||``,onChange:e=>c(e.target.value||null),options:[{label:`${f(`logs.allAccessPoint`)}`,value:``},...o.map(e=>({label:e.name,value:e.id}))],minimal:!0}),u&&(0,V.jsx)(_,{size:16})]})]})},K=({title:e,value:t,icon:n})=>(0,V.jsxs)(E,{elevation:m.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,V.jsx)(`div`,{className:`p-3 bg-gray-50 dark:bg-gray-800 rounded-lg`,children:n}),(0,V.jsxs)(`div`,{children:[(0,V.jsx)(`div`,{className:`text-xs text-gray-500 font-medium uppercase tracking-wider`,children:e}),(0,V.jsx)(`div`,{className:`text-xl font-bold dark:text-white`,children:t})]})]}),q=({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,V.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,V.jsx)(c,{className:`text-blue-500`,size:20})},{title:i(`analytics.blocked`),value:l.toLocaleString(),icon:(0,V.jsx)(a,{className:`text-red-500`,size:20})},{title:i(`analytics.redirected`),value:u.toLocaleString(),icon:(0,V.jsx)(n,{className:`text-amber-500`,size:20})},{title:i(`analytics.blockRate`),value:`${d}%`,icon:(0,V.jsx)(t,{className:`text-green-500`,size:20})},{title:i(`analytics.activeIPs`),value:e?.clients.length.toString()||`0`,icon:(0,V.jsx)(s,{className:`text-purple-500`,size:20})}].map((e,t)=>(0,V.jsx)(K,{title:e.title,value:e.value,icon:e.icon},t))})},J=({clients:e})=>{let{t}=r();return(0,V.jsx)(S,{title:t(`analytics.clientActivity`),icon:(0,V.jsx)(s,{size:16}),children:(0,V.jsxs)(T,{striped:!0,className:`w-full mt-2`,children:[(0,V.jsx)(`thead`,{children:(0,V.jsxs)(`tr`,{children:[(0,V.jsx)(`th`,{className:`text-xs uppercase opacity-60`,children:t(`analytics.ipAddress`)}),(0,V.jsx)(`th`,{className:`text-xs uppercase opacity-60`,children:t(`analytics.location`)}),(0,V.jsx)(`th`,{className:`text-xs uppercase opacity-60 text-right`,children:t(`analytics.queries`)})]})}),(0,V.jsxs)(`tbody`,{children:[e?.map((e,n)=>(0,V.jsxs)(`tr`,{children:[(0,V.jsx)(`td`,{className:`font-mono text-xs`,children:e.client_ip===`[Encrypted]`?(0,V.jsxs)(`span`,{className:`inline-flex items-center gap-1.5 text-gray-400 dark:text-gray-500 italic`,children:[(0,V.jsx)(i,{size:12,className:`text-amber-500 shrink-0`}),(0,V.jsx)(`span`,{children:t(`logs.encryptedRecord`,`[加密记录]`)})]}):e.client_ip===`[Decryption Failed]`?(0,V.jsxs)(`span`,{className:`inline-flex items-center gap-1.5 text-red-400 dark:text-red-500 italic`,children:[(0,V.jsx)(i,{size:12,className:`text-red-500 shrink-0`}),(0,V.jsx)(`span`,{children:t(`logs.decryptionFailed`,`[解密失败]`)})]}):e.client_ip||`-`}),(0,V.jsx)(`td`,{children:(0,V.jsx)(w,{minimal:!0,children:P(e.geo_country)})}),(0,V.jsx)(`td`,{className:`text-right font-bold`,children:e.count})]},n)),(!e||e.length===0)&&(0,V.jsx)(`tr`,{children:(0,V.jsx)(`td`,{colSpan:3,className:`text-center py-8 opacity-50`,children:t(`analytics.noData`)})})]})]})})};var Y=(0,z.lazy)(()=>f(()=>import(`./TrendChart-CDyqUTCQ.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10])).then(e=>({default:e.TrendChart}))),X=(0,z.lazy)(()=>f(()=>import(`./DestinationMap-DAk0zqdP.js`),__vite__mapDeps([11,1,2,3,4,5,6,7,8,9,10,12,13])).then(e=>({default:e.DestinationMap}))),Z=()=>(0,V.jsx)(`div`,{className:`h-64 flex items-center justify-center`,children:(0,V.jsx)(_,{size:30})});const Q=({profileId:e,toasterRef:t})=>{let{t:n}=r(),i=O(),{data:a,loading:s,range:c,setRange:l,customRange:u,setCustomRange:d,accessPointIdFilter:f,setAccessPointIdFilter:p,accessPoints:g,logRetentionDays:v,fetchData:b}=U(e),{isE2eeEnabled:x,isE2eeUnlocked:C,unlocking:T,recoveryDialogOpen:k,setRecoveryDialogOpen:A,recoveryKeyInput:j,setRecoveryKeyInput:M,recoveryError:N,setRecoveryError:P,rotatedKey:W,setRotatedKey:K,copiedKey:Q,handleCopyRotatedKey:$,handleUnlockPasskey:ee,handleUnlockRecoveryKey:te}=R({profileId:e,range:c,onUnlocked:()=>{b(c,u.start,u.end,f)},toasterRef:t}),ne=!!(a&&(a.top_allowed?.some(e=>e.domain===`[Encrypted]`)||a.top_blocked?.some(e=>e.domain===`[Encrypted]`)||a.clients?.some(e=>e.client_ip===`[Encrypted]`)));if(s&&!a)return(0,V.jsx)(`div`,{className:`p-20 flex justify-center`,children:(0,V.jsx)(_,{size:50})});let re=B(a,c,u);return(0,V.jsxs)(`div`,{className:D(`max-w-7xl mx-auto space-y-6`,i?`p-0`:`p-6`),children:[(0,V.jsx)(G,{range:c,setRange:l,customRange:u,setCustomRange:d,logRetentionDays:v,accessPoints:g,accessPointIdFilter:f,setAccessPointIdFilter:p,loading:s,onApplyCustom:()=>{l(`custom`),b(`custom`,u.start,u.end,f)}}),(x||ne)&&!C&&(0,V.jsx)(F,{isMobile:i,unlocking:T,onUnlockPasskey:ee,onOpenRecoveryDialog:()=>{P(``),M(``),A(!0)}}),(0,V.jsx)(q,{data:a}),(0,V.jsxs)(E,{elevation:m.ONE,className:`dark:bg-gray-900 dark:border-gray-800 relative`,children:[(0,V.jsxs)(h,{className:`mb-4 font-bold flex items-center gap-2`,children:[n(`analytics.queryTrend`),(0,V.jsx)(w,{minimal:!0,round:!0,children:c===`custom`?n(`analytics.custom`):c.toUpperCase()})]}),(0,V.jsx)(z.Suspense,{fallback:(0,V.jsx)(Z,{}),children:(0,V.jsx)(Y,{chartData:re,range:c})})]}),(0,V.jsxs)(`div`,{className:`grid grid-cols-1 lg:grid-cols-2 gap-6`,children:[(0,V.jsx)(H,{title:n(`analytics.topAllowed`),data:a?.top_allowed||[],intent:y.SUCCESS}),(0,V.jsx)(H,{title:n(`analytics.topBlocked`),data:a?.top_blocked||[],intent:y.DANGER})]}),(0,V.jsxs)(`div`,{className:`grid gap-6 grid-cols-1`,children:[(0,V.jsx)(S,{title:n(`analytics.destinationDistribution`),icon:(0,V.jsx)(o,{size:16}),children:(0,V.jsx)(z.Suspense,{fallback:(0,V.jsx)(Z,{}),children:(0,V.jsx)(X,{destinations:a?.destinations||[],profileId:e||``,range:c,customRange:u,accessPointId:f||void 0})})}),(0,V.jsx)(J,{clients:a?.clients})]}),(0,V.jsx)(L,{isOpen:k,onClose:()=>A(!1),recoveryKeyInput:j,setRecoveryKeyInput:M,recoveryError:N,unlocking:T,onSubmit:te}),(0,V.jsx)(I,{rotatedKey:W,onClose:()=>K(null),copiedKey:Q,onCopyKey:$})]})};export{Q as AnalyticsView};
|
|
@@ -1 +1 @@
|
|
|
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-De1zEwOV.js";import{S as p,b as m}from"./vendor-icons-other-BTYC6Wvz.js";import"./vendor-i18next-CevVzhh3.js";import"./vendor-utils-rmW6cqPl.js";import{Z as h,k as g,y as _}from"./index-CrB_HdIL.js";import{n as v,t as y}from"./formatCountryName-JTcoEopY.js";import{t as b}from"./getFlagEmoji-DiZiGyWX.js";var x=e(p(),1);function S(e){let[t,n]=(0,x.useState)(null);(0,x.useEffect)(()=>{g().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:g})=>{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 _.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)}h(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&&g()}},t=setTimeout(()=>{document.addEventListener(`click`,e,!0)},0);return()=>{clearTimeout(t),document.removeEventListener(`click`,e,!0)}},[m,g]),(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?g: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(),g()},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-De1zEwOV.js";import{S as p,b as m}from"./vendor-icons-other-BTYC6Wvz.js";import"./vendor-i18next-CevVzhh3.js";import"./vendor-utils-rmW6cqPl.js";import{Z as h,k as g,y as _}from"./index-C5rHE6WK.js";import{n as v,t as y}from"./formatCountryName-JTcoEopY.js";import{t as b}from"./getFlagEmoji-DiZiGyWX.js";var x=e(p(),1);function S(e){let[t,n]=(0,x.useState)(null);(0,x.useEffect)(()=>{g().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:g})=>{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 _.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)}h(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&&g()}},t=setTimeout(()=>{document.addEventListener(`click`,e,!0)},0);return()=>{clearTimeout(t),document.removeEventListener(`click`,e,!0)}},[m,g]),(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?g: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(),g()},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 +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-De1zEwOV.js";import{S as l,b as u}from"./vendor-icons-other-BTYC6Wvz.js";import"./vendor-i18next-CevVzhh3.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-ClwQiwMI.js";import{_t as T}from"./vendor-utils-rmW6cqPl.js";import{$ as E,$t as D,G as O,R as k,U as A,V as j,ct as M,h as N,j as P,ut as F}from"./index-CrB_HdIL.js";var I=e(l(),1);const L=()=>{let{t:e}=i(),[t,n]=(0,I.useState)([]);return(0,I.useEffect)(()=>{P().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?N(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,E]=(0,I.useState)(null),[D,O]=(0,I.useState)(null),[k,j]=(0,I.useState)(!1),[M,P]=(0,I.useState)(!1),[F,L]=(0,I.useState)(!1),z=(0,I.useRef)(0),B=()=>{z.current++,w(!1),S(``),E(null),O(null),P(!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),O(null),E(null),P(!1);try{let r=await A(e,i,t);z.current===n&&E(r)}catch(e){z.current===n&&O(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),P(!0)}catch(e){O(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),E(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()})]}),D&&(0,R.jsx)(g,{intent:v.DANGER,className:`text-xs`,children:D}),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:k,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?N(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=D(),[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 E(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 E(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 M(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 k(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 O(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 j(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};
|
|
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-De1zEwOV.js";import{S as l,b as u}from"./vendor-icons-other-BTYC6Wvz.js";import"./vendor-i18next-CevVzhh3.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-ClwQiwMI.js";import{_t as T}from"./vendor-utils-rmW6cqPl.js";import{$ as E,$t as D,G as O,R as k,U as A,V as j,ct as M,h as N,j as P,ut as F}from"./index-C5rHE6WK.js";var I=e(l(),1);const L=()=>{let{t:e}=i(),[t,n]=(0,I.useState)([]);return(0,I.useEffect)(()=>{P().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?N(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,E]=(0,I.useState)(null),[D,O]=(0,I.useState)(null),[k,j]=(0,I.useState)(!1),[M,P]=(0,I.useState)(!1),[F,L]=(0,I.useState)(!1),z=(0,I.useRef)(0),B=()=>{z.current++,w(!1),S(``),E(null),O(null),P(!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),O(null),E(null),P(!1);try{let r=await A(e,i,t);z.current===n&&E(r)}catch(e){z.current===n&&O(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),P(!0)}catch(e){O(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),E(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()})]}),D&&(0,R.jsx)(g,{intent:v.DANGER,className:`text-xs`,children:D}),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:k,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?N(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=D(),[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 E(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 E(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 M(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 k(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 O(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 j(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};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/services-B-OKDv75.js","assets/index-C5rHE6WK.js","assets/vendor-icons-other-BTYC6Wvz.js","assets/vendor-icons-16-BgwRBCeU.js","assets/rolldown-runtime-C4Xdq4VV.js","assets/vendor-icons-20-X5NPN60g.js","assets/vendor-react-De1zEwOV.js","assets/vendor-i18next-CevVzhh3.js","assets/vendor-ui-core-ClwQiwMI.js","assets/vendor-utils-rmW6cqPl.js","assets/index-BJJdTKLc.css"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{i as e}from"./rolldown-runtime-C4Xdq4VV.js";import{A as t,Et as n,G as r,H as i,Qt as a,V as o,X as s,b as c,j as l,nt as u,q as d,tt as f,vt as p,xt as m,yt as h}from"./vendor-react-De1zEwOV.js";import{S as g,b as _,x as v}from"./vendor-icons-other-BTYC6Wvz.js";import"./vendor-i18next-CevVzhh3.js";import{C as y,E as b,M as x,N as S,P as C,S as w,T,V as E,a as D,f as O,h as k,l as A,o as j,p as M,r as N,u as P,w as F,x as I}from"./vendor-ui-core-ClwQiwMI.js";import{_t as L}from"./vendor-utils-rmW6cqPl.js";import{$t as ee,Q as R,X as te,Z as z,et as B,h as V,tt as H,v as U,x as W,y as G}from"./index-C5rHE6WK.js";import{n as K,t as q}from"./formatCountryName-JTcoEopY.js";import{t as J}from"./getFlagEmoji-DiZiGyWX.js";import{i as ne,n as re,r as ie,t as ae}from"./useLogsE2ee-Crd_rHKZ.js";import{t as Y}from"./SwipeableDrawer-BrlOF_Xg.js";var X=e(g(),1),Z=e(_(),1);const oe=({range:e,setRange:t,customRange:n,setCustomRange:r,nowStr:i,fetchLogs:o,isMobile:s,logRetentionDays:c})=>{let{t:l}=a(),u=[{key:`10m`,days:.007},{key:`1h`,days:.0416},{key:`24h`,days:1},{key:`7d`,days:7},{key:`30d`,days:30}].filter(e=>e.days<=c).map(e=>e.key);return(0,Z.jsx)(`div`,{className:`overflow-x-auto pb-1 -mx-4 px-4 md:mx-0 md:px-0`,children:(0,Z.jsxs)(y,{minimal:s,variant:s?void 0:`minimal`,children:[u.map(n=>(0,Z.jsx)(S,{active:e===n,onClick:()=>t(n),text:n.toUpperCase(),small:s},n)),(0,Z.jsx)(T,{content:(0,Z.jsxs)(`div`,{className:`p-4 space-y-2 w-64`,children:[(0,Z.jsx)(x,{children:l(`analytics.customRange`)}),(0,Z.jsx)(M,{label:l(`analytics.startTime`),children:(0,Z.jsx)(O,{type:`datetime-local`,max:n.end||i,value:n.start,onChange:e=>r({...n,start:e.target.value})})}),(0,Z.jsx)(M,{label:l(`analytics.endTime`),children:(0,Z.jsx)(O,{type:`datetime-local`,min:n.start,max:i,value:n.end,onChange:e=>r({...n,end:e.target.value})})}),(0,Z.jsx)(S,{fill:!0,intent:E.PRIMARY,text:l(`analytics.apply`),onClick:()=>{t(`custom`),o(`custom`,!0)}})]}),children:(0,Z.jsx)(S,{active:e===`custom`,icon:(0,Z.jsx)(p,{size:14}),text:s?``:l(`analytics.custom`),small:s})})]})})},se=({statusFilter:e,setStatusFilter:t,isMobile:n})=>{let{t:r}=a(),i=(0,Z.jsxs)(b,{children:[(0,Z.jsx)(F,{icon:e===null?`tick`:void 0,text:r(`logs.allStatus`),onClick:()=>t(null)}),(0,Z.jsx)(A,{}),(0,Z.jsx)(F,{icon:e===`PASS`?`tick`:void 0,intent:E.SUCCESS,text:r(`logs.onlyPass`),onClick:()=>t(`PASS`)}),(0,Z.jsx)(F,{icon:e===`BLOCK`?`tick`:void 0,intent:E.DANGER,text:r(`logs.onlyBlock`),onClick:()=>t(`BLOCK`)}),(0,Z.jsx)(F,{icon:e===`REDIRECT`?`tick`:void 0,intent:E.WARNING,text:r(`logs.onlyRedirect`),onClick:()=>t(`REDIRECT`)})]}),o=(()=>{switch(e){case`PASS`:return{text:r(`logs.statusPass`),intent:E.SUCCESS};case`BLOCK`:return{text:r(`logs.statusBlock`),intent:E.DANGER};case`REDIRECT`:return{text:r(`logs.statusRedirect`),intent:E.WARNING};default:return{text:r(`logs.allStatus`),intent:E.NONE}}})();return(0,Z.jsx)(T,{content:i,placement:`bottom-start`,children:(0,Z.jsx)(S,{icon:(0,Z.jsx)(u,{size:14}),rightIcon:`caret-down`,intent:o.intent,text:o.text,variant:`outlined`,fill:n})})},ce=({accessPointIdFilter:e,setAccessPointIdFilter:t,accessPoints:n,isMobile:i})=>{let{t:o}=a(),s=(0,Z.jsxs)(b,{children:[(0,Z.jsx)(F,{icon:e===null?`tick`:void 0,text:o(`logs.allAccessPoint`),onClick:()=>t(null)}),(0,Z.jsx)(A,{}),n.map(n=>(0,Z.jsx)(F,{icon:e===n.id?`tick`:void 0,text:n.name,onClick:()=>t(n.id)},n.id))]}),c=e&&n.find(t=>t.id===e)?.name||o(`logs.allAccessPoint`);return(0,Z.jsx)(T,{content:s,placement:`bottom-start`,children:(0,Z.jsx)(S,{icon:(0,Z.jsx)(r,{size:14}),rightIcon:`caret-down`,intent:e?E.PRIMARY:E.NONE,text:c,variant:`outlined`,fill:i})})},le=Array.from(new Set(Object.values(K))).sort((e,t)=>e.localeCompare(t)),ue=({destCountryFilter:e,setDestCountryFilter:t,isMobile:n})=>{let{t:r,i18n:i}=a(),[o,s]=(0,X.useState)(!1),[c,l]=(0,X.useState)(``),u=(0,X.useMemo)(()=>{let e=i.language;return le.map(t=>{let n=q(t,e),r=q(t,`en`);return{code:t,name:n||r||t,searchStr:`${t} ${n} ${r}`.toLowerCase()}})},[i.language]),d=(0,X.useMemo)(()=>{let e=c.trim().toLowerCase();return e?u.filter(t=>t.searchStr.includes(e)):u},[u,c]),p=(0,Z.jsxs)(`div`,{className:`w-72 flex flex-col p-1.5`,children:[(0,Z.jsx)(`div`,{className:`pb-1.5`,children:(0,Z.jsx)(O,{leftIcon:`search`,placeholder:r(`logs.searchCountry`,`Search country...`),value:c,onChange:e=>l(e.target.value),small:!0,autoFocus:!0,rightElement:c?(0,Z.jsx)(S,{icon:`cross`,variant:`minimal`,small:!0,onClick:()=>l(``)}):void 0})}),(0,Z.jsxs)(b,{className:`max-h-64 overflow-y-auto`,children:[!c&&(0,Z.jsxs)(Z.Fragment,{children:[(0,Z.jsx)(F,{icon:e===null?`tick`:void 0,text:r(`logs.allCountry`),onClick:()=>{t(null),s(!1)}}),(0,Z.jsx)(A,{})]}),d.length===0?(0,Z.jsx)(F,{disabled:!0,text:r(`logs.noMatchingCountries`,`No matching countries found`)}):d.map(n=>(0,Z.jsx)(F,{icon:e===n.code?`tick`:void 0,text:(0,Z.jsxs)(`span`,{className:`flex items-center justify-between gap-2 w-full`,children:[(0,Z.jsxs)(`span`,{className:`truncate`,children:[J(n.code),` `,n.name]}),(0,Z.jsx)(`span`,{className:`text-xs text-gray-400 shrink-0 font-mono`,children:n.code})]}),onClick:()=>{t(n.code),s(!1)}},n.code))]})]}),m=e?`${J(e)} ${q(e,i.language)||e} (${e})`:r(`logs.allCountry`);return(0,Z.jsx)(T,{content:p,placement:`bottom-start`,isOpen:o,onInteraction:e=>{s(e),e||l(``)},children:(0,Z.jsx)(S,{icon:(0,Z.jsx)(f,{size:14}),rightIcon:`caret-down`,intent:e?E.PRIMARY:E.NONE,text:m,variant:`outlined`,fill:n})})},de=({profileId:e,range:t,customRange:n,destCountryFilter:r,accessPointIdFilter:o,ispFilter:s,setIspFilter:c,isMobile:l})=>{let{t:u}=a(),[d,f]=(0,X.useState)(!1),[p,m]=(0,X.useState)([]),[h,g]=(0,X.useState)(!1),[_,v]=(0,X.useState)(``),y=(0,X.useRef)(``),x=`${e}:${t}:${n.start?Math.floor(new Date(n.start).getTime()/1e3):``}:${n.end?Math.floor(new Date(n.end).getTime()/1e3):``}:${r||``}:${o||``}`,w=async()=>{g(!0);try{let i=Math.floor(Date.now()/1e3),a,s=i,c=new URLSearchParams;if(t===`custom`&&n.start&&n.end)a=Math.floor(new Date(n.start).getTime()/1e3),s=Math.floor(new Date(n.end).getTime()/1e3),c.set(`range`,`custom`),c.set(`start`,String(a)),c.set(`end`,String(s));else{switch(t){case`10m`:a=i-600;break;case`1h`:a=i-3600;break;case`24h`:a=i-86400;break;case`7d`:a=i-604800;break;case`30d`:a=i-2592e3;break;default:a=i-86400;break}c.set(`range`,t)}r&&c.set(`country_code`,r),o&&c.set(`access_point_id`,o);try{let t=await G.queryISPs({profileId:e,countryCode:r||void 0,since:a,until:s,accessPointId:o||void 0});if(t&&t.length>0){m(t),y.current=x,g(!1);return}}catch(e){console.warn(`[IspFilter] Local SQLite query failed, falling back to server:`,e)}let l=await z(e,`isps`,c.toString());m(Array.isArray(l)?l:[]),y.current=x}catch(e){console.error(`Failed to fetch ISPs for filter`,e)}finally{g(!1)}},D=e=>{f(e),e?y.current!==x&&w():v(``)},k=(0,X.useMemo)(()=>{let e=_.trim().toLowerCase();return e?p.filter(t=>t.name.toLowerCase().includes(e)):p},[p,_]),j=(0,Z.jsxs)(`div`,{className:`w-72 flex flex-col p-1.5`,children:[(0,Z.jsx)(`div`,{className:`pb-1.5`,children:(0,Z.jsx)(O,{leftIcon:`search`,placeholder:u(`logs.searchIsp`,`Search ISP...`),value:_,onChange:e=>v(e.target.value),small:!0,autoFocus:!0,rightElement:_?(0,Z.jsx)(S,{icon:`cross`,variant:`minimal`,small:!0,onClick:()=>v(``)}):void 0})}),(0,Z.jsx)(b,{className:`max-h-64 overflow-y-auto`,children:h?(0,Z.jsxs)(`div`,{className:`flex items-center justify-center p-6 text-gray-500 gap-2`,children:[(0,Z.jsx)(C,{size:16}),(0,Z.jsx)(`span`,{className:`text-xs`,children:u(`logs.loadingIsps`,`Loading ISPs...`)})]}):(0,Z.jsxs)(Z.Fragment,{children:[!_&&(0,Z.jsxs)(Z.Fragment,{children:[(0,Z.jsx)(F,{icon:s===null?`tick`:void 0,text:u(`logs.allIsp`),onClick:()=>{c(null),f(!1)}}),(0,Z.jsx)(A,{})]}),k.length===0?(0,Z.jsx)(F,{disabled:!0,text:u(`logs.noMatchingIsps`,`No matching ISPs found`)}):k.map(e=>(0,Z.jsx)(F,{icon:s===e.name?`tick`:void 0,text:(0,Z.jsxs)(`span`,{className:`flex items-center justify-between gap-2 w-full`,children:[(0,Z.jsx)(`span`,{className:`truncate`,title:e.name,children:e.name}),(0,Z.jsx)(`span`,{className:`text-xs text-gray-400 shrink-0 font-mono`,children:e.count.toLocaleString()})]}),onClick:()=>{c(e.name),f(!1)}},e.name))]})})]}),M=s||u(`logs.allIsp`);return(0,Z.jsx)(T,{content:j,placement:`bottom-start`,isOpen:d,onInteraction:D,children:(0,Z.jsx)(S,{icon:(0,Z.jsx)(i,{size:14}),rightIcon:`caret-down`,intent:s?E.PRIMARY:E.NONE,text:M,variant:`outlined`,fill:l})})},fe=({profileId:e,range:t,setRange:n,customRange:r,setCustomRange:i,nowStr:o,fetchLogs:s,isMobile:c,realtimeRefresh:l,setRealtimeRefresh:u,statusFilter:d,setStatusFilter:f,accessPointIdFilter:p,setAccessPointIdFilter:m,accessPoints:h,destCountryFilter:g,setDestCountryFilter:_,ispFilter:v,setIspFilter:y,searchQuery:b,setSearchQuery:x,stats:C,logRetentionDays:w,onExport:T,exporting:D,loading:A=!1,syncing:j=!1})=>{let{t:M}=a(),[P,F]=(0,X.useState)(!0),I=d!==null||p!==null||g!==null||v!==null;return(0,Z.jsxs)(`div`,{className:`p-4 ${c&&P?`space-y-0`:`space-y-4`} shrink-0 bg-white/50 dark:bg-gray-900/50 backdrop-blur-sm border-b border-gray-100 dark:border-gray-800`,children:[(0,Z.jsxs)(`div`,{className:`flex flex-col md:flex-row md:items-center justify-between gap-4`,children:[(0,Z.jsxs)(`div`,{className:`flex items-center justify-between w-full md:w-auto`,children:[(0,Z.jsxs)(`div`,{children:[(0,Z.jsxs)(`h2`,{className:`bp6-heading flex flex-wrap items-center gap-2 text-xl md:text-2xl m-0`,children:[M(`logs.title`),` `,(!c||!P)&&(0,Z.jsx)(N,{minimal:!0,round:!0,children:t===`custom`?M(`analytics.custom`):t.toUpperCase()}),C&&(0,Z.jsxs)(Z.Fragment,{children:[(0,Z.jsx)(N,{minimal:!0,round:!0,children:C.total.toLocaleString()}),(0,Z.jsx)(N,{minimal:!0,round:!0,intent:E.SUCCESS,children:C.pass.toLocaleString()}),(0,Z.jsx)(N,{minimal:!0,round:!0,intent:E.DANGER,children:C.block.toLocaleString()}),(0,Z.jsx)(N,{minimal:!0,round:!0,intent:E.WARNING,children:C.redirect.toLocaleString()})]})]}),!c&&(0,Z.jsx)(`p`,{className:`bp6-text-muted mt-1`,children:M(`logs.subtitle`)})]}),c&&(0,Z.jsx)(S,{icon:P?`chevron-down`:`chevron-up`,variant:`minimal`,onClick:()=>F(!P)})]}),(!c||!P)&&(0,Z.jsxs)(`div`,{className:`flex flex-col items-stretch md:items-end gap-2`,children:[(0,Z.jsx)(oe,{range:t,setRange:n,customRange:r,setCustomRange:i,nowStr:o,fetchLogs:s,isMobile:c,logRetentionDays:w}),(0,Z.jsxs)(`div`,{className:`flex items-center justify-end gap-4`,children:[(0,Z.jsx)(S,{icon:`download`,onClick:T,loading:D,title:M(`logs.export`,`Export Logs`),text:c?void 0:M(`logs.export`,`Export Logs`)}),(0,Z.jsx)(k,{label:M(`logs.realtime`),checked:l,onChange:e=>u(e.target.checked),className:`mb-0!`}),(0,Z.jsx)(S,{icon:`refresh`,onClick:()=>s(t,!0,!1,!0),loading:A||j,variant:`minimal`,small:c})]})]})]}),(!c||!P)&&(0,Z.jsxs)(`div`,{className:`flex flex-col md:flex-row items-stretch md:items-center justify-between gap-3`,children:[(0,Z.jsxs)(`div`,{className:`grid grid-cols-2 md:flex md:items-center gap-2`,children:[I&&(0,Z.jsx)(`div`,{className:`col-span-2 md:contents`,children:(0,Z.jsx)(S,{icon:`filter-remove`,onClick:()=>{f(null),m(null),_(null),y(null)},variant:`minimal`,title:M(`logs.clearFilters`),text:c?M(`logs.clearFilters`):void 0,fill:c})}),(0,Z.jsx)(se,{statusFilter:d,setStatusFilter:f,isMobile:c}),h.length>0&&(0,Z.jsx)(ce,{accessPointIdFilter:p,setAccessPointIdFilter:m,accessPoints:h,isMobile:c}),(0,Z.jsx)(ue,{destCountryFilter:g,setDestCountryFilter:_,isMobile:c}),(0,Z.jsx)(de,{profileId:e,range:t,customRange:r,destCountryFilter:g,accessPointIdFilter:p,ispFilter:v,setIspFilter:y,isMobile:c})]}),(0,Z.jsx)(`div`,{className:`flex items-center gap-2 flex-1 md:max-w-md justify-end`,children:(0,Z.jsx)(`div`,{className:`flex-1 md:max-w-xs`,children:(0,Z.jsx)(O,{leftIcon:`search`,placeholder:M(`logs.searchPlaceholder`),value:b,onChange:e=>x(e.target.value),rightElement:b?(0,Z.jsx)(S,{icon:`cross`,minimal:!0,onClick:()=>x(``)}):void 0,fill:!0})})})]})]})},pe=({logs:e,setSelectedLog:t,setIsDrawerOpen:n,lastLogElementRef:r,prevLatestTimestamp:i,realtimeRefresh:o})=>{let{t:c}=a();return(0,Z.jsx)(`div`,{className:`space-y-3 py-4`,children:e.map((a,l)=>{let u=o&&i!==null&&a.timestamp>i,d=(a.encrypt_version??0)>0||!!(a.kem_key_id||a.encrypted_payload),f=d&&(!a.domain||a.domain===`[Encrypted]`),p=d&&!!(a.domain&&a.domain!==`[Encrypted]`);return(0,Z.jsxs)(I,{interactive:!0,onClick:()=>{t(a),n(!0)},className:L(`p-3 dark:bg-gray-900 rounded-xl border border-gray-200 dark:border-gray-800 shadow-sm overflow-hidden`,{"animate-row-glow":u}),ref:l===e.length-1?r:null,children:[(0,Z.jsxs)(`div`,{className:`flex justify-between items-start mb-2`,children:[(0,Z.jsxs)(`div`,{className:`flex items-center gap-2 min-w-0`,children:[f?(0,Z.jsx)(s,{size:14,className:`text-amber-500 shrink-0`}):(0,Z.jsx)(`img`,{src:`/api/icon/${a.domain.replace(/^\*\./,``)}.ico`,className:`w-4 h-4 rounded-sm shrink-0`,alt:``,referrerPolicy:`no-referrer`,onError:e=>e.currentTarget.style.opacity=`0`}),(0,Z.jsx)(`span`,{className:L(`font-bold text-sm truncate`,{"italic text-gray-400 dark:text-gray-500":f}),children:f?c(`logs.encryptedRecord`,`[加密记录]`):a.domain}),p&&(0,Z.jsx)(s,{size:12,className:`text-emerald-500 shrink-0 opacity-80`})]}),(0,Z.jsx)(N,{minimal:!0,round:!0,intent:a.action===`PASS`?E.SUCCESS:a.action===`BLOCK`?E.DANGER:E.WARNING,className:`text-[10px] shrink-0`,children:a.action})]}),(0,Z.jsxs)(`div`,{className:`flex justify-between items-center`,children:[(0,Z.jsxs)(`div`,{className:`flex gap-2 items-center`,children:[(0,Z.jsx)(`span`,{className:`text-[10px] font-mono opacity-50`,children:new Date(a.timestamp*1e3).toLocaleTimeString([],{hour12:!1})}),(0,Z.jsx)(`span`,{className:`text-[10px] bg-gray-100 dark:bg-gray-800 px-1 rounded opacity-60`,children:a.record_type}),a.access_point_name&&(0,Z.jsx)(`span`,{className:`text-[10px] opacity-50 truncate max-w-25`,children:a.access_point_name})]}),(0,Z.jsx)(`div`,{className:`text-[10px] opacity-40 font-mono italic`,children:a.latency?`${a.latency}ms`:``})]})]},a.id)})})},me=({logs:e,setSelectedLog:t,setIsDrawerOpen:n,lastLogElementRef:r,prevLatestTimestamp:i,realtimeRefresh:o})=>{let{t:c}=a(),l=[{key:`time`,header:c(`logs.tableTime`),headerClassName:`w-24 rounded-tl-xl`,cellClassName:`font-mono text-[11px] opacity-60`,render:e=>new Date(e.timestamp*1e3).toLocaleTimeString([],{hour12:!1})},{key:`domain`,header:c(`logs.tableDomain`),headerClassName:`w-1/4`,render:e=>{let t=(e.encrypt_version??0)>0||!!(e.kem_key_id||e.encrypted_payload),n=t&&(!e.domain||e.domain===`[Encrypted]`),r=t&&!!(e.domain&&e.domain!==`[Encrypted]`);return(0,Z.jsxs)(`div`,{className:`flex items-center gap-2 truncate`,children:[n?(0,Z.jsx)(s,{size:14,className:`text-amber-500 shrink-0`}):(0,Z.jsx)(`img`,{src:`/api/icon/${e.domain.replace(/^\*\./,``)}.ico`,className:`w-4 h-4 rounded-sm shrink-0`,alt:``,referrerPolicy:`no-referrer`}),(0,Z.jsx)(`span`,{className:L(`font-bold text-sm truncate`,{"italic text-gray-400 dark:text-gray-500":n}),children:n?c(`logs.encryptedRecord`,`[加密记录]`):e.domain}),r&&(0,Z.jsx)(`span`,{title:c(`settings.e2eeEnabled`,`已加密`),className:`inline-flex items-center`,children:(0,Z.jsx)(s,{size:12,className:`text-emerald-500 shrink-0 opacity-80`})})]})}},{key:`answer`,header:c(`logs.tableAnswer`),headerClassName:`w-1/4`,cellClassName:`truncate font-mono text-[11px] opacity-70`,render:e=>e.answer||`-`},{key:`source`,header:c(`logs.tableSource`),headerClassName:`w-32`,render:e=>(0,Z.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Z.jsx)(N,{minimal:!0,className:`font-mono text-[10px]`,title:e.geo_country||`Unknown`,children:J(e.geo_country)}),e.access_point_name&&(0,Z.jsx)(`span`,{className:`text-xs opacity-70 truncate max-w-20`,title:e.access_point_name,children:e.access_point_name})]})},{key:`type`,header:c(`logs.tableType`),headerClassName:`w-20`,cellClassName:`text-center`,render:e=>(0,Z.jsx)(`code`,{className:`text-[10px]`,children:e.record_type})},{key:`status`,header:c(`logs.tableStatus`),headerClassName:`w-28`,cellClassName:`text-center`,render:e=>(0,Z.jsx)(`span`,{className:L(`bp6-tag`,`bp6-fill`,`bp6-minimal`,`bp6-round`,{"bp6-intent-success":e.action===`PASS`,"bp6-intent-danger":e.action===`BLOCK`,"bp6-intent-warning":e.action===`REDIRECT`}),children:(0,Z.jsx)(`span`,{className:`bp6-text-overflow-ellipsis bp6-fill text-center`,children:e.action})})},{key:`reason`,header:c(`logs.tableReason`),headerClassName:`rounded-tr-xl`,cellClassName:`text-xs text-gray-500 italic truncate`,render:e=>e.reason||`-`}];return(0,Z.jsx)(`div`,{className:`min-w-full inline-block align-middle py-0`,children:(0,Z.jsx)(`div`,{className:`bg-white dark:bg-gray-900 rounded-xl border border-gray-200 dark:border-gray-800 shadow-sm overflow-visible`,children:(0,Z.jsxs)(P,{interactive:!0,striped:!0,className:`w-full table-fixed`,children:[(0,Z.jsx)(`thead`,{className:`sticky top-0 z-20 backdrop-blur-md`,children:(0,Z.jsx)(`tr`,{children:l.map(e=>(0,Z.jsx)(`th`,{className:L(`px-4 py-3 text-xs font-bold uppercase text-gray-500 bg-white/80 dark:bg-gray-900/80 border-b border-gray-100 dark:border-gray-800`,e.headerClassName),children:e.header},e.key))})}),(0,Z.jsx)(`tbody`,{className:`divide-y divide-gray-100 dark:divide-gray-800`,children:e.map((a,s)=>{let c=o&&i!==null&&a.timestamp>i;return(0,Z.jsx)(`tr`,{onClick:()=>{t(a),n(!0)},className:L(`cursor-pointer`,{"animate-row-glow":c}),ref:s===e.length-1?r:null,children:l.map(e=>(0,Z.jsx)(`td`,{className:L(`px-4 py-3`,e.cellClassName),children:e.render(a,s)},e.key))},a.id)})})]})})})},he=({logs:e,loading:t,loadingMore:n,hasMore:r,realtimeRefresh:i,isMobile:o,searchQuery:s,scrollContainerRef:c,lastLogElementRef:l,prevLatestTimestamp:u,setSelectedLog:d,setIsDrawerOpen:f,logRetentionDays:p})=>{let{t:m}=a(),[g,_]=(0,X.useState)(!1),v=(0,X.useCallback)(()=>{c.current&&_(c.current.scrollTop>300)},[c]);return(0,X.useEffect)(()=>{let e=c.current;if(e)return e.addEventListener(`scroll`,v,{passive:!0}),v(),()=>{e.removeEventListener(`scroll`,v)}},[c,v,e]),(0,Z.jsxs)(`div`,{className:`flex-1 relative overflow-hidden flex flex-col min-h-0`,children:[(0,Z.jsxs)(`div`,{ref:c,onScroll:v,className:L(`flex-1 overflow-y-auto`,o?`px-1`:`px-0`),children:[e.length===0&&!t?(0,Z.jsx)(`div`,{className:`py-20`,children:(0,Z.jsx)(w,{title:p===0?m(`logs.loggingDisabledTitle`,`日志记录已关闭`):m(s?`logs.noResults`:`logs.noRecords`),icon:p===0?`disable`:s?`search`:`outdated`,intent:p===0?E.WARNING:E.NONE,children:p===0?m(`logs.loggingDisabledDesc`,`当前配置的日志留存已设置为“关闭”,系统不记录任何查询日志。如需查看,请在设置中启用日志留存。`):s?m(`logs.noResultsDesc`,{query:s}):m(`logs.noRecordsDesc`)})}):o?(0,Z.jsx)(pe,{logs:e,setSelectedLog:d,setIsDrawerOpen:f,lastLogElementRef:l,prevLatestTimestamp:u,realtimeRefresh:i}):(0,Z.jsx)(me,{logs:e,setSelectedLog:d,setIsDrawerOpen:f,lastLogElementRef:l,prevLatestTimestamp:u,realtimeRefresh:i}),(0,Z.jsx)(`div`,{className:`p-6 flex flex-col items-center`,children:n?(0,Z.jsx)(C,{size:16}):i?e.length>0&&(0,Z.jsx)(`span`,{className:`text-[10px] opacity-30 italic`,children:m(`logs.realtimeLoadMoreTip`)}):!r&&e.length>0&&(0,Z.jsx)(`span`,{className:`text-[10px] opacity-30 italic`,children:m(`logs.loadedAll`,{count:e.length})})})]}),(0,Z.jsx)(`div`,{className:L(`absolute z-30 pointer-events-none transition-all duration-300 ease-out`,o?`bottom-20 right-3`:`bottom-6 right-6`,g?`opacity-100 translate-y-0`:`opacity-0 translate-y-3`),children:(0,Z.jsx)(`button`,{type:`button`,onClick:()=>{c.current?.scrollTo({top:0,behavior:`smooth`})},"aria-label":m(`logs.scrollToTop`),title:m(`logs.scrollToTop`),className:L(`pointer-events-auto group inline-flex items-center gap-1.5 rounded-full select-none`,`backdrop-blur-md bg-white/70 dark:bg-gray-900/70 hover:bg-white/90 dark:hover:bg-gray-800/90`,`border border-gray-200/80 dark:border-gray-700/80 hover:border-gray-300 dark:hover:border-gray-600`,`text-gray-700 dark:text-gray-200 hover:text-gray-950 dark:hover:text-white`,`shadow-sm hover:shadow active:scale-95 transition-all duration-200 cursor-pointer`,o?`px-2.5 py-1.5 text-[11px]`:`px-3.5 py-2 text-xs`),children:(0,Z.jsx)(h,{size:o?13:15,strokeWidth:2.4,className:`transition-transform duration-200 group-hover:scale-105`})})})]})};function ge(e,t,n){let[r,i]=(0,X.useState)(null),[a,o]=(0,X.useState)(!1);return(0,X.useEffect)(()=>{if(e&&t?.id){o(!0),i(t);let e=new AbortController;return B(n,t.id,t.timestamp,{signal:e.signal}).then(async r=>{if(!e.signal.aborted)try{let e=r?.encrypt_version??t.encrypt_version,a=await W.decryptLogEntry(n,r);i(n=>({...n||t,...a,encrypt_version:e??a.encrypt_version}))}catch{i(e=>({...e||t,...r}))}}).catch(e=>{e.name!==`AbortError`&&(console.error(e),i(e=>e||t))}).finally(()=>{e.signal.aborted||o(!1)}),()=>{e.abort()}}else i(null)},[e,t?.id,n]),{detailedLog:r,loading:a}}const Q=({label:e,value:t,bold:n,italic:r})=>(0,Z.jsxs)(`div`,{className:`flex justify-between items-start gap-4`,children:[(0,Z.jsx)(`span`,{className:`text-xs opacity-50 mt-1`,children:e}),(0,Z.jsx)(`span`,{className:L(`text-sm text-right`,n&&`font-bold`,r&&`italic`),children:t})]}),_e=({selectedLog:e,detailedLog:t,loading:r})=>{let{t:i}=a(),o=t?.encrypt_version??e.encrypt_version??(t?.kem_key_id||e.kem_key_id?2:0),c=o>0||!!(e.kem_key_id||e.encrypted_payload||t?.kem_key_id||t?.encrypted_payload),l=o===2||!!(e.kem_key_id||t?.kem_key_id),u=c&&(!e.domain||e.domain===`[Encrypted]`);return(0,Z.jsx)(j,{title:i(`logs.basicInfo`),icon:(0,Z.jsx)(n,{size:16}),className:`shadow-none! rounded-lg!`,children:(0,Z.jsx)(D,{children:(0,Z.jsxs)(`div`,{className:`space-y-3`,children:[(0,Z.jsx)(Q,{label:i(`logs.detailDomain`),value:(0,Z.jsxs)(`div`,{className:`flex items-center gap-2 justify-end font-bold`,children:[u?(0,Z.jsx)(s,{size:14,className:`text-amber-500`}):(0,Z.jsx)(`img`,{src:`/api/icon/${e.domain.replace(/^\*\./,``)}.ico`,className:`w-4 h-4 rounded-sm`,alt:``,referrerPolicy:`no-referrer`,onError:e=>e.currentTarget.style.display=`none`}),(0,Z.jsx)(`span`,{className:L({"italic text-gray-400 dark:text-gray-500":u}),children:u?i(`logs.encryptedRecord`,`[加密记录]`):e.domain})]}),bold:!0}),(0,Z.jsx)(Q,{label:i(`logs.detailType`),value:e.record_type}),(0,Z.jsx)(Q,{label:i(`logs.detailLatency`),value:e.latency?`${e.latency} ms`:`-`}),(0,Z.jsx)(Q,{label:i(`logs.detailAccessPoint`),value:(()=>{let n=t?.access_point_name||e.access_point_name,i=t?.access_point_id||e.access_point_id;return n?i&&i!==n?(0,Z.jsx)(`span`,{title:i,className:`cursor-help`,children:n}):n:i?(0,Z.jsx)(`span`,{className:`font-mono text-xs`,children:i}):r?(0,Z.jsx)(C,{size:12}):`-`})()}),(0,Z.jsx)(Q,{label:i(`logs.detailProfile`),value:t?.profile_name||t?.client_ip||e.client_ip||(r?(0,Z.jsx)(C,{size:12}):`-`)}),(0,Z.jsx)(Q,{label:i(`logs.detailTime`),value:V(new Date(e.timestamp*1e3))}),(0,Z.jsx)(Q,{label:i(`logs.detailStatus`),value:(0,Z.jsx)(N,{minimal:!0,intent:e.action===`PASS`?E.SUCCESS:e.action===`BLOCK`?E.DANGER:E.WARNING,children:e.action})}),(0,Z.jsx)(Q,{label:i(`logs.detailUpstream`),value:t?.upstream||e.upstream||(r?(0,Z.jsx)(C,{size:12}):`-`)}),(0,Z.jsx)(Q,{label:i(`logs.detailReason`),value:e.reason||i(`logs.detailNoReason`),italic:!0}),(0,Z.jsx)(Q,{label:i(`logs.detailECS`),value:t?.ecs||e.ecs||(r?(0,Z.jsx)(C,{size:12}):`-`),italic:!0}),(0,Z.jsx)(Q,{label:i(`logs.detailIsClientEncrypted`,`是否用户端加密`),value:c?(0,Z.jsxs)(`div`,{className:`flex items-center gap-1.5 justify-end`,children:[(0,Z.jsx)(s,{size:13,className:u?`text-amber-500`:`text-emerald-500`}),(0,Z.jsxs)(`span`,{className:L(`text-xs font-medium`,u?`text-amber-600 dark:text-amber-400`:`text-emerald-600 dark:text-emerald-400`),children:[u?i(`logs.encryptedLocked`,`是 (未解锁)`):i(`logs.encryptedYes`,`是`),l?` (PQC)`:``]})]}):(0,Z.jsx)(`span`,{className:`text-xs text-gray-400 dark:text-gray-500`,children:i(`logs.notEncrypted`,`否`)})})]})})})},ve=({selectedLog:e})=>{let{t}=a(),n=e.record_type===`HTTPS`||e.record_type===`SVCB`||e.record_type===`TYPE65`||e.record_type===`TYPE64`,r=n&&(e.reason===`ECH Rewritten`||(e.reason?.toLowerCase().includes(`rewritten`)??!1));return(0,Z.jsx)(j,{title:(0,Z.jsxs)(`div`,{className:`flex items-center justify-between w-full pr-2`,children:[(0,Z.jsx)(`span`,{children:t(`logs.resolutionResult`)}),r&&(0,Z.jsx)(N,{minimal:!0,intent:E.PRIMARY,className:`text-xs`,children:t(`logs.rewritten`,`已重写`)})]}),icon:(0,Z.jsx)(f,{size:16}),className:`shadow-none! rounded-lg!`,children:(0,Z.jsx)(D,{children:(0,Z.jsx)(`div`,{className:`bg-gray-50 dark:bg-gray-800 p-3 font-mono text-xs break-all leading-relaxed rounded-lg`,children:(()=>{if(!e.answer)return t(`logs.noResult`);let r=e.answer.split(`
|
|
3
|
+
`).map(e=>e.trim()).filter(Boolean);return r.length===0?t(`logs.noResult`):(0,Z.jsx)(`div`,{className:`space-y-2`,children:r.map((e,t)=>{let r=e.match(/^(\d+)\s+([^\s]+)(?:\s+(.*))?$/);if(r&&(n||e.includes(`alpn=`)||e.includes(`ech=`)||e.includes(`ipv4hint=`))){let e=r[1],n=r[2],i=(r[3]||``).split(/\s+/).filter(Boolean);return(0,Z.jsxs)(`div`,{className:`bg-white dark:bg-gray-900 p-2.5 rounded-md space-y-2 border border-gray-200 dark:border-gray-700`,children:[(0,Z.jsxs)(`div`,{className:`flex items-center gap-2 text-xs`,children:[(0,Z.jsxs)(N,{minimal:!0,intent:E.PRIMARY,children:[`Priority `,e]}),(0,Z.jsxs)(`span`,{className:`font-semibold text-gray-700 dark:text-gray-300`,children:[`Target: `,n]})]}),i.length>0&&(0,Z.jsx)(`div`,{className:`flex flex-wrap gap-1.5 pt-1 border-t border-gray-100 dark:border-gray-800 text-xs`,children:i.map((e,t)=>{let n=e.indexOf(`=`);if(n===-1)return(0,Z.jsx)(N,{minimal:!0,className:`font-mono`,children:e},t);let r=e.substring(0,n),i=e.substring(n+1);return r===`ech`?(0,Z.jsxs)(N,{minimal:!0,intent:E.SUCCESS,className:`font-mono break-all max-w-full select-all text-left whitespace-normal h-auto py-1 inline-block`,title:i,children:[(0,Z.jsx)(`span`,{className:`font-bold`,children:`ech:`}),` `,i]},t):r===`alpn`?(0,Z.jsxs)(N,{minimal:!0,intent:E.WARNING,className:`font-mono`,children:[(0,Z.jsx)(`span`,{className:`font-bold`,children:`alpn:`}),` `,i]},t):(0,Z.jsxs)(N,{minimal:!0,className:`font-mono`,children:[(0,Z.jsxs)(`span`,{className:`font-bold`,children:[r,`:`]}),` `,i]},t)})})]},t)}return(0,Z.jsx)(`div`,{className:`space-y-1`,children:e.split(`,`).map(e=>e.trim()).filter(Boolean).map((e,t)=>(0,Z.jsx)(`div`,{className:`text-xs font-mono text-gray-800 dark:text-gray-200 select-all`,children:e},t))},t)})})})()})})})},ye=({selectedLog:e,detailedLog:t,loading:n})=>{let{t:r,i18n:i}=a(),o=t?.client_ip||e.client_ip,s=t?.geo_country||e.geo_country,l=`Unknown`;if(s){let e=s.toUpperCase().trim();l=e===`LAN`||e===`LOCAL`||e===`PRIVATE`||e===`PRIVATE NETWORK`?r(`setup.privateNetwork`,`Private Network`):e===`UN`||e===`UNKNOWN`||e===`XX`?r(`common.unknown`,`Unknown`):q(s,i.language)||s}let u=t?.dest_country_code||e.dest_country_code,f=t?.dest_country||e.dest_country,p=t?.dest_isp||e.dest_isp,m=null,h=t?.dest_geoip||e.dest_geoip;if(h)try{let e=JSON.parse(h);!u&&e.country_code&&(u=e.country_code);let t=[e.city,e.region,e.country].filter(Boolean),n=f||u||void 0;m={locationTitle:t.length>0?t.join(`, `):n,isp:e.isp||p||void 0,as:e.as||void 0}}catch{}return!m&&(f||u||p)&&(m={locationTitle:f||u||void 0,isp:p||void 0}),(0,Z.jsx)(j,{title:r(`logs.networkDetails`),icon:(0,Z.jsx)(c,{size:16}),className:`shadow-none! rounded-lg!`,children:(0,Z.jsx)(D,{children:(0,Z.jsxs)(`div`,{className:`space-y-4`,children:[(0,Z.jsxs)(`div`,{children:[(0,Z.jsx)(`div`,{className:`text-[10px] uppercase font-bold opacity-50 mb-1`,children:r(`logs.clientSource`)}),(0,Z.jsxs)(`div`,{className:`flex justify-between items-center`,children:[(0,Z.jsx)(`span`,{className:`font-mono`,children:o||(n?(0,Z.jsx)(C,{size:12}):`-`)}),(s||n)&&(0,Z.jsx)(N,{minimal:!0,title:l,children:s?J(s):`-`})]})]}),(0,Z.jsxs)(`div`,{children:[(0,Z.jsxs)(`div`,{className:`flex justify-between items-center mb-1`,children:[(0,Z.jsx)(`div`,{className:`text-[10px] uppercase font-bold opacity-50`,children:r(`logs.destination`)}),(u||n)&&(0,Z.jsx)(N,{minimal:!0,title:f||u||`Unknown`,children:u?J(u):`-`})]}),n&&!m?(0,Z.jsx)(`div`,{className:`flex items-center justify-center py-2`,children:(0,Z.jsx)(C,{size:16})}):m?(0,Z.jsx)(`div`,{className:`bg-gray-50 dark:bg-gray-800 p-3 rounded-lg mt-1`,children:(0,Z.jsxs)(`div`,{className:`flex items-start gap-3`,children:[(0,Z.jsx)(d,{size:16,className:`oklch(60.9% 0.126 221.723) mt-1 shrink-0`}),(0,Z.jsxs)(`div`,{children:[m.locationTitle&&(0,Z.jsx)(`div`,{className:`font-bold text-sm`,children:m.locationTitle}),(m.isp||m.as)&&(0,Z.jsxs)(`div`,{className:`text-xs opacity-70 mt-1`,children:[m.isp,m.as&&(0,Z.jsx)(`span`,{className:`opacity-60 block mt-0.5`,children:m.as})]})]})]})}):(0,Z.jsx)(`div`,{className:`text-xs opacity-50 py-1`,children:`-`})]})]})})})},be=({selectedLog:e,onQuickAction:n})=>{let{t:r}=a(),i=(e.encrypt_version??0)>0&&(!e.domain||e.domain===`[Encrypted]`);return(0,Z.jsx)(j,{title:r(`logs.quickActions`),icon:(0,Z.jsx)(o,{size:16}),className:`shadow-none! rounded-lg!`,children:(0,Z.jsx)(D,{children:i?(0,Z.jsx)(`p`,{className:`text-xs text-center text-gray-500 italic py-2 m-0`,children:r(`settings.e2eeUnlockPrompt`,`此记录已加密,请先解锁私钥后再进行操作。`)}):(0,Z.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,Z.jsx)(S,{fill:!0,intent:E.SUCCESS,icon:(0,Z.jsx)(t,{size:16}),text:r(`logs.actionAllow`),onClick:()=>n?.(e.domain,`ALLOW`)}),(0,Z.jsx)(S,{fill:!0,intent:E.DANGER,icon:(0,Z.jsx)(l,{size:16}),text:r(`logs.actionBlock`),onClick:()=>n?.(e.domain,`BLOCK`)}),(0,Z.jsx)(S,{fill:!0,icon:(0,Z.jsx)(m,{size:16}),text:r(`logs.actionRedirect`),onClick:()=>n?.(e.domain,`REDIRECT`,e.record_type)})]})})})},xe=({isDrawerOpen:e,setIsDrawerOpen:t,selectedLog:r,profileId:i,isMobile:o,onQuickAction:s})=>{let{t:c}=a(),{detailedLog:l,loading:u}=ge(e,r,i);return(0,Z.jsx)(Y,{isOpen:e&&r!==null,onClose:()=>t(!1),title:(0,Z.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,Z.jsx)(n,{size:18}),(0,Z.jsx)(`span`,{children:c(`logs.logDetails`)})]}),icon:`info-sign`,size:o?`100%`:`450px`,children:r&&(0,Z.jsxs)(Z.Fragment,{children:[(0,Z.jsx)(_e,{selectedLog:r,detailedLog:l,loading:u}),(0,Z.jsx)(ve,{selectedLog:r}),(0,Z.jsx)(ye,{selectedLog:r,detailedLog:l,loading:u}),(0,Z.jsx)(be,{selectedLog:r,onQuickAction:s})]})})};function Se(e){let[t,n]=(0,X.useState)(`24h`),[r,i]=(0,X.useState)({start:``,end:``}),[a,o]=(0,X.useState)(null),[s,c]=(0,X.useState)(null),[l,u]=(0,X.useState)([]),[d,f]=(0,X.useState)(null),[p,m]=(0,X.useState)(null),[h,g]=(0,X.useState)(``);return(0,X.useEffect)(()=>{te(e).then(u).catch(console.error)},[e]),(0,X.useEffect)(()=>{m(null)},[d]),{range:t,setRange:n,customRange:r,setCustomRange:i,statusFilter:a,setStatusFilter:o,accessPointIdFilter:s,setAccessPointIdFilter:c,accessPoints:l,destCountryFilter:d,setDestCountryFilter:f,ispFilter:p,setIspFilter:m,searchQuery:h,setSearchQuery:g}}function Ce(e){let[t,n]=(0,X.useState)(30);return(0,X.useEffect)(()=>{R(e).then(e=>{try{let t=JSON.parse(e.settings||`{}`);n(t.log_retention_days===void 0?30:Number(t.log_retention_days))}catch(e){console.error(`[useProfileRetention] Failed to parse settings:`,e)}}).catch(e=>console.error(`[useProfileRetention] Failed to fetch profile details:`,e))},[e]),t}function we(e,t){let n=Math.floor(Date.now()/1e3);if(e===`custom`&&t.start&&t.end)return{since:Math.floor(new Date(t.start).getTime()/1e3),until:Math.floor(new Date(t.end).getTime()/1e3)};let r;switch(e){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}return{since:r,until:n}}function Te(e){if(!(!e||e.length===0)&&`serviceWorker`in navigator&&navigator.serviceWorker.controller){let t=Array.from(new Set(e.map(e=>e.domain)));navigator.serviceWorker.controller.postMessage({type:`PREFETCH_ICONS`,domains:t})}}async function Ee(e){let{profileId:t,currentRange:n,customRange:r,since:i,until:a,limit:o,isInitial:s,statusFilter:c,accessPointIdFilter:l,destCountryFilter:u,ispFilter:d,searchQuery:f,lastTimestamp:p,signal:m}=e,h=new URLSearchParams({range:n,limit:String(o)});n===`custom`&&r.start&&r.end&&(h.set(`start`,String(i)),h.set(`end`,String(a))),c&&h.set(`status`,c),l&&h.set(`access_point_id`,l),u&&h.set(`dest_country`,u),d&&h.set(`isp`,d),f&&h.set(`search`,f),!s&&p!==void 0&&h.set(`before`,String(p));let g=H(t,h.toString(),{signal:m}),_=Promise.resolve(null);if(s){let e=new URLSearchParams({range:n});n===`custom`&&r.start&&r.end&&(e.set(`start`,String(i)),e.set(`end`,String(a))),f&&e.set(`search`,f),_=z(t,`summary`,e.toString(),{signal:m})}let[v,y]=await Promise.all([g,_]),b=null;if(y){let e={total:0,pass:0,block:0,redirect:0};y.forEach(t=>{let n=t.count;e.total+=n,t.action===`PASS`?e.pass=n:t.action===`BLOCK`?e.block=n:t.action===`REDIRECT`&&(e.redirect=n)}),b=e}return{logs:v||[],stats:b}}async function De(e,t,n,r){if(!await G.init()||t.aborted)return{success:!1};let{profileId:i,searchQuery:a,statusFilter:o,accessPointIdFilter:s,destCountryFilter:c,ispFilter:l,since:u,until:d,limit:f}=e,p=await G.queryLogs({profileId:i,search:a||void 0,action:o||void 0,accessPointId:s||void 0,destCountry:c||void 0,isp:l||void 0,since:u,until:d,before:void 0,limit:f,offset:0});if(t.aborted)return{success:!1};p.rows.length>0&&r&&r({rows:p.rows,hasMore:p.rows.length>=f,stats:p.stats});try{let e=await G.syncProfileLogs(i,void 0,u,t,n);if(!t.aborted&&(e>0||p.rows.length===0)&&(p=await G.queryLogs({profileId:i,search:a||void 0,action:o||void 0,accessPointId:s||void 0,destCountry:c||void 0,isp:l||void 0,since:u,until:d,before:void 0,limit:f,offset:0}),t.aborted))return{success:!1}}catch(e){e.name!==`AbortError`&&console.warn(`[localDbStrategy] Incremental sync error:`,e)}return p.rows.length>0?{success:!0,result:{rows:p.rows,hasMore:p.rows.length>=f,stats:p.stats}}:{success:!1}}async function Oe(e,t,n){if(!await G.init()||n.aborted)return{success:!1};let{profileId:r,searchQuery:i,statusFilter:a,accessPointIdFilter:o,destCountryFilter:s,ispFilter:c,since:l,until:u,limit:d}=e,f=await G.queryLogs({profileId:r,search:i||void 0,action:a||void 0,accessPointId:o||void 0,destCountry:s||void 0,isp:c||void 0,since:l,until:u,before:t,limit:d,offset:0});if(n.aborted)return{success:!1};if(f.rows.length>=d)return{success:!0,result:{rows:f.rows,hasMore:f.rows.length>=d}};if(t>l)try{let e=await G.backfillLogs(r,t,l,d,n);if(n.aborted)return{success:!1};if(e.length>0){let f=await G.queryLogs({profileId:r,search:i||void 0,action:a||void 0,accessPointId:o||void 0,destCountry:s||void 0,isp:c||void 0,since:l,until:u,before:t,limit:d,offset:0});return n.aborted?{success:!1}:{success:!0,result:{rows:f.rows,hasMore:f.rows.length>=d&&e.length>=d}}}return{success:!0,result:{rows:f.rows,hasMore:!1}}}catch(e){return e.name!==`AbortError`&&console.warn(`[localDbStrategy] Backfill error:`,e),{success:!0,result:{rows:f.rows,hasMore:!1}}}return{success:!0,result:{rows:f.rows,hasMore:!1}}}function ke({profileId:e,range:t,customRange:n,statusFilter:r,accessPointIdFilter:i,destCountryFilter:a,ispFilter:o,searchQuery:s,realtimeRefresh:c}){let[l,u]=(0,X.useState)([]),[d,f]=(0,X.useState)(!0),[p,m]=(0,X.useState)(!1),[h,g]=(0,X.useState)(!1),[_,v]=(0,X.useState)(!0),[y,b]=(0,X.useState)(null),[x,S]=(0,X.useState)(null),C=(0,X.useRef)([]);(0,X.useEffect)(()=>{C.current=l},[l]);let w=(0,X.useRef)(null),T=(0,X.useRef)(!1);return(0,X.useEffect)(()=>()=>{w.current&&w.current.abort()},[]),{logs:l,setLogs:u,loading:d,loadingMore:p,syncing:h,hasMore:_,setHasMore:v,stats:y,setStats:b,prevLatestTimestamp:x,setPrevLatestTimestamp:S,fetchLogs:(0,X.useCallback)(async(t,l=!0,d=!1,p=!1)=>{w.current&&w.current.abort();let h=new AbortController;w.current=h,T.current=!0,l?f(!0):m(!0);try{let _=c?25:50,{since:y,until:x}=we(t,n),E={profileId:e,searchQuery:s,statusFilter:r,accessPointIdFilter:i,destCountryFilter:a,ispFilter:o,since:y,until:x,limit:_},D=!1;if(l){d||g(!0);let e=await De(E,h.signal,p,e=>{D=!0,S(d&&C.current.length>0?C.current[0].timestamp:null),u(e.rows),v(c?!1:e.hasMore),c&&e.rows.length>0&&U.updateCursor(e.rows[0].timestamp,e.rows[0].id),e.stats&&b(e.stats),f(!1)});if(h.signal.aborted)return;e.success&&e.result&&(D=!0,S(d&&C.current.length>0?C.current[0].timestamp:null),u(e.result.rows),v(c?!1:e.result.hasMore),c&&e.result.rows.length>0&&U.updateCursor(e.result.rows[0].timestamp,e.result.rows[0].id),e.result.stats&&b(e.result.stats))}else{let e=C.current.length>0?C.current[C.current.length-1].timestamp:void 0;if(e!==void 0){let t=await Oe(E,e,h.signal);if(h.signal.aborted)return;t.success&&t.result&&(D=!0,u(e=>[...e,...t.result.rows]),v(c?!1:t.result.hasMore))}else D=!0,v(!1)}if(D){Te(C.current),w.current===h&&(f(!1),m(!1),g(!1),T.current=!1);return}let O=await Ee({profileId:e,currentRange:t,customRange:n,since:y,until:x,limit:_,isInitial:l,statusFilter:r,accessPointIdFilter:i,destCountryFilter:a,ispFilter:o,searchQuery:s,lastTimestamp:!l&&C.current.length>0?C.current[C.current.length-1].timestamp:void 0,signal:h.signal});if(h.signal.aborted)return;l?(S(d&&C.current.length>0?C.current[0].timestamp:null),u(O.logs),v(c?!1:O.logs.length>=_),O.stats&&b(O.stats)):(u(e=>[...e,...O.logs]),v(c?!1:O.logs.length>=_)),O.logs.length>0&&(c&&U.updateCursor(O.logs[0].timestamp,O.logs[0].id),Te(O.logs))}catch(e){e.name!==`AbortError`&&console.error(e)}finally{w.current===h&&(f(!1),m(!1),g(!1),T.current=!1)}},[e,c,n,s,r,i,a,o]),isFetchingRef:T,logsRef:C}}function Ae({realtimeRefresh:e,statusFilter:t,accessPointIdFilter:n,destCountryFilter:r,ispFilter:i,searchQuery:a,pageSize:o,logsRef:s,setLogs:c,setStats:l,setPrevLatestTimestamp:u}){(0,X.useEffect)(()=>{if(e)return U.onNewLogs(e=>{if(!e||e.length===0)return;let d=e.filter(e=>{if(t&&e.action!==t||n&&e.access_point_id!==n||r&&(e.dest_country_code||e.dest_country)!==r||i&&e.dest_isp!==i)return!1;if(a){let t=a.toLowerCase(),n=e.domain?.toLowerCase().includes(t),r=e.client_ip?.toLowerCase().includes(t),i=e.reason?.toLowerCase().includes(t);if(!n&&!r&&!i)return!1}return!0});d.length!==0&&(u(s.current.length>0?s.current[0].timestamp:null),c(e=>{let t=new Set(e.map(e=>`${e.timestamp}-${e.id}`)),n=d.filter(e=>!t.has(`${e.timestamp}-${e.id}`));return n.length===0?e:[...n,...e].slice(0,o)}),l(t=>{if(!t)return t;let n=0,r=0,i=0;for(let t of e)t.action===`PASS`?n++:t.action===`BLOCK`?r++:t.action===`REDIRECT`&&i++;return{total:t.total+e.length,pass:t.pass+n,block:t.block+r,redirect:t.redirect+i}}))})},[e,t,n,r,i,a,o,s,c,l,u])}function je({profileId:e,range:t,customRange:n,statusFilter:r,accessPointIdFilter:i,destCountryFilter:a,ispFilter:o,searchQuery:s,realtimeRefresh:c}){let l=Ce(e),{logs:u,setLogs:d,loading:f,loadingMore:p,syncing:m,hasMore:h,stats:g,setStats:_,prevLatestTimestamp:v,setPrevLatestTimestamp:y,fetchLogs:b,isFetchingRef:x,logsRef:S}=ke({profileId:e,range:t,customRange:n,statusFilter:r,accessPointIdFilter:i,destCountryFilter:a,ispFilter:o,searchQuery:s,realtimeRefresh:c});Ae({realtimeRefresh:c,statusFilter:r,accessPointIdFilter:i,destCountryFilter:a,ispFilter:o,searchQuery:s,pageSize:25,logsRef:S,setLogs:d,setStats:_,setPrevLatestTimestamp:y});let C=(0,X.useRef)(null),w=(0,X.useRef)(null),T=(0,X.useCallback)(()=>{c||x.current||f||p||!h||b(t,!1)},[f,p,h,t,c,b,x]),E=(0,X.useCallback)(e=>{w.current&&w.current.disconnect(),!(f||p||c||!h)&&(w.current=new IntersectionObserver(e=>{e[0]?.isIntersecting&&h&&!x.current&&T()},{root:C.current,rootMargin:`100px`}),e&&w.current.observe(e))},[f,p,h,T,c,x]);return(0,X.useEffect)(()=>{if(t===`custom`&&(!n.start||!n.end))return;let e=setTimeout(()=>{b(t,!0)},s?500:0);return()=>clearTimeout(e)},[t,n.start,n.end,s,b]),{logs:u,loading:f,loadingMore:p,syncing:m,hasMore:h,stats:g,logRetentionDays:l,prevLatestTimestamp:v,scrollContainerRef:C,lastLogElementRef:E,fetchLogs:b,isFetchingRef:x,logsRef:S}}function Me({profileId:e,range:t,searchQuery:n,realtimeRefresh:r,scrollContainerRef:i,isFetchingRef:a,fetchLogs:o,logsRef:s}){let c=(0,X.useRef)({range:t,searchQuery:n,fetchLogs:o,logsRef:s});(0,X.useEffect)(()=>{c.current={range:t,searchQuery:n,fetchLogs:o,logsRef:s}}),(0,X.useEffect)(()=>{if(!r){U.disconnect();return}let t=!1,n=null,o=()=>{n||=setInterval(()=>{let{range:e,searchQuery:n,fetchLogs:r}=c.current;!t&&document.visibilityState===`visible`&&i.current&&i.current.scrollTop<50&&!a.current&&!n&&e!==`custom`&&r(e,!0,!0)},8e3)},s=()=>{n&&=(clearInterval(n),null)},l=U.onStatusChange(e=>{t=e,e?s():o()}),u=c.current.logsRef.current,d=u.length>0?u[0]:null,f=d?d.timestamp:Math.floor(Date.now()/1e3)-60,p=d?d.id:0;U.connect(e,f,p);let m=setTimeout(()=>{t||o()},2500),h=()=>{if(document.visibilityState===`visible`)if(t){let e=c.current.logsRef.current,t=e.length>0?e[0]:null;t&&U.updateCursor(t.timestamp,t.id)}else{let{range:e,fetchLogs:t}=c.current;t(e,!0,!0)}};return document.addEventListener(`visibilitychange`,h),()=>{clearTimeout(m),s(),l(),U.disconnect(),document.removeEventListener(`visibilitychange`,h)}},[e,r])}function $(e){let t=new Date(e*1e3),n=-t.getTimezoneOffset(),r=n>=0?`+`:`-`,i=e=>String(e).padStart(2,`0`);return t.getFullYear()+`-`+i(t.getMonth()+1)+`-`+i(t.getDate())+`T`+i(t.getHours())+`:`+i(t.getMinutes())+`:`+i(t.getSeconds())+`.`+(e=>String(e).padStart(3,`0`))(t.getMilliseconds())+(n===0?`Z`:r+i(Math.floor(Math.abs(n)/60))+`:`+i(Math.abs(n)%60))}function Ne(e){let t=[`profile_id`,`access_point_id`,`time`,`client_ip`,`geo_country`,`domain`,`record_type`,`action`,`reason`,`answer`,`dest_geoip`,`ecs`,`upstream`,`latency`],n=[t.join(`,`)];for(let r of e){let e=t.map(e=>{let t=``;if(e===`time`)t=$(r.timestamp);else{let n=r[e];t=n==null?e===`dest_geoip`&&(r.dest_country_code||r.dest_country||r.dest_isp)?JSON.stringify({country_code:r.dest_country_code||``,country:r.dest_country||``,isp:r.dest_isp||``}):``:typeof n==`object`?JSON.stringify(n):String(n)}let n=t.replace(/"/g,`""`);return n.includes(`,`)||n.includes(`
|
|
4
|
+
`)||n.includes(`\r`)||n.includes(`"`)?`"${n}"`:n});n.push(e.join(`,`))}return n.join(`
|
|
5
|
+
`)}function Pe(e,t){let n=new Blob([e],{type:`text/csv;charset=utf-8;`}),r=URL.createObjectURL(n),i=document.createElement(`a`);i.setAttribute(`href`,r),i.setAttribute(`download`,t),document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(r)}function Fe(e,t,n,r){let i=e=>e.replace(/[:*?"<>|]/g,`-`),a=i($(t)),o=i($(n)),s=i(r.toString());return`query_logs_${e}_${a}_${o}${s?`_${s}`:``}.csv`}function Ie({profileId:e,range:t,customRange:n,statusFilter:r,accessPointIdFilter:i,destCountryFilter:o,ispFilter:s,searchQuery:c,toasterRef:l}){let{t:u}=a(),[d,f]=(0,X.useState)(!1);return{exporting:d,handleExportLogs:async()=>{f(!0);try{let{since:a,until:d}=we(t,n),f=new URLSearchParams({range:t});if(t===`custom`&&n.start&&n.end){let e=Math.floor(new Date(n.start).getTime()/1e3),t=Math.floor(new Date(n.end).getTime()/1e3);f.set(`start`,String(e)),f.set(`end`,String(t))}r&&f.set(`status`,r),i&&f.set(`access_point_id`,i),o&&f.set(`dest_country`,o),s&&f.set(`isp`,s),c&&f.set(`search`,c);let p=[],m=!1;try{if(await G.init()){let t=await G.queryLogs({profileId:e,search:c.trim()||void 0,action:r||void 0,accessPointId:i||void 0,destCountry:o||void 0,isp:s||void 0,since:a,until:d,limit:1e5});t&&Array.isArray(t.rows)&&t.rows.length>0&&(p=t.rows)}}catch(e){console.warn(`[LogExport] Local SQLite query failed or unavailable, falling back to server:`,e)}if(!p||p.length===0){m=!0;let{exportProfileLogs:t}=await v(async()=>{let{exportProfileLogs:e}=await import(`./services-B-OKDv75.js`);return{exportProfileLogs:e}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10])),n=await t(e,f.toString());n&&Array.isArray(n)&&(p=n)}if(!p||p.length===0){l?.current?.show({message:u(`logs.noResults`,`No logs found to export`),intent:E.WARNING});return}if(p.some(e=>(e.encrypt_version??(e.encrypted_payload?1:0))>0)){if(!W.isProfileUnlocked(e))try{await W.unlockProfile(e)}catch(e){console.warn(`[LogExport] Auto-unlock attempt failed or was cancelled:`,e)}p=await W.decryptLogsBatch(e,p),p.some(e=>(e.encrypt_version??(e.encrypted_payload?1:0))>0||e.domain===`[Encrypted]`)&&l?.current?.show({message:u(`logs.e2eeLockedExportWarning`,`部分日志处于加密状态且未解锁,导出的数据可能包含未解密内容。`),intent:E.WARNING,icon:`lock`})}m&&p.length>0&&G.batchInsertLogs(e,p).catch(e=>{console.warn(`[LogExport] Failed to cache exported logs into local SQLite:`,e)}),Pe(Ne(p),Fe(e,p[0].timestamp,p[p.length-1].timestamp,f)),l?.current?.show({message:u(`logs.exportSuccess`,`Logs exported successfully`),intent:E.SUCCESS})}catch(e){console.error(`Failed to export logs`,e),l?.current?.show({message:u(`logs.exportError`,`Failed to export logs`),intent:E.DANGER})}finally{f(!1)}}}}function Le({profileId:e,toasterRef:t}){let[n,r]=(0,X.useState)(!1),i=Se(e),a=je({profileId:e,realtimeRefresh:n,range:i.range,customRange:i.customRange,statusFilter:i.statusFilter,accessPointIdFilter:i.accessPointIdFilter,destCountryFilter:i.destCountryFilter,ispFilter:i.ispFilter,searchQuery:i.searchQuery});Me({profileId:e,realtimeRefresh:n,range:i.range,searchQuery:i.searchQuery,scrollContainerRef:a.scrollContainerRef,isFetchingRef:a.isFetchingRef,fetchLogs:a.fetchLogs,logsRef:a.logsRef});let o=Ie({profileId:e,range:i.range,customRange:i.customRange,statusFilter:i.statusFilter,accessPointIdFilter:i.accessPointIdFilter,destCountryFilter:i.destCountryFilter,ispFilter:i.ispFilter,searchQuery:i.searchQuery,toasterRef:t});return{realtimeRefresh:n,setRealtimeRefresh:r,...i,...a,...o}}const Re=({profileId:e,onQuickAction:t,toasterRef:n})=>{let r=ee(),[i,a]=(0,X.useState)(null),[o,s]=(0,X.useState)(!1),{realtimeRefresh:c,setRealtimeRefresh:l,range:u,setRange:d,customRange:f,setCustomRange:p,statusFilter:m,setStatusFilter:h,accessPointIdFilter:g,setAccessPointIdFilter:_,accessPoints:v,destCountryFilter:y,setDestCountryFilter:b,ispFilter:x,setIspFilter:S,searchQuery:w,setSearchQuery:T,logs:E,loading:D,loadingMore:O,syncing:k,hasMore:A,stats:j,logRetentionDays:M,prevLatestTimestamp:N,scrollContainerRef:P,lastLogElementRef:F,fetchLogs:I,exporting:L,handleExportLogs:R}=Le({profileId:e,toasterRef:n}),{isE2eeEnabled:te,isE2eeUnlocked:z,unlocking:B,recoveryDialogOpen:V,setRecoveryDialogOpen:H,recoveryKeyInput:U,setRecoveryKeyInput:W,recoveryError:G,setRecoveryError:K,rotatedKey:q,setRotatedKey:J,copiedKey:Y,handleCopyRotatedKey:oe,handleUnlockPasskey:se,handleUnlockRecoveryKey:ce}=ae({profileId:e,range:u,fetchLogs:I,toasterRef:n}),le=new Date().toLocaleString(`sv-SE`).replace(` `,`T`).slice(0,16);return D&&E.length===0?(0,Z.jsx)(`div`,{className:`h-full flex items-center justify-center`,children:(0,Z.jsx)(C,{})}):(0,Z.jsxs)(`div`,{className:`h-full flex flex-col overflow-hidden bg-gray-50/30 dark:bg-gray-950/10 max-w-7xl mx-auto w-full pt-14`,children:[(0,Z.jsx)(fe,{profileId:e,range:u,setRange:d,customRange:f,setCustomRange:p,nowStr:le,fetchLogs:I,isMobile:r,realtimeRefresh:c,setRealtimeRefresh:l,statusFilter:m,setStatusFilter:h,accessPointIdFilter:g,setAccessPointIdFilter:_,accessPoints:v,destCountryFilter:y,setDestCountryFilter:b,ispFilter:x,setIspFilter:S,searchQuery:w,setSearchQuery:T,stats:j,logRetentionDays:M,onExport:R,exporting:L,loading:D,syncing:k}),te&&!z&&(0,Z.jsx)(ne,{isMobile:r,unlocking:B,onUnlockPasskey:se,onOpenRecoveryDialog:()=>{K(``),W(``),H(!0)}}),(0,Z.jsx)(he,{logs:E,loading:D,loadingMore:O,hasMore:A,realtimeRefresh:c,isMobile:r,searchQuery:w,scrollContainerRef:P,lastLogElementRef:F,prevLatestTimestamp:N,setSelectedLog:a,setIsDrawerOpen:s,logRetentionDays:M}),(0,Z.jsx)(xe,{isDrawerOpen:o,setIsDrawerOpen:s,selectedLog:i,profileId:e,isMobile:r,onQuickAction:t}),(0,Z.jsx)(ie,{isOpen:V,onClose:()=>H(!1),recoveryKeyInput:U,setRecoveryKeyInput:W,recoveryError:G,unlocking:B,onSubmit:ce}),(0,Z.jsx)(re,{rotatedKey:q,onClose:()=>J(null),copiedKey:Y,onCopyKey:oe})]})};export{Re as LogsView};
|