agim-cli 1.2.43 → 1.2.44
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/dist/web/public/assets/{a2a-Dvz7ig4m.js → a2a-Bg_mT0z1.js} +2 -2
- package/dist/web/public/assets/{a2a-Dvz7ig4m.js.map → a2a-Bg_mT0z1.js.map} +1 -1
- package/dist/web/public/assets/{activity-BJqk7b-v.js → activity-U9AaNlDt.js} +2 -2
- package/dist/web/public/assets/{activity-BJqk7b-v.js.map → activity-U9AaNlDt.js.map} +1 -1
- package/dist/web/public/assets/{admins-DeiNQcMh.js → admins-BTC_YEK9.js} +2 -2
- package/dist/web/public/assets/{admins-DeiNQcMh.js.map → admins-BTC_YEK9.js.map} +1 -1
- package/dist/web/public/assets/{agents-DJGdXKLv.js → agents-o9odac79.js} +2 -2
- package/dist/web/public/assets/{agents-DJGdXKLv.js.map → agents-o9odac79.js.map} +1 -1
- package/dist/web/public/assets/{approvals-BOJ9et5G.js → approvals-Boj7iXz4.js} +2 -2
- package/dist/web/public/assets/{approvals-BOJ9et5G.js.map → approvals-Boj7iXz4.js.map} +1 -1
- package/dist/web/public/assets/{audit-Dnnevx6v.js → audit-MprCFoy_.js} +2 -2
- package/dist/web/public/assets/{audit-Dnnevx6v.js.map → audit-MprCFoy_.js.map} +1 -1
- package/dist/web/public/assets/{bgjobs-BZAxNFpA.js → bgjobs-B6XvxURz.js} +2 -2
- package/dist/web/public/assets/{bgjobs-BZAxNFpA.js.map → bgjobs-B6XvxURz.js.map} +1 -1
- package/dist/web/public/assets/{brain-fC59o4ZL.js → brain-C5HejASN.js} +2 -2
- package/dist/web/public/assets/{brain-fC59o4ZL.js.map → brain-C5HejASN.js.map} +1 -1
- package/dist/web/public/assets/{briefcase-DJRv77W6.js → briefcase-DkCTxO1A.js} +2 -2
- package/dist/web/public/assets/{briefcase-DJRv77W6.js.map → briefcase-DkCTxO1A.js.map} +1 -1
- package/dist/web/public/assets/{chevron-right-DzyVDoQs.js → chevron-right-DEyrYFz4.js} +2 -2
- package/dist/web/public/assets/{chevron-right-DzyVDoQs.js.map → chevron-right-DEyrYFz4.js.map} +1 -1
- package/dist/web/public/assets/{circle-check-B7B_CkmJ.js → circle-check-bADFEXGw.js} +2 -2
- package/dist/web/public/assets/{circle-check-B7B_CkmJ.js.map → circle-check-bADFEXGw.js.map} +1 -1
- package/dist/web/public/assets/{circle-check-big-dmFsJv6U.js → circle-check-big-U4xrkHiS.js} +2 -2
- package/dist/web/public/assets/{circle-check-big-dmFsJv6U.js.map → circle-check-big-U4xrkHiS.js.map} +1 -1
- package/dist/web/public/assets/{circle-x-epC-av6L.js → circle-x-C6qY5UUl.js} +2 -2
- package/dist/web/public/assets/{circle-x-epC-av6L.js.map → circle-x-C6qY5UUl.js.map} +1 -1
- package/dist/web/public/assets/{confirm-dialog-BEzhDlk7.js → confirm-dialog-B53cbWzX.js} +2 -2
- package/dist/web/public/assets/{confirm-dialog-BEzhDlk7.js.map → confirm-dialog-B53cbWzX.js.map} +1 -1
- package/dist/web/public/assets/{data-table-B_BxQrSj.js → data-table-BKTemkw9.js} +2 -2
- package/dist/web/public/assets/{data-table-B_BxQrSj.js.map → data-table-BKTemkw9.js.map} +1 -1
- package/dist/web/public/assets/{dialog-BAZNQtMt.js → dialog-Cevi7KvQ.js} +2 -2
- package/dist/web/public/assets/{dialog-BAZNQtMt.js.map → dialog-Cevi7KvQ.js.map} +1 -1
- package/dist/web/public/assets/{download-C08F-eA4.js → download-DwJNwdwV.js} +2 -2
- package/dist/web/public/assets/{download-C08F-eA4.js.map → download-DwJNwdwV.js.map} +1 -1
- package/dist/web/public/assets/{email-qzOnhITw.js → email-CZVaRhG_.js} +2 -2
- package/dist/web/public/assets/{email-qzOnhITw.js.map → email-CZVaRhG_.js.map} +1 -1
- package/dist/web/public/assets/{empty-state-BKs1qKHx.js → empty-state-C87S9Wor.js} +2 -2
- package/dist/web/public/assets/{empty-state-BKs1qKHx.js.map → empty-state-C87S9Wor.js.map} +1 -1
- package/dist/web/public/assets/{external-link-HML--jya.js → external-link-CIM1wjHP.js} +2 -2
- package/dist/web/public/assets/{external-link-HML--jya.js.map → external-link-CIM1wjHP.js.map} +1 -1
- package/dist/web/public/assets/{eye-C20O3zvh.js → eye-TUAOhz72.js} +2 -2
- package/dist/web/public/assets/{eye-C20O3zvh.js.map → eye-TUAOhz72.js.map} +1 -1
- package/dist/web/public/assets/{facts-B7VlqoVs.js → facts-ByM1VHCp.js} +2 -2
- package/dist/web/public/assets/{facts-B7VlqoVs.js.map → facts-ByM1VHCp.js.map} +1 -1
- package/dist/web/public/assets/{health-IF_VcgWW.js → health-B4GF06J-.js} +2 -2
- package/dist/web/public/assets/{health-IF_VcgWW.js.map → health-B4GF06J-.js.map} +1 -1
- package/dist/web/public/assets/{hot-D-aKQ8y2.js → hot-O9Z19xXa.js} +2 -2
- package/dist/web/public/assets/{hot-D-aKQ8y2.js.map → hot-O9Z19xXa.js.map} +1 -1
- package/dist/web/public/assets/{index-B48azMO-.js → index-CITyis5g.js} +4 -4
- package/dist/web/public/assets/{index-B48azMO-.js.map → index-CITyis5g.js.map} +1 -1
- package/dist/web/public/assets/{installed-CkiQRc89.js → installed-CM34mlDU.js} +2 -2
- package/dist/web/public/assets/{installed-CkiQRc89.js.map → installed-CM34mlDU.js.map} +1 -1
- package/dist/web/public/assets/{jobs-g1Wl8_zd.js → jobs-DwA9Ip87.js} +2 -2
- package/dist/web/public/assets/{jobs-g1Wl8_zd.js.map → jobs-DwA9Ip87.js.map} +1 -1
- package/dist/web/public/assets/{layout-D_CUXsIR.js → layout-BxrFilDN.js} +2 -2
- package/dist/web/public/assets/{layout-D_CUXsIR.js.map → layout-BxrFilDN.js.map} +1 -1
- package/dist/web/public/assets/{layout-ChcpcCB8.js → layout-CR5gLapT.js} +2 -2
- package/dist/web/public/assets/{layout-ChcpcCB8.js.map → layout-CR5gLapT.js.map} +1 -1
- package/dist/web/public/assets/{layout-CjLzz--E.js → layout-CcJQxFci.js} +2 -2
- package/dist/web/public/assets/{layout-CjLzz--E.js.map → layout-CcJQxFci.js.map} +1 -1
- package/dist/web/public/assets/{layout-CS9s-Q0a.js → layout-DRRveTaR.js} +2 -2
- package/dist/web/public/assets/{layout-CS9s-Q0a.js.map → layout-DRRveTaR.js.map} +1 -1
- package/dist/web/public/assets/{layout-fTZD9lJN.js → layout-zotlJ5fW.js} +2 -2
- package/dist/web/public/assets/{layout-fTZD9lJN.js.map → layout-zotlJ5fW.js.map} +1 -1
- package/dist/web/public/assets/{loader-circle-DBf4xFjo.js → loader-circle-BFp6Oc8_.js} +2 -2
- package/dist/web/public/assets/{loader-circle-DBf4xFjo.js.map → loader-circle-BFp6Oc8_.js.map} +1 -1
- package/dist/web/public/assets/{map-pin-BYR0Sf5r.js → map-pin-DPqnsBIG.js} +2 -2
- package/dist/web/public/assets/{map-pin-BYR0Sf5r.js.map → map-pin-DPqnsBIG.js.map} +1 -1
- package/dist/web/public/assets/{memos-ChfapnyG.js → memos-DCACQN26.js} +2 -2
- package/dist/web/public/assets/{memos-ChfapnyG.js.map → memos-DCACQN26.js.map} +1 -1
- package/dist/web/public/assets/{messengers-zBIYakPW.js → messengers-CwWP1qI4.js} +2 -2
- package/dist/web/public/assets/{messengers-zBIYakPW.js.map → messengers-CwWP1qI4.js.map} +1 -1
- package/dist/web/public/assets/{network-CEqTiog6.js → network-CrMEVz4-.js} +2 -2
- package/dist/web/public/assets/{network-CEqTiog6.js.map → network-CrMEVz4-.js.map} +1 -1
- package/dist/web/public/assets/{outbox-D4IQcACJ.js → outbox-C7FpZzwS.js} +2 -2
- package/dist/web/public/assets/{outbox-D4IQcACJ.js.map → outbox-C7FpZzwS.js.map} +1 -1
- package/dist/web/public/assets/{pagination-R9mql8VB.js → pagination-Cgt8W6EX.js} +2 -2
- package/dist/web/public/assets/{pagination-R9mql8VB.js.map → pagination-Cgt8W6EX.js.map} +1 -1
- package/dist/web/public/assets/{persona-Cj_C5frK.js → persona-Bjty6uqM.js} +2 -2
- package/dist/web/public/assets/{persona-Cj_C5frK.js.map → persona-Bjty6uqM.js.map} +1 -1
- package/dist/web/public/assets/{play-CTWqoMcj.js → play-CEoS1N8t.js} +2 -2
- package/dist/web/public/assets/{play-CTWqoMcj.js.map → play-CEoS1N8t.js.map} +1 -1
- package/dist/web/public/assets/{policy-BKEZ2ziu.js → policy-DwI-ov9J.js} +2 -2
- package/dist/web/public/assets/{policy-BKEZ2ziu.js.map → policy-DwI-ov9J.js.map} +1 -1
- package/dist/web/public/assets/{refresh-ccw-Clj5sQNF.js → refresh-ccw-CPSYEbgh.js} +2 -2
- package/dist/web/public/assets/{refresh-ccw-Clj5sQNF.js.map → refresh-ccw-CPSYEbgh.js.map} +1 -1
- package/dist/web/public/assets/{reminders-C5bVkLgj.js → reminders-X-QFSWvZ.js} +2 -2
- package/dist/web/public/assets/{reminders-C5bVkLgj.js.map → reminders-X-QFSWvZ.js.map} +1 -1
- package/dist/web/public/assets/{save-CAFra1jb.js → save-tS3IBPf3.js} +2 -2
- package/dist/web/public/assets/{save-CAFra1jb.js.map → save-tS3IBPf3.js.map} +1 -1
- package/dist/web/public/assets/{schedules-KQCD7978.js → schedules-CfCNvhCV.js} +2 -2
- package/dist/web/public/assets/{schedules-KQCD7978.js.map → schedules-CfCNvhCV.js.map} +1 -1
- package/dist/web/public/assets/{search-bDqizeZv.js → search-BPvPCccn.js} +2 -2
- package/dist/web/public/assets/{search-bDqizeZv.js.map → search-BPvPCccn.js.map} +1 -1
- package/dist/web/public/assets/{service-DTeMmX2u.js → service-DSitDFzD.js} +2 -2
- package/dist/web/public/assets/{service-DTeMmX2u.js.map → service-DSitDFzD.js.map} +1 -1
- package/dist/web/public/assets/{status-badge-_3Ve0Jef.js → status-badge-HSHkhdur.js} +2 -2
- package/dist/web/public/assets/{status-badge-_3Ve0Jef.js.map → status-badge-HSHkhdur.js.map} +1 -1
- package/dist/web/public/assets/{subtasks-DROeZcfT.js → subtasks-eKq_P0v6.js} +2 -2
- package/dist/web/public/assets/{subtasks-DROeZcfT.js.map → subtasks-eKq_P0v6.js.map} +1 -1
- package/dist/web/public/assets/{table-CZwKizat.js → table-BBISYTH-.js} +2 -2
- package/dist/web/public/assets/{table-CZwKizat.js.map → table-BBISYTH-.js.map} +1 -1
- package/dist/web/public/assets/{topn-DpErN6N8.js → topn-JA8llaUI.js} +2 -2
- package/dist/web/public/assets/{topn-DpErN6N8.js.map → topn-JA8llaUI.js.map} +1 -1
- package/dist/web/public/assets/{trash-2-BkZrVFdH.js → trash-2-D8F96aYm.js} +2 -2
- package/dist/web/public/assets/{trash-2-BkZrVFdH.js.map → trash-2-D8F96aYm.js.map} +1 -1
- package/dist/web/public/assets/{use-memory-CElm89Hg.js → use-memory-BDa1R8Tf.js} +2 -2
- package/dist/web/public/assets/{use-memory-CElm89Hg.js.map → use-memory-BDa1R8Tf.js.map} +1 -1
- package/dist/web/public/assets/{use-observability-D8qHfj0S.js → use-observability-XgxLMQsY.js} +2 -2
- package/dist/web/public/assets/{use-observability-D8qHfj0S.js.map → use-observability-XgxLMQsY.js.map} +1 -1
- package/dist/web/public/assets/{use-settings-DgU8YmGj.js → use-settings-Bc4s-JUD.js} +2 -2
- package/dist/web/public/assets/{use-settings-DgU8YmGj.js.map → use-settings-Bc4s-JUD.js.map} +1 -1
- package/dist/web/public/assets/{use-skills-Cp_ok0Uq.js → use-skills-DCOYAQ8s.js} +2 -2
- package/dist/web/public/assets/{use-skills-Cp_ok0Uq.js.map → use-skills-DCOYAQ8s.js.map} +1 -1
- package/dist/web/public/assets/{use-workspace-Dc6rNi5d.js → use-workspace-JalfqH6H.js} +2 -2
- package/dist/web/public/assets/{use-workspace-Dc6rNi5d.js.map → use-workspace-JalfqH6H.js.map} +1 -1
- package/dist/web/public/assets/{useQuery-BjFqOBV3.js → useQuery-DFryK9Pn.js} +2 -2
- package/dist/web/public/assets/{useQuery-BjFqOBV3.js.map → useQuery-DFryK9Pn.js.map} +1 -1
- package/dist/web/public/assets/{vector-Bb3l7TOa.js → vector-G2dN_aut.js} +2 -2
- package/dist/web/public/assets/{vector-Bb3l7TOa.js.map → vector-G2dN_aut.js.map} +1 -1
- package/dist/web/public/assets/viewer-DliYQkQQ.js +12 -0
- package/dist/web/public/assets/viewer-DliYQkQQ.js.map +1 -0
- package/dist/web/public/assets/{workspace-Du8va-tD.js → workspace-BaLZIgGn.js} +2 -2
- package/dist/web/public/assets/{workspace-Du8va-tD.js.map → workspace-BaLZIgGn.js.map} +1 -1
- package/dist/web/public/assets/{workspaces-BjgDtEnF.js → workspaces-cX_rV523.js} +2 -2
- package/dist/web/public/assets/{workspaces-BjgDtEnF.js.map → workspaces-cX_rV523.js.map} +1 -1
- package/dist/web/public/assets/{x-CHe1y-sG.js → x-D5196-9X.js} +2 -2
- package/dist/web/public/assets/{x-CHe1y-sG.js.map → x-D5196-9X.js.map} +1 -1
- package/dist/web/public/index.html +1 -1
- package/package.json +1 -1
- package/dist/web/public/assets/viewer-BeyW50lw.js +0 -12
- package/dist/web/public/assets/viewer-BeyW50lw.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{x as A,ac as w,Q as e,c as f,B as F,a2 as y,z as q,L as P,I as C}from"./index-
|
|
1
|
+
import{x as A,ac as w,Q as e,c as f,B as F,a2 as y,z as q,L as P,I as C}from"./index-CITyis5g.js";import{e as p}from"./react-C9F3QeMB.js";import{D,a as R,d as E,e as Q,b as $}from"./dialog-Cevi7KvQ.js";import{b as M,m as z,i as O,q as B}from"./use-settings-Bc4s-JUD.js";import{L as S}from"./loader-circle-BFp6Oc8_.js";import{R as L}from"./refresh-ccw-CPSYEbgh.js";import{X as T}from"./x-D5196-9X.js";import{S as H}from"./save-tS3IBPf3.js";import"./useQuery-DFryK9Pn.js";/**
|
|
2
2
|
* @license lucide-react v0.469.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/const W=A("QrCode",[["rect",{width:"5",height:"5",x:"3",y:"3",rx:"1",key:"1tu5fj"}],["rect",{width:"5",height:"5",x:"16",y:"3",rx:"1",key:"1v8r4q"}],["rect",{width:"5",height:"5",x:"3",y:"16",rx:"1",key:"1x03jg"}],["path",{d:"M21 16h-3a2 2 0 0 0-2 2v3",key:"177gqh"}],["path",{d:"M21 21v.01",key:"ents32"}],["path",{d:"M12 7v3a2 2 0 0 1-2 2H7",key:"8crl2c"}],["path",{d:"M3 12h.01",key:"nlz23k"}],["path",{d:"M12 3h.01",key:"n36tog"}],["path",{d:"M12 16v.01",key:"133mhm"}],["path",{d:"M16 12h1",key:"1slzba"}],["path",{d:"M21 12v.01",key:"1lwtk9"}],["path",{d:"M12 21v-1",key:"1880an"}]]);function N(s){const i=new Set(s?.messengers??[]);return{"wechat-ilink":{enabled:i.has("wechat-ilink")},telegram:{enabled:i.has("telegram"),telegram:{...s?.telegram??{}}},feishu:{enabled:i.has("feishu"),feishu:{...s?.feishu??{}}},dingtalk:{enabled:i.has("dingtalk"),dingtalk:{...s?.dingtalk??{}}},discord:{enabled:i.has("discord"),discord:{...s?.discord??{}}}}}function J(s,i){const t=[];for(const a of Object.keys(s))s[a].enabled&&t.push(a);return{messengers:t,telegram:s.telegram.telegram,feishu:s.feishu.feishu,dingtalk:s.dingtalk.dingtalk,discord:s.discord.discord,...Object.fromEntries(Object.entries(i).filter(([a])=>!["messengers","telegram","feishu","dingtalk","discord"].includes(a)))}}function le(){const{t:s}=w(["settings","common"]),i=M(),t=z(),[a,c]=p.useState(()=>N(i.data)),[g,h]=p.useState(!1);p.useEffect(()=>{g||i.data&&(c(N(i.data)),h(!0))},[i.data,g]);const m=i.data,n=p.useMemo(()=>m?JSON.stringify(N(m))!==JSON.stringify(a):!1,[m,a]),[r,o]=p.useState(!1);function d(l,j){c(I=>({...I,[l]:{...I[l],...j}}))}async function x(){if(m)try{await t.mutateAsync(J(a,m)),y.success(s("messengers.savedToast")),h(!1)}catch(l){y.error(q(l,s).message)}}function b(){m&&c(N(m))}return e.jsxs("div",{className:"mx-auto flex max-w-4xl flex-col gap-4",children:[e.jsxs("header",{className:"flex flex-col gap-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("h1",{className:"text-xl font-semibold",children:s("messengers.title")}),e.jsxs(f,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>i.refetch(),disabled:i.isFetching,"aria-label":s("actions.refresh",{ns:"common"}),children:[i.isFetching?e.jsx(S,{className:"h-4 w-4 animate-spin"}):e.jsx(L,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:s("actions.refresh",{ns:"common"})})]})]}),e.jsx("p",{className:"text-sm text-text-dim",children:s("messengers.subtitle")})]}),e.jsx("div",{className:"flex flex-wrap items-center gap-2",children:n?e.jsxs(e.Fragment,{children:[e.jsx(F,{variant:"info",children:s("messengers.dirtyHint")}),e.jsxs(f,{type:"button",variant:"secondary",size:"sm",onClick:b,disabled:t.isPending,children:[e.jsx(T,{className:"h-4 w-4"}),s("messengers.discardAll")]}),e.jsxs(f,{type:"button",size:"sm",onClick:()=>void x(),disabled:t.isPending,children:[t.isPending?e.jsx(S,{className:"h-4 w-4 animate-spin"}):e.jsx(H,{className:"h-4 w-4"}),t.isPending?s("messengers.saving"):s("messengers.saveAll")]})]}):e.jsx("span",{className:"text-xs text-text-muted",children:s("env.noChanges")})}),i.isLoading?e.jsx("div",{className:"h-96 rounded-md bg-surface-2 animate-pulse"}):m?e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsx(v,{slot:"wechat-ilink",label:s("messengers.platform.wechat"),hint:s("messengers.hint.wechat"),enabled:a["wechat-ilink"].enabled,onToggle:l=>d("wechat-ilink",{enabled:l}),children:e.jsxs(f,{type:"button",variant:"secondary",size:"sm",onClick:()=>o(!0),children:[e.jsx(W,{className:"h-4 w-4"}),s("messengers.scanQr")]})}),m.features?.globalIm?e.jsxs(v,{slot:"telegram",label:s("messengers.platform.telegram"),hint:s("messengers.hint.telegram"),enabled:a.telegram.enabled,onToggle:l=>d("telegram",{enabled:l}),children:[e.jsx(u,{id:"tg-token",label:s("messengers.fields.botToken"),value:a.telegram.telegram?.botToken??"",type:"password",onChange:l=>d("telegram",{telegram:{...a.telegram.telegram,botToken:l}})}),e.jsx(u,{id:"tg-channel",label:s("messengers.fields.channelId"),value:a.telegram.telegram?.channelId??"",onChange:l=>d("telegram",{telegram:{...a.telegram.telegram,channelId:l}})})]}):null,e.jsxs(v,{slot:"feishu",label:s("messengers.platform.feishu"),hint:s("messengers.hint.feishu"),enabled:a.feishu.enabled,onToggle:l=>d("feishu",{enabled:l}),children:[e.jsx(u,{id:"fs-appid",label:s("messengers.fields.appId"),value:a.feishu.feishu?.appId??"",onChange:l=>d("feishu",{feishu:{...a.feishu.feishu,appId:l}})}),e.jsx(u,{id:"fs-secret",label:s("messengers.fields.appSecret"),value:a.feishu.feishu?.appSecret??"",type:"password",onChange:l=>d("feishu",{feishu:{...a.feishu.feishu,appSecret:l}})}),e.jsx(u,{id:"fs-channel",label:s("messengers.fields.channelId"),value:a.feishu.feishu?.channelId??"",onChange:l=>d("feishu",{feishu:{...a.feishu.feishu,channelId:l}})})]}),e.jsxs(v,{slot:"dingtalk",label:s("messengers.platform.dingtalk"),hint:s("messengers.hint.dingtalk"),enabled:a.dingtalk.enabled,onToggle:l=>d("dingtalk",{enabled:l}),children:[e.jsx(u,{id:"dt-cid",label:s("messengers.fields.clientId"),value:a.dingtalk.dingtalk?.clientId??"",onChange:l=>d("dingtalk",{dingtalk:{...a.dingtalk.dingtalk,clientId:l}})}),e.jsx(u,{id:"dt-secret",label:s("messengers.fields.clientSecret"),value:a.dingtalk.dingtalk?.clientSecret??"",type:"password",onChange:l=>d("dingtalk",{dingtalk:{...a.dingtalk.dingtalk,clientSecret:l}})}),e.jsx(u,{id:"dt-channel",label:s("messengers.fields.channelId"),value:a.dingtalk.dingtalk?.channelId??"",onChange:l=>d("dingtalk",{dingtalk:{...a.dingtalk.dingtalk,channelId:l}})}),e.jsx(k,{id:"dt-dm-policy",label:s("messengers.dingtalk.dmPolicy"),value:a.dingtalk.dingtalk?.dmPolicy??"open",onChange:l=>d("dingtalk",{dingtalk:{...a.dingtalk.dingtalk,dmPolicy:l}}),options:[{value:"open",label:s("messengers.dingtalk.policy.open")},{value:"pairing",label:s("messengers.dingtalk.policy.pairing")},{value:"allowlist",label:s("messengers.dingtalk.policy.allowlist")}]}),e.jsx(k,{id:"dt-group-policy",label:s("messengers.dingtalk.groupPolicy"),value:a.dingtalk.dingtalk?.groupPolicy??"open",onChange:l=>d("dingtalk",{dingtalk:{...a.dingtalk.dingtalk,groupPolicy:l}}),options:[{value:"open",label:s("messengers.dingtalk.policy.open")},{value:"allowlist",label:s("messengers.dingtalk.policy.allowlist")},{value:"disabled",label:s("messengers.dingtalk.policy.disabled")}]}),e.jsx(u,{id:"dt-allow-from",label:s("messengers.dingtalk.allowFrom"),value:(a.dingtalk.dingtalk?.allowFrom??[]).join(","),onChange:l=>d("dingtalk",{dingtalk:{...a.dingtalk.dingtalk,allowFrom:l.split(",").map(j=>j.trim()).filter(Boolean)}})}),e.jsx(u,{id:"dt-group-allow-from",label:s("messengers.dingtalk.groupAllowFrom"),value:(a.dingtalk.dingtalk?.groupAllowFrom??[]).join(","),onChange:l=>d("dingtalk",{dingtalk:{...a.dingtalk.dingtalk,groupAllowFrom:l.split(",").map(j=>j.trim()).filter(Boolean)}})}),e.jsx(k,{id:"dt-ack",label:s("messengers.dingtalk.ackReaction"),value:a.dingtalk.dingtalk?.ackReaction??"off",onChange:l=>d("dingtalk",{dingtalk:{...a.dingtalk.dingtalk,ackReaction:l}}),options:[{value:"off",label:s("messengers.dingtalk.ack.off")},{value:"emoji",label:s("messengers.dingtalk.ack.emoji")},{value:"kaomoji",label:s("messengers.dingtalk.ack.kaomoji")}]}),e.jsx(U,{accounts:a.dingtalk.dingtalk?.accounts??{},onChange:l=>d("dingtalk",{dingtalk:{...a.dingtalk.dingtalk,accounts:l}})})]}),m.features?.globalIm?e.jsxs(v,{slot:"discord",label:s("messengers.platform.discord"),hint:s("messengers.hint.discord"),enabled:a.discord.enabled,onToggle:l=>d("discord",{enabled:l}),children:[e.jsx(u,{id:"dc-token",label:s("messengers.fields.botToken"),value:a.discord.discord?.botToken??"",type:"password",onChange:l=>d("discord",{discord:{...a.discord.discord,botToken:l}})}),e.jsx(u,{id:"dc-channel",label:s("messengers.fields.channelId"),value:a.discord.discord?.channelId??"",onChange:l=>d("discord",{discord:{...a.discord.discord,channelId:l}})})]}):null]}):null,e.jsx(_,{open:r,onOpenChange:o,onConfirmed:()=>{i.refetch(),h(!1)}})]})}function v({label:s,hint:i,enabled:t,onToggle:a,children:c}){const{t:g}=w("settings");return e.jsxs("div",{className:"rounded-md border border-border bg-surface p-4",children:[e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-medium text-text",children:s}),e.jsx(F,{variant:t?"success":"outline",children:g(t?"messengers.enabled":"messengers.disabled")})]}),e.jsx("p",{className:"mt-1 text-xs text-text-dim",children:i})]}),e.jsx("label",{className:"inline-flex items-center gap-2 text-sm",children:e.jsx("input",{type:"checkbox",checked:t,onChange:h=>a(h.target.checked),className:"h-4 w-4 accent-accent cursor-pointer"})})]}),t&&c&&e.jsx("div",{className:"mt-3 flex flex-col gap-2",children:c})]})}function u({id:s,label:i,value:t,onChange:a,type:c="text"}){return e.jsxs("div",{className:"grid grid-cols-1 gap-1 sm:grid-cols-[180px_1fr] sm:items-center sm:gap-2",children:[e.jsx(P,{htmlFor:s,className:"text-xs text-text-dim",children:i}),e.jsx(C,{id:s,type:c,value:t,onChange:g=>a(g.target.value),autoComplete:"off",className:"font-mono text-xs"})]})}function k({id:s,label:i,value:t,onChange:a,options:c}){return e.jsxs("div",{className:"grid grid-cols-1 gap-1 sm:grid-cols-[180px_1fr] sm:items-center sm:gap-2",children:[e.jsx(P,{htmlFor:s,className:"text-xs text-text-dim",children:i}),e.jsx("select",{id:s,value:t,onChange:g=>a(g.target.value),className:"rounded-md border border-input bg-background px-2 py-1 text-xs",children:c.map(g=>e.jsx("option",{value:g.value,children:g.label},g.value))})]})}function _({open:s,onOpenChange:i,onConfirmed:t}){const{t:a}=w(["settings","common"]),c=O(),[g,h]=p.useState(null),[m,n]=p.useState(null),[r,o]=p.useState(null);p.useEffect(()=>{if(!s){h(null),n(null),o(null);return}let b=!0;return c.mutateAsync().then(l=>{b&&(n(l.qrImage),h(l.qrToken))}).catch(l=>{b&&o(l instanceof Error?l.message:String(l))}),()=>{b=!1}},[s]);const x=B(s?g:null).data?.status;return p.useEffect(()=>{x==="confirmed"&&(y.success(a("messengers.qr.confirmed")),t(),i(!1)),x==="expired"&&y.error(a("messengers.qr.expired"))},[x]),e.jsx(D,{open:s,onOpenChange:i,children:e.jsxs(R,{children:[e.jsxs(E,{children:[e.jsx(Q,{children:a("messengers.qr.title")}),e.jsx($,{children:a("messengers.qr.description")})]}),e.jsx("div",{className:"flex flex-col items-center gap-3",children:c.isPending&&!m?e.jsxs(e.Fragment,{children:[e.jsx(S,{className:"h-8 w-8 animate-spin text-text-dim"}),e.jsx("p",{className:"text-sm text-text-dim",children:a("messengers.qr.starting")})]}):r?e.jsxs("p",{className:"text-sm text-danger",children:[a("messengers.qr.loadFailed"),": ",r]}):m?e.jsxs(e.Fragment,{children:[e.jsx("img",{src:m,alt:a("messengers.qr.title"),className:"rounded-md border border-border"}),x==="expired"?e.jsx("p",{className:"text-xs text-danger",children:a("messengers.qr.expired")}):e.jsx("p",{className:"text-xs text-text-dim",children:x?`· ${x} ·`:""})]}):null})]})})}function U({accounts:s,onChange:i}){const{t}=w(["settings","common"]),a=Object.entries(s),c=(n,r)=>{i({...s,[n]:{...s[n],...r}})},g=n=>{const r={...s};delete r[n],i(r)},h=(n,r)=>{if(!r||r===n)return;if(s[r]){y.error(t("messengers.dingtalk.accountRenameCollision",{id:r}));return}const o={};for(const[d,x]of Object.entries(s))o[d===n?r:d]=x;i(o)},m=()=>{let n=a.length+1,r=`account-${n}`;for(;s[r];)n+=1,r=`account-${n}`;i({...s,[r]:{enabled:!0}})};return e.jsxs("div",{className:"mt-3 border-t border-input pt-3",children:[e.jsxs("div",{className:"mb-2 flex items-center justify-between",children:[e.jsx("div",{className:"text-xs font-semibold text-text-dim",children:t("messengers.dingtalk.accountsTitle")}),e.jsxs(f,{type:"button",size:"sm",variant:"outline",onClick:m,children:["+ ",t("messengers.dingtalk.addAccount")]})]}),a.length===0?e.jsx("div",{className:"text-xs text-text-dim italic",children:t("messengers.dingtalk.accountsEmpty")}):e.jsx("div",{className:"space-y-3",children:a.map(([n,r])=>e.jsxs("div",{className:"rounded-md border border-input p-2",children:[e.jsxs("div",{className:"mb-2 flex items-center gap-2",children:[e.jsx(C,{id:`acct-id-${n}`,defaultValue:n,onBlur:o=>h(n,o.target.value.trim()),className:"font-mono text-xs w-40",placeholder:"account-id"}),e.jsx(C,{id:`acct-name-${n}`,value:r.name??"",onChange:o=>c(n,{name:o.target.value}),className:"text-xs flex-1",placeholder:t("messengers.dingtalk.accountName")}),e.jsxs("label",{className:"flex items-center gap-1 text-xs",children:[e.jsx("input",{type:"checkbox",checked:r.enabled!==!1,onChange:o=>c(n,{enabled:o.target.checked})}),t("messengers.enabled")]}),e.jsx(f,{type:"button",size:"sm",variant:"ghost",onClick:()=>g(n),className:"text-danger",children:e.jsx(T,{className:"size-4"})})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(u,{id:`acct-cid-${n}`,label:t("messengers.fields.clientId"),value:r.clientId??"",onChange:o=>c(n,{clientId:o})}),e.jsx(u,{id:`acct-secret-${n}`,label:t("messengers.fields.clientSecret"),value:r.clientSecret??"",type:"password",onChange:o=>c(n,{clientSecret:o})}),e.jsx(k,{id:`acct-dm-${n}`,label:t("messengers.dingtalk.dmPolicy"),value:r.dmPolicy??"open",onChange:o=>c(n,{dmPolicy:o}),options:[{value:"open",label:t("messengers.dingtalk.policy.open")},{value:"pairing",label:t("messengers.dingtalk.policy.pairing")},{value:"allowlist",label:t("messengers.dingtalk.policy.allowlist")}]}),e.jsx(k,{id:`acct-group-${n}`,label:t("messengers.dingtalk.groupPolicy"),value:r.groupPolicy??"open",onChange:o=>c(n,{groupPolicy:o}),options:[{value:"open",label:t("messengers.dingtalk.policy.open")},{value:"allowlist",label:t("messengers.dingtalk.policy.allowlist")},{value:"disabled",label:t("messengers.dingtalk.policy.disabled")}]}),e.jsx(u,{id:`acct-allow-${n}`,label:t("messengers.dingtalk.allowFrom"),value:(r.allowFrom??[]).join(","),onChange:o=>c(n,{allowFrom:o.split(",").map(d=>d.trim()).filter(Boolean)})}),e.jsx(u,{id:`acct-gallow-${n}`,label:t("messengers.dingtalk.groupAllowFrom"),value:(r.groupAllowFrom??[]).join(","),onChange:o=>c(n,{groupAllowFrom:o.split(",").map(d=>d.trim()).filter(Boolean)})}),e.jsx(k,{id:`acct-ack-${n}`,label:t("messengers.dingtalk.ackReaction"),value:r.ackReaction??"off",onChange:o=>c(n,{ackReaction:o}),options:[{value:"off",label:t("messengers.dingtalk.ack.off")},{value:"emoji",label:t("messengers.dingtalk.ack.emoji")},{value:"kaomoji",label:t("messengers.dingtalk.ack.kaomoji")}]})]})]},n))}),e.jsx("div",{className:"mt-1 text-xs text-text-dim",children:t("messengers.dingtalk.accountsHint")})]})}export{le as default};
|
|
7
|
-
//# sourceMappingURL=messengers-
|
|
7
|
+
//# sourceMappingURL=messengers-CwWP1qI4.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messengers-zBIYakPW.js","sources":["../../node_modules/lucide-react/dist/esm/icons/qr-code.js","../../src/routes/settings/messengers.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst QrCode = createLucideIcon(\"QrCode\", [\n [\"rect\", { width: \"5\", height: \"5\", x: \"3\", y: \"3\", rx: \"1\", key: \"1tu5fj\" }],\n [\"rect\", { width: \"5\", height: \"5\", x: \"16\", y: \"3\", rx: \"1\", key: \"1v8r4q\" }],\n [\"rect\", { width: \"5\", height: \"5\", x: \"3\", y: \"16\", rx: \"1\", key: \"1x03jg\" }],\n [\"path\", { d: \"M21 16h-3a2 2 0 0 0-2 2v3\", key: \"177gqh\" }],\n [\"path\", { d: \"M21 21v.01\", key: \"ents32\" }],\n [\"path\", { d: \"M12 7v3a2 2 0 0 1-2 2H7\", key: \"8crl2c\" }],\n [\"path\", { d: \"M3 12h.01\", key: \"nlz23k\" }],\n [\"path\", { d: \"M12 3h.01\", key: \"n36tog\" }],\n [\"path\", { d: \"M12 16v.01\", key: \"133mhm\" }],\n [\"path\", { d: \"M16 12h1\", key: \"1slzba\" }],\n [\"path\", { d: \"M21 12v.01\", key: \"1lwtk9\" }],\n [\"path\", { d: \"M12 21v-1\", key: \"1880an\" }]\n]);\n\nexport { QrCode as default };\n//# sourceMappingURL=qr-code.js.map\n","/**\n * /settings/messengers — per-IM-platform connection config.\n *\n * Layout: one card per platform (WeChat / Telegram / Feishu /\n * DingTalk / Discord). Each card has:\n * * Title + hint\n * * Enable / disable toggle (reads / writes config.messengers[])\n * * When enabled, the platform's config fields (texted)\n * * For WeChat: a \"Scan QR\" button → modal with QR + 2s polling\n *\n * Save All button at the top batches every dirty platform into one\n * PUT /api/config. The discard button reverts the local draft to\n * server-side values.\n *\n * The WeChat QR flow is special: enabling WeChat requires scanning\n * a QR code (the slot in config.messengers gets added by the\n * backend on `confirmed`, so we just open the modal and re-fetch\n * config after a successful scan).\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Loader2, QrCode, RefreshCcw, Save, X } from 'lucide-react'\n\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from '@/components/ui/dialog'\nimport {\n useConfig,\n useUpdateConfig,\n useStartWechatQr,\n useWechatQrStatus,\n} from '@/hooks/use-settings'\nimport { describeError } from '@/lib/api/errors'\nimport type { AppConfig } from '@/types/api'\n\n/** Slot names match what `config.messengers[]` contains.\n * WeChat uses 'wechat-ilink' (the iLink adapter ID). */\ntype Slot = 'wechat-ilink' | 'telegram' | 'feishu' | 'dingtalk' | 'discord'\n\ninterface PlatformDraft {\n enabled: boolean\n telegram?: { botToken?: string; channelId?: string }\n feishu?: { appId?: string; appSecret?: string; channelId?: string }\n dingtalk?: {\n clientId?: string\n clientSecret?: string\n channelId?: string\n // v1.2.37 (batch 1)\n dmPolicy?: 'open' | 'pairing' | 'allowlist'\n groupPolicy?: 'open' | 'allowlist' | 'disabled'\n allowFrom?: string[]\n groupAllowFrom?: string[]\n ackReaction?: 'off' | 'emoji' | 'kaomoji'\n // v1.2.41 (batch 4 follow-up) — full multi-account editor\n accounts?: Record<string, DingTalkAccountDraft>\n }\n discord?: { botToken?: string; channelId?: string }\n}\n\ntype Draft = Record<Slot, PlatformDraft>\n\nfunction buildDraft(cfg: AppConfig | undefined): Draft {\n const m = new Set(cfg?.messengers ?? [])\n return {\n 'wechat-ilink': { enabled: m.has('wechat-ilink') },\n telegram: { enabled: m.has('telegram'), telegram: { ...(cfg?.telegram ?? {}) } },\n feishu: { enabled: m.has('feishu'), feishu: { ...(cfg?.feishu ?? {}) } },\n dingtalk: { enabled: m.has('dingtalk'), dingtalk: { ...(cfg?.dingtalk ?? {}) } },\n discord: { enabled: m.has('discord'), discord: { ...(cfg?.discord ?? {}) } },\n }\n}\n\nfunction buildPatch(draft: Draft, cfg: AppConfig): Partial<AppConfig> {\n const messengers: string[] = []\n for (const k of Object.keys(draft) as Slot[]) if (draft[k].enabled) messengers.push(k)\n return {\n messengers,\n telegram: draft.telegram.telegram,\n feishu: draft.feishu.feishu,\n dingtalk: draft.dingtalk.dingtalk,\n discord: draft.discord.discord,\n // Preserve unknown extra fields the AppConfig type permits.\n ...Object.fromEntries(\n Object.entries(cfg).filter(([k]) => ![\n 'messengers', 'telegram', 'feishu', 'dingtalk', 'discord',\n ].includes(k)),\n ),\n }\n}\n\nexport default function SettingsMessengersRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const cfgQuery = useConfig()\n const updateCfg = useUpdateConfig()\n\n const [draft, setDraft] = useState<Draft>(() => buildDraft(cfgQuery.data))\n // Sync the draft once cfg lands. We don't re-sync on every cfg\n // refetch — that would discard unsaved edits.\n const [synced, setSynced] = useState(false)\n useEffect(() => {\n if (synced) return\n if (!cfgQuery.data) return\n setDraft(buildDraft(cfgQuery.data))\n setSynced(true)\n }, [cfgQuery.data, synced])\n\n const cfg = cfgQuery.data\n const isDirty = useMemo(() => {\n if (!cfg) return false\n return JSON.stringify(buildDraft(cfg)) !== JSON.stringify(draft)\n }, [cfg, draft])\n\n // WeChat QR modal state\n const [qrOpen, setQrOpen] = useState(false)\n\n function patchSlot(slot: Slot, partial: Partial<PlatformDraft>): void {\n setDraft((prev) => ({ ...prev, [slot]: { ...prev[slot], ...partial } }))\n }\n\n async function onSave(): Promise<void> {\n if (!cfg) return\n try {\n await updateCfg.mutateAsync(buildPatch(draft, cfg))\n toast.success(t('messengers.savedToast'))\n setSynced(false) // rebuild draft from refreshed cfg on next paint\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n function onDiscard(): void {\n if (cfg) setDraft(buildDraft(cfg))\n }\n\n return (\n <div className=\"mx-auto flex max-w-4xl flex-col gap-4\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('messengers.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => cfgQuery.refetch()}\n disabled={cfgQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {cfgQuery.isFetching ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('actions.refresh', { ns: 'common' })}</span>\n </Button>\n </div>\n <p className=\"text-sm text-text-dim\">{t('messengers.subtitle')}</p>\n </header>\n\n {/* Save bar */}\n <div className=\"flex flex-wrap items-center gap-2\">\n {isDirty ? (\n <>\n <Badge variant=\"info\">{t('messengers.dirtyHint')}</Badge>\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"sm\"\n onClick={onDiscard}\n disabled={updateCfg.isPending}\n >\n <X className=\"h-4 w-4\" />\n {t('messengers.discardAll')}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => void onSave()}\n disabled={updateCfg.isPending}\n >\n {updateCfg.isPending ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Save className=\"h-4 w-4\" />}\n {updateCfg.isPending ? t('messengers.saving') : t('messengers.saveAll')}\n </Button>\n </>\n ) : (\n <span className=\"text-xs text-text-muted\">{t('env.noChanges')}</span>\n )}\n </div>\n\n {cfgQuery.isLoading ? (\n <div className=\"h-96 rounded-md bg-surface-2 animate-pulse\" />\n ) : !cfg ? null : (\n <div className=\"flex flex-col gap-3\">\n <PlatformCard\n slot=\"wechat-ilink\"\n label={t('messengers.platform.wechat')}\n hint={t('messengers.hint.wechat')}\n enabled={draft['wechat-ilink'].enabled}\n onToggle={(v) => patchSlot('wechat-ilink', { enabled: v })}\n >\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => setQrOpen(true)}\n >\n <QrCode className=\"h-4 w-4\" />\n {t('messengers.scanQr')}\n </Button>\n </PlatformCard>\n\n {cfg.features?.globalIm ? (\n <PlatformCard\n slot=\"telegram\"\n label={t('messengers.platform.telegram')}\n hint={t('messengers.hint.telegram')}\n enabled={draft.telegram.enabled}\n onToggle={(v) => patchSlot('telegram', { enabled: v })}\n >\n <FieldRow\n id=\"tg-token\" label={t('messengers.fields.botToken')}\n value={draft.telegram.telegram?.botToken ?? ''}\n type=\"password\"\n onChange={(v) => patchSlot('telegram', { telegram: { ...draft.telegram.telegram, botToken: v } })}\n />\n <FieldRow\n id=\"tg-channel\" label={t('messengers.fields.channelId')}\n value={draft.telegram.telegram?.channelId ?? ''}\n onChange={(v) => patchSlot('telegram', { telegram: { ...draft.telegram.telegram, channelId: v } })}\n />\n </PlatformCard>\n ) : null}\n\n <PlatformCard\n slot=\"feishu\"\n label={t('messengers.platform.feishu')}\n hint={t('messengers.hint.feishu')}\n enabled={draft.feishu.enabled}\n onToggle={(v) => patchSlot('feishu', { enabled: v })}\n >\n <FieldRow\n id=\"fs-appid\" label={t('messengers.fields.appId')}\n value={draft.feishu.feishu?.appId ?? ''}\n onChange={(v) => patchSlot('feishu', { feishu: { ...draft.feishu.feishu, appId: v } })}\n />\n <FieldRow\n id=\"fs-secret\" label={t('messengers.fields.appSecret')}\n value={draft.feishu.feishu?.appSecret ?? ''}\n type=\"password\"\n onChange={(v) => patchSlot('feishu', { feishu: { ...draft.feishu.feishu, appSecret: v } })}\n />\n <FieldRow\n id=\"fs-channel\" label={t('messengers.fields.channelId')}\n value={draft.feishu.feishu?.channelId ?? ''}\n onChange={(v) => patchSlot('feishu', { feishu: { ...draft.feishu.feishu, channelId: v } })}\n />\n </PlatformCard>\n\n <PlatformCard\n slot=\"dingtalk\"\n label={t('messengers.platform.dingtalk')}\n hint={t('messengers.hint.dingtalk')}\n enabled={draft.dingtalk.enabled}\n onToggle={(v) => patchSlot('dingtalk', { enabled: v })}\n >\n <FieldRow\n id=\"dt-cid\" label={t('messengers.fields.clientId')}\n value={draft.dingtalk.dingtalk?.clientId ?? ''}\n onChange={(v) => patchSlot('dingtalk', { dingtalk: { ...draft.dingtalk.dingtalk, clientId: v } })}\n />\n <FieldRow\n id=\"dt-secret\" label={t('messengers.fields.clientSecret')}\n value={draft.dingtalk.dingtalk?.clientSecret ?? ''}\n type=\"password\"\n onChange={(v) => patchSlot('dingtalk', { dingtalk: { ...draft.dingtalk.dingtalk, clientSecret: v } })}\n />\n <FieldRow\n id=\"dt-channel\" label={t('messengers.fields.channelId')}\n value={draft.dingtalk.dingtalk?.channelId ?? ''}\n onChange={(v) => patchSlot('dingtalk', { dingtalk: { ...draft.dingtalk.dingtalk, channelId: v } })}\n />\n {/* v1.2.37 (batch 1) — access policy + ack-reaction */}\n <SelectRow<'open' | 'pairing' | 'allowlist'>\n id=\"dt-dm-policy\" label={t('messengers.dingtalk.dmPolicy')}\n value={draft.dingtalk.dingtalk?.dmPolicy ?? 'open'}\n onChange={(v) => patchSlot('dingtalk', { dingtalk: { ...draft.dingtalk.dingtalk, dmPolicy: v } })}\n options={[\n { value: 'open', label: t('messengers.dingtalk.policy.open') },\n { value: 'pairing', label: t('messengers.dingtalk.policy.pairing') },\n { value: 'allowlist', label: t('messengers.dingtalk.policy.allowlist') },\n ]}\n />\n <SelectRow<'open' | 'allowlist' | 'disabled'>\n id=\"dt-group-policy\" label={t('messengers.dingtalk.groupPolicy')}\n value={draft.dingtalk.dingtalk?.groupPolicy ?? 'open'}\n onChange={(v) => patchSlot('dingtalk', { dingtalk: { ...draft.dingtalk.dingtalk, groupPolicy: v } })}\n options={[\n { value: 'open', label: t('messengers.dingtalk.policy.open') },\n { value: 'allowlist', label: t('messengers.dingtalk.policy.allowlist') },\n { value: 'disabled', label: t('messengers.dingtalk.policy.disabled') },\n ]}\n />\n <FieldRow\n id=\"dt-allow-from\" label={t('messengers.dingtalk.allowFrom')}\n value={(draft.dingtalk.dingtalk?.allowFrom ?? []).join(',')}\n onChange={(v) => patchSlot('dingtalk', {\n dingtalk: {\n ...draft.dingtalk.dingtalk,\n allowFrom: v.split(',').map((s) => s.trim()).filter(Boolean),\n },\n })}\n />\n <FieldRow\n id=\"dt-group-allow-from\" label={t('messengers.dingtalk.groupAllowFrom')}\n value={(draft.dingtalk.dingtalk?.groupAllowFrom ?? []).join(',')}\n onChange={(v) => patchSlot('dingtalk', {\n dingtalk: {\n ...draft.dingtalk.dingtalk,\n groupAllowFrom: v.split(',').map((s) => s.trim()).filter(Boolean),\n },\n })}\n />\n <SelectRow<'off' | 'emoji' | 'kaomoji'>\n id=\"dt-ack\" label={t('messengers.dingtalk.ackReaction')}\n value={draft.dingtalk.dingtalk?.ackReaction ?? 'off'}\n onChange={(v) => patchSlot('dingtalk', { dingtalk: { ...draft.dingtalk.dingtalk, ackReaction: v } })}\n options={[\n { value: 'off', label: t('messengers.dingtalk.ack.off') },\n { value: 'emoji', label: t('messengers.dingtalk.ack.emoji') },\n { value: 'kaomoji', label: t('messengers.dingtalk.ack.kaomoji') },\n ]}\n />\n {/* v1.2.41 (batch 4 follow-up) — multi-account CRUD editor. */}\n <DingTalkAccountsEditor\n accounts={draft.dingtalk.dingtalk?.accounts ?? {}}\n onChange={(next) => patchSlot('dingtalk', {\n dingtalk: { ...draft.dingtalk.dingtalk, accounts: next },\n })}\n />\n </PlatformCard>\n\n {cfg.features?.globalIm ? (\n <PlatformCard\n slot=\"discord\"\n label={t('messengers.platform.discord')}\n hint={t('messengers.hint.discord')}\n enabled={draft.discord.enabled}\n onToggle={(v) => patchSlot('discord', { enabled: v })}\n >\n <FieldRow\n id=\"dc-token\" label={t('messengers.fields.botToken')}\n value={draft.discord.discord?.botToken ?? ''}\n type=\"password\"\n onChange={(v) => patchSlot('discord', { discord: { ...draft.discord.discord, botToken: v } })}\n />\n <FieldRow\n id=\"dc-channel\" label={t('messengers.fields.channelId')}\n value={draft.discord.discord?.channelId ?? ''}\n onChange={(v) => patchSlot('discord', { discord: { ...draft.discord.discord, channelId: v } })}\n />\n </PlatformCard>\n ) : null}\n </div>\n )}\n\n <WechatQrDialog\n open={qrOpen}\n onOpenChange={setQrOpen}\n onConfirmed={() => { void cfgQuery.refetch(); setSynced(false) }}\n />\n </div>\n )\n}\n\ninterface PlatformCardProps {\n slot: Slot\n label: string\n hint: string\n enabled: boolean\n onToggle: (v: boolean) => void\n children?: React.ReactNode\n}\n\nfunction PlatformCard({ label, hint, enabled, onToggle, children }: PlatformCardProps): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <div className=\"rounded-md border border-border bg-surface p-4\">\n <div className=\"flex items-start gap-3\">\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium text-text\">{label}</span>\n <Badge variant={enabled ? 'success' : 'outline'}>\n {enabled ? t('messengers.enabled') : t('messengers.disabled')}\n </Badge>\n </div>\n <p className=\"mt-1 text-xs text-text-dim\">{hint}</p>\n </div>\n <label className=\"inline-flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={enabled}\n onChange={(e) => onToggle(e.target.checked)}\n className=\"h-4 w-4 accent-accent cursor-pointer\"\n />\n </label>\n </div>\n {enabled && children && (\n <div className=\"mt-3 flex flex-col gap-2\">\n {children}\n </div>\n )}\n </div>\n )\n}\n\ninterface FieldRowProps {\n id: string\n label: string\n value: string\n onChange: (v: string) => void\n type?: 'text' | 'password'\n}\n\nfunction FieldRow({ id, label, value, onChange, type = 'text' }: FieldRowProps): JSX.Element {\n return (\n <div className=\"grid grid-cols-1 gap-1 sm:grid-cols-[180px_1fr] sm:items-center sm:gap-2\">\n <Label htmlFor={id} className=\"text-xs text-text-dim\">{label}</Label>\n <Input\n id={id}\n type={type}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n autoComplete=\"off\"\n className=\"font-mono text-xs\"\n />\n </div>\n )\n}\n\n// v1.2.37 (batch 1) — dropdown sibling of FieldRow for enum settings.\ninterface SelectRowProps<T extends string> {\n id: string\n label: string\n value: T\n onChange: (v: T) => void\n options: Array<{ value: T; label: string }>\n}\nfunction SelectRow<T extends string>({ id, label, value, onChange, options }: SelectRowProps<T>): JSX.Element {\n return (\n <div className=\"grid grid-cols-1 gap-1 sm:grid-cols-[180px_1fr] sm:items-center sm:gap-2\">\n <Label htmlFor={id} className=\"text-xs text-text-dim\">{label}</Label>\n <select\n id={id}\n value={value}\n onChange={(e) => onChange(e.target.value as T)}\n className=\"rounded-md border border-input bg-background px-2 py-1 text-xs\"\n >\n {options.map((o) => (\n <option key={o.value} value={o.value}>{o.label}</option>\n ))}\n </select>\n </div>\n )\n}\n\ninterface WechatQrDialogProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n onConfirmed: () => void\n}\n\nfunction WechatQrDialog({ open, onOpenChange, onConfirmed }: WechatQrDialogProps): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const start = useStartWechatQr()\n const [token, setToken] = useState<string | null>(null)\n const [qrImage, setQrImage] = useState<string | null>(null)\n const [startError, setStartError] = useState<string | null>(null)\n\n // Kick off the start mutation each time the dialog opens; reset on close.\n useEffect(() => {\n if (!open) {\n setToken(null)\n setQrImage(null)\n setStartError(null)\n return\n }\n let active = true\n start.mutateAsync().then((r) => {\n if (!active) return\n setQrImage(r.qrImage)\n setToken(r.qrToken)\n }).catch((err) => {\n if (!active) return\n setStartError(err instanceof Error ? err.message : String(err))\n })\n return () => { active = false }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open])\n\n const statusQuery = useWechatQrStatus(open ? token : null)\n const status = statusQuery.data?.status\n\n useEffect(() => {\n if (status === 'confirmed') {\n toast.success(t('messengers.qr.confirmed'))\n onConfirmed()\n onOpenChange(false)\n }\n if (status === 'expired') {\n toast.error(t('messengers.qr.expired'))\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [status])\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>{t('messengers.qr.title')}</DialogTitle>\n <DialogDescription>{t('messengers.qr.description')}</DialogDescription>\n </DialogHeader>\n <div className=\"flex flex-col items-center gap-3\">\n {start.isPending && !qrImage ? (\n <>\n <Loader2 className=\"h-8 w-8 animate-spin text-text-dim\" />\n <p className=\"text-sm text-text-dim\">{t('messengers.qr.starting')}</p>\n </>\n ) : startError ? (\n <p className=\"text-sm text-danger\">{t('messengers.qr.loadFailed')}: {startError}</p>\n ) : qrImage ? (\n <>\n <img\n src={qrImage}\n alt={t('messengers.qr.title')}\n className=\"rounded-md border border-border\"\n />\n {status === 'expired'\n ? <p className=\"text-xs text-danger\">{t('messengers.qr.expired')}</p>\n : <p className=\"text-xs text-text-dim\">{status ? `· ${status} ·` : ''}</p>}\n </>\n ) : null}\n </div>\n </DialogContent>\n </Dialog>\n )\n}\n\n// ─── v1.2.41 — DingTalk multi-account CRUD editor ───────────────────\n// Renders below the main DingTalk card. Owns the in-memory accounts\n// dict and bubbles every change up via `onChange` so the page-level\n// dirty/save logic notices and lights up the Save button.\n//\n// Each row shows: id (read-only after creation), name, clientId,\n// clientSecret (password mode, masked on echo), dmPolicy / groupPolicy /\n// ackReaction selectors, allowFrom / groupAllowFrom CSVs, enabled\n// toggle, and a delete button. \"Add account\" appends a fresh row with\n// a generated id the operator can rename inline.\n\nexport interface DingTalkAccountDraft {\n name?: string\n clientId?: string\n clientSecret?: string\n dmPolicy?: 'open' | 'pairing' | 'allowlist'\n groupPolicy?: 'open' | 'allowlist' | 'disabled'\n allowFrom?: string[]\n groupAllowFrom?: string[]\n ackReaction?: 'off' | 'emoji' | 'kaomoji'\n enabled?: boolean\n}\n\ninterface DingTalkAccountsEditorProps {\n accounts: Record<string, DingTalkAccountDraft>\n onChange: (next: Record<string, DingTalkAccountDraft>) => void\n}\n\nfunction DingTalkAccountsEditor({ accounts, onChange }: DingTalkAccountsEditorProps): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const entries = Object.entries(accounts)\n\n const updateAccount = (id: string, patch: Partial<DingTalkAccountDraft>) => {\n onChange({ ...accounts, [id]: { ...accounts[id], ...patch } })\n }\n const deleteAccount = (id: string) => {\n const next = { ...accounts }\n delete next[id]\n onChange(next)\n }\n const renameAccount = (oldId: string, newId: string) => {\n if (!newId || newId === oldId) return\n if (accounts[newId]) {\n toast.error(t('messengers.dingtalk.accountRenameCollision', { id: newId }))\n return\n }\n const next: Record<string, DingTalkAccountDraft> = {}\n for (const [k, v] of Object.entries(accounts)) {\n next[k === oldId ? newId : k] = v\n }\n onChange(next)\n }\n const addAccount = () => {\n // Find an unused id of shape account-N.\n let n = entries.length + 1\n let candidate = `account-${n}`\n while (accounts[candidate]) { n += 1; candidate = `account-${n}` }\n onChange({ ...accounts, [candidate]: { enabled: true } })\n }\n\n return (\n <div className=\"mt-3 border-t border-input pt-3\">\n <div className=\"mb-2 flex items-center justify-between\">\n <div className=\"text-xs font-semibold text-text-dim\">\n {t('messengers.dingtalk.accountsTitle')}\n </div>\n <Button type=\"button\" size=\"sm\" variant=\"outline\" onClick={addAccount}>\n + {t('messengers.dingtalk.addAccount')}\n </Button>\n </div>\n\n {entries.length === 0 ? (\n <div className=\"text-xs text-text-dim italic\">\n {t('messengers.dingtalk.accountsEmpty')}\n </div>\n ) : (\n <div className=\"space-y-3\">\n {entries.map(([id, acct]) => (\n <div key={id} className=\"rounded-md border border-input p-2\">\n <div className=\"mb-2 flex items-center gap-2\">\n <Input\n id={`acct-id-${id}`}\n defaultValue={id}\n onBlur={(e) => renameAccount(id, e.target.value.trim())}\n className=\"font-mono text-xs w-40\"\n placeholder=\"account-id\"\n />\n <Input\n id={`acct-name-${id}`}\n value={acct.name ?? ''}\n onChange={(e) => updateAccount(id, { name: e.target.value })}\n className=\"text-xs flex-1\"\n placeholder={t('messengers.dingtalk.accountName')}\n />\n <label className=\"flex items-center gap-1 text-xs\">\n <input\n type=\"checkbox\"\n checked={acct.enabled !== false}\n onChange={(e) => updateAccount(id, { enabled: e.target.checked })}\n />\n {t('messengers.enabled')}\n </label>\n <Button\n type=\"button\" size=\"sm\" variant=\"ghost\"\n onClick={() => deleteAccount(id)}\n className=\"text-danger\"\n >\n <X className=\"size-4\" />\n </Button>\n </div>\n <div className=\"space-y-1\">\n <FieldRow\n id={`acct-cid-${id}`} label={t('messengers.fields.clientId')}\n value={acct.clientId ?? ''}\n onChange={(v) => updateAccount(id, { clientId: v })}\n />\n <FieldRow\n id={`acct-secret-${id}`} label={t('messengers.fields.clientSecret')}\n value={acct.clientSecret ?? ''}\n type=\"password\"\n onChange={(v) => updateAccount(id, { clientSecret: v })}\n />\n <SelectRow<'open' | 'pairing' | 'allowlist'>\n id={`acct-dm-${id}`} label={t('messengers.dingtalk.dmPolicy')}\n value={acct.dmPolicy ?? 'open'}\n onChange={(v) => updateAccount(id, { dmPolicy: v })}\n options={[\n { value: 'open', label: t('messengers.dingtalk.policy.open') },\n { value: 'pairing', label: t('messengers.dingtalk.policy.pairing') },\n { value: 'allowlist', label: t('messengers.dingtalk.policy.allowlist') },\n ]}\n />\n <SelectRow<'open' | 'allowlist' | 'disabled'>\n id={`acct-group-${id}`} label={t('messengers.dingtalk.groupPolicy')}\n value={acct.groupPolicy ?? 'open'}\n onChange={(v) => updateAccount(id, { groupPolicy: v })}\n options={[\n { value: 'open', label: t('messengers.dingtalk.policy.open') },\n { value: 'allowlist', label: t('messengers.dingtalk.policy.allowlist') },\n { value: 'disabled', label: t('messengers.dingtalk.policy.disabled') },\n ]}\n />\n <FieldRow\n id={`acct-allow-${id}`} label={t('messengers.dingtalk.allowFrom')}\n value={(acct.allowFrom ?? []).join(',')}\n onChange={(v) => updateAccount(id, {\n allowFrom: v.split(',').map((s) => s.trim()).filter(Boolean),\n })}\n />\n <FieldRow\n id={`acct-gallow-${id}`} label={t('messengers.dingtalk.groupAllowFrom')}\n value={(acct.groupAllowFrom ?? []).join(',')}\n onChange={(v) => updateAccount(id, {\n groupAllowFrom: v.split(',').map((s) => s.trim()).filter(Boolean),\n })}\n />\n <SelectRow<'off' | 'emoji' | 'kaomoji'>\n id={`acct-ack-${id}`} label={t('messengers.dingtalk.ackReaction')}\n value={acct.ackReaction ?? 'off'}\n onChange={(v) => updateAccount(id, { ackReaction: v })}\n options={[\n { value: 'off', label: t('messengers.dingtalk.ack.off') },\n { value: 'emoji', label: t('messengers.dingtalk.ack.emoji') },\n { value: 'kaomoji', label: t('messengers.dingtalk.ack.kaomoji') },\n ]}\n />\n </div>\n </div>\n ))}\n </div>\n )}\n <div className=\"mt-1 text-xs text-text-dim\">{t('messengers.dingtalk.accountsHint')}</div>\n </div>\n )\n}\n"],"names":["QrCode","createLucideIcon","buildDraft","cfg","m","buildPatch","draft","messengers","k","SettingsMessengersRoute","t","useTranslation","cfgQuery","useConfig","updateCfg","useUpdateConfig","setDraft","useState","synced","setSynced","useEffect","isDirty","useMemo","qrOpen","setQrOpen","patchSlot","slot","partial","prev","onSave","toast","err","describeError","onDiscard","jsxs","jsx","Button","Loader2","RefreshCcw","Fragment","Badge","X","Save","PlatformCard","v","FieldRow","SelectRow","s","DingTalkAccountsEditor","next","WechatQrDialog","label","hint","enabled","onToggle","children","e","id","value","onChange","type","Label","Input","options","o","open","onOpenChange","onConfirmed","start","useStartWechatQr","token","setToken","qrImage","setQrImage","startError","setStartError","active","r","status","useWechatQrStatus","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","accounts","entries","updateAccount","patch","deleteAccount","renameAccount","oldId","newId","addAccount","candidate","acct"],"mappings":"sdAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMA,EAASC,EAAiB,SAAU,CACxC,CAAC,OAAQ,CAAE,MAAO,IAAK,OAAQ,IAAK,EAAG,IAAK,EAAG,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC5E,CAAC,OAAQ,CAAE,MAAO,IAAK,OAAQ,IAAK,EAAG,KAAM,EAAG,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC7E,CAAC,OAAQ,CAAE,MAAO,IAAK,OAAQ,IAAK,EAAG,IAAK,EAAG,KAAM,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC7E,CAAC,OAAQ,CAAE,EAAG,4BAA6B,IAAK,QAAQ,CAAE,EAC1D,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,EAC3C,CAAC,OAAQ,CAAE,EAAG,0BAA2B,IAAK,QAAQ,CAAE,EACxD,CAAC,OAAQ,CAAE,EAAG,YAAa,IAAK,QAAQ,CAAE,EAC1C,CAAC,OAAQ,CAAE,EAAG,YAAa,IAAK,QAAQ,CAAE,EAC1C,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,EAC3C,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,EACzC,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,EAC3C,CAAC,OAAQ,CAAE,EAAG,YAAa,IAAK,QAAQ,CAAE,CAC5C,CAAC,ECiDD,SAASC,EAAWC,EAAmC,CACrD,MAAMC,EAAI,IAAI,IAAID,GAAK,YAAc,CAAA,CAAE,EACvC,MAAO,CACL,eAAgB,CAAE,QAASC,EAAE,IAAI,cAAc,CAAA,EAC/C,SAAgB,CAAE,QAASA,EAAE,IAAI,UAAU,EAAG,SAAU,CAAE,GAAID,GAAK,UAAY,CAAA,EAAI,EACnF,OAAgB,CAAE,QAASC,EAAE,IAAI,QAAQ,EAAK,OAAU,CAAE,GAAID,GAAK,QAAU,CAAA,EAAI,EACjF,SAAgB,CAAE,QAASC,EAAE,IAAI,UAAU,EAAG,SAAU,CAAE,GAAID,GAAK,UAAY,CAAA,EAAI,EACnF,QAAgB,CAAE,QAASC,EAAE,IAAI,SAAS,EAAI,QAAU,CAAE,GAAID,GAAK,SAAW,CAAA,EAAI,CAAE,CAExF,CAEA,SAASE,EAAWC,EAAcH,EAAoC,CACpE,MAAMI,EAAuB,CAAA,EAC7B,UAAWC,KAAK,OAAO,KAAKF,CAAK,EAAiBA,EAAME,CAAC,EAAE,SAASD,EAAW,KAAKC,CAAC,EACrF,MAAO,CACL,WAAAD,EACA,SAAUD,EAAM,SAAS,SACzB,OAAUA,EAAM,OAAO,OACvB,SAAUA,EAAM,SAAS,SACzB,QAAUA,EAAM,QAAQ,QAExB,GAAG,OAAO,YACR,OAAO,QAAQH,CAAG,EAAE,OAAO,CAAC,CAACK,CAAC,IAAM,CAAC,CACnC,aAAc,WAAY,SAAU,WAAY,SAAA,EAChD,SAASA,CAAC,CAAC,CAAA,CACf,CAEJ,CAEA,SAAwBC,IAAuC,CAC7D,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAe,CAAC,WAAY,QAAQ,CAAC,EAC7CC,EAAWC,EAAA,EACXC,EAAYC,EAAA,EAEZ,CAACT,EAAOU,CAAQ,EAAIC,EAAAA,SAAgB,IAAMf,EAAWU,EAAS,IAAI,CAAC,EAGnE,CAACM,EAAQC,CAAS,EAAIF,EAAAA,SAAS,EAAK,EAC1CG,EAAAA,UAAU,IAAM,CACVF,GACCN,EAAS,OACdI,EAASd,EAAWU,EAAS,IAAI,CAAC,EAClCO,EAAU,EAAI,EAChB,EAAG,CAACP,EAAS,KAAMM,CAAM,CAAC,EAE1B,MAAMf,EAAMS,EAAS,KACfS,EAAUC,EAAAA,QAAQ,IACjBnB,EACE,KAAK,UAAUD,EAAWC,CAAG,CAAC,IAAM,KAAK,UAAUG,CAAK,EAD9C,GAEhB,CAACH,EAAKG,CAAK,CAAC,EAGT,CAACiB,EAAQC,CAAS,EAAIP,EAAAA,SAAS,EAAK,EAE1C,SAASQ,EAAUC,EAAYC,EAAuC,CACpEX,EAAUY,IAAU,CAAE,GAAGA,EAAM,CAACF,CAAI,EAAG,CAAE,GAAGE,EAAKF,CAAI,EAAG,GAAGC,CAAA,GAAY,CACzE,CAEA,eAAeE,GAAwB,CACrC,GAAK1B,EACL,GAAI,CACF,MAAMW,EAAU,YAAYT,EAAWC,EAAOH,CAAG,CAAC,EAClD2B,EAAM,QAAQpB,EAAE,uBAAuB,CAAC,EACxCS,EAAU,EAAK,CACjB,OAASY,EAAK,CACZD,EAAM,MAAME,EAAcD,EAAKrB,CAAC,EAAE,OAAO,CAC3C,CACF,CAEA,SAASuB,GAAkB,CACrB9B,GAAKa,EAASd,EAAWC,CAAG,CAAC,CACnC,CAEA,OACE+B,EAAAA,KAAC,MAAA,CAAI,UAAU,wCACb,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,sBAChB,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAC,MAAC,KAAA,CAAG,UAAU,wBAAyB,SAAAzB,EAAE,kBAAkB,EAAE,EAC7DwB,EAAAA,KAACE,EAAA,CACC,QAAQ,QACR,KAAK,KACL,UAAU,UACV,QAAS,IAAMxB,EAAS,QAAA,EACxB,SAAUA,EAAS,WACnB,aAAYF,EAAE,kBAAmB,CAAE,GAAI,SAAU,EAEhD,SAAA,CAAAE,EAAS,iBAAcyB,EAAA,CAAQ,UAAU,uBAAuB,EAAKF,EAAAA,IAACG,EAAA,CAAW,UAAU,SAAA,CAAU,EACtGH,EAAAA,IAAC,OAAA,CAAK,UAAU,mBAAoB,SAAAzB,EAAE,kBAAmB,CAAE,GAAI,QAAA,CAAU,CAAA,CAAE,CAAA,CAAA,CAAA,CAC7E,EACF,QACC,IAAA,CAAE,UAAU,wBAAyB,SAAAA,EAAE,qBAAqB,CAAA,CAAE,CAAA,EACjE,EAGAyB,MAAC,MAAA,CAAI,UAAU,oCACZ,WACCD,EAAAA,KAAAK,WAAA,CACE,SAAA,CAAAJ,MAACK,EAAA,CAAM,QAAQ,OAAQ,SAAA9B,EAAE,sBAAsB,EAAE,EACjDwB,EAAAA,KAACE,EAAA,CACC,KAAK,SACL,QAAQ,YACR,KAAK,KACL,QAASH,EACT,SAAUnB,EAAU,UAEpB,SAAA,CAAAqB,EAAAA,IAACM,EAAA,CAAE,UAAU,SAAA,CAAU,EACtB/B,EAAE,uBAAuB,CAAA,CAAA,CAAA,EAE5BwB,EAAAA,KAACE,EAAA,CACC,KAAK,SACL,KAAK,KACL,QAAS,IAAM,KAAKP,EAAA,EACpB,SAAUf,EAAU,UAEnB,SAAA,CAAAA,EAAU,gBAAauB,EAAA,CAAQ,UAAU,uBAAuB,EAAKF,EAAAA,IAACO,EAAA,CAAK,UAAU,SAAA,CAAU,EAC/F5B,EAAU,UAAYJ,EAAE,mBAAmB,EAAIA,EAAE,oBAAoB,CAAA,CAAA,CAAA,CACxE,CAAA,CACF,QAEC,OAAA,CAAK,UAAU,0BAA2B,SAAAA,EAAE,eAAe,EAAE,CAAA,CAElE,EAECE,EAAS,UACRuB,EAAAA,IAAC,MAAA,CAAI,UAAU,6CAA6C,EACzDhC,EACH+B,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACb,SAAA,CAAAC,EAAAA,IAACQ,EAAA,CACC,KAAK,eACL,MAAOjC,EAAE,4BAA4B,EACrC,KAAMA,EAAE,wBAAwB,EAChC,QAASJ,EAAM,cAAc,EAAE,QAC/B,SAAWsC,GAAMnB,EAAU,eAAgB,CAAE,QAASmB,EAAG,EAEzD,SAAAV,EAAAA,KAACE,EAAA,CACC,KAAK,SACL,QAAQ,YACR,KAAK,KACL,QAAS,IAAMZ,EAAU,EAAI,EAE7B,SAAA,CAAAW,EAAAA,IAACnC,EAAA,CAAO,UAAU,SAAA,CAAU,EAC3BU,EAAE,mBAAmB,CAAA,CAAA,CAAA,CACxB,CAAA,EAGDP,EAAI,UAAU,SACb+B,EAAAA,KAACS,EAAA,CACC,KAAK,WACL,MAAOjC,EAAE,8BAA8B,EACvC,KAAMA,EAAE,0BAA0B,EAClC,QAASJ,EAAM,SAAS,QACxB,SAAWsC,GAAMnB,EAAU,WAAY,CAAE,QAASmB,EAAG,EAErD,SAAA,CAAAT,EAAAA,IAACU,EAAA,CACC,GAAG,WAAY,MAAOnC,EAAE,4BAA4B,EACpD,MAAOJ,EAAM,SAAS,UAAU,UAAY,GAC5C,KAAK,WACL,SAAWsC,GAAMnB,EAAU,WAAY,CAAE,SAAU,CAAE,GAAGnB,EAAM,SAAS,SAAU,SAAUsC,CAAA,EAAK,CAAA,CAAA,EAElGT,EAAAA,IAACU,EAAA,CACC,GAAG,aAAa,MAAOnC,EAAE,6BAA6B,EACtD,MAAOJ,EAAM,SAAS,UAAU,WAAa,GAC7C,SAAWsC,GAAMnB,EAAU,WAAY,CAAE,SAAU,CAAE,GAAGnB,EAAM,SAAS,SAAU,UAAWsC,CAAA,EAAK,CAAA,CAAA,CACnG,CAAA,CAAA,EAEA,KAEJV,EAAAA,KAACS,EAAA,CACC,KAAK,SACL,MAAOjC,EAAE,4BAA4B,EACrC,KAAMA,EAAE,wBAAwB,EAChC,QAASJ,EAAM,OAAO,QACtB,SAAWsC,GAAMnB,EAAU,SAAU,CAAE,QAASmB,EAAG,EAEnD,SAAA,CAAAT,EAAAA,IAACU,EAAA,CACC,GAAG,WAAW,MAAOnC,EAAE,yBAAyB,EAChD,MAAOJ,EAAM,OAAO,QAAQ,OAAS,GACrC,SAAWsC,GAAMnB,EAAU,SAAU,CAAE,OAAQ,CAAE,GAAGnB,EAAM,OAAO,OAAQ,MAAOsC,CAAA,EAAK,CAAA,CAAA,EAEvFT,EAAAA,IAACU,EAAA,CACC,GAAG,YAAY,MAAOnC,EAAE,6BAA6B,EACrD,MAAOJ,EAAM,OAAO,QAAQ,WAAa,GACzC,KAAK,WACL,SAAWsC,GAAMnB,EAAU,SAAU,CAAE,OAAQ,CAAE,GAAGnB,EAAM,OAAO,OAAQ,UAAWsC,CAAA,EAAK,CAAA,CAAA,EAE3FT,EAAAA,IAACU,EAAA,CACC,GAAG,aAAa,MAAOnC,EAAE,6BAA6B,EACtD,MAAOJ,EAAM,OAAO,QAAQ,WAAa,GACzC,SAAWsC,GAAMnB,EAAU,SAAU,CAAE,OAAQ,CAAE,GAAGnB,EAAM,OAAO,OAAQ,UAAWsC,CAAA,EAAK,CAAA,CAAA,CAC3F,CAAA,CAAA,EAGFV,EAAAA,KAACS,EAAA,CACC,KAAK,WACL,MAAOjC,EAAE,8BAA8B,EACvC,KAAMA,EAAE,0BAA0B,EAClC,QAASJ,EAAM,SAAS,QACxB,SAAWsC,GAAMnB,EAAU,WAAY,CAAE,QAASmB,EAAG,EAErD,SAAA,CAAAT,EAAAA,IAACU,EAAA,CACC,GAAG,SAAS,MAAOnC,EAAE,4BAA4B,EACjD,MAAOJ,EAAM,SAAS,UAAU,UAAY,GAC5C,SAAWsC,GAAMnB,EAAU,WAAY,CAAE,SAAU,CAAE,GAAGnB,EAAM,SAAS,SAAU,SAAUsC,CAAA,EAAK,CAAA,CAAA,EAElGT,EAAAA,IAACU,EAAA,CACC,GAAG,YAAY,MAAOnC,EAAE,gCAAgC,EACxD,MAAOJ,EAAM,SAAS,UAAU,cAAgB,GAChD,KAAK,WACL,SAAWsC,GAAMnB,EAAU,WAAY,CAAE,SAAU,CAAE,GAAGnB,EAAM,SAAS,SAAU,aAAcsC,CAAA,EAAK,CAAA,CAAA,EAEtGT,EAAAA,IAACU,EAAA,CACC,GAAG,aAAa,MAAOnC,EAAE,6BAA6B,EACtD,MAAOJ,EAAM,SAAS,UAAU,WAAa,GAC7C,SAAWsC,GAAMnB,EAAU,WAAY,CAAE,SAAU,CAAE,GAAGnB,EAAM,SAAS,SAAU,UAAWsC,CAAA,EAAK,CAAA,CAAA,EAGnGT,EAAAA,IAACW,EAAA,CACC,GAAG,eAAe,MAAOpC,EAAE,8BAA8B,EACzD,MAAOJ,EAAM,SAAS,UAAU,UAAY,OAC5C,SAAWsC,GAAMnB,EAAU,WAAY,CAAE,SAAU,CAAE,GAAGnB,EAAM,SAAS,SAAU,SAAUsC,CAAA,EAAK,EAChG,QAAS,CACP,CAAE,MAAO,OAAa,MAAOlC,EAAE,iCAAiC,CAAA,EAChE,CAAE,MAAO,UAAa,MAAOA,EAAE,oCAAoC,CAAA,EACnE,CAAE,MAAO,YAAa,MAAOA,EAAE,sCAAsC,CAAA,CAAE,CACzE,CAAA,EAEFyB,EAAAA,IAACW,EAAA,CACC,GAAG,kBAAkB,MAAOpC,EAAE,iCAAiC,EAC/D,MAAOJ,EAAM,SAAS,UAAU,aAAe,OAC/C,SAAWsC,GAAMnB,EAAU,WAAY,CAAE,SAAU,CAAE,GAAGnB,EAAM,SAAS,SAAU,YAAasC,CAAA,EAAK,EACnG,QAAS,CACP,CAAE,MAAO,OAAa,MAAOlC,EAAE,iCAAiC,CAAA,EAChE,CAAE,MAAO,YAAa,MAAOA,EAAE,sCAAsC,CAAA,EACrE,CAAE,MAAO,WAAa,MAAOA,EAAE,qCAAqC,CAAA,CAAE,CACxE,CAAA,EAEFyB,EAAAA,IAACU,EAAA,CACC,GAAG,gBAAgB,MAAOnC,EAAE,+BAA+B,EAC3D,OAAQJ,EAAM,SAAS,UAAU,WAAa,CAAA,GAAI,KAAK,GAAG,EAC1D,SAAWsC,GAAMnB,EAAU,WAAY,CACrC,SAAU,CACR,GAAGnB,EAAM,SAAS,SAClB,UAAWsC,EAAE,MAAM,GAAG,EAAE,IAAKG,GAAMA,EAAE,MAAM,EAAE,OAAO,OAAO,CAAA,CAC7D,CACD,CAAA,CAAA,EAEHZ,EAAAA,IAACU,EAAA,CACC,GAAG,sBAAsB,MAAOnC,EAAE,oCAAoC,EACtE,OAAQJ,EAAM,SAAS,UAAU,gBAAkB,CAAA,GAAI,KAAK,GAAG,EAC/D,SAAWsC,GAAMnB,EAAU,WAAY,CACrC,SAAU,CACR,GAAGnB,EAAM,SAAS,SAClB,eAAgBsC,EAAE,MAAM,GAAG,EAAE,IAAKG,GAAMA,EAAE,MAAM,EAAE,OAAO,OAAO,CAAA,CAClE,CACD,CAAA,CAAA,EAEHZ,EAAAA,IAACW,EAAA,CACC,GAAG,SAAS,MAAOpC,EAAE,iCAAiC,EACtD,MAAOJ,EAAM,SAAS,UAAU,aAAe,MAC/C,SAAWsC,GAAMnB,EAAU,WAAY,CAAE,SAAU,CAAE,GAAGnB,EAAM,SAAS,SAAU,YAAasC,CAAA,EAAK,EACnG,QAAS,CACP,CAAE,MAAO,MAAW,MAAOlC,EAAE,6BAA6B,CAAA,EAC1D,CAAE,MAAO,QAAW,MAAOA,EAAE,+BAA+B,CAAA,EAC5D,CAAE,MAAO,UAAW,MAAOA,EAAE,iCAAiC,CAAA,CAAE,CAClE,CAAA,EAGFyB,EAAAA,IAACa,EAAA,CACC,SAAU1C,EAAM,SAAS,UAAU,UAAY,CAAA,EAC/C,SAAW2C,GAASxB,EAAU,WAAY,CACxC,SAAU,CAAE,GAAGnB,EAAM,SAAS,SAAU,SAAU2C,CAAA,CAAK,CACxD,CAAA,CAAA,CACH,CAAA,CAAA,EAGD9C,EAAI,UAAU,SACb+B,EAAAA,KAACS,EAAA,CACC,KAAK,UACL,MAAOjC,EAAE,6BAA6B,EACtC,KAAMA,EAAE,yBAAyB,EACjC,QAASJ,EAAM,QAAQ,QACvB,SAAWsC,GAAMnB,EAAU,UAAW,CAAE,QAASmB,EAAG,EAEpD,SAAA,CAAAT,EAAAA,IAACU,EAAA,CACC,GAAG,WAAW,MAAOnC,EAAE,4BAA4B,EACnD,MAAOJ,EAAM,QAAQ,SAAS,UAAY,GAC1C,KAAK,WACL,SAAWsC,GAAMnB,EAAU,UAAW,CAAE,QAAS,CAAE,GAAGnB,EAAM,QAAQ,QAAS,SAAUsC,CAAA,EAAK,CAAA,CAAA,EAE9FT,EAAAA,IAACU,EAAA,CACC,GAAG,aAAa,MAAOnC,EAAE,6BAA6B,EACtD,MAAOJ,EAAM,QAAQ,SAAS,WAAa,GAC3C,SAAWsC,GAAMnB,EAAU,UAAW,CAAE,QAAS,CAAE,GAAGnB,EAAM,QAAQ,QAAS,UAAWsC,CAAA,EAAK,CAAA,CAAA,CAC/F,CAAA,CAAA,EAEA,IAAA,EACN,EA3KS,KA8KXT,EAAAA,IAACe,EAAA,CACC,KAAM3B,EACN,aAAcC,EACd,YAAa,IAAM,CAAOZ,EAAS,QAAA,EAAWO,EAAU,EAAK,CAAE,CAAA,CAAA,CACjE,EACF,CAEJ,CAWA,SAASwB,EAAa,CAAE,MAAAQ,EAAO,KAAAC,EAAM,QAAAC,EAAS,SAAAC,EAAU,SAAAC,GAA4C,CAClG,KAAM,CAAE,EAAA7C,CAAA,EAAMC,EAAe,UAAU,EACvC,OACEuB,EAAAA,KAAC,MAAA,CAAI,UAAU,iDACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,yBACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,SACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAK,UAAU,wBAAyB,SAAAgB,EAAM,EAC/ChB,EAAAA,IAACK,EAAA,CAAM,QAASa,EAAU,UAAY,UACnC,SAAU3C,EAAV2C,EAAY,qBAA0B,qBAAN,CAA2B,CAC9D,CAAA,EACF,EACAlB,EAAAA,IAAC,IAAA,CAAE,UAAU,6BAA8B,SAAAiB,CAAA,CAAK,CAAA,EAClD,EACAjB,EAAAA,IAAC,QAAA,CAAM,UAAU,yCACf,SAAAA,EAAAA,IAAC,QAAA,CACC,KAAK,WACL,QAASkB,EACT,SAAWG,GAAMF,EAASE,EAAE,OAAO,OAAO,EAC1C,UAAU,sCAAA,CAAA,CACZ,CACF,CAAA,EACF,EACCH,GAAWE,GACVpB,MAAC,MAAA,CAAI,UAAU,2BACZ,SAAAoB,CAAA,CACH,CAAA,EAEJ,CAEJ,CAUA,SAASV,EAAS,CAAE,GAAAY,EAAI,MAAAN,EAAO,MAAAO,EAAO,SAAAC,EAAU,KAAAC,EAAO,QAAsC,CAC3F,OACE1B,EAAAA,KAAC,MAAA,CAAI,UAAU,2EACb,SAAA,CAAAC,MAAC0B,EAAA,CAAM,QAASJ,EAAI,UAAU,wBAAyB,SAAAN,EAAM,EAC7DhB,EAAAA,IAAC2B,EAAA,CACC,GAAAL,EACA,KAAAG,EACA,MAAAF,EACA,SAAWF,GAAMG,EAASH,EAAE,OAAO,KAAK,EACxC,aAAa,MACb,UAAU,mBAAA,CAAA,CACZ,EACF,CAEJ,CAUA,SAASV,EAA4B,CAAE,GAAAW,EAAI,MAAAN,EAAO,MAAAO,EAAO,SAAAC,EAAU,QAAAI,GAA2C,CAC5G,OACE7B,EAAAA,KAAC,MAAA,CAAI,UAAU,2EACb,SAAA,CAAAC,MAAC0B,EAAA,CAAM,QAASJ,EAAI,UAAU,wBAAyB,SAAAN,EAAM,EAC7DhB,EAAAA,IAAC,SAAA,CACC,GAAAsB,EACA,MAAAC,EACA,SAAWF,GAAMG,EAASH,EAAE,OAAO,KAAU,EAC7C,UAAU,iEAET,SAAAO,EAAQ,IAAKC,GACZ7B,EAAAA,IAAC,SAAA,CAAqB,MAAO6B,EAAE,MAAQ,SAAAA,EAAE,KAAA,EAA5BA,EAAE,KAAgC,CAChD,CAAA,CAAA,CACH,EACF,CAEJ,CAQA,SAASd,EAAe,CAAE,KAAAe,EAAM,aAAAC,EAAc,YAAAC,GAAiD,CAC7F,KAAM,CAAE,EAAAzD,CAAA,EAAMC,EAAe,CAAC,WAAY,QAAQ,CAAC,EAC7CyD,EAAQC,EAAA,EACR,CAACC,EAAOC,CAAQ,EAAItD,EAAAA,SAAwB,IAAI,EAChD,CAACuD,EAASC,CAAU,EAAIxD,EAAAA,SAAwB,IAAI,EACpD,CAACyD,EAAYC,CAAa,EAAI1D,EAAAA,SAAwB,IAAI,EAGhEG,EAAAA,UAAU,IAAM,CACd,GAAI,CAAC6C,EAAM,CACTM,EAAS,IAAI,EACbE,EAAW,IAAI,EACfE,EAAc,IAAI,EAClB,MACF,CACA,IAAIC,EAAS,GACb,OAAAR,EAAM,YAAA,EAAc,KAAMS,GAAM,CACzBD,IACLH,EAAWI,EAAE,OAAO,EACpBN,EAASM,EAAE,OAAO,EACpB,CAAC,EAAE,MAAO9C,GAAQ,CACX6C,GACLD,EAAc5C,aAAe,MAAQA,EAAI,QAAU,OAAOA,CAAG,CAAC,CAChE,CAAC,EACM,IAAM,CAAE6C,EAAS,EAAM,CAEhC,EAAG,CAACX,CAAI,CAAC,EAGT,MAAMa,EADcC,EAAkBd,EAAOK,EAAQ,IAAI,EAC9B,MAAM,OAEjClD,OAAAA,EAAAA,UAAU,IAAM,CACV0D,IAAW,cACbhD,EAAM,QAAQpB,EAAE,yBAAyB,CAAC,EAC1CyD,EAAA,EACAD,EAAa,EAAK,GAEhBY,IAAW,WACbhD,EAAM,MAAMpB,EAAE,uBAAuB,CAAC,CAG1C,EAAG,CAACoE,CAAM,CAAC,EAGT3C,EAAAA,IAAC6C,EAAA,CAAO,KAAAf,EAAY,aAAAC,EAClB,gBAACe,EAAA,CACC,SAAA,CAAA/C,OAACgD,EAAA,CACC,SAAA,CAAA/C,EAAAA,IAACgD,EAAA,CAAa,SAAAzE,EAAE,qBAAqB,CAAA,CAAE,EACvCyB,EAAAA,IAACiD,EAAA,CAAmB,SAAA1E,EAAE,2BAA2B,CAAA,CAAE,CAAA,EACrD,EACAyB,EAAAA,IAAC,OAAI,UAAU,mCACZ,WAAM,WAAa,CAACqC,EACnBtC,EAAAA,KAAAK,EAAAA,SAAA,CACE,SAAA,CAAAJ,EAAAA,IAACE,EAAA,CAAQ,UAAU,oCAAA,CAAqC,QACvD,IAAA,CAAE,UAAU,wBAAyB,SAAA3B,EAAE,wBAAwB,CAAA,CAAE,CAAA,CAAA,CACpE,EACEgE,EACFxC,EAAAA,KAAC,IAAA,CAAE,UAAU,sBAAuB,SAAA,CAAAxB,EAAE,0BAA0B,EAAE,KAAGgE,CAAA,CAAA,CAAW,EAC9EF,EACFtC,EAAAA,KAAAK,EAAAA,SAAA,CACE,SAAA,CAAAJ,EAAAA,IAAC,MAAA,CACC,IAAKqC,EACL,IAAK9D,EAAE,qBAAqB,EAC5B,UAAU,iCAAA,CAAA,EAEXoE,IAAW,UACR3C,MAAC,KAAE,UAAU,sBAAuB,WAAE,uBAAuB,EAAE,EAC/DA,MAAC,KAAE,UAAU,wBAAyB,WAAS,KAAK2C,CAAM,KAAO,EAAA,CAAG,CAAA,CAAA,CAC1E,EACE,IAAA,CACN,CAAA,CAAA,CACF,CAAA,CACF,CAEJ,CA8BA,SAAS9B,EAAuB,CAAE,SAAAqC,EAAU,SAAA1B,GAAsD,CAChG,KAAM,CAAE,CAAA,EAAMhD,EAAe,CAAC,WAAY,QAAQ,CAAC,EAC7C2E,EAAU,OAAO,QAAQD,CAAQ,EAEjCE,EAAgB,CAAC9B,EAAY+B,IAAyC,CAC1E7B,EAAS,CAAE,GAAG0B,EAAU,CAAC5B,CAAE,EAAG,CAAE,GAAG4B,EAAS5B,CAAE,EAAG,GAAG+B,CAAA,EAAS,CAC/D,EACMC,EAAiBhC,GAAe,CACpC,MAAMR,EAAO,CAAE,GAAGoC,CAAA,EAClB,OAAOpC,EAAKQ,CAAE,EACdE,EAASV,CAAI,CACf,EACMyC,EAAgB,CAACC,EAAeC,IAAkB,CACtD,GAAI,CAACA,GAASA,IAAUD,EAAO,OAC/B,GAAIN,EAASO,CAAK,EAAG,CACnB9D,EAAM,MAAM,EAAE,6CAA8C,CAAE,GAAI8D,CAAA,CAAO,CAAC,EAC1E,MACF,CACA,MAAM3C,EAA6C,CAAA,EACnD,SAAW,CAACzC,EAAGoC,CAAC,IAAK,OAAO,QAAQyC,CAAQ,EAC1CpC,EAAKzC,IAAMmF,EAAQC,EAAQpF,CAAC,EAAIoC,EAElCe,EAASV,CAAI,CACf,EACM4C,EAAa,IAAM,CAEvB,IAAI,EAAIP,EAAQ,OAAS,EACrBQ,EAAY,WAAW,CAAC,GAC5B,KAAOT,EAASS,CAAS,GAAK,GAAK,EAAGA,EAAY,WAAW,CAAC,GAC9DnC,EAAS,CAAE,GAAG0B,EAAU,CAACS,CAAS,EAAG,CAAE,QAAS,EAAA,EAAQ,CAC1D,EAEA,OACE5D,EAAAA,KAAC,MAAA,CAAI,UAAU,kCACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,yCACb,SAAA,CAAAC,MAAC,MAAA,CAAI,UAAU,sCACZ,SAAA,EAAE,mCAAmC,EACxC,EACAD,EAAAA,KAACE,GAAO,KAAK,SAAS,KAAK,KAAK,QAAQ,UAAU,QAASyD,EAAY,SAAA,CAAA,KAClE,EAAE,gCAAgC,CAAA,CAAA,CACvC,CAAA,EACF,EAECP,EAAQ,SAAW,EAClBnD,EAAAA,IAAC,MAAA,CAAI,UAAU,+BACZ,SAAA,EAAE,mCAAmC,CAAA,CACxC,EAEAA,EAAAA,IAAC,OAAI,UAAU,YACZ,SAAAmD,EAAQ,IAAI,CAAC,CAAC7B,EAAIsC,CAAI,IACrB7D,EAAAA,KAAC,MAAA,CAAa,UAAU,qCACtB,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,+BACb,SAAA,CAAAC,EAAAA,IAAC2B,EAAA,CACC,GAAI,WAAWL,CAAE,GACjB,aAAcA,EACd,OAASD,GAAMkC,EAAcjC,EAAID,EAAE,OAAO,MAAM,MAAM,EACtD,UAAU,yBACV,YAAY,YAAA,CAAA,EAEdrB,EAAAA,IAAC2B,EAAA,CACC,GAAI,aAAaL,CAAE,GACnB,MAAOsC,EAAK,MAAQ,GACpB,SAAWvC,GAAM+B,EAAc9B,EAAI,CAAE,KAAMD,EAAE,OAAO,MAAO,EAC3D,UAAU,iBACV,YAAa,EAAE,iCAAiC,CAAA,CAAA,EAElDtB,EAAAA,KAAC,QAAA,CAAM,UAAU,kCACf,SAAA,CAAAC,EAAAA,IAAC,QAAA,CACC,KAAK,WACL,QAAS4D,EAAK,UAAY,GAC1B,SAAWvC,GAAM+B,EAAc9B,EAAI,CAAE,QAASD,EAAE,OAAO,OAAA,CAAS,CAAA,CAAA,EAEjE,EAAE,oBAAoB,CAAA,EACzB,EACArB,EAAAA,IAACC,EAAA,CACC,KAAK,SAAS,KAAK,KAAK,QAAQ,QAChC,QAAS,IAAMqD,EAAchC,CAAE,EAC/B,UAAU,cAEV,SAAAtB,EAAAA,IAACM,EAAA,CAAE,UAAU,QAAA,CAAS,CAAA,CAAA,CACxB,EACF,EACAP,EAAAA,KAAC,MAAA,CAAI,UAAU,YACb,SAAA,CAAAC,EAAAA,IAACU,EAAA,CACC,GAAI,YAAYY,CAAE,GAAI,MAAO,EAAE,4BAA4B,EAC3D,MAAOsC,EAAK,UAAY,GACxB,SAAWnD,GAAM2C,EAAc9B,EAAI,CAAE,SAAUb,EAAG,CAAA,CAAA,EAEpDT,EAAAA,IAACU,EAAA,CACC,GAAI,eAAeY,CAAE,GAAI,MAAO,EAAE,gCAAgC,EAClE,MAAOsC,EAAK,cAAgB,GAC5B,KAAK,WACL,SAAWnD,GAAM2C,EAAc9B,EAAI,CAAE,aAAcb,EAAG,CAAA,CAAA,EAExDT,EAAAA,IAACW,EAAA,CACC,GAAI,WAAWW,CAAE,GAAI,MAAO,EAAE,8BAA8B,EAC5D,MAAOsC,EAAK,UAAY,OACxB,SAAWnD,GAAM2C,EAAc9B,EAAI,CAAE,SAAUb,EAAG,EAClD,QAAS,CACP,CAAE,MAAO,OAAa,MAAO,EAAE,iCAAiC,CAAA,EAChE,CAAE,MAAO,UAAa,MAAO,EAAE,oCAAoC,CAAA,EACnE,CAAE,MAAO,YAAa,MAAO,EAAE,sCAAsC,CAAA,CAAE,CACzE,CAAA,EAEFT,EAAAA,IAACW,EAAA,CACC,GAAI,cAAcW,CAAE,GAAI,MAAO,EAAE,iCAAiC,EAClE,MAAOsC,EAAK,aAAe,OAC3B,SAAWnD,GAAM2C,EAAc9B,EAAI,CAAE,YAAab,EAAG,EACrD,QAAS,CACP,CAAE,MAAO,OAAa,MAAO,EAAE,iCAAiC,CAAA,EAChE,CAAE,MAAO,YAAa,MAAO,EAAE,sCAAsC,CAAA,EACrE,CAAE,MAAO,WAAa,MAAO,EAAE,qCAAqC,CAAA,CAAE,CACxE,CAAA,EAEFT,EAAAA,IAACU,EAAA,CACC,GAAI,cAAcY,CAAE,GAAI,MAAO,EAAE,+BAA+B,EAChE,OAAQsC,EAAK,WAAa,CAAA,GAAI,KAAK,GAAG,EACtC,SAAWnD,GAAM2C,EAAc9B,EAAI,CACjC,UAAWb,EAAE,MAAM,GAAG,EAAE,IAAKG,GAAMA,EAAE,MAAM,EAAE,OAAO,OAAO,CAAA,CAC5D,CAAA,CAAA,EAEHZ,EAAAA,IAACU,EAAA,CACC,GAAI,eAAeY,CAAE,GAAI,MAAO,EAAE,oCAAoC,EACtE,OAAQsC,EAAK,gBAAkB,CAAA,GAAI,KAAK,GAAG,EAC3C,SAAWnD,GAAM2C,EAAc9B,EAAI,CACjC,eAAgBb,EAAE,MAAM,GAAG,EAAE,IAAKG,GAAMA,EAAE,MAAM,EAAE,OAAO,OAAO,CAAA,CACjE,CAAA,CAAA,EAEHZ,EAAAA,IAACW,EAAA,CACC,GAAI,YAAYW,CAAE,GAAI,MAAO,EAAE,iCAAiC,EAChE,MAAOsC,EAAK,aAAe,MAC3B,SAAWnD,GAAM2C,EAAc9B,EAAI,CAAE,YAAab,EAAG,EACrD,QAAS,CACP,CAAE,MAAO,MAAW,MAAO,EAAE,6BAA6B,CAAA,EAC1D,CAAE,MAAO,QAAW,MAAO,EAAE,+BAA+B,CAAA,EAC5D,CAAE,MAAO,UAAW,MAAO,EAAE,iCAAiC,CAAA,CAAE,CAClE,CAAA,CACF,CAAA,CACF,CAAA,GAxFQa,CAyFV,CACD,EACH,QAED,MAAA,CAAI,UAAU,6BAA8B,SAAA,EAAE,kCAAkC,CAAA,CAAE,CAAA,EACrF,CAEJ","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"messengers-CwWP1qI4.js","sources":["../../node_modules/lucide-react/dist/esm/icons/qr-code.js","../../src/routes/settings/messengers.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst QrCode = createLucideIcon(\"QrCode\", [\n [\"rect\", { width: \"5\", height: \"5\", x: \"3\", y: \"3\", rx: \"1\", key: \"1tu5fj\" }],\n [\"rect\", { width: \"5\", height: \"5\", x: \"16\", y: \"3\", rx: \"1\", key: \"1v8r4q\" }],\n [\"rect\", { width: \"5\", height: \"5\", x: \"3\", y: \"16\", rx: \"1\", key: \"1x03jg\" }],\n [\"path\", { d: \"M21 16h-3a2 2 0 0 0-2 2v3\", key: \"177gqh\" }],\n [\"path\", { d: \"M21 21v.01\", key: \"ents32\" }],\n [\"path\", { d: \"M12 7v3a2 2 0 0 1-2 2H7\", key: \"8crl2c\" }],\n [\"path\", { d: \"M3 12h.01\", key: \"nlz23k\" }],\n [\"path\", { d: \"M12 3h.01\", key: \"n36tog\" }],\n [\"path\", { d: \"M12 16v.01\", key: \"133mhm\" }],\n [\"path\", { d: \"M16 12h1\", key: \"1slzba\" }],\n [\"path\", { d: \"M21 12v.01\", key: \"1lwtk9\" }],\n [\"path\", { d: \"M12 21v-1\", key: \"1880an\" }]\n]);\n\nexport { QrCode as default };\n//# sourceMappingURL=qr-code.js.map\n","/**\n * /settings/messengers — per-IM-platform connection config.\n *\n * Layout: one card per platform (WeChat / Telegram / Feishu /\n * DingTalk / Discord). Each card has:\n * * Title + hint\n * * Enable / disable toggle (reads / writes config.messengers[])\n * * When enabled, the platform's config fields (texted)\n * * For WeChat: a \"Scan QR\" button → modal with QR + 2s polling\n *\n * Save All button at the top batches every dirty platform into one\n * PUT /api/config. The discard button reverts the local draft to\n * server-side values.\n *\n * The WeChat QR flow is special: enabling WeChat requires scanning\n * a QR code (the slot in config.messengers gets added by the\n * backend on `confirmed`, so we just open the modal and re-fetch\n * config after a successful scan).\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Loader2, QrCode, RefreshCcw, Save, X } from 'lucide-react'\n\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from '@/components/ui/dialog'\nimport {\n useConfig,\n useUpdateConfig,\n useStartWechatQr,\n useWechatQrStatus,\n} from '@/hooks/use-settings'\nimport { describeError } from '@/lib/api/errors'\nimport type { AppConfig } from '@/types/api'\n\n/** Slot names match what `config.messengers[]` contains.\n * WeChat uses 'wechat-ilink' (the iLink adapter ID). */\ntype Slot = 'wechat-ilink' | 'telegram' | 'feishu' | 'dingtalk' | 'discord'\n\ninterface PlatformDraft {\n enabled: boolean\n telegram?: { botToken?: string; channelId?: string }\n feishu?: { appId?: string; appSecret?: string; channelId?: string }\n dingtalk?: {\n clientId?: string\n clientSecret?: string\n channelId?: string\n // v1.2.37 (batch 1)\n dmPolicy?: 'open' | 'pairing' | 'allowlist'\n groupPolicy?: 'open' | 'allowlist' | 'disabled'\n allowFrom?: string[]\n groupAllowFrom?: string[]\n ackReaction?: 'off' | 'emoji' | 'kaomoji'\n // v1.2.41 (batch 4 follow-up) — full multi-account editor\n accounts?: Record<string, DingTalkAccountDraft>\n }\n discord?: { botToken?: string; channelId?: string }\n}\n\ntype Draft = Record<Slot, PlatformDraft>\n\nfunction buildDraft(cfg: AppConfig | undefined): Draft {\n const m = new Set(cfg?.messengers ?? [])\n return {\n 'wechat-ilink': { enabled: m.has('wechat-ilink') },\n telegram: { enabled: m.has('telegram'), telegram: { ...(cfg?.telegram ?? {}) } },\n feishu: { enabled: m.has('feishu'), feishu: { ...(cfg?.feishu ?? {}) } },\n dingtalk: { enabled: m.has('dingtalk'), dingtalk: { ...(cfg?.dingtalk ?? {}) } },\n discord: { enabled: m.has('discord'), discord: { ...(cfg?.discord ?? {}) } },\n }\n}\n\nfunction buildPatch(draft: Draft, cfg: AppConfig): Partial<AppConfig> {\n const messengers: string[] = []\n for (const k of Object.keys(draft) as Slot[]) if (draft[k].enabled) messengers.push(k)\n return {\n messengers,\n telegram: draft.telegram.telegram,\n feishu: draft.feishu.feishu,\n dingtalk: draft.dingtalk.dingtalk,\n discord: draft.discord.discord,\n // Preserve unknown extra fields the AppConfig type permits.\n ...Object.fromEntries(\n Object.entries(cfg).filter(([k]) => ![\n 'messengers', 'telegram', 'feishu', 'dingtalk', 'discord',\n ].includes(k)),\n ),\n }\n}\n\nexport default function SettingsMessengersRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const cfgQuery = useConfig()\n const updateCfg = useUpdateConfig()\n\n const [draft, setDraft] = useState<Draft>(() => buildDraft(cfgQuery.data))\n // Sync the draft once cfg lands. We don't re-sync on every cfg\n // refetch — that would discard unsaved edits.\n const [synced, setSynced] = useState(false)\n useEffect(() => {\n if (synced) return\n if (!cfgQuery.data) return\n setDraft(buildDraft(cfgQuery.data))\n setSynced(true)\n }, [cfgQuery.data, synced])\n\n const cfg = cfgQuery.data\n const isDirty = useMemo(() => {\n if (!cfg) return false\n return JSON.stringify(buildDraft(cfg)) !== JSON.stringify(draft)\n }, [cfg, draft])\n\n // WeChat QR modal state\n const [qrOpen, setQrOpen] = useState(false)\n\n function patchSlot(slot: Slot, partial: Partial<PlatformDraft>): void {\n setDraft((prev) => ({ ...prev, [slot]: { ...prev[slot], ...partial } }))\n }\n\n async function onSave(): Promise<void> {\n if (!cfg) return\n try {\n await updateCfg.mutateAsync(buildPatch(draft, cfg))\n toast.success(t('messengers.savedToast'))\n setSynced(false) // rebuild draft from refreshed cfg on next paint\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n function onDiscard(): void {\n if (cfg) setDraft(buildDraft(cfg))\n }\n\n return (\n <div className=\"mx-auto flex max-w-4xl flex-col gap-4\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('messengers.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => cfgQuery.refetch()}\n disabled={cfgQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {cfgQuery.isFetching ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('actions.refresh', { ns: 'common' })}</span>\n </Button>\n </div>\n <p className=\"text-sm text-text-dim\">{t('messengers.subtitle')}</p>\n </header>\n\n {/* Save bar */}\n <div className=\"flex flex-wrap items-center gap-2\">\n {isDirty ? (\n <>\n <Badge variant=\"info\">{t('messengers.dirtyHint')}</Badge>\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"sm\"\n onClick={onDiscard}\n disabled={updateCfg.isPending}\n >\n <X className=\"h-4 w-4\" />\n {t('messengers.discardAll')}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => void onSave()}\n disabled={updateCfg.isPending}\n >\n {updateCfg.isPending ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Save className=\"h-4 w-4\" />}\n {updateCfg.isPending ? t('messengers.saving') : t('messengers.saveAll')}\n </Button>\n </>\n ) : (\n <span className=\"text-xs text-text-muted\">{t('env.noChanges')}</span>\n )}\n </div>\n\n {cfgQuery.isLoading ? (\n <div className=\"h-96 rounded-md bg-surface-2 animate-pulse\" />\n ) : !cfg ? null : (\n <div className=\"flex flex-col gap-3\">\n <PlatformCard\n slot=\"wechat-ilink\"\n label={t('messengers.platform.wechat')}\n hint={t('messengers.hint.wechat')}\n enabled={draft['wechat-ilink'].enabled}\n onToggle={(v) => patchSlot('wechat-ilink', { enabled: v })}\n >\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => setQrOpen(true)}\n >\n <QrCode className=\"h-4 w-4\" />\n {t('messengers.scanQr')}\n </Button>\n </PlatformCard>\n\n {cfg.features?.globalIm ? (\n <PlatformCard\n slot=\"telegram\"\n label={t('messengers.platform.telegram')}\n hint={t('messengers.hint.telegram')}\n enabled={draft.telegram.enabled}\n onToggle={(v) => patchSlot('telegram', { enabled: v })}\n >\n <FieldRow\n id=\"tg-token\" label={t('messengers.fields.botToken')}\n value={draft.telegram.telegram?.botToken ?? ''}\n type=\"password\"\n onChange={(v) => patchSlot('telegram', { telegram: { ...draft.telegram.telegram, botToken: v } })}\n />\n <FieldRow\n id=\"tg-channel\" label={t('messengers.fields.channelId')}\n value={draft.telegram.telegram?.channelId ?? ''}\n onChange={(v) => patchSlot('telegram', { telegram: { ...draft.telegram.telegram, channelId: v } })}\n />\n </PlatformCard>\n ) : null}\n\n <PlatformCard\n slot=\"feishu\"\n label={t('messengers.platform.feishu')}\n hint={t('messengers.hint.feishu')}\n enabled={draft.feishu.enabled}\n onToggle={(v) => patchSlot('feishu', { enabled: v })}\n >\n <FieldRow\n id=\"fs-appid\" label={t('messengers.fields.appId')}\n value={draft.feishu.feishu?.appId ?? ''}\n onChange={(v) => patchSlot('feishu', { feishu: { ...draft.feishu.feishu, appId: v } })}\n />\n <FieldRow\n id=\"fs-secret\" label={t('messengers.fields.appSecret')}\n value={draft.feishu.feishu?.appSecret ?? ''}\n type=\"password\"\n onChange={(v) => patchSlot('feishu', { feishu: { ...draft.feishu.feishu, appSecret: v } })}\n />\n <FieldRow\n id=\"fs-channel\" label={t('messengers.fields.channelId')}\n value={draft.feishu.feishu?.channelId ?? ''}\n onChange={(v) => patchSlot('feishu', { feishu: { ...draft.feishu.feishu, channelId: v } })}\n />\n </PlatformCard>\n\n <PlatformCard\n slot=\"dingtalk\"\n label={t('messengers.platform.dingtalk')}\n hint={t('messengers.hint.dingtalk')}\n enabled={draft.dingtalk.enabled}\n onToggle={(v) => patchSlot('dingtalk', { enabled: v })}\n >\n <FieldRow\n id=\"dt-cid\" label={t('messengers.fields.clientId')}\n value={draft.dingtalk.dingtalk?.clientId ?? ''}\n onChange={(v) => patchSlot('dingtalk', { dingtalk: { ...draft.dingtalk.dingtalk, clientId: v } })}\n />\n <FieldRow\n id=\"dt-secret\" label={t('messengers.fields.clientSecret')}\n value={draft.dingtalk.dingtalk?.clientSecret ?? ''}\n type=\"password\"\n onChange={(v) => patchSlot('dingtalk', { dingtalk: { ...draft.dingtalk.dingtalk, clientSecret: v } })}\n />\n <FieldRow\n id=\"dt-channel\" label={t('messengers.fields.channelId')}\n value={draft.dingtalk.dingtalk?.channelId ?? ''}\n onChange={(v) => patchSlot('dingtalk', { dingtalk: { ...draft.dingtalk.dingtalk, channelId: v } })}\n />\n {/* v1.2.37 (batch 1) — access policy + ack-reaction */}\n <SelectRow<'open' | 'pairing' | 'allowlist'>\n id=\"dt-dm-policy\" label={t('messengers.dingtalk.dmPolicy')}\n value={draft.dingtalk.dingtalk?.dmPolicy ?? 'open'}\n onChange={(v) => patchSlot('dingtalk', { dingtalk: { ...draft.dingtalk.dingtalk, dmPolicy: v } })}\n options={[\n { value: 'open', label: t('messengers.dingtalk.policy.open') },\n { value: 'pairing', label: t('messengers.dingtalk.policy.pairing') },\n { value: 'allowlist', label: t('messengers.dingtalk.policy.allowlist') },\n ]}\n />\n <SelectRow<'open' | 'allowlist' | 'disabled'>\n id=\"dt-group-policy\" label={t('messengers.dingtalk.groupPolicy')}\n value={draft.dingtalk.dingtalk?.groupPolicy ?? 'open'}\n onChange={(v) => patchSlot('dingtalk', { dingtalk: { ...draft.dingtalk.dingtalk, groupPolicy: v } })}\n options={[\n { value: 'open', label: t('messengers.dingtalk.policy.open') },\n { value: 'allowlist', label: t('messengers.dingtalk.policy.allowlist') },\n { value: 'disabled', label: t('messengers.dingtalk.policy.disabled') },\n ]}\n />\n <FieldRow\n id=\"dt-allow-from\" label={t('messengers.dingtalk.allowFrom')}\n value={(draft.dingtalk.dingtalk?.allowFrom ?? []).join(',')}\n onChange={(v) => patchSlot('dingtalk', {\n dingtalk: {\n ...draft.dingtalk.dingtalk,\n allowFrom: v.split(',').map((s) => s.trim()).filter(Boolean),\n },\n })}\n />\n <FieldRow\n id=\"dt-group-allow-from\" label={t('messengers.dingtalk.groupAllowFrom')}\n value={(draft.dingtalk.dingtalk?.groupAllowFrom ?? []).join(',')}\n onChange={(v) => patchSlot('dingtalk', {\n dingtalk: {\n ...draft.dingtalk.dingtalk,\n groupAllowFrom: v.split(',').map((s) => s.trim()).filter(Boolean),\n },\n })}\n />\n <SelectRow<'off' | 'emoji' | 'kaomoji'>\n id=\"dt-ack\" label={t('messengers.dingtalk.ackReaction')}\n value={draft.dingtalk.dingtalk?.ackReaction ?? 'off'}\n onChange={(v) => patchSlot('dingtalk', { dingtalk: { ...draft.dingtalk.dingtalk, ackReaction: v } })}\n options={[\n { value: 'off', label: t('messengers.dingtalk.ack.off') },\n { value: 'emoji', label: t('messengers.dingtalk.ack.emoji') },\n { value: 'kaomoji', label: t('messengers.dingtalk.ack.kaomoji') },\n ]}\n />\n {/* v1.2.41 (batch 4 follow-up) — multi-account CRUD editor. */}\n <DingTalkAccountsEditor\n accounts={draft.dingtalk.dingtalk?.accounts ?? {}}\n onChange={(next) => patchSlot('dingtalk', {\n dingtalk: { ...draft.dingtalk.dingtalk, accounts: next },\n })}\n />\n </PlatformCard>\n\n {cfg.features?.globalIm ? (\n <PlatformCard\n slot=\"discord\"\n label={t('messengers.platform.discord')}\n hint={t('messengers.hint.discord')}\n enabled={draft.discord.enabled}\n onToggle={(v) => patchSlot('discord', { enabled: v })}\n >\n <FieldRow\n id=\"dc-token\" label={t('messengers.fields.botToken')}\n value={draft.discord.discord?.botToken ?? ''}\n type=\"password\"\n onChange={(v) => patchSlot('discord', { discord: { ...draft.discord.discord, botToken: v } })}\n />\n <FieldRow\n id=\"dc-channel\" label={t('messengers.fields.channelId')}\n value={draft.discord.discord?.channelId ?? ''}\n onChange={(v) => patchSlot('discord', { discord: { ...draft.discord.discord, channelId: v } })}\n />\n </PlatformCard>\n ) : null}\n </div>\n )}\n\n <WechatQrDialog\n open={qrOpen}\n onOpenChange={setQrOpen}\n onConfirmed={() => { void cfgQuery.refetch(); setSynced(false) }}\n />\n </div>\n )\n}\n\ninterface PlatformCardProps {\n slot: Slot\n label: string\n hint: string\n enabled: boolean\n onToggle: (v: boolean) => void\n children?: React.ReactNode\n}\n\nfunction PlatformCard({ label, hint, enabled, onToggle, children }: PlatformCardProps): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <div className=\"rounded-md border border-border bg-surface p-4\">\n <div className=\"flex items-start gap-3\">\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium text-text\">{label}</span>\n <Badge variant={enabled ? 'success' : 'outline'}>\n {enabled ? t('messengers.enabled') : t('messengers.disabled')}\n </Badge>\n </div>\n <p className=\"mt-1 text-xs text-text-dim\">{hint}</p>\n </div>\n <label className=\"inline-flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={enabled}\n onChange={(e) => onToggle(e.target.checked)}\n className=\"h-4 w-4 accent-accent cursor-pointer\"\n />\n </label>\n </div>\n {enabled && children && (\n <div className=\"mt-3 flex flex-col gap-2\">\n {children}\n </div>\n )}\n </div>\n )\n}\n\ninterface FieldRowProps {\n id: string\n label: string\n value: string\n onChange: (v: string) => void\n type?: 'text' | 'password'\n}\n\nfunction FieldRow({ id, label, value, onChange, type = 'text' }: FieldRowProps): JSX.Element {\n return (\n <div className=\"grid grid-cols-1 gap-1 sm:grid-cols-[180px_1fr] sm:items-center sm:gap-2\">\n <Label htmlFor={id} className=\"text-xs text-text-dim\">{label}</Label>\n <Input\n id={id}\n type={type}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n autoComplete=\"off\"\n className=\"font-mono text-xs\"\n />\n </div>\n )\n}\n\n// v1.2.37 (batch 1) — dropdown sibling of FieldRow for enum settings.\ninterface SelectRowProps<T extends string> {\n id: string\n label: string\n value: T\n onChange: (v: T) => void\n options: Array<{ value: T; label: string }>\n}\nfunction SelectRow<T extends string>({ id, label, value, onChange, options }: SelectRowProps<T>): JSX.Element {\n return (\n <div className=\"grid grid-cols-1 gap-1 sm:grid-cols-[180px_1fr] sm:items-center sm:gap-2\">\n <Label htmlFor={id} className=\"text-xs text-text-dim\">{label}</Label>\n <select\n id={id}\n value={value}\n onChange={(e) => onChange(e.target.value as T)}\n className=\"rounded-md border border-input bg-background px-2 py-1 text-xs\"\n >\n {options.map((o) => (\n <option key={o.value} value={o.value}>{o.label}</option>\n ))}\n </select>\n </div>\n )\n}\n\ninterface WechatQrDialogProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n onConfirmed: () => void\n}\n\nfunction WechatQrDialog({ open, onOpenChange, onConfirmed }: WechatQrDialogProps): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const start = useStartWechatQr()\n const [token, setToken] = useState<string | null>(null)\n const [qrImage, setQrImage] = useState<string | null>(null)\n const [startError, setStartError] = useState<string | null>(null)\n\n // Kick off the start mutation each time the dialog opens; reset on close.\n useEffect(() => {\n if (!open) {\n setToken(null)\n setQrImage(null)\n setStartError(null)\n return\n }\n let active = true\n start.mutateAsync().then((r) => {\n if (!active) return\n setQrImage(r.qrImage)\n setToken(r.qrToken)\n }).catch((err) => {\n if (!active) return\n setStartError(err instanceof Error ? err.message : String(err))\n })\n return () => { active = false }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open])\n\n const statusQuery = useWechatQrStatus(open ? token : null)\n const status = statusQuery.data?.status\n\n useEffect(() => {\n if (status === 'confirmed') {\n toast.success(t('messengers.qr.confirmed'))\n onConfirmed()\n onOpenChange(false)\n }\n if (status === 'expired') {\n toast.error(t('messengers.qr.expired'))\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [status])\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>{t('messengers.qr.title')}</DialogTitle>\n <DialogDescription>{t('messengers.qr.description')}</DialogDescription>\n </DialogHeader>\n <div className=\"flex flex-col items-center gap-3\">\n {start.isPending && !qrImage ? (\n <>\n <Loader2 className=\"h-8 w-8 animate-spin text-text-dim\" />\n <p className=\"text-sm text-text-dim\">{t('messengers.qr.starting')}</p>\n </>\n ) : startError ? (\n <p className=\"text-sm text-danger\">{t('messengers.qr.loadFailed')}: {startError}</p>\n ) : qrImage ? (\n <>\n <img\n src={qrImage}\n alt={t('messengers.qr.title')}\n className=\"rounded-md border border-border\"\n />\n {status === 'expired'\n ? <p className=\"text-xs text-danger\">{t('messengers.qr.expired')}</p>\n : <p className=\"text-xs text-text-dim\">{status ? `· ${status} ·` : ''}</p>}\n </>\n ) : null}\n </div>\n </DialogContent>\n </Dialog>\n )\n}\n\n// ─── v1.2.41 — DingTalk multi-account CRUD editor ───────────────────\n// Renders below the main DingTalk card. Owns the in-memory accounts\n// dict and bubbles every change up via `onChange` so the page-level\n// dirty/save logic notices and lights up the Save button.\n//\n// Each row shows: id (read-only after creation), name, clientId,\n// clientSecret (password mode, masked on echo), dmPolicy / groupPolicy /\n// ackReaction selectors, allowFrom / groupAllowFrom CSVs, enabled\n// toggle, and a delete button. \"Add account\" appends a fresh row with\n// a generated id the operator can rename inline.\n\nexport interface DingTalkAccountDraft {\n name?: string\n clientId?: string\n clientSecret?: string\n dmPolicy?: 'open' | 'pairing' | 'allowlist'\n groupPolicy?: 'open' | 'allowlist' | 'disabled'\n allowFrom?: string[]\n groupAllowFrom?: string[]\n ackReaction?: 'off' | 'emoji' | 'kaomoji'\n enabled?: boolean\n}\n\ninterface DingTalkAccountsEditorProps {\n accounts: Record<string, DingTalkAccountDraft>\n onChange: (next: Record<string, DingTalkAccountDraft>) => void\n}\n\nfunction DingTalkAccountsEditor({ accounts, onChange }: DingTalkAccountsEditorProps): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const entries = Object.entries(accounts)\n\n const updateAccount = (id: string, patch: Partial<DingTalkAccountDraft>) => {\n onChange({ ...accounts, [id]: { ...accounts[id], ...patch } })\n }\n const deleteAccount = (id: string) => {\n const next = { ...accounts }\n delete next[id]\n onChange(next)\n }\n const renameAccount = (oldId: string, newId: string) => {\n if (!newId || newId === oldId) return\n if (accounts[newId]) {\n toast.error(t('messengers.dingtalk.accountRenameCollision', { id: newId }))\n return\n }\n const next: Record<string, DingTalkAccountDraft> = {}\n for (const [k, v] of Object.entries(accounts)) {\n next[k === oldId ? newId : k] = v\n }\n onChange(next)\n }\n const addAccount = () => {\n // Find an unused id of shape account-N.\n let n = entries.length + 1\n let candidate = `account-${n}`\n while (accounts[candidate]) { n += 1; candidate = `account-${n}` }\n onChange({ ...accounts, [candidate]: { enabled: true } })\n }\n\n return (\n <div className=\"mt-3 border-t border-input pt-3\">\n <div className=\"mb-2 flex items-center justify-between\">\n <div className=\"text-xs font-semibold text-text-dim\">\n {t('messengers.dingtalk.accountsTitle')}\n </div>\n <Button type=\"button\" size=\"sm\" variant=\"outline\" onClick={addAccount}>\n + {t('messengers.dingtalk.addAccount')}\n </Button>\n </div>\n\n {entries.length === 0 ? (\n <div className=\"text-xs text-text-dim italic\">\n {t('messengers.dingtalk.accountsEmpty')}\n </div>\n ) : (\n <div className=\"space-y-3\">\n {entries.map(([id, acct]) => (\n <div key={id} className=\"rounded-md border border-input p-2\">\n <div className=\"mb-2 flex items-center gap-2\">\n <Input\n id={`acct-id-${id}`}\n defaultValue={id}\n onBlur={(e) => renameAccount(id, e.target.value.trim())}\n className=\"font-mono text-xs w-40\"\n placeholder=\"account-id\"\n />\n <Input\n id={`acct-name-${id}`}\n value={acct.name ?? ''}\n onChange={(e) => updateAccount(id, { name: e.target.value })}\n className=\"text-xs flex-1\"\n placeholder={t('messengers.dingtalk.accountName')}\n />\n <label className=\"flex items-center gap-1 text-xs\">\n <input\n type=\"checkbox\"\n checked={acct.enabled !== false}\n onChange={(e) => updateAccount(id, { enabled: e.target.checked })}\n />\n {t('messengers.enabled')}\n </label>\n <Button\n type=\"button\" size=\"sm\" variant=\"ghost\"\n onClick={() => deleteAccount(id)}\n className=\"text-danger\"\n >\n <X className=\"size-4\" />\n </Button>\n </div>\n <div className=\"space-y-1\">\n <FieldRow\n id={`acct-cid-${id}`} label={t('messengers.fields.clientId')}\n value={acct.clientId ?? ''}\n onChange={(v) => updateAccount(id, { clientId: v })}\n />\n <FieldRow\n id={`acct-secret-${id}`} label={t('messengers.fields.clientSecret')}\n value={acct.clientSecret ?? ''}\n type=\"password\"\n onChange={(v) => updateAccount(id, { clientSecret: v })}\n />\n <SelectRow<'open' | 'pairing' | 'allowlist'>\n id={`acct-dm-${id}`} label={t('messengers.dingtalk.dmPolicy')}\n value={acct.dmPolicy ?? 'open'}\n onChange={(v) => updateAccount(id, { dmPolicy: v })}\n options={[\n { value: 'open', label: t('messengers.dingtalk.policy.open') },\n { value: 'pairing', label: t('messengers.dingtalk.policy.pairing') },\n { value: 'allowlist', label: t('messengers.dingtalk.policy.allowlist') },\n ]}\n />\n <SelectRow<'open' | 'allowlist' | 'disabled'>\n id={`acct-group-${id}`} label={t('messengers.dingtalk.groupPolicy')}\n value={acct.groupPolicy ?? 'open'}\n onChange={(v) => updateAccount(id, { groupPolicy: v })}\n options={[\n { value: 'open', label: t('messengers.dingtalk.policy.open') },\n { value: 'allowlist', label: t('messengers.dingtalk.policy.allowlist') },\n { value: 'disabled', label: t('messengers.dingtalk.policy.disabled') },\n ]}\n />\n <FieldRow\n id={`acct-allow-${id}`} label={t('messengers.dingtalk.allowFrom')}\n value={(acct.allowFrom ?? []).join(',')}\n onChange={(v) => updateAccount(id, {\n allowFrom: v.split(',').map((s) => s.trim()).filter(Boolean),\n })}\n />\n <FieldRow\n id={`acct-gallow-${id}`} label={t('messengers.dingtalk.groupAllowFrom')}\n value={(acct.groupAllowFrom ?? []).join(',')}\n onChange={(v) => updateAccount(id, {\n groupAllowFrom: v.split(',').map((s) => s.trim()).filter(Boolean),\n })}\n />\n <SelectRow<'off' | 'emoji' | 'kaomoji'>\n id={`acct-ack-${id}`} label={t('messengers.dingtalk.ackReaction')}\n value={acct.ackReaction ?? 'off'}\n onChange={(v) => updateAccount(id, { ackReaction: v })}\n options={[\n { value: 'off', label: t('messengers.dingtalk.ack.off') },\n { value: 'emoji', label: t('messengers.dingtalk.ack.emoji') },\n { value: 'kaomoji', label: t('messengers.dingtalk.ack.kaomoji') },\n ]}\n />\n </div>\n </div>\n ))}\n </div>\n )}\n <div className=\"mt-1 text-xs text-text-dim\">{t('messengers.dingtalk.accountsHint')}</div>\n </div>\n )\n}\n"],"names":["QrCode","createLucideIcon","buildDraft","cfg","m","buildPatch","draft","messengers","k","SettingsMessengersRoute","t","useTranslation","cfgQuery","useConfig","updateCfg","useUpdateConfig","setDraft","useState","synced","setSynced","useEffect","isDirty","useMemo","qrOpen","setQrOpen","patchSlot","slot","partial","prev","onSave","toast","err","describeError","onDiscard","jsxs","jsx","Button","Loader2","RefreshCcw","Fragment","Badge","X","Save","PlatformCard","v","FieldRow","SelectRow","s","DingTalkAccountsEditor","next","WechatQrDialog","label","hint","enabled","onToggle","children","e","id","value","onChange","type","Label","Input","options","o","open","onOpenChange","onConfirmed","start","useStartWechatQr","token","setToken","qrImage","setQrImage","startError","setStartError","active","r","status","useWechatQrStatus","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","accounts","entries","updateAccount","patch","deleteAccount","renameAccount","oldId","newId","addAccount","candidate","acct"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{x as e}from"./index-
|
|
1
|
+
import{x as e}from"./index-CITyis5g.js";/**
|
|
2
2
|
* @license lucide-react v0.469.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/const h=e("Network",[["rect",{x:"16",y:"16",width:"6",height:"6",rx:"1",key:"4q2zg0"}],["rect",{x:"2",y:"16",width:"6",height:"6",rx:"1",key:"8cvhb9"}],["rect",{x:"9",y:"2",width:"6",height:"6",rx:"1",key:"1egb70"}],["path",{d:"M5 16v-3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3",key:"1jsf9p"}],["path",{d:"M12 12V8",key:"2874zd"}]]);export{h as N};
|
|
7
|
-
//# sourceMappingURL=network-
|
|
7
|
+
//# sourceMappingURL=network-CrMEVz4-.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"network-
|
|
1
|
+
{"version":3,"file":"network-CrMEVz4-.js","sources":["../../node_modules/lucide-react/dist/esm/icons/network.js"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Network = createLucideIcon(\"Network\", [\n [\"rect\", { x: \"16\", y: \"16\", width: \"6\", height: \"6\", rx: \"1\", key: \"4q2zg0\" }],\n [\"rect\", { x: \"2\", y: \"16\", width: \"6\", height: \"6\", rx: \"1\", key: \"8cvhb9\" }],\n [\"rect\", { x: \"9\", y: \"2\", width: \"6\", height: \"6\", rx: \"1\", key: \"1egb70\" }],\n [\"path\", { d: \"M5 16v-3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3\", key: \"1jsf9p\" }],\n [\"path\", { d: \"M12 12V8\", key: \"2874zd\" }]\n]);\n\nexport { Network as default };\n//# sourceMappingURL=network.js.map\n"],"names":["Network","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAAUC,EAAiB,UAAW,CAC1C,CAAC,OAAQ,CAAE,EAAG,KAAM,EAAG,KAAM,MAAO,IAAK,OAAQ,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC9E,CAAC,OAAQ,CAAE,EAAG,IAAK,EAAG,KAAM,MAAO,IAAK,OAAQ,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC7E,CAAC,OAAQ,CAAE,EAAG,IAAK,EAAG,IAAK,MAAO,IAAK,OAAQ,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC5E,CAAC,OAAQ,CAAE,EAAG,4CAA6C,IAAK,QAAQ,CAAE,EAC1E,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,CAC3C,CAAC","x_google_ignoreList":[0]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{x as L,aa as E,a9 as P,q as m,ac as A,ab as D,Q as t,c as j,i as M,L as N,S as q,l as F,m as Q,j as z,k as y,I as B,a2 as v,z as K,r as V}from"./index-
|
|
1
|
+
import{x as L,aa as E,a9 as P,q as m,ac as A,ab as D,Q as t,c as j,i as M,L as N,S as q,l as F,m as Q,j as z,k as y,I as B,a2 as v,z as K,r as V}from"./index-CITyis5g.js";import{e as w}from"./react-C9F3QeMB.js";import{D as J}from"./data-table-BKTemkw9.js";import{E as U}from"./empty-state-C87S9Wor.js";import{S as $}from"./status-badge-HSHkhdur.js";import{C as H}from"./confirm-dialog-B53cbWzX.js";import{u as C}from"./useQuery-DFryK9Pn.js";import{L as Y}from"./loader-circle-BFp6Oc8_.js";import{R as G}from"./refresh-ccw-CPSYEbgh.js";import"./table-BBISYTH-.js";import"./dialog-Cevi7KvQ.js";import"./x-D5196-9X.js";/**
|
|
2
2
|
* @license lucide-react v0.469.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/const W=L("Inbox",[["polyline",{points:"22 12 16 12 14 15 10 15 8 12 2 12",key:"o97t9d"}],["path",{d:"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z",key:"oot6mr"}]]),h={all:["outbox"],list:e=>["outbox","list",e],stats:["outbox","stats"]};function X(e){return C({queryKey:h.list(e),queryFn:()=>m.listOutbox(e),refetchInterval:5e3,refetchIntervalInBackground:!1})}function Z(){return C({queryKey:h.stats,queryFn:()=>m.getOutboxStats(),refetchInterval:1e4,refetchIntervalInBackground:!1})}function ee(){const e=E();return P({mutationFn:a=>m.retryOutbox(a),onSuccess:()=>e.invalidateQueries({queryKey:h.all})})}const te=["pending","delivered","giving_up"];function be(){const{t:e}=A(["tasks","common"]),[a,r]=D(),l=a.get("status")??null,i=a.get("thread")??"",{data:_,isLoading:O,isFetching:f,refetch:k}=X({...l?{status:l}:{},...i?{thread:i}:{},limit:200}),I=_?.rows??[],o=Z().data,c=ee(),[d,p]=w.useState(null);function b(s){const n=new URLSearchParams(a);for(const[g,u]of Object.entries(s))u==null||u===""?n.delete(g):n.set(g,u);r(n,{replace:!0})}async function R(){if(d!=null)try{await c.mutateAsync(d),v.success(e("states.saved",{ns:"common"}))}catch(s){const{message:n}=K(s,e);throw v.error(n),s}}const T=w.useMemo(()=>[{id:"id",header:e("outbox.col.id"),cell:s=>t.jsxs("span",{className:"tabular-nums text-text-dim",children:["#",s.id]}),headClassName:"w-20"},{id:"status",header:e("outbox.col.status"),cell:s=>t.jsx($,{status:s.status,children:e(`outbox.status.${s.status}`,{defaultValue:s.status})}),headClassName:"w-28"},{id:"platform",header:e("outbox.col.platform"),cell:s=>t.jsx("span",{className:"font-medium",children:s.platform}),headClassName:"w-28"},{id:"preview",header:e("outbox.col.preview"),cell:s=>t.jsx("span",{className:"line-clamp-2 text-text",title:s.payload,children:ae(s.payload,s.kind)}),asCardTitle:!0},{id:"thread",header:e("outbox.col.thread"),cell:s=>t.jsx("span",{className:"font-mono text-xs text-text-dim line-clamp-1",title:s.thread_key,children:s.thread_key}),headClassName:"w-44",hideOnMobile:!0},{id:"kind",header:e("outbox.col.kind"),cell:s=>t.jsx("span",{className:"text-text-dim",children:s.kind}),headClassName:"w-20",hideOnMobile:!0},{id:"attempts",header:e("outbox.col.attempts"),cell:s=>t.jsx("span",{className:"tabular-nums",children:s.attempts}),headClassName:"w-20"},{id:"createdAt",header:e("outbox.col.createdAt"),cell:s=>t.jsx("span",{className:"text-text-dim",children:S(s.created_at)}),headClassName:"w-32",hideOnMobile:!0},{id:"lastError",header:e("outbox.col.lastError"),cell:s=>s.last_error?t.jsx("span",{className:"line-clamp-1 text-danger text-xs",title:s.last_error,children:s.last_error}):t.jsx("span",{className:"text-text-muted",children:"—"}),hideOnMobile:!1},{id:"actions",header:"",cell:s=>s.status==="giving_up"?t.jsxs(j,{variant:"outline",size:"sm",onClick:n=>{n.stopPropagation(),p(s.id)},disabled:c.isPending,children:[t.jsx(M,{className:"h-3 w-3"}),e("outbox.action.retry")]}):null,headClassName:"w-28"}],[e,c.isPending]);return t.jsxs("div",{className:"mx-auto flex max-w-7xl flex-col gap-4",children:[t.jsxs("header",{className:"flex flex-col gap-1",children:[t.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[t.jsx("h1",{className:"text-xl font-semibold",children:e("outbox.title")}),t.jsxs(j,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>k(),disabled:f,"aria-label":e("actions.refresh",{ns:"common"}),children:[f?t.jsx(Y,{className:"h-4 w-4 animate-spin"}):t.jsx(G,{className:"h-4 w-4"}),t.jsx("span",{className:"hidden sm:inline",children:e("actions.refresh",{ns:"common"})})]})]}),t.jsx("p",{className:"text-sm text-text-dim",children:e("outbox.subtitle")})]}),o&&t.jsxs("div",{className:"grid grid-cols-2 gap-2 sm:grid-cols-4",children:[t.jsx(x,{label:e("outbox.stats.pending"),value:o.pending,tone:"info"}),t.jsx(x,{label:e("outbox.stats.giving_up"),value:o.giving_up,tone:"danger"}),t.jsx(x,{label:e("outbox.stats.delivered"),value:o.delivered,tone:"success"}),t.jsxs("div",{className:"rounded-md border border-border bg-surface px-3 py-2",children:[t.jsx("div",{className:"text-xs uppercase tracking-wide text-text-dim",children:e("outbox.stats.lastDelivered")}),t.jsx("div",{className:"text-sm font-medium tabular-nums",children:o.lastDeliveredAt?S(o.lastDeliveredAt):"—"})]})]}),t.jsxs("div",{className:"flex flex-wrap items-end gap-2",children:[t.jsxs("div",{className:"flex flex-col gap-1",children:[t.jsx(N,{htmlFor:"status-filter",className:"text-xs text-text-dim",children:e("outbox.filter.status")}),t.jsxs(q,{value:l??"__any__",onValueChange:s=>b({status:s==="__any__"?null:s}),children:[t.jsx(F,{id:"status-filter",className:"w-[160px]",children:t.jsx(Q,{})}),t.jsxs(z,{children:[t.jsx(y,{value:"__any__",children:e("outbox.filter.statusAny")}),te.map(s=>t.jsx(y,{value:s,children:e(`outbox.status.${s}`,{defaultValue:s})},s))]})]})]}),t.jsxs("div",{className:"flex flex-col gap-1",children:[t.jsx(N,{htmlFor:"thread-filter",className:"text-xs text-text-dim",children:e("outbox.filter.thread")}),t.jsx(B,{id:"thread-filter",value:i,onChange:s=>b({thread:s.target.value}),placeholder:"wechat:room:...",className:"w-72 font-mono text-xs"})]})]}),t.jsx(J,{columns:T,rows:I,getRowId:s=>String(s.id),loading:O,emptyState:t.jsx(U,{icon:t.jsx(W,{}),title:e("outbox.empty.title"),description:e("outbox.empty.description")})}),t.jsx(H,{open:d!=null,onOpenChange:s=>{s||p(null)},title:e("outbox.action.confirmRetry"),description:e("outbox.action.confirmRetryDesc"),confirmLabel:e("outbox.action.retry"),onConfirm:R})]})}const se={info:"border-info/30 text-info",success:"border-success/30 text-success",warning:"border-warning/30 text-warning",danger:"border-danger/30 text-danger"};function x({label:e,value:a,tone:r}){return t.jsxs("div",{className:V("rounded-md border bg-surface px-3 py-2",se[r]),children:[t.jsx("div",{className:"text-xs uppercase tracking-wide text-text-dim",children:e}),t.jsx("div",{className:"text-2xl font-semibold tabular-nums",children:a})]})}function ae(e,a){if(!e)return"—";if(a==="text")return e;try{const r=JSON.parse(e),l=r.text??r.message??r.title??r.body??null;return typeof l=="string"&&l.length>0?l:JSON.stringify(r)}catch{return e}}function S(e){if(e==null)return"—";try{const a=new Date(e);return Number.isNaN(a.getTime())?e:a.toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return e}}export{be as default};
|
|
7
|
-
//# sourceMappingURL=outbox-
|
|
7
|
+
//# sourceMappingURL=outbox-C7FpZzwS.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outbox-D4IQcACJ.js","sources":["../../node_modules/lucide-react/dist/esm/icons/inbox.js","../../src/hooks/use-outbox.ts","../../src/routes/tasks/outbox.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Inbox = createLucideIcon(\"Inbox\", [\n [\"polyline\", { points: \"22 12 16 12 14 15 10 15 8 12 2 12\", key: \"o97t9d\" }],\n [\n \"path\",\n {\n d: \"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z\",\n key: \"oot6mr\"\n }\n ]\n]);\n\nexport { Inbox as default };\n//# sourceMappingURL=inbox.js.map\n","/**\n * useOutbox — react-query wrappers for the delivery queue.\n *\n * useOutbox(query) — list rows (status / thread / limit)\n * useOutboxStats() — small summary for KPI cards\n * useRetryOutbox() — retry a giving_up row by id\n *\n * The outbox isn't on the SSE bus. Routes use the react-query\n * polling fallback (5s) plus the existing SSE `job` event, which\n * effectively covers any newly-enqueued row (a job that runs to\n * completion enqueues one or more outbox rows).\n */\n\nimport { useQueryClient, useQuery, useMutation } from '@tanstack/react-query'\nimport { api } from '@/lib/api/endpoints'\nimport type { ListOutboxQuery, ListOutboxResponse, OutboxStats } from '@/types/api'\n\nexport const outboxKeys = {\n all: ['outbox'] as const,\n list: (q: ListOutboxQuery) => ['outbox', 'list', q] as const,\n stats: ['outbox', 'stats'] as const,\n}\n\nexport function useOutbox(query: ListOutboxQuery) {\n return useQuery<ListOutboxResponse>({\n queryKey: outboxKeys.list(query),\n queryFn: () => api.listOutbox(query),\n refetchInterval: 5000,\n refetchIntervalInBackground: false,\n })\n}\n\nexport function useOutboxStats() {\n return useQuery<OutboxStats>({\n queryKey: outboxKeys.stats,\n queryFn: () => api.getOutboxStats(),\n refetchInterval: 10000,\n refetchIntervalInBackground: false,\n })\n}\n\nexport function useInvalidateOutbox() {\n const qc = useQueryClient()\n return () => qc.invalidateQueries({ queryKey: outboxKeys.all })\n}\n\nexport function useRetryOutbox() {\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (id: number) => api.retryOutbox(id),\n onSuccess: () => qc.invalidateQueries({ queryKey: outboxKeys.all }),\n })\n}\n","/**\n * /tasks/outbox — IM-platform delivery queue. Read-mostly; the one\n * mutation is \"retry\" on rows stuck in `giving_up`. Per-row action\n * routes through ConfirmDialog so an accidental click doesn't re-\n * fire a possibly-flaky delivery against the user's IM channel.\n */\n\nimport { useMemo, useState } from 'react'\nimport { useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Inbox, Loader2, RefreshCcw, RotateCcw } from 'lucide-react'\n\nimport { DataTable, type DataTableColumn } from '@/components/common/data-table'\nimport { EmptyState } from '@/components/common/empty-state'\nimport { StatusBadge } from '@/components/common/status-badge'\nimport { ConfirmDialog } from '@/components/common/confirm-dialog'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport {\n useOutbox,\n useOutboxStats,\n useRetryOutbox,\n} from '@/hooks/use-outbox'\nimport type { OutboxRow, OutboxStatus } from '@/types/api'\nimport { describeError } from '@/lib/api/errors'\nimport { cn } from '@/lib/utils'\n\nconst STATUS_OPTIONS: OutboxStatus[] = ['pending', 'delivered', 'giving_up']\n\nexport default function OutboxRoute(): JSX.Element {\n const { t } = useTranslation(['tasks', 'common'])\n const [params, setParams] = useSearchParams()\n const status = (params.get('status') as OutboxStatus | null) ?? null\n const thread = params.get('thread') ?? ''\n\n const { data, isLoading, isFetching, refetch } = useOutbox({\n ...(status ? { status } : {}),\n ...(thread ? { thread } : {}),\n limit: 200,\n })\n const rows = data?.rows ?? []\n const statsQuery = useOutboxStats()\n const stats = statsQuery.data\n\n const retryMut = useRetryOutbox()\n const [confirmRetryId, setConfirmRetryId] = useState<number | null>(null)\n\n function patchParams(patch: Record<string, string | null>): void {\n const next = new URLSearchParams(params)\n for (const [k, v] of Object.entries(patch)) {\n if (v == null || v === '') next.delete(k)\n else next.set(k, v)\n }\n setParams(next, { replace: true })\n }\n\n async function onConfirmRetry(): Promise<void> {\n if (confirmRetryId == null) return\n try {\n await retryMut.mutateAsync(confirmRetryId)\n toast.success(t('states.saved', { ns: 'common' }))\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n throw err\n }\n }\n\n const columns: DataTableColumn<OutboxRow>[] = useMemo(\n () => [\n {\n id: 'id',\n header: t('outbox.col.id'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">#{r.id}</span>,\n headClassName: 'w-20',\n },\n {\n id: 'status',\n header: t('outbox.col.status'),\n cell: (r) => (\n <StatusBadge status={r.status}>\n {t(`outbox.status.${r.status}`, { defaultValue: r.status })}\n </StatusBadge>\n ),\n headClassName: 'w-28',\n },\n {\n id: 'platform',\n header: t('outbox.col.platform'),\n cell: (r) => <span className=\"font-medium\">{r.platform}</span>,\n headClassName: 'w-28',\n },\n {\n id: 'preview',\n header: t('outbox.col.preview'),\n cell: (r) => (\n <span\n className=\"line-clamp-2 text-text\"\n title={r.payload}\n >\n {previewPayload(r.payload, r.kind)}\n </span>\n ),\n asCardTitle: true,\n },\n {\n id: 'thread',\n header: t('outbox.col.thread'),\n cell: (r) => (\n <span\n className=\"font-mono text-xs text-text-dim line-clamp-1\"\n title={r.thread_key}\n >\n {r.thread_key}\n </span>\n ),\n headClassName: 'w-44',\n hideOnMobile: true,\n },\n {\n id: 'kind',\n header: t('outbox.col.kind'),\n cell: (r) => <span className=\"text-text-dim\">{r.kind}</span>,\n headClassName: 'w-20',\n hideOnMobile: true,\n },\n {\n id: 'attempts',\n header: t('outbox.col.attempts'),\n cell: (r) => <span className=\"tabular-nums\">{r.attempts}</span>,\n headClassName: 'w-20',\n },\n {\n id: 'createdAt',\n header: t('outbox.col.createdAt'),\n cell: (r) => <span className=\"text-text-dim\">{formatTime(r.created_at)}</span>,\n headClassName: 'w-32',\n hideOnMobile: true,\n },\n {\n id: 'lastError',\n header: t('outbox.col.lastError'),\n cell: (r) =>\n r.last_error ? (\n <span className=\"line-clamp-1 text-danger text-xs\" title={r.last_error}>\n {r.last_error}\n </span>\n ) : (\n <span className=\"text-text-muted\">—</span>\n ),\n hideOnMobile: false,\n },\n {\n id: 'actions',\n header: '',\n cell: (r) =>\n r.status === 'giving_up' ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation()\n setConfirmRetryId(r.id)\n }}\n disabled={retryMut.isPending}\n >\n <RotateCcw className=\"h-3 w-3\" />\n {t('outbox.action.retry')}\n </Button>\n ) : null,\n headClassName: 'w-28',\n },\n ],\n [t, retryMut.isPending],\n )\n\n return (\n <div className=\"mx-auto flex max-w-7xl flex-col gap-4\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('outbox.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => refetch()}\n disabled={isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {isFetching ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('actions.refresh', { ns: 'common' })}</span>\n </Button>\n </div>\n <p className=\"text-sm text-text-dim\">{t('outbox.subtitle')}</p>\n </header>\n\n {/* Stats strip */}\n {stats && (\n <div className=\"grid grid-cols-2 gap-2 sm:grid-cols-4\">\n <StatCard label={t('outbox.stats.pending')} value={stats.pending} tone=\"info\" />\n <StatCard label={t('outbox.stats.giving_up')} value={stats.giving_up} tone=\"danger\" />\n <StatCard label={t('outbox.stats.delivered')} value={stats.delivered} tone=\"success\" />\n <div className=\"rounded-md border border-border bg-surface px-3 py-2\">\n <div className=\"text-xs uppercase tracking-wide text-text-dim\">\n {t('outbox.stats.lastDelivered')}\n </div>\n <div className=\"text-sm font-medium tabular-nums\">\n {stats.lastDeliveredAt ? formatTime(stats.lastDeliveredAt) : '—'}\n </div>\n </div>\n </div>\n )}\n\n {/* Filter row */}\n <div className=\"flex flex-wrap items-end gap-2\">\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor=\"status-filter\" className=\"text-xs text-text-dim\">\n {t('outbox.filter.status')}\n </Label>\n <Select\n value={status ?? '__any__'}\n onValueChange={(v) => patchParams({ status: v === '__any__' ? null : v })}\n >\n <SelectTrigger id=\"status-filter\" className=\"w-[160px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__any__\">{t('outbox.filter.statusAny')}</SelectItem>\n {STATUS_OPTIONS.map((s) => (\n <SelectItem key={s} value={s}>\n {t(`outbox.status.${s}`, { defaultValue: s })}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor=\"thread-filter\" className=\"text-xs text-text-dim\">\n {t('outbox.filter.thread')}\n </Label>\n <Input\n id=\"thread-filter\"\n value={thread}\n onChange={(e) => patchParams({ thread: e.target.value })}\n placeholder=\"wechat:room:...\"\n className=\"w-72 font-mono text-xs\"\n />\n </div>\n </div>\n\n <DataTable\n columns={columns}\n rows={rows}\n getRowId={(r) => String(r.id)}\n loading={isLoading}\n emptyState={\n <EmptyState\n icon={<Inbox />}\n title={t('outbox.empty.title')}\n description={t('outbox.empty.description')}\n />\n }\n />\n\n <ConfirmDialog\n open={confirmRetryId != null}\n onOpenChange={(open) => {\n if (!open) setConfirmRetryId(null)\n }}\n title={t('outbox.action.confirmRetry')}\n description={t('outbox.action.confirmRetryDesc')}\n confirmLabel={t('outbox.action.retry')}\n onConfirm={onConfirmRetry}\n />\n </div>\n )\n}\n\ninterface StatCardProps {\n label: string\n value: number\n tone: 'info' | 'success' | 'warning' | 'danger'\n}\n\nconst TONE_STYLES: Record<StatCardProps['tone'], string> = {\n info: 'border-info/30 text-info',\n success: 'border-success/30 text-success',\n warning: 'border-warning/30 text-warning',\n danger: 'border-danger/30 text-danger',\n}\n\nfunction StatCard({ label, value, tone }: StatCardProps): JSX.Element {\n return (\n <div\n className={cn(\n 'rounded-md border bg-surface px-3 py-2',\n TONE_STYLES[tone],\n )}\n >\n <div className=\"text-xs uppercase tracking-wide text-text-dim\">{label}</div>\n <div className=\"text-2xl font-semibold tabular-nums\">{value}</div>\n </div>\n )\n}\n\n/** Render a one-line preview of an outbox row's payload.\n *\n * Card payloads are JSON encoded by the agent. We pluck the most\n * likely \"message\" field if we can parse it; otherwise we fall back\n * to the raw string. Text payloads are returned as-is, truncated\n * by the surrounding `line-clamp-2`. */\nfunction previewPayload(payload: string, kind: string): string {\n if (!payload) return '—'\n if (kind === 'text') return payload\n try {\n const parsed = JSON.parse(payload) as Record<string, unknown>\n const text = (parsed.text ?? parsed.message ?? parsed.title ?? parsed.body ?? null) as string | null\n if (typeof text === 'string' && text.length > 0) return text\n // Fallback: serialise the object compactly so the operator still\n // sees something useful.\n return JSON.stringify(parsed)\n } catch {\n return payload\n }\n}\n\nfunction formatTime(iso: string | null): string {\n if (iso == null) return '—'\n try {\n const d = new Date(iso)\n if (Number.isNaN(d.getTime())) return iso\n return d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })\n } catch {\n return iso\n }\n}\n"],"names":["Inbox","createLucideIcon","outboxKeys","q","useOutbox","query","useQuery","api","useOutboxStats","useRetryOutbox","qc","useQueryClient","useMutation","id","STATUS_OPTIONS","OutboxRoute","t","useTranslation","params","setParams","useSearchParams","status","thread","data","isLoading","isFetching","refetch","rows","stats","retryMut","confirmRetryId","setConfirmRetryId","useState","patchParams","patch","next","k","v","onConfirmRetry","toast","err","message","describeError","columns","useMemo","r","jsxs","StatusBadge","jsx","previewPayload","formatTime","Button","e","RotateCcw","Loader2","RefreshCcw","StatCard","Label","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","Input","DataTable","EmptyState","ConfirmDialog","open","TONE_STYLES","label","value","tone","cn","payload","kind","parsed","text","iso","d"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"outbox-C7FpZzwS.js","sources":["../../node_modules/lucide-react/dist/esm/icons/inbox.js","../../src/hooks/use-outbox.ts","../../src/routes/tasks/outbox.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Inbox = createLucideIcon(\"Inbox\", [\n [\"polyline\", { points: \"22 12 16 12 14 15 10 15 8 12 2 12\", key: \"o97t9d\" }],\n [\n \"path\",\n {\n d: \"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z\",\n key: \"oot6mr\"\n }\n ]\n]);\n\nexport { Inbox as default };\n//# sourceMappingURL=inbox.js.map\n","/**\n * useOutbox — react-query wrappers for the delivery queue.\n *\n * useOutbox(query) — list rows (status / thread / limit)\n * useOutboxStats() — small summary for KPI cards\n * useRetryOutbox() — retry a giving_up row by id\n *\n * The outbox isn't on the SSE bus. Routes use the react-query\n * polling fallback (5s) plus the existing SSE `job` event, which\n * effectively covers any newly-enqueued row (a job that runs to\n * completion enqueues one or more outbox rows).\n */\n\nimport { useQueryClient, useQuery, useMutation } from '@tanstack/react-query'\nimport { api } from '@/lib/api/endpoints'\nimport type { ListOutboxQuery, ListOutboxResponse, OutboxStats } from '@/types/api'\n\nexport const outboxKeys = {\n all: ['outbox'] as const,\n list: (q: ListOutboxQuery) => ['outbox', 'list', q] as const,\n stats: ['outbox', 'stats'] as const,\n}\n\nexport function useOutbox(query: ListOutboxQuery) {\n return useQuery<ListOutboxResponse>({\n queryKey: outboxKeys.list(query),\n queryFn: () => api.listOutbox(query),\n refetchInterval: 5000,\n refetchIntervalInBackground: false,\n })\n}\n\nexport function useOutboxStats() {\n return useQuery<OutboxStats>({\n queryKey: outboxKeys.stats,\n queryFn: () => api.getOutboxStats(),\n refetchInterval: 10000,\n refetchIntervalInBackground: false,\n })\n}\n\nexport function useInvalidateOutbox() {\n const qc = useQueryClient()\n return () => qc.invalidateQueries({ queryKey: outboxKeys.all })\n}\n\nexport function useRetryOutbox() {\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (id: number) => api.retryOutbox(id),\n onSuccess: () => qc.invalidateQueries({ queryKey: outboxKeys.all }),\n })\n}\n","/**\n * /tasks/outbox — IM-platform delivery queue. Read-mostly; the one\n * mutation is \"retry\" on rows stuck in `giving_up`. Per-row action\n * routes through ConfirmDialog so an accidental click doesn't re-\n * fire a possibly-flaky delivery against the user's IM channel.\n */\n\nimport { useMemo, useState } from 'react'\nimport { useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Inbox, Loader2, RefreshCcw, RotateCcw } from 'lucide-react'\n\nimport { DataTable, type DataTableColumn } from '@/components/common/data-table'\nimport { EmptyState } from '@/components/common/empty-state'\nimport { StatusBadge } from '@/components/common/status-badge'\nimport { ConfirmDialog } from '@/components/common/confirm-dialog'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport {\n useOutbox,\n useOutboxStats,\n useRetryOutbox,\n} from '@/hooks/use-outbox'\nimport type { OutboxRow, OutboxStatus } from '@/types/api'\nimport { describeError } from '@/lib/api/errors'\nimport { cn } from '@/lib/utils'\n\nconst STATUS_OPTIONS: OutboxStatus[] = ['pending', 'delivered', 'giving_up']\n\nexport default function OutboxRoute(): JSX.Element {\n const { t } = useTranslation(['tasks', 'common'])\n const [params, setParams] = useSearchParams()\n const status = (params.get('status') as OutboxStatus | null) ?? null\n const thread = params.get('thread') ?? ''\n\n const { data, isLoading, isFetching, refetch } = useOutbox({\n ...(status ? { status } : {}),\n ...(thread ? { thread } : {}),\n limit: 200,\n })\n const rows = data?.rows ?? []\n const statsQuery = useOutboxStats()\n const stats = statsQuery.data\n\n const retryMut = useRetryOutbox()\n const [confirmRetryId, setConfirmRetryId] = useState<number | null>(null)\n\n function patchParams(patch: Record<string, string | null>): void {\n const next = new URLSearchParams(params)\n for (const [k, v] of Object.entries(patch)) {\n if (v == null || v === '') next.delete(k)\n else next.set(k, v)\n }\n setParams(next, { replace: true })\n }\n\n async function onConfirmRetry(): Promise<void> {\n if (confirmRetryId == null) return\n try {\n await retryMut.mutateAsync(confirmRetryId)\n toast.success(t('states.saved', { ns: 'common' }))\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n throw err\n }\n }\n\n const columns: DataTableColumn<OutboxRow>[] = useMemo(\n () => [\n {\n id: 'id',\n header: t('outbox.col.id'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">#{r.id}</span>,\n headClassName: 'w-20',\n },\n {\n id: 'status',\n header: t('outbox.col.status'),\n cell: (r) => (\n <StatusBadge status={r.status}>\n {t(`outbox.status.${r.status}`, { defaultValue: r.status })}\n </StatusBadge>\n ),\n headClassName: 'w-28',\n },\n {\n id: 'platform',\n header: t('outbox.col.platform'),\n cell: (r) => <span className=\"font-medium\">{r.platform}</span>,\n headClassName: 'w-28',\n },\n {\n id: 'preview',\n header: t('outbox.col.preview'),\n cell: (r) => (\n <span\n className=\"line-clamp-2 text-text\"\n title={r.payload}\n >\n {previewPayload(r.payload, r.kind)}\n </span>\n ),\n asCardTitle: true,\n },\n {\n id: 'thread',\n header: t('outbox.col.thread'),\n cell: (r) => (\n <span\n className=\"font-mono text-xs text-text-dim line-clamp-1\"\n title={r.thread_key}\n >\n {r.thread_key}\n </span>\n ),\n headClassName: 'w-44',\n hideOnMobile: true,\n },\n {\n id: 'kind',\n header: t('outbox.col.kind'),\n cell: (r) => <span className=\"text-text-dim\">{r.kind}</span>,\n headClassName: 'w-20',\n hideOnMobile: true,\n },\n {\n id: 'attempts',\n header: t('outbox.col.attempts'),\n cell: (r) => <span className=\"tabular-nums\">{r.attempts}</span>,\n headClassName: 'w-20',\n },\n {\n id: 'createdAt',\n header: t('outbox.col.createdAt'),\n cell: (r) => <span className=\"text-text-dim\">{formatTime(r.created_at)}</span>,\n headClassName: 'w-32',\n hideOnMobile: true,\n },\n {\n id: 'lastError',\n header: t('outbox.col.lastError'),\n cell: (r) =>\n r.last_error ? (\n <span className=\"line-clamp-1 text-danger text-xs\" title={r.last_error}>\n {r.last_error}\n </span>\n ) : (\n <span className=\"text-text-muted\">—</span>\n ),\n hideOnMobile: false,\n },\n {\n id: 'actions',\n header: '',\n cell: (r) =>\n r.status === 'giving_up' ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation()\n setConfirmRetryId(r.id)\n }}\n disabled={retryMut.isPending}\n >\n <RotateCcw className=\"h-3 w-3\" />\n {t('outbox.action.retry')}\n </Button>\n ) : null,\n headClassName: 'w-28',\n },\n ],\n [t, retryMut.isPending],\n )\n\n return (\n <div className=\"mx-auto flex max-w-7xl flex-col gap-4\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('outbox.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => refetch()}\n disabled={isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {isFetching ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('actions.refresh', { ns: 'common' })}</span>\n </Button>\n </div>\n <p className=\"text-sm text-text-dim\">{t('outbox.subtitle')}</p>\n </header>\n\n {/* Stats strip */}\n {stats && (\n <div className=\"grid grid-cols-2 gap-2 sm:grid-cols-4\">\n <StatCard label={t('outbox.stats.pending')} value={stats.pending} tone=\"info\" />\n <StatCard label={t('outbox.stats.giving_up')} value={stats.giving_up} tone=\"danger\" />\n <StatCard label={t('outbox.stats.delivered')} value={stats.delivered} tone=\"success\" />\n <div className=\"rounded-md border border-border bg-surface px-3 py-2\">\n <div className=\"text-xs uppercase tracking-wide text-text-dim\">\n {t('outbox.stats.lastDelivered')}\n </div>\n <div className=\"text-sm font-medium tabular-nums\">\n {stats.lastDeliveredAt ? formatTime(stats.lastDeliveredAt) : '—'}\n </div>\n </div>\n </div>\n )}\n\n {/* Filter row */}\n <div className=\"flex flex-wrap items-end gap-2\">\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor=\"status-filter\" className=\"text-xs text-text-dim\">\n {t('outbox.filter.status')}\n </Label>\n <Select\n value={status ?? '__any__'}\n onValueChange={(v) => patchParams({ status: v === '__any__' ? null : v })}\n >\n <SelectTrigger id=\"status-filter\" className=\"w-[160px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__any__\">{t('outbox.filter.statusAny')}</SelectItem>\n {STATUS_OPTIONS.map((s) => (\n <SelectItem key={s} value={s}>\n {t(`outbox.status.${s}`, { defaultValue: s })}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor=\"thread-filter\" className=\"text-xs text-text-dim\">\n {t('outbox.filter.thread')}\n </Label>\n <Input\n id=\"thread-filter\"\n value={thread}\n onChange={(e) => patchParams({ thread: e.target.value })}\n placeholder=\"wechat:room:...\"\n className=\"w-72 font-mono text-xs\"\n />\n </div>\n </div>\n\n <DataTable\n columns={columns}\n rows={rows}\n getRowId={(r) => String(r.id)}\n loading={isLoading}\n emptyState={\n <EmptyState\n icon={<Inbox />}\n title={t('outbox.empty.title')}\n description={t('outbox.empty.description')}\n />\n }\n />\n\n <ConfirmDialog\n open={confirmRetryId != null}\n onOpenChange={(open) => {\n if (!open) setConfirmRetryId(null)\n }}\n title={t('outbox.action.confirmRetry')}\n description={t('outbox.action.confirmRetryDesc')}\n confirmLabel={t('outbox.action.retry')}\n onConfirm={onConfirmRetry}\n />\n </div>\n )\n}\n\ninterface StatCardProps {\n label: string\n value: number\n tone: 'info' | 'success' | 'warning' | 'danger'\n}\n\nconst TONE_STYLES: Record<StatCardProps['tone'], string> = {\n info: 'border-info/30 text-info',\n success: 'border-success/30 text-success',\n warning: 'border-warning/30 text-warning',\n danger: 'border-danger/30 text-danger',\n}\n\nfunction StatCard({ label, value, tone }: StatCardProps): JSX.Element {\n return (\n <div\n className={cn(\n 'rounded-md border bg-surface px-3 py-2',\n TONE_STYLES[tone],\n )}\n >\n <div className=\"text-xs uppercase tracking-wide text-text-dim\">{label}</div>\n <div className=\"text-2xl font-semibold tabular-nums\">{value}</div>\n </div>\n )\n}\n\n/** Render a one-line preview of an outbox row's payload.\n *\n * Card payloads are JSON encoded by the agent. We pluck the most\n * likely \"message\" field if we can parse it; otherwise we fall back\n * to the raw string. Text payloads are returned as-is, truncated\n * by the surrounding `line-clamp-2`. */\nfunction previewPayload(payload: string, kind: string): string {\n if (!payload) return '—'\n if (kind === 'text') return payload\n try {\n const parsed = JSON.parse(payload) as Record<string, unknown>\n const text = (parsed.text ?? parsed.message ?? parsed.title ?? parsed.body ?? null) as string | null\n if (typeof text === 'string' && text.length > 0) return text\n // Fallback: serialise the object compactly so the operator still\n // sees something useful.\n return JSON.stringify(parsed)\n } catch {\n return payload\n }\n}\n\nfunction formatTime(iso: string | null): string {\n if (iso == null) return '—'\n try {\n const d = new Date(iso)\n if (Number.isNaN(d.getTime())) return iso\n return d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })\n } catch {\n return iso\n }\n}\n"],"names":["Inbox","createLucideIcon","outboxKeys","q","useOutbox","query","useQuery","api","useOutboxStats","useRetryOutbox","qc","useQueryClient","useMutation","id","STATUS_OPTIONS","OutboxRoute","t","useTranslation","params","setParams","useSearchParams","status","thread","data","isLoading","isFetching","refetch","rows","stats","retryMut","confirmRetryId","setConfirmRetryId","useState","patchParams","patch","next","k","v","onConfirmRetry","toast","err","message","describeError","columns","useMemo","r","jsxs","StatusBadge","jsx","previewPayload","formatTime","Button","e","RotateCcw","Loader2","RefreshCcw","StatCard","Label","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","Input","DataTable","EmptyState","ConfirmDialog","open","TONE_STYLES","label","value","tone","cn","payload","kind","parsed","text","iso","d"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{x as d,ac as f,Q as i,S as b,l as g,m as N,j as k,k as C,c as r,r as y}from"./index-
|
|
1
|
+
import{x as d,ac as f,Q as i,S as b,l as g,m as N,j as k,k as C,c as r,r as y}from"./index-CITyis5g.js";import{C as S}from"./chevron-right-DEyrYFz4.js";/**
|
|
2
2
|
* @license lucide-react v0.469.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -14,4 +14,4 @@ import{x as d,ac as f,Q as i,S as b,l as g,m as N,j as k,k as C,c as r,r as y}fr
|
|
|
14
14
|
* This source code is licensed under the ISC license.
|
|
15
15
|
* See the LICENSE file in the root directory of this source tree.
|
|
16
16
|
*/const M=d("ChevronLeft",[["path",{d:"m15 18-6-6 6-6",key:"1wnfg3"}]]);function T({page:a,totalPages:c,totalRows:s,perPage:n,perPageOptions:o,onPageChange:l,onPerPageChange:x,className:p}){const{t:e}=f("common"),m=a>1,h=a<c,u=n!==void 0&&o&&o.length>0&&x,v=n?(a-1)*n+1:null,j=n&&s!==void 0?Math.min(a*n,s):null;return i.jsxs("div",{className:y("flex flex-wrap items-center justify-between gap-3 py-2",p),role:"navigation","aria-label":e("pagination.label"),children:[i.jsxs("div",{className:"flex items-center gap-2 text-sm text-text-dim",children:[u&&i.jsxs("div",{className:"hidden sm:flex items-center gap-2",children:[i.jsx("span",{children:e("pagination.perPage")}),i.jsxs(b,{value:String(n),onValueChange:t=>x?.(Number(t)),children:[i.jsx(g,{className:"h-8 w-[80px]",children:i.jsx(N,{})}),i.jsx(k,{children:o.map(t=>i.jsx(C,{value:String(t),children:t},t))})]})]}),s!==void 0&&v!==null&&j!==null&&i.jsx("span",{"aria-live":"polite",children:e("pagination.range",{from:s===0?0:v,to:j,total:s})})]}),i.jsxs("div",{className:"flex items-center gap-1",children:[i.jsx(r,{variant:"ghost",size:"icon","aria-label":e("pagination.firstPage"),disabled:!m,onClick:()=>l(1),className:"hidden sm:inline-flex",children:i.jsx(z,{})}),i.jsx(r,{variant:"ghost",size:"icon","aria-label":e("actions.previous"),disabled:!m,onClick:()=>l(a-1),children:i.jsx(M,{})}),i.jsx("span",{className:"px-2 text-sm tabular-nums","aria-live":"polite",children:e("pagination.pageOfTotal",{page:a,totalPages:Math.max(1,c)})}),i.jsx(r,{variant:"ghost",size:"icon","aria-label":e("actions.next"),disabled:!h,onClick:()=>l(a+1),children:i.jsx(S,{})}),i.jsx(r,{variant:"ghost",size:"icon","aria-label":e("pagination.lastPage"),disabled:!h,onClick:()=>l(c),className:"hidden sm:inline-flex",children:i.jsx(L,{})})]})]})}T.displayName="Pagination";export{T as P};
|
|
17
|
-
//# sourceMappingURL=pagination-
|
|
17
|
+
//# sourceMappingURL=pagination-Cgt8W6EX.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination-
|
|
1
|
+
{"version":3,"file":"pagination-Cgt8W6EX.js","sources":["../../node_modules/lucide-react/dist/esm/icons/chevron-first.js","../../node_modules/lucide-react/dist/esm/icons/chevron-last.js","../../node_modules/lucide-react/dist/esm/icons/chevron-left.js","../../src/components/common/pagination.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ChevronFirst = createLucideIcon(\"ChevronFirst\", [\n [\"path\", { d: \"m17 18-6-6 6-6\", key: \"1yerx2\" }],\n [\"path\", { d: \"M7 6v12\", key: \"1p53r6\" }]\n]);\n\nexport { ChevronFirst as default };\n//# sourceMappingURL=chevron-first.js.map\n","/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ChevronLast = createLucideIcon(\"ChevronLast\", [\n [\"path\", { d: \"m7 18 6-6-6-6\", key: \"lwmzdw\" }],\n [\"path\", { d: \"M17 6v12\", key: \"1o0aio\" }]\n]);\n\nexport { ChevronLast as default };\n//# sourceMappingURL=chevron-last.js.map\n","/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ChevronLeft = createLucideIcon(\"ChevronLeft\", [\n [\"path\", { d: \"m15 18-6-6 6-6\", key: \"1wnfg3\" }]\n]);\n\nexport { ChevronLeft as default };\n//# sourceMappingURL=chevron-left.js.map\n","/**\n * Pagination — controlled page navigator. Drives the URL via the\n * `page` / `perPage` callbacks; the caller decides whether to write\n * useSearchParams (recommended), zustand, or just local state.\n *\n * Why controlled: each M2 page wants the page index in the URL so\n * deep-links work (\"here's row 42 — share it\"). Forcing the component\n * to manage its own state would either duplicate the search-params\n * read or trap callers into useEffect to sync. Controlled keeps the\n * data flow obvious.\n *\n * Mobile behavior:\n * - The page-size selector hides below sm (no room; default 20 is\n * fine on phone).\n * - The first / last buttons hide below sm (the page label keeps\n * the user oriented; prev / next is enough).\n * - All buttons have a 44×44 hit target via the `icon` size.\n *\n * Edge cases:\n * - page count of 0 / 1 → component still renders so the table\n * footer doesn't jump on the next page-flip; buttons are disabled.\n * - page > totalPages → clamp on the caller's side (we display the\n * label as-is so the caller sees the bug instead of us masking it).\n */\n\nimport { ChevronFirst, ChevronLast, ChevronLeft, ChevronRight } from 'lucide-react'\nimport { useTranslation } from 'react-i18next'\nimport { Button } from '@/components/ui/button'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'\nimport { cn } from '@/lib/utils'\n\nexport interface PaginationProps {\n /** 1-based current page. */\n page: number\n /** Total number of pages. Pass `Math.max(1, Math.ceil(total / perPage))`. */\n totalPages: number\n /** Optional row count — when present, renders \"1–20 of 150\" alongside the page label. */\n totalRows?: number\n /** Optional rows-per-page slot. Pass `[10, 20, 50, 100]` to enable. */\n perPage?: number\n perPageOptions?: number[]\n onPageChange: (page: number) => void\n onPerPageChange?: (perPage: number) => void\n className?: string\n}\n\nfunction Pagination({\n page,\n totalPages,\n totalRows,\n perPage,\n perPageOptions,\n onPageChange,\n onPerPageChange,\n className,\n}: PaginationProps): JSX.Element {\n const { t } = useTranslation('common')\n const canPrev = page > 1\n const canNext = page < totalPages\n const showPerPage = perPage !== undefined && perPageOptions && perPageOptions.length > 0 && onPerPageChange\n\n const rangeFrom = perPage ? (page - 1) * perPage + 1 : null\n const rangeTo = perPage && totalRows !== undefined\n ? Math.min(page * perPage, totalRows)\n : null\n\n return (\n <div\n className={cn(\n 'flex flex-wrap items-center justify-between gap-3 py-2',\n className,\n )}\n role=\"navigation\"\n aria-label={t('pagination.label')}\n >\n <div className=\"flex items-center gap-2 text-sm text-text-dim\">\n {showPerPage && (\n <div className=\"hidden sm:flex items-center gap-2\">\n <span>{t('pagination.perPage')}</span>\n <Select\n value={String(perPage)}\n onValueChange={(v) => onPerPageChange?.(Number(v))}\n >\n <SelectTrigger className=\"h-8 w-[80px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {perPageOptions.map((n) => (\n <SelectItem key={n} value={String(n)}>\n {n}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n )}\n {totalRows !== undefined && rangeFrom !== null && rangeTo !== null && (\n <span aria-live=\"polite\">\n {t('pagination.range', {\n from: totalRows === 0 ? 0 : rangeFrom,\n to: rangeTo,\n total: totalRows,\n })}\n </span>\n )}\n </div>\n\n <div className=\"flex items-center gap-1\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={t('pagination.firstPage')}\n disabled={!canPrev}\n onClick={() => onPageChange(1)}\n className=\"hidden sm:inline-flex\"\n >\n <ChevronFirst />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={t('actions.previous')}\n disabled={!canPrev}\n onClick={() => onPageChange(page - 1)}\n >\n <ChevronLeft />\n </Button>\n\n <span className=\"px-2 text-sm tabular-nums\" aria-live=\"polite\">\n {t('pagination.pageOfTotal', { page, totalPages: Math.max(1, totalPages) })}\n </span>\n\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={t('actions.next')}\n disabled={!canNext}\n onClick={() => onPageChange(page + 1)}\n >\n <ChevronRight />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={t('pagination.lastPage')}\n disabled={!canNext}\n onClick={() => onPageChange(totalPages)}\n className=\"hidden sm:inline-flex\"\n >\n <ChevronLast />\n </Button>\n </div>\n </div>\n )\n}\nPagination.displayName = 'Pagination'\n\nexport { Pagination }\n"],"names":["ChevronFirst","createLucideIcon","ChevronLast","ChevronLeft","Pagination","page","totalPages","totalRows","perPage","perPageOptions","onPageChange","onPerPageChange","className","t","useTranslation","canPrev","canNext","showPerPage","rangeFrom","rangeTo","jsxs","cn","jsx","Select","v","SelectTrigger","SelectValue","SelectContent","n","SelectItem","Button","ChevronRight"],"mappings":"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","x_google_ignoreList":[0,1,2]}
|