agim-cli 1.3.5 → 1.3.8
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/CHANGELOG.md +30 -6
- package/dist/cli-ui/tui/app.js +2 -2
- package/dist/cli-ui/tui/app.js.map +1 -1
- package/dist/cli-ui/tui/markdown.d.ts +46 -2
- package/dist/cli-ui/tui/markdown.d.ts.map +1 -1
- package/dist/cli-ui/tui/markdown.js +362 -34
- package/dist/cli-ui/tui/markdown.js.map +1 -1
- package/dist/cli-ui/tui/markdown.test.d.ts +2 -0
- package/dist/cli-ui/tui/markdown.test.d.ts.map +1 -0
- package/dist/cli-ui/tui/markdown.test.js +240 -0
- package/dist/cli-ui/tui/markdown.test.js.map +1 -0
- package/dist/cli.js +25 -4
- package/dist/cli.js.map +1 -1
- package/dist/core/a2a.d.ts.map +1 -1
- package/dist/core/a2a.js +6 -0
- package/dist/core/a2a.js.map +1 -1
- package/dist/core/access-token.d.ts.map +1 -1
- package/dist/core/access-token.js +16 -4
- package/dist/core/access-token.js.map +1 -1
- package/dist/core/approval-bus.d.ts +5 -0
- package/dist/core/approval-bus.d.ts.map +1 -1
- package/dist/core/approval-bus.js +32 -0
- package/dist/core/approval-bus.js.map +1 -1
- package/dist/core/commands/job.d.ts.map +1 -1
- package/dist/core/commands/job.js +10 -3
- package/dist/core/commands/job.js.map +1 -1
- package/dist/core/goal-rpc.d.ts +7 -0
- package/dist/core/goal-rpc.d.ts.map +1 -1
- package/dist/core/goal-rpc.js +47 -3
- package/dist/core/goal-rpc.js.map +1 -1
- package/dist/core/llm/exec-dispatcher.d.ts +2 -0
- package/dist/core/llm/exec-dispatcher.d.ts.map +1 -1
- package/dist/core/llm/exec-dispatcher.js +60 -6
- package/dist/core/llm/exec-dispatcher.js.map +1 -1
- package/dist/core/llm/fs-dispatcher.d.ts +3 -0
- package/dist/core/llm/fs-dispatcher.d.ts.map +1 -1
- package/dist/core/llm/fs-dispatcher.js +31 -12
- package/dist/core/llm/fs-dispatcher.js.map +1 -1
- package/dist/core/llm/imhub-dispatcher.d.ts.map +1 -1
- package/dist/core/llm/imhub-dispatcher.js +9 -5
- package/dist/core/llm/imhub-dispatcher.js.map +1 -1
- package/dist/core/llm/model-catalog.js +1 -1
- package/dist/core/llm/model-catalog.js.map +1 -1
- package/dist/core/llm/policy-approval-gate.d.ts.map +1 -1
- package/dist/core/llm/policy-approval-gate.js +17 -4
- package/dist/core/llm/policy-approval-gate.js.map +1 -1
- package/dist/core/llm/registry.d.ts +2 -2
- package/dist/core/llm/registry.js +1 -1
- package/dist/core/llm/web-dispatcher.d.ts +20 -0
- package/dist/core/llm/web-dispatcher.d.ts.map +1 -1
- package/dist/core/llm/web-dispatcher.js +70 -5
- package/dist/core/llm/web-dispatcher.js.map +1 -1
- package/dist/core/registry.d.ts.map +1 -1
- package/dist/core/registry.js +5 -19
- package/dist/core/registry.js.map +1 -1
- package/dist/core/router.js +1 -1
- package/dist/core/router.js.map +1 -1
- package/dist/core/schedule.d.ts.map +1 -1
- package/dist/core/schedule.js +6 -2
- package/dist/core/schedule.js.map +1 -1
- package/dist/core/skills/loader.js +3 -3
- package/dist/core/skills/loader.js.map +1 -1
- package/dist/core/types.d.ts +3 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/plugins/agents/native/index.d.ts +0 -146
- package/dist/plugins/agents/native/index.d.ts.map +1 -1
- package/dist/plugins/agents/native/index.js +41 -1291
- package/dist/plugins/agents/native/index.js.map +1 -1
- package/dist/plugins/agents/pi-native/approval.d.ts.map +1 -1
- package/dist/plugins/agents/pi-native/approval.js +2 -3
- package/dist/plugins/agents/pi-native/approval.js.map +1 -1
- package/dist/plugins/agents/pi-native/factory.d.ts +3 -4
- package/dist/plugins/agents/pi-native/factory.d.ts.map +1 -1
- package/dist/plugins/agents/pi-native/factory.js +8 -14
- package/dist/plugins/agents/pi-native/factory.js.map +1 -1
- package/dist/plugins/agents/pi-native/index.d.ts +8 -8
- package/dist/plugins/agents/pi-native/index.d.ts.map +1 -1
- package/dist/plugins/agents/pi-native/index.js +78 -13
- package/dist/plugins/agents/pi-native/index.js.map +1 -1
- package/dist/plugins/agents/pi-native/provider-resolver.d.ts +4 -4
- package/dist/plugins/agents/pi-native/provider-resolver.d.ts.map +1 -1
- package/dist/plugins/agents/pi-native/provider-resolver.js +1 -1
- package/dist/plugins/agents/pi-native/provider-resolver.js.map +1 -1
- package/dist/plugins/agents/pi-native/tool-bridge.js +1 -1
- package/dist/plugins/agents/pi-native/tool-bridge.js.map +1 -1
- package/dist/plugins/agents/pi-native/tools.d.ts +3 -4
- package/dist/plugins/agents/pi-native/tools.d.ts.map +1 -1
- package/dist/plugins/agents/pi-native/tools.js +7 -9
- package/dist/plugins/agents/pi-native/tools.js.map +1 -1
- package/dist/plugins/messengers/discord/discord-adapter.d.ts.map +1 -1
- package/dist/plugins/messengers/discord/discord-adapter.js +14 -2
- package/dist/plugins/messengers/discord/discord-adapter.js.map +1 -1
- package/dist/web/public/assets/{a2a-Bk51ozUt.js → a2a-D_I9ZX8i.js} +2 -2
- package/dist/web/public/assets/{a2a-Bk51ozUt.js.map → a2a-D_I9ZX8i.js.map} +1 -1
- package/dist/web/public/assets/{activity-DzKONPpA.js → activity-ZxWknBf9.js} +2 -2
- package/dist/web/public/assets/{activity-DzKONPpA.js.map → activity-ZxWknBf9.js.map} +1 -1
- package/dist/web/public/assets/{admins-CmZ4eQnt.js → admins-DFZcKgq0.js} +2 -2
- package/dist/web/public/assets/{admins-CmZ4eQnt.js.map → admins-DFZcKgq0.js.map} +1 -1
- package/dist/web/public/assets/{agents-lj76gn9U.js → agents-DTONSU0R.js} +2 -2
- package/dist/web/public/assets/{agents-lj76gn9U.js.map → agents-DTONSU0R.js.map} +1 -1
- package/dist/web/public/assets/{approvals-C5-3WBcb.js → approvals-BdDJvH8b.js} +2 -2
- package/dist/web/public/assets/{approvals-C5-3WBcb.js.map → approvals-BdDJvH8b.js.map} +1 -1
- package/dist/web/public/assets/{arrow-down-DAjYgwW2.js → arrow-down-Bhl7hNwa.js} +2 -2
- package/dist/web/public/assets/{arrow-down-DAjYgwW2.js.map → arrow-down-Bhl7hNwa.js.map} +1 -1
- package/dist/web/public/assets/{arrow-up-Cba9TuAO.js → arrow-up-DZLw3qr1.js} +2 -2
- package/dist/web/public/assets/{arrow-up-Cba9TuAO.js.map → arrow-up-DZLw3qr1.js.map} +1 -1
- package/dist/web/public/assets/{asks-qlttx_de.js → asks-Cj2QazUD.js} +2 -2
- package/dist/web/public/assets/{asks-qlttx_de.js.map → asks-Cj2QazUD.js.map} +1 -1
- package/dist/web/public/assets/{audit-CSjpfK6P.js → audit-sxS7UUa6.js} +2 -2
- package/dist/web/public/assets/{audit-CSjpfK6P.js.map → audit-sxS7UUa6.js.map} +1 -1
- package/dist/web/public/assets/{bell-Dm9oEZR5.js → bell-CqimaF3k.js} +2 -2
- package/dist/web/public/assets/{bell-Dm9oEZR5.js.map → bell-CqimaF3k.js.map} +1 -1
- package/dist/web/public/assets/{bgjobs-IOX_MrKV.js → bgjobs-BnXdz4TP.js} +2 -2
- package/dist/web/public/assets/{bgjobs-IOX_MrKV.js.map → bgjobs-BnXdz4TP.js.map} +1 -1
- package/dist/web/public/assets/{brain-D24bSBeM.js → brain-4TIClaVZ.js} +2 -2
- package/dist/web/public/assets/{brain-D24bSBeM.js.map → brain-4TIClaVZ.js.map} +1 -1
- package/dist/web/public/assets/{briefcase-BrIzC9EZ.js → briefcase-iKF60CJd.js} +2 -2
- package/dist/web/public/assets/{briefcase-BrIzC9EZ.js.map → briefcase-iKF60CJd.js.map} +1 -1
- package/dist/web/public/assets/{chat-DXki5zbL.js → chat-Cjp0ECm5.js} +2 -2
- package/dist/web/public/assets/{chat-DXki5zbL.js.map → chat-Cjp0ECm5.js.map} +1 -1
- package/dist/web/public/assets/{chevron-left-C8Ha_lMZ.js → chevron-left-sZyMkeG-.js} +2 -2
- package/dist/web/public/assets/{chevron-left-C8Ha_lMZ.js.map → chevron-left-sZyMkeG-.js.map} +1 -1
- package/dist/web/public/assets/{chevron-right-LF_j8BGd.js → chevron-right-CPHPRLSX.js} +2 -2
- package/dist/web/public/assets/{chevron-right-LF_j8BGd.js.map → chevron-right-CPHPRLSX.js.map} +1 -1
- package/dist/web/public/assets/{circle-check-CpSR3rJi.js → circle-check-BB11MxVm.js} +2 -2
- package/dist/web/public/assets/{circle-check-CpSR3rJi.js.map → circle-check-BB11MxVm.js.map} +1 -1
- package/dist/web/public/assets/{circle-check-big-Dbz0XziN.js → circle-check-big-Sj-6H_3x.js} +2 -2
- package/dist/web/public/assets/{circle-check-big-Dbz0XziN.js.map → circle-check-big-Sj-6H_3x.js.map} +1 -1
- package/dist/web/public/assets/{circle-x-XWMjbfp5.js → circle-x-DYcD4BUu.js} +2 -2
- package/dist/web/public/assets/{circle-x-XWMjbfp5.js.map → circle-x-DYcD4BUu.js.map} +1 -1
- package/dist/web/public/assets/{clock-BjVFYz37.js → clock-BVXa81yB.js} +2 -2
- package/dist/web/public/assets/{clock-BjVFYz37.js.map → clock-BVXa81yB.js.map} +1 -1
- package/dist/web/public/assets/{confirm-dialog-C8nuBNh3.js → confirm-dialog-C2melodU.js} +2 -2
- package/dist/web/public/assets/{confirm-dialog-C8nuBNh3.js.map → confirm-dialog-C2melodU.js.map} +1 -1
- package/dist/web/public/assets/{copy-BUxvUnbP.js → copy-D1OIgfLU.js} +2 -2
- package/dist/web/public/assets/{copy-BUxvUnbP.js.map → copy-D1OIgfLU.js.map} +1 -1
- package/dist/web/public/assets/{data-table-BHctKsHM.js → data-table-BYJ2qMyY.js} +2 -2
- package/dist/web/public/assets/{data-table-BHctKsHM.js.map → data-table-BYJ2qMyY.js.map} +1 -1
- package/dist/web/public/assets/{download-C0hikBL7.js → download-BChufhnl.js} +2 -2
- package/dist/web/public/assets/{download-C0hikBL7.js.map → download-BChufhnl.js.map} +1 -1
- package/dist/web/public/assets/{email-D940p9kF.js → email-exon2FvQ.js} +2 -2
- package/dist/web/public/assets/{email-D940p9kF.js.map → email-exon2FvQ.js.map} +1 -1
- package/dist/web/public/assets/{empty-state-BzzUgjlL.js → empty-state-De5ls0uC.js} +2 -2
- package/dist/web/public/assets/{empty-state-BzzUgjlL.js.map → empty-state-De5ls0uC.js.map} +1 -1
- package/dist/web/public/assets/{external-link-Cjuz11n7.js → external-link-CiJZi5YL.js} +2 -2
- package/dist/web/public/assets/{external-link-Cjuz11n7.js.map → external-link-CiJZi5YL.js.map} +1 -1
- package/dist/web/public/assets/{eye-DVQjbb2Z.js → eye-DowB5M1R.js} +2 -2
- package/dist/web/public/assets/{eye-DVQjbb2Z.js.map → eye-DowB5M1R.js.map} +1 -1
- package/dist/web/public/assets/{facts-C4hVaO6t.js → facts-BdnrzWfV.js} +2 -2
- package/dist/web/public/assets/{facts-C4hVaO6t.js.map → facts-BdnrzWfV.js.map} +1 -1
- package/dist/web/public/assets/{goals-89sYO75m.js → goals-D6ibCBqb.js} +2 -2
- package/dist/web/public/assets/{goals-89sYO75m.js.map → goals-D6ibCBqb.js.map} +1 -1
- package/dist/web/public/assets/{health-CKfZBddX.js → health-BA8ydz1A.js} +2 -2
- package/dist/web/public/assets/{health-CKfZBddX.js.map → health-BA8ydz1A.js.map} +1 -1
- package/dist/web/public/assets/{heart-pulse-BfYs3KFD.js → heart-pulse-ClrbGrB7.js} +2 -2
- package/dist/web/public/assets/{heart-pulse-BfYs3KFD.js.map → heart-pulse-ClrbGrB7.js.map} +1 -1
- package/dist/web/public/assets/{heartbeat-oKkyHWgV.js → heartbeat-j03zupAy.js} +2 -2
- package/dist/web/public/assets/{heartbeat-oKkyHWgV.js.map → heartbeat-j03zupAy.js.map} +1 -1
- package/dist/web/public/assets/{hot-Cas_nZv9.js → hot-D3bwuObi.js} +2 -2
- package/dist/web/public/assets/{hot-Cas_nZv9.js.map → hot-D3bwuObi.js.map} +1 -1
- package/dist/web/public/assets/{index-B795P_3p.js → index-DvWldAJY.js} +15 -15
- package/dist/web/public/assets/{index-B795P_3p.js.map → index-DvWldAJY.js.map} +1 -1
- package/dist/web/public/assets/{injection-DksSjIsi.js → injection-C89g9123.js} +2 -2
- package/dist/web/public/assets/{injection-DksSjIsi.js.map → injection-C89g9123.js.map} +1 -1
- package/dist/web/public/assets/{installed-DWq0Eluy.js → installed-1Hal8dxW.js} +2 -2
- package/dist/web/public/assets/{installed-DWq0Eluy.js.map → installed-1Hal8dxW.js.map} +1 -1
- package/dist/web/public/assets/{jobs-CqY-xtBr.js → jobs-cQ7V-7ec.js} +2 -2
- package/dist/web/public/assets/{jobs-CqY-xtBr.js.map → jobs-cQ7V-7ec.js.map} +1 -1
- package/dist/web/public/assets/{layout-DsoDxB0i.js → layout-BbRAk_tA.js} +2 -2
- package/dist/web/public/assets/{layout-DsoDxB0i.js.map → layout-BbRAk_tA.js.map} +1 -1
- package/dist/web/public/assets/{layout-CqgDOB5t.js → layout-CXGgZCd2.js} +2 -2
- package/dist/web/public/assets/{layout-CqgDOB5t.js.map → layout-CXGgZCd2.js.map} +1 -1
- package/dist/web/public/assets/{layout-Cltp3ikG.js → layout-CZ9hb8_a.js} +2 -2
- package/dist/web/public/assets/{layout-Cltp3ikG.js.map → layout-CZ9hb8_a.js.map} +1 -1
- package/dist/web/public/assets/{layout-BiAVhWgU.js → layout-U5o6RgqN.js} +2 -2
- package/dist/web/public/assets/{layout-BiAVhWgU.js.map → layout-U5o6RgqN.js.map} +1 -1
- package/dist/web/public/assets/{layout-BodTIhhE.js → layout-Y9JSZczb.js} +2 -2
- package/dist/web/public/assets/{layout-BodTIhhE.js.map → layout-Y9JSZczb.js.map} +1 -1
- package/dist/web/public/assets/{llm-D3Kd9gqa.js → llm-CumYZM83.js} +2 -2
- package/dist/web/public/assets/{llm-D3Kd9gqa.js.map → llm-CumYZM83.js.map} +1 -1
- package/dist/web/public/assets/{loader-circle-DsLQMvHE.js → loader-circle-CZQXsfz7.js} +2 -2
- package/dist/web/public/assets/{loader-circle-DsLQMvHE.js.map → loader-circle-CZQXsfz7.js.map} +1 -1
- package/dist/web/public/assets/{map-pin-e694Eet6.js → map-pin-CYj0xBbt.js} +2 -2
- package/dist/web/public/assets/{map-pin-e694Eet6.js.map → map-pin-CYj0xBbt.js.map} +1 -1
- package/dist/web/public/assets/{mcp-BoWJqog4.js → mcp-DP4Vj1Nh.js} +2 -2
- package/dist/web/public/assets/{mcp-BoWJqog4.js.map → mcp-DP4Vj1Nh.js.map} +1 -1
- package/dist/web/public/assets/{memos-C81bimPJ.js → memos-ZDpt1S28.js} +2 -2
- package/dist/web/public/assets/{memos-C81bimPJ.js.map → memos-ZDpt1S28.js.map} +1 -1
- package/dist/web/public/assets/{messengers-CGcjXUeJ.js → messengers-B007J8et.js} +2 -2
- package/dist/web/public/assets/{messengers-CGcjXUeJ.js.map → messengers-B007J8et.js.map} +1 -1
- package/dist/web/public/assets/{mobile-Duy_If5A.js → mobile-Crm0YJ36.js} +2 -2
- package/dist/web/public/assets/{mobile-Duy_If5A.js.map → mobile-Crm0YJ36.js.map} +1 -1
- package/dist/web/public/assets/{network-DnBhCncp.js → network-BYbGwOEp.js} +2 -2
- package/dist/web/public/assets/{network-DnBhCncp.js.map → network-BYbGwOEp.js.map} +1 -1
- package/dist/web/public/assets/{outbox-DrReVtHr.js → outbox-D7xZ5y2T.js} +2 -2
- package/dist/web/public/assets/{outbox-DrReVtHr.js.map → outbox-D7xZ5y2T.js.map} +1 -1
- package/dist/web/public/assets/{pagination-DgS8vaZM.js → pagination-bzSoQOAd.js} +2 -2
- package/dist/web/public/assets/{pagination-DgS8vaZM.js.map → pagination-bzSoQOAd.js.map} +1 -1
- package/dist/web/public/assets/{persona-NTg-RuPa.js → persona-VT6A3VYL.js} +2 -2
- package/dist/web/public/assets/{persona-NTg-RuPa.js.map → persona-VT6A3VYL.js.map} +1 -1
- package/dist/web/public/assets/{plans-CUsr4aMb.js → plans-b4DAc_3a.js} +2 -2
- package/dist/web/public/assets/{plans-CUsr4aMb.js.map → plans-b4DAc_3a.js.map} +1 -1
- package/dist/web/public/assets/{play-G96k2QBR.js → play-SPYhVFeC.js} +2 -2
- package/dist/web/public/assets/{play-G96k2QBR.js.map → play-SPYhVFeC.js.map} +1 -1
- package/dist/web/public/assets/{plus-6RZ3XScp.js → plus-D__n9IVW.js} +2 -2
- package/dist/web/public/assets/{plus-6RZ3XScp.js.map → plus-D__n9IVW.js.map} +1 -1
- package/dist/web/public/assets/{policy-BFlQnPo5.js → policy-CWeiR9UO.js} +2 -2
- package/dist/web/public/assets/{policy-BFlQnPo5.js.map → policy-CWeiR9UO.js.map} +1 -1
- package/dist/web/public/assets/{qr-code-L7ClZ31U.js → qr-code-BqDQw03Z.js} +2 -2
- package/dist/web/public/assets/{qr-code-L7ClZ31U.js.map → qr-code-BqDQw03Z.js.map} +1 -1
- package/dist/web/public/assets/{refresh-ccw-S3sFYfDb.js → refresh-ccw-CW2loqyz.js} +2 -2
- package/dist/web/public/assets/{refresh-ccw-S3sFYfDb.js.map → refresh-ccw-CW2loqyz.js.map} +1 -1
- package/dist/web/public/assets/{reminders-DVzHdBpK.js → reminders-BAl8NC0R.js} +2 -2
- package/dist/web/public/assets/{reminders-DVzHdBpK.js.map → reminders-BAl8NC0R.js.map} +1 -1
- package/dist/web/public/assets/{save-DetwgDjo.js → save-DzWp78MC.js} +2 -2
- package/dist/web/public/assets/{save-DetwgDjo.js.map → save-DzWp78MC.js.map} +1 -1
- package/dist/web/public/assets/{schedules-CslP2Ntr.js → schedules-6cyfjv0O.js} +2 -2
- package/dist/web/public/assets/{schedules-CslP2Ntr.js.map → schedules-6cyfjv0O.js.map} +1 -1
- package/dist/web/public/assets/{search-ByHc__pY.js → search-Bh7gD1Aq.js} +2 -2
- package/dist/web/public/assets/{search-ByHc__pY.js.map → search-Bh7gD1Aq.js.map} +1 -1
- package/dist/web/public/assets/{search-Bx2TNvqF.js → search-DVWPME2t.js} +2 -2
- package/dist/web/public/assets/{search-Bx2TNvqF.js.map → search-DVWPME2t.js.map} +1 -1
- package/dist/web/public/assets/{security-B4dw2-ZU.js → security-DlZ_rDwC.js} +2 -2
- package/dist/web/public/assets/{security-B4dw2-ZU.js.map → security-DlZ_rDwC.js.map} +1 -1
- package/dist/web/public/assets/{service-LujRx8DT.js → service-DKkji52r.js} +2 -2
- package/dist/web/public/assets/{service-LujRx8DT.js.map → service-DKkji52r.js.map} +1 -1
- package/dist/web/public/assets/{shield-alert-BM2sbwiD.js → shield-alert-5pYX52s1.js} +2 -2
- package/dist/web/public/assets/{shield-alert-BM2sbwiD.js.map → shield-alert-5pYX52s1.js.map} +1 -1
- package/dist/web/public/assets/{status-badge-Bz0a-nE1.js → status-badge-W8PRNBT2.js} +2 -2
- package/dist/web/public/assets/{status-badge-Bz0a-nE1.js.map → status-badge-W8PRNBT2.js.map} +1 -1
- package/dist/web/public/assets/{subtasks-BEAppda9.js → subtasks-DSvOTpF0.js} +2 -2
- package/dist/web/public/assets/{subtasks-BEAppda9.js.map → subtasks-DSvOTpF0.js.map} +1 -1
- package/dist/web/public/assets/{table-Dl8Faxz-.js → table-B695Fh_p.js} +2 -2
- package/dist/web/public/assets/{table-Dl8Faxz-.js.map → table-B695Fh_p.js.map} +1 -1
- package/dist/web/public/assets/{topn-CXTn3Qdn.js → topn-DqUC9bYh.js} +2 -2
- package/dist/web/public/assets/{topn-CXTn3Qdn.js.map → topn-DqUC9bYh.js.map} +1 -1
- package/dist/web/public/assets/{trash-2-DUSLukqd.js → trash-2-DH4UNSUm.js} +2 -2
- package/dist/web/public/assets/{trash-2-DUSLukqd.js.map → trash-2-DH4UNSUm.js.map} +1 -1
- package/dist/web/public/assets/{use-agim-skills-BD1AIi8d.js → use-agim-skills-BD17YQCK.js} +2 -2
- package/dist/web/public/assets/{use-agim-skills-BD1AIi8d.js.map → use-agim-skills-BD17YQCK.js.map} +1 -1
- package/dist/web/public/assets/{use-background-tasks-FuodO-_C.js → use-background-tasks-Clyo1IGE.js} +2 -2
- package/dist/web/public/assets/{use-background-tasks-FuodO-_C.js.map → use-background-tasks-Clyo1IGE.js.map} +1 -1
- package/dist/web/public/assets/{use-memory-4xOyJX4L.js → use-memory-BGvVWIQX.js} +2 -2
- package/dist/web/public/assets/{use-memory-4xOyJX4L.js.map → use-memory-BGvVWIQX.js.map} +1 -1
- package/dist/web/public/assets/{use-observability-DMebP5-1.js → use-observability-IlURblVq.js} +2 -2
- package/dist/web/public/assets/{use-observability-DMebP5-1.js.map → use-observability-IlURblVq.js.map} +1 -1
- package/dist/web/public/assets/{use-settings-GPajsGBB.js → use-settings-DFTGCq8J.js} +2 -2
- package/dist/web/public/assets/{use-settings-GPajsGBB.js.map → use-settings-DFTGCq8J.js.map} +1 -1
- package/dist/web/public/assets/{use-workspace-C6qix-sY.js → use-workspace-DaXX6QdK.js} +2 -2
- package/dist/web/public/assets/{use-workspace-C6qix-sY.js.map → use-workspace-DaXX6QdK.js.map} +1 -1
- package/dist/web/public/assets/{vector-hGc2RFNQ.js → vector-CKUwZBiK.js} +2 -2
- package/dist/web/public/assets/{vector-hGc2RFNQ.js.map → vector-CKUwZBiK.js.map} +1 -1
- package/dist/web/public/assets/{viewer-YkLMRkmd.js → viewer-edlHJiVg.js} +2 -2
- package/dist/web/public/assets/{viewer-YkLMRkmd.js.map → viewer-edlHJiVg.js.map} +1 -1
- package/dist/web/public/assets/{workspace-0GRMLd5j.js → workspace-B0jlv7Gj.js} +2 -2
- package/dist/web/public/assets/{workspace-0GRMLd5j.js.map → workspace-B0jlv7Gj.js.map} +1 -1
- package/dist/web/public/assets/{workspaces-DPa7ByRm.js → workspaces-_Ho1uiD-.js} +2 -2
- package/dist/web/public/assets/{workspaces-DPa7ByRm.js.map → workspaces-_Ho1uiD-.js.map} +1 -1
- package/dist/web/public/index.html +1 -1
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{u as C,j as e,B as b,l as P,X as T,m as N,n as R,L as A,I as S,D as q,t as E,v as $,w as Q,x as B}from"./index-B795P_3p.js";import{r as f}from"./react-DlP5eolq.js";import{b as O,c as z,d as L,e as H}from"./use-settings-GPajsGBB.js";import{L as I}from"./loader-circle-DsLQMvHE.js";import{R as W}from"./refresh-ccw-S3sFYfDb.js";import{S as J}from"./save-DetwgDjo.js";import{Q as M}from"./qr-code-L7ClZ31U.js";function w(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 _(s,i){const n=[];for(const d of Object.keys(s))s[d].enabled&&n.push(d);const l={messengers:n,...Object.fromEntries(Object.entries(i).filter(([d])=>!["messengers","telegram","feishu","dingtalk","discord"].includes(d)))};return s.telegram.enabled&&s.telegram.telegram&&(l.telegram=s.telegram.telegram),s.feishu.enabled&&s.feishu.feishu&&(l.feishu=s.feishu.feishu),s.dingtalk.enabled&&s.dingtalk.dingtalk&&(l.dingtalk=s.dingtalk.dingtalk),s.discord.enabled&&s.discord.discord&&(l.discord=s.discord.discord),l}function le(){const{t:s}=C(["settings","common"]),i=O(),n=z(),[l,d]=f.useState(()=>w(i.data)),[g,x]=f.useState(!1);f.useEffect(()=>{g||i.data&&(d(w(i.data)),x(!0))},[i.data,g]);const m=i.data,t=f.useMemo(()=>m?JSON.stringify(w(m))!==JSON.stringify(l):!1,[m,l]),[r,o]=f.useState(!1),p=new Set(m?.features?.blacklistedPlatforms??[]),h=a=>p.has(a);function c(a,v){d(F=>({...F,[a]:{...F[a],...v}}))}async function k(){if(m)try{await n.mutateAsync(_(l,m)),N.success(s("messengers.savedToast")),x(!1)}catch(a){N.error(R(a,s).message)}}function D(){m&&d(w(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(b,{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(I,{className:"h-4 w-4 animate-spin"}):e.jsx(W,{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:t?e.jsxs(e.Fragment,{children:[e.jsx(P,{variant:"info",children:s("messengers.dirtyHint")}),e.jsxs(b,{type:"button",variant:"secondary",size:"sm",onClick:D,disabled:n.isPending,children:[e.jsx(T,{className:"h-4 w-4"}),s("messengers.discardAll")]}),e.jsxs(b,{type:"button",size:"sm",onClick:()=>void k(),disabled:n.isPending,children:[n.isPending?e.jsx(I,{className:"h-4 w-4 animate-spin"}):e.jsx(J,{className:"h-4 w-4"}),n.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:[h("wechat-ilink")?null:e.jsx(y,{slot:"wechat-ilink",label:s("messengers.platform.wechat"),hint:s("messengers.hint.wechat"),enabled:l["wechat-ilink"].enabled,onToggle:a=>c("wechat-ilink",{enabled:a}),children:e.jsxs(b,{type:"button",variant:"secondary",size:"sm",onClick:()=>o(!0),children:[e.jsx(M,{className:"h-4 w-4"}),s("messengers.scanQr")]})}),m.features?.globalIm&&!h("telegram")?e.jsxs(y,{slot:"telegram",label:s("messengers.platform.telegram"),hint:s("messengers.hint.telegram"),enabled:l.telegram.enabled,onToggle:a=>c("telegram",{enabled:a}),children:[e.jsx(u,{id:"tg-token",label:s("messengers.fields.botToken"),value:l.telegram.telegram?.botToken??"",type:"password",onChange:a=>c("telegram",{telegram:{...l.telegram.telegram,botToken:a}})}),e.jsx(u,{id:"tg-channel",label:s("messengers.fields.channelId"),value:l.telegram.telegram?.channelId??"",onChange:a=>c("telegram",{telegram:{...l.telegram.telegram,channelId:a}})})]}):null,h("feishu")?null:e.jsxs(y,{slot:"feishu",label:s("messengers.platform.feishu"),hint:s("messengers.hint.feishu"),enabled:l.feishu.enabled,onToggle:a=>c("feishu",{enabled:a}),children:[e.jsx(u,{id:"fs-appid",label:s("messengers.fields.appId"),value:l.feishu.feishu?.appId??"",onChange:a=>c("feishu",{feishu:{...l.feishu.feishu,appId:a}})}),e.jsx(u,{id:"fs-secret",label:s("messengers.fields.appSecret"),value:l.feishu.feishu?.appSecret??"",type:"password",onChange:a=>c("feishu",{feishu:{...l.feishu.feishu,appSecret:a}})}),e.jsx(u,{id:"fs-channel",label:s("messengers.fields.channelId"),value:l.feishu.feishu?.channelId??"",onChange:a=>c("feishu",{feishu:{...l.feishu.feishu,channelId:a}})})]}),h("dingtalk")?null:e.jsxs(y,{slot:"dingtalk",label:s("messengers.platform.dingtalk"),hint:s("messengers.hint.dingtalk"),enabled:l.dingtalk.enabled,onToggle:a=>c("dingtalk",{enabled:a}),children:[e.jsx(u,{id:"dt-cid",label:s("messengers.fields.clientId"),value:l.dingtalk.dingtalk?.clientId??"",onChange:a=>c("dingtalk",{dingtalk:{...l.dingtalk.dingtalk,clientId:a}})}),e.jsx(u,{id:"dt-secret",label:s("messengers.fields.clientSecret"),value:l.dingtalk.dingtalk?.clientSecret??"",type:"password",onChange:a=>c("dingtalk",{dingtalk:{...l.dingtalk.dingtalk,clientSecret:a}})}),e.jsx(u,{id:"dt-channel",label:s("messengers.fields.channelId"),value:l.dingtalk.dingtalk?.channelId??"",onChange:a=>c("dingtalk",{dingtalk:{...l.dingtalk.dingtalk,channelId:a}})}),e.jsx(j,{id:"dt-dm-policy",label:s("messengers.dingtalk.dmPolicy"),value:l.dingtalk.dingtalk?.dmPolicy??"open",onChange:a=>c("dingtalk",{dingtalk:{...l.dingtalk.dingtalk,dmPolicy:a}}),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(j,{id:"dt-group-policy",label:s("messengers.dingtalk.groupPolicy"),value:l.dingtalk.dingtalk?.groupPolicy??"open",onChange:a=>c("dingtalk",{dingtalk:{...l.dingtalk.dingtalk,groupPolicy:a}}),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:(l.dingtalk.dingtalk?.allowFrom??[]).join(","),onChange:a=>c("dingtalk",{dingtalk:{...l.dingtalk.dingtalk,allowFrom:a.split(",").map(v=>v.trim()).filter(Boolean)}})}),e.jsx(u,{id:"dt-group-allow-from",label:s("messengers.dingtalk.groupAllowFrom"),value:(l.dingtalk.dingtalk?.groupAllowFrom??[]).join(","),onChange:a=>c("dingtalk",{dingtalk:{...l.dingtalk.dingtalk,groupAllowFrom:a.split(",").map(v=>v.trim()).filter(Boolean)}})}),e.jsx(j,{id:"dt-ack",label:s("messengers.dingtalk.ackReaction"),value:l.dingtalk.dingtalk?.ackReaction??"off",onChange:a=>c("dingtalk",{dingtalk:{...l.dingtalk.dingtalk,ackReaction:a}}),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(V,{accounts:l.dingtalk.dingtalk?.accounts??{},onChange:a=>c("dingtalk",{dingtalk:{...l.dingtalk.dingtalk,accounts:a}})})]}),m.features?.globalIm&&!h("discord")?e.jsxs(y,{slot:"discord",label:s("messengers.platform.discord"),hint:s("messengers.hint.discord"),enabled:l.discord.enabled,onToggle:a=>c("discord",{enabled:a}),children:[e.jsx(u,{id:"dc-token",label:s("messengers.fields.botToken"),value:l.discord.discord?.botToken??"",type:"password",onChange:a=>c("discord",{discord:{...l.discord.discord,botToken:a}})}),e.jsx(u,{id:"dc-channel",label:s("messengers.fields.channelId"),value:l.discord.discord?.channelId??"",onChange:a=>c("discord",{discord:{...l.discord.discord,channelId:a}})})]}):null]}):null,e.jsx(U,{open:r,onOpenChange:o,onConfirmed:()=>{i.refetch(),x(!1)}})]})}function y({label:s,hint:i,enabled:n,onToggle:l,children:d}){const{t:g}=C("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(P,{variant:n?"success":"outline",children:g(n?"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:n,onChange:x=>l(x.target.checked),className:"h-4 w-4 accent-accent cursor-pointer"})})]}),n&&d&&e.jsx("div",{className:"mt-3 flex flex-col gap-2",children:d})]})}function u({id:s,label:i,value:n,onChange:l,type:d="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(A,{htmlFor:s,className:"text-xs text-text-dim",children:i}),e.jsx(S,{id:s,type:d,value:n,onChange:g=>l(g.target.value),autoComplete:"off",className:"font-mono text-xs"})]})}function j({id:s,label:i,value:n,onChange:l,options:d}){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(A,{htmlFor:s,className:"text-xs text-text-dim",children:i}),e.jsx("select",{id:s,value:n,onChange:g=>l(g.target.value),className:"rounded-md border border-input bg-background px-2 py-1 text-xs",children:d.map(g=>e.jsx("option",{value:g.value,children:g.label},g.value))})]})}function U({open:s,onOpenChange:i,onConfirmed:n}){const{t:l}=C(["settings","common"]),d=L(),[g,x]=f.useState(null),[m,t]=f.useState(null),[r,o]=f.useState(null);f.useEffect(()=>{if(!s){x(null),t(null),o(null);return}let c=!0;return d.mutateAsync().then(k=>{c&&(t(k.qrImage),x(k.qrToken))}).catch(k=>{c&&o(k instanceof Error?k.message:String(k))}),()=>{c=!1}},[s]);const h=H(s?g:null).data?.status;return f.useEffect(()=>{h==="confirmed"&&(N.success(l("messengers.qr.confirmed")),n(),i(!1)),h==="expired"&&N.error(l("messengers.qr.expired"))},[h]),e.jsx(q,{open:s,onOpenChange:i,children:e.jsxs(E,{children:[e.jsxs($,{children:[e.jsx(Q,{children:l("messengers.qr.title")}),e.jsx(B,{children:l("messengers.qr.description")})]}),e.jsx("div",{className:"flex flex-col items-center gap-3",children:d.isPending&&!m?e.jsxs(e.Fragment,{children:[e.jsx(I,{className:"h-8 w-8 animate-spin text-text-dim"}),e.jsx("p",{className:"text-sm text-text-dim",children:l("messengers.qr.starting")})]}):r?e.jsxs("p",{className:"text-sm text-danger",children:[l("messengers.qr.loadFailed"),": ",r]}):m?e.jsxs(e.Fragment,{children:[e.jsx("img",{src:m,alt:l("messengers.qr.title"),className:"rounded-md border border-border"}),h==="expired"?e.jsx("p",{className:"text-xs text-danger",children:l("messengers.qr.expired")}):e.jsx("p",{className:"text-xs text-text-dim",children:h?`· ${h} ·`:""})]}):null})]})})}function V({accounts:s,onChange:i}){const{t:n}=C(["settings","common"]),l=Object.entries(s),d=(t,r)=>{i({...s,[t]:{...s[t],...r}})},g=t=>{const r={...s};delete r[t],i(r)},x=(t,r)=>{if(!r||r===t)return;if(s[r]){N.error(n("messengers.dingtalk.accountRenameCollision",{id:r}));return}const o={};for(const[p,h]of Object.entries(s))o[p===t?r:p]=h;i(o)},m=()=>{let t=l.length+1,r=`account-${t}`;for(;s[r];)t+=1,r=`account-${t}`;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:n("messengers.dingtalk.accountsTitle")}),e.jsxs(b,{type:"button",size:"sm",variant:"outline",onClick:m,children:["+ ",n("messengers.dingtalk.addAccount")]})]}),l.length===0?e.jsx("div",{className:"text-xs text-text-dim italic",children:n("messengers.dingtalk.accountsEmpty")}):e.jsx("div",{className:"space-y-3",children:l.map(([t,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(S,{id:`acct-id-${t}`,defaultValue:t,onBlur:o=>x(t,o.target.value.trim()),className:"font-mono text-xs w-40",placeholder:"account-id"}),e.jsx(S,{id:`acct-name-${t}`,value:r.name??"",onChange:o=>d(t,{name:o.target.value}),className:"text-xs flex-1",placeholder:n("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=>d(t,{enabled:o.target.checked})}),n("messengers.enabled")]}),e.jsx(b,{type:"button",size:"sm",variant:"ghost",onClick:()=>g(t),className:"text-danger",children:e.jsx(T,{className:"size-4"})})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(u,{id:`acct-cid-${t}`,label:n("messengers.fields.clientId"),value:r.clientId??"",onChange:o=>d(t,{clientId:o})}),e.jsx(u,{id:`acct-secret-${t}`,label:n("messengers.fields.clientSecret"),value:r.clientSecret??"",type:"password",onChange:o=>d(t,{clientSecret:o})}),e.jsx(j,{id:`acct-dm-${t}`,label:n("messengers.dingtalk.dmPolicy"),value:r.dmPolicy??"open",onChange:o=>d(t,{dmPolicy:o}),options:[{value:"open",label:n("messengers.dingtalk.policy.open")},{value:"pairing",label:n("messengers.dingtalk.policy.pairing")},{value:"allowlist",label:n("messengers.dingtalk.policy.allowlist")}]}),e.jsx(j,{id:`acct-group-${t}`,label:n("messengers.dingtalk.groupPolicy"),value:r.groupPolicy??"open",onChange:o=>d(t,{groupPolicy:o}),options:[{value:"open",label:n("messengers.dingtalk.policy.open")},{value:"allowlist",label:n("messengers.dingtalk.policy.allowlist")},{value:"disabled",label:n("messengers.dingtalk.policy.disabled")}]}),e.jsx(u,{id:`acct-allow-${t}`,label:n("messengers.dingtalk.allowFrom"),value:(r.allowFrom??[]).join(","),onChange:o=>d(t,{allowFrom:o.split(",").map(p=>p.trim()).filter(Boolean)})}),e.jsx(u,{id:`acct-gallow-${t}`,label:n("messengers.dingtalk.groupAllowFrom"),value:(r.groupAllowFrom??[]).join(","),onChange:o=>d(t,{groupAllowFrom:o.split(",").map(p=>p.trim()).filter(Boolean)})}),e.jsx(j,{id:`acct-ack-${t}`,label:n("messengers.dingtalk.ackReaction"),value:r.ackReaction??"off",onChange:o=>d(t,{ackReaction:o}),options:[{value:"off",label:n("messengers.dingtalk.ack.off")},{value:"emoji",label:n("messengers.dingtalk.ack.emoji")},{value:"kaomoji",label:n("messengers.dingtalk.ack.kaomoji")}]})]})]},t))}),e.jsx("div",{className:"mt-1 text-xs text-text-dim",children:n("messengers.dingtalk.accountsHint")})]})}export{le as default};
|
|
2
|
-
//# sourceMappingURL=messengers-
|
|
1
|
+
import{u as C,j as e,B as b,l as P,X as T,m as N,n as R,L as A,I as S,D as q,t as E,v as $,w as Q,x as B}from"./index-DvWldAJY.js";import{r as f}from"./react-DlP5eolq.js";import{b as O,c as z,d as L,e as H}from"./use-settings-DFTGCq8J.js";import{L as I}from"./loader-circle-CZQXsfz7.js";import{R as W}from"./refresh-ccw-CW2loqyz.js";import{S as J}from"./save-DzWp78MC.js";import{Q as M}from"./qr-code-BqDQw03Z.js";function w(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 _(s,i){const n=[];for(const d of Object.keys(s))s[d].enabled&&n.push(d);const l={messengers:n,...Object.fromEntries(Object.entries(i).filter(([d])=>!["messengers","telegram","feishu","dingtalk","discord"].includes(d)))};return s.telegram.enabled&&s.telegram.telegram&&(l.telegram=s.telegram.telegram),s.feishu.enabled&&s.feishu.feishu&&(l.feishu=s.feishu.feishu),s.dingtalk.enabled&&s.dingtalk.dingtalk&&(l.dingtalk=s.dingtalk.dingtalk),s.discord.enabled&&s.discord.discord&&(l.discord=s.discord.discord),l}function le(){const{t:s}=C(["settings","common"]),i=O(),n=z(),[l,d]=f.useState(()=>w(i.data)),[g,x]=f.useState(!1);f.useEffect(()=>{g||i.data&&(d(w(i.data)),x(!0))},[i.data,g]);const m=i.data,t=f.useMemo(()=>m?JSON.stringify(w(m))!==JSON.stringify(l):!1,[m,l]),[r,o]=f.useState(!1),p=new Set(m?.features?.blacklistedPlatforms??[]),h=a=>p.has(a);function c(a,v){d(F=>({...F,[a]:{...F[a],...v}}))}async function k(){if(m)try{await n.mutateAsync(_(l,m)),N.success(s("messengers.savedToast")),x(!1)}catch(a){N.error(R(a,s).message)}}function D(){m&&d(w(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(b,{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(I,{className:"h-4 w-4 animate-spin"}):e.jsx(W,{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:t?e.jsxs(e.Fragment,{children:[e.jsx(P,{variant:"info",children:s("messengers.dirtyHint")}),e.jsxs(b,{type:"button",variant:"secondary",size:"sm",onClick:D,disabled:n.isPending,children:[e.jsx(T,{className:"h-4 w-4"}),s("messengers.discardAll")]}),e.jsxs(b,{type:"button",size:"sm",onClick:()=>void k(),disabled:n.isPending,children:[n.isPending?e.jsx(I,{className:"h-4 w-4 animate-spin"}):e.jsx(J,{className:"h-4 w-4"}),n.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:[h("wechat-ilink")?null:e.jsx(y,{slot:"wechat-ilink",label:s("messengers.platform.wechat"),hint:s("messengers.hint.wechat"),enabled:l["wechat-ilink"].enabled,onToggle:a=>c("wechat-ilink",{enabled:a}),children:e.jsxs(b,{type:"button",variant:"secondary",size:"sm",onClick:()=>o(!0),children:[e.jsx(M,{className:"h-4 w-4"}),s("messengers.scanQr")]})}),m.features?.globalIm&&!h("telegram")?e.jsxs(y,{slot:"telegram",label:s("messengers.platform.telegram"),hint:s("messengers.hint.telegram"),enabled:l.telegram.enabled,onToggle:a=>c("telegram",{enabled:a}),children:[e.jsx(u,{id:"tg-token",label:s("messengers.fields.botToken"),value:l.telegram.telegram?.botToken??"",type:"password",onChange:a=>c("telegram",{telegram:{...l.telegram.telegram,botToken:a}})}),e.jsx(u,{id:"tg-channel",label:s("messengers.fields.channelId"),value:l.telegram.telegram?.channelId??"",onChange:a=>c("telegram",{telegram:{...l.telegram.telegram,channelId:a}})})]}):null,h("feishu")?null:e.jsxs(y,{slot:"feishu",label:s("messengers.platform.feishu"),hint:s("messengers.hint.feishu"),enabled:l.feishu.enabled,onToggle:a=>c("feishu",{enabled:a}),children:[e.jsx(u,{id:"fs-appid",label:s("messengers.fields.appId"),value:l.feishu.feishu?.appId??"",onChange:a=>c("feishu",{feishu:{...l.feishu.feishu,appId:a}})}),e.jsx(u,{id:"fs-secret",label:s("messengers.fields.appSecret"),value:l.feishu.feishu?.appSecret??"",type:"password",onChange:a=>c("feishu",{feishu:{...l.feishu.feishu,appSecret:a}})}),e.jsx(u,{id:"fs-channel",label:s("messengers.fields.channelId"),value:l.feishu.feishu?.channelId??"",onChange:a=>c("feishu",{feishu:{...l.feishu.feishu,channelId:a}})})]}),h("dingtalk")?null:e.jsxs(y,{slot:"dingtalk",label:s("messengers.platform.dingtalk"),hint:s("messengers.hint.dingtalk"),enabled:l.dingtalk.enabled,onToggle:a=>c("dingtalk",{enabled:a}),children:[e.jsx(u,{id:"dt-cid",label:s("messengers.fields.clientId"),value:l.dingtalk.dingtalk?.clientId??"",onChange:a=>c("dingtalk",{dingtalk:{...l.dingtalk.dingtalk,clientId:a}})}),e.jsx(u,{id:"dt-secret",label:s("messengers.fields.clientSecret"),value:l.dingtalk.dingtalk?.clientSecret??"",type:"password",onChange:a=>c("dingtalk",{dingtalk:{...l.dingtalk.dingtalk,clientSecret:a}})}),e.jsx(u,{id:"dt-channel",label:s("messengers.fields.channelId"),value:l.dingtalk.dingtalk?.channelId??"",onChange:a=>c("dingtalk",{dingtalk:{...l.dingtalk.dingtalk,channelId:a}})}),e.jsx(j,{id:"dt-dm-policy",label:s("messengers.dingtalk.dmPolicy"),value:l.dingtalk.dingtalk?.dmPolicy??"open",onChange:a=>c("dingtalk",{dingtalk:{...l.dingtalk.dingtalk,dmPolicy:a}}),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(j,{id:"dt-group-policy",label:s("messengers.dingtalk.groupPolicy"),value:l.dingtalk.dingtalk?.groupPolicy??"open",onChange:a=>c("dingtalk",{dingtalk:{...l.dingtalk.dingtalk,groupPolicy:a}}),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:(l.dingtalk.dingtalk?.allowFrom??[]).join(","),onChange:a=>c("dingtalk",{dingtalk:{...l.dingtalk.dingtalk,allowFrom:a.split(",").map(v=>v.trim()).filter(Boolean)}})}),e.jsx(u,{id:"dt-group-allow-from",label:s("messengers.dingtalk.groupAllowFrom"),value:(l.dingtalk.dingtalk?.groupAllowFrom??[]).join(","),onChange:a=>c("dingtalk",{dingtalk:{...l.dingtalk.dingtalk,groupAllowFrom:a.split(",").map(v=>v.trim()).filter(Boolean)}})}),e.jsx(j,{id:"dt-ack",label:s("messengers.dingtalk.ackReaction"),value:l.dingtalk.dingtalk?.ackReaction??"off",onChange:a=>c("dingtalk",{dingtalk:{...l.dingtalk.dingtalk,ackReaction:a}}),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(V,{accounts:l.dingtalk.dingtalk?.accounts??{},onChange:a=>c("dingtalk",{dingtalk:{...l.dingtalk.dingtalk,accounts:a}})})]}),m.features?.globalIm&&!h("discord")?e.jsxs(y,{slot:"discord",label:s("messengers.platform.discord"),hint:s("messengers.hint.discord"),enabled:l.discord.enabled,onToggle:a=>c("discord",{enabled:a}),children:[e.jsx(u,{id:"dc-token",label:s("messengers.fields.botToken"),value:l.discord.discord?.botToken??"",type:"password",onChange:a=>c("discord",{discord:{...l.discord.discord,botToken:a}})}),e.jsx(u,{id:"dc-channel",label:s("messengers.fields.channelId"),value:l.discord.discord?.channelId??"",onChange:a=>c("discord",{discord:{...l.discord.discord,channelId:a}})})]}):null]}):null,e.jsx(U,{open:r,onOpenChange:o,onConfirmed:()=>{i.refetch(),x(!1)}})]})}function y({label:s,hint:i,enabled:n,onToggle:l,children:d}){const{t:g}=C("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(P,{variant:n?"success":"outline",children:g(n?"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:n,onChange:x=>l(x.target.checked),className:"h-4 w-4 accent-accent cursor-pointer"})})]}),n&&d&&e.jsx("div",{className:"mt-3 flex flex-col gap-2",children:d})]})}function u({id:s,label:i,value:n,onChange:l,type:d="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(A,{htmlFor:s,className:"text-xs text-text-dim",children:i}),e.jsx(S,{id:s,type:d,value:n,onChange:g=>l(g.target.value),autoComplete:"off",className:"font-mono text-xs"})]})}function j({id:s,label:i,value:n,onChange:l,options:d}){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(A,{htmlFor:s,className:"text-xs text-text-dim",children:i}),e.jsx("select",{id:s,value:n,onChange:g=>l(g.target.value),className:"rounded-md border border-input bg-background px-2 py-1 text-xs",children:d.map(g=>e.jsx("option",{value:g.value,children:g.label},g.value))})]})}function U({open:s,onOpenChange:i,onConfirmed:n}){const{t:l}=C(["settings","common"]),d=L(),[g,x]=f.useState(null),[m,t]=f.useState(null),[r,o]=f.useState(null);f.useEffect(()=>{if(!s){x(null),t(null),o(null);return}let c=!0;return d.mutateAsync().then(k=>{c&&(t(k.qrImage),x(k.qrToken))}).catch(k=>{c&&o(k instanceof Error?k.message:String(k))}),()=>{c=!1}},[s]);const h=H(s?g:null).data?.status;return f.useEffect(()=>{h==="confirmed"&&(N.success(l("messengers.qr.confirmed")),n(),i(!1)),h==="expired"&&N.error(l("messengers.qr.expired"))},[h]),e.jsx(q,{open:s,onOpenChange:i,children:e.jsxs(E,{children:[e.jsxs($,{children:[e.jsx(Q,{children:l("messengers.qr.title")}),e.jsx(B,{children:l("messengers.qr.description")})]}),e.jsx("div",{className:"flex flex-col items-center gap-3",children:d.isPending&&!m?e.jsxs(e.Fragment,{children:[e.jsx(I,{className:"h-8 w-8 animate-spin text-text-dim"}),e.jsx("p",{className:"text-sm text-text-dim",children:l("messengers.qr.starting")})]}):r?e.jsxs("p",{className:"text-sm text-danger",children:[l("messengers.qr.loadFailed"),": ",r]}):m?e.jsxs(e.Fragment,{children:[e.jsx("img",{src:m,alt:l("messengers.qr.title"),className:"rounded-md border border-border"}),h==="expired"?e.jsx("p",{className:"text-xs text-danger",children:l("messengers.qr.expired")}):e.jsx("p",{className:"text-xs text-text-dim",children:h?`· ${h} ·`:""})]}):null})]})})}function V({accounts:s,onChange:i}){const{t:n}=C(["settings","common"]),l=Object.entries(s),d=(t,r)=>{i({...s,[t]:{...s[t],...r}})},g=t=>{const r={...s};delete r[t],i(r)},x=(t,r)=>{if(!r||r===t)return;if(s[r]){N.error(n("messengers.dingtalk.accountRenameCollision",{id:r}));return}const o={};for(const[p,h]of Object.entries(s))o[p===t?r:p]=h;i(o)},m=()=>{let t=l.length+1,r=`account-${t}`;for(;s[r];)t+=1,r=`account-${t}`;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:n("messengers.dingtalk.accountsTitle")}),e.jsxs(b,{type:"button",size:"sm",variant:"outline",onClick:m,children:["+ ",n("messengers.dingtalk.addAccount")]})]}),l.length===0?e.jsx("div",{className:"text-xs text-text-dim italic",children:n("messengers.dingtalk.accountsEmpty")}):e.jsx("div",{className:"space-y-3",children:l.map(([t,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(S,{id:`acct-id-${t}`,defaultValue:t,onBlur:o=>x(t,o.target.value.trim()),className:"font-mono text-xs w-40",placeholder:"account-id"}),e.jsx(S,{id:`acct-name-${t}`,value:r.name??"",onChange:o=>d(t,{name:o.target.value}),className:"text-xs flex-1",placeholder:n("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=>d(t,{enabled:o.target.checked})}),n("messengers.enabled")]}),e.jsx(b,{type:"button",size:"sm",variant:"ghost",onClick:()=>g(t),className:"text-danger",children:e.jsx(T,{className:"size-4"})})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(u,{id:`acct-cid-${t}`,label:n("messengers.fields.clientId"),value:r.clientId??"",onChange:o=>d(t,{clientId:o})}),e.jsx(u,{id:`acct-secret-${t}`,label:n("messengers.fields.clientSecret"),value:r.clientSecret??"",type:"password",onChange:o=>d(t,{clientSecret:o})}),e.jsx(j,{id:`acct-dm-${t}`,label:n("messengers.dingtalk.dmPolicy"),value:r.dmPolicy??"open",onChange:o=>d(t,{dmPolicy:o}),options:[{value:"open",label:n("messengers.dingtalk.policy.open")},{value:"pairing",label:n("messengers.dingtalk.policy.pairing")},{value:"allowlist",label:n("messengers.dingtalk.policy.allowlist")}]}),e.jsx(j,{id:`acct-group-${t}`,label:n("messengers.dingtalk.groupPolicy"),value:r.groupPolicy??"open",onChange:o=>d(t,{groupPolicy:o}),options:[{value:"open",label:n("messengers.dingtalk.policy.open")},{value:"allowlist",label:n("messengers.dingtalk.policy.allowlist")},{value:"disabled",label:n("messengers.dingtalk.policy.disabled")}]}),e.jsx(u,{id:`acct-allow-${t}`,label:n("messengers.dingtalk.allowFrom"),value:(r.allowFrom??[]).join(","),onChange:o=>d(t,{allowFrom:o.split(",").map(p=>p.trim()).filter(Boolean)})}),e.jsx(u,{id:`acct-gallow-${t}`,label:n("messengers.dingtalk.groupAllowFrom"),value:(r.groupAllowFrom??[]).join(","),onChange:o=>d(t,{groupAllowFrom:o.split(",").map(p=>p.trim()).filter(Boolean)})}),e.jsx(j,{id:`acct-ack-${t}`,label:n("messengers.dingtalk.ackReaction"),value:r.ackReaction??"off",onChange:o=>d(t,{ackReaction:o}),options:[{value:"off",label:n("messengers.dingtalk.ack.off")},{value:"emoji",label:n("messengers.dingtalk.ack.emoji")},{value:"kaomoji",label:n("messengers.dingtalk.ack.kaomoji")}]})]})]},t))}),e.jsx("div",{className:"mt-1 text-xs text-text-dim",children:n("messengers.dingtalk.accountsHint")})]})}export{le as default};
|
|
2
|
+
//# sourceMappingURL=messengers-B007J8et.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messengers-CGcjXUeJ.js","sources":["../../src/routes/settings/messengers.tsx"],"sourcesContent":["/**\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 const patch: Partial<AppConfig> = {\n messengers,\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 // Only include platform blocks that are enabled. Omitting disabled\n // platforms avoids PUT /api/config merging `{}` and failing zod\n // (telegram.botToken / feishu.appSecret / discord.botToken require\n // min(1) when the key is present).\n if (draft.telegram.enabled && draft.telegram.telegram) {\n patch.telegram = draft.telegram.telegram\n }\n if (draft.feishu.enabled && draft.feishu.feishu) {\n patch.feishu = draft.feishu.feishu\n }\n if (draft.dingtalk.enabled && draft.dingtalk.dingtalk) {\n patch.dingtalk = draft.dingtalk.dingtalk\n }\n if (draft.discord.enabled && draft.discord.discord) {\n patch.discord = draft.discord.discord\n }\n return patch\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 // v1.2.71 — IMHUB_PLATFORM_BLACKLIST gate. Backend sends the\n // alias-expanded set in features.blacklistedPlatforms; we hide the\n // matching PlatformCard so blacklisted IMs disappear from the page\n // entirely (not just have empty data).\n const blockedPlatforms = new Set(cfg?.features?.blacklistedPlatforms ?? [])\n const isBlocked = (slot: Slot): boolean => blockedPlatforms.has(slot)\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 {!isBlocked('wechat-ilink') ? (\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 ) : null}\n\n {cfg.features?.globalIm && !isBlocked('telegram') ? (\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 {!isBlocked('feishu') ? (\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 ) : null}\n\n {!isBlocked('dingtalk') ? (\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 ) : null}\n\n {cfg.features?.globalIm && !isBlocked('discord') ? (\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":["buildDraft","cfg","m","buildPatch","draft","messengers","k","patch","SettingsMessengersRoute","t","useTranslation","cfgQuery","useConfig","updateCfg","useUpdateConfig","setDraft","useState","synced","setSynced","useEffect","isDirty","useMemo","qrOpen","setQrOpen","blockedPlatforms","isBlocked","slot","patchSlot","partial","prev","onSave","toast","err","describeError","onDiscard","jsxs","jsx","Button","Loader2","RefreshCcw","Fragment","Badge","X","Save","PlatformCard","v","QrCode","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","deleteAccount","renameAccount","oldId","newId","addAccount","n","candidate","acct"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"messengers-B007J8et.js","sources":["../../src/routes/settings/messengers.tsx"],"sourcesContent":["/**\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 const patch: Partial<AppConfig> = {\n messengers,\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 // Only include platform blocks that are enabled. Omitting disabled\n // platforms avoids PUT /api/config merging `{}` and failing zod\n // (telegram.botToken / feishu.appSecret / discord.botToken require\n // min(1) when the key is present).\n if (draft.telegram.enabled && draft.telegram.telegram) {\n patch.telegram = draft.telegram.telegram\n }\n if (draft.feishu.enabled && draft.feishu.feishu) {\n patch.feishu = draft.feishu.feishu\n }\n if (draft.dingtalk.enabled && draft.dingtalk.dingtalk) {\n patch.dingtalk = draft.dingtalk.dingtalk\n }\n if (draft.discord.enabled && draft.discord.discord) {\n patch.discord = draft.discord.discord\n }\n return patch\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 // v1.2.71 — IMHUB_PLATFORM_BLACKLIST gate. Backend sends the\n // alias-expanded set in features.blacklistedPlatforms; we hide the\n // matching PlatformCard so blacklisted IMs disappear from the page\n // entirely (not just have empty data).\n const blockedPlatforms = new Set(cfg?.features?.blacklistedPlatforms ?? [])\n const isBlocked = (slot: Slot): boolean => blockedPlatforms.has(slot)\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 {!isBlocked('wechat-ilink') ? (\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 ) : null}\n\n {cfg.features?.globalIm && !isBlocked('telegram') ? (\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 {!isBlocked('feishu') ? (\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 ) : null}\n\n {!isBlocked('dingtalk') ? (\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 ) : null}\n\n {cfg.features?.globalIm && !isBlocked('discord') ? (\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":["buildDraft","cfg","m","buildPatch","draft","messengers","k","patch","SettingsMessengersRoute","t","useTranslation","cfgQuery","useConfig","updateCfg","useUpdateConfig","setDraft","useState","synced","setSynced","useEffect","isDirty","useMemo","qrOpen","setQrOpen","blockedPlatforms","isBlocked","slot","patchSlot","partial","prev","onSave","toast","err","describeError","onDiscard","jsxs","jsx","Button","Loader2","RefreshCcw","Fragment","Badge","X","Save","PlatformCard","v","QrCode","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","deleteAccount","renameAccount","oldId","newId","addAccount","n","candidate","acct"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{o as j,u as g,e as N,m as i,d as v,j as e,L as m,I as x,B as n,l as h}from"./index-
|
|
1
|
+
import{o as j,u as g,e as N,m as i,d as v,j as e,L as m,I as x,B as n,l as h}from"./index-DvWldAJY.js";import{r as c}from"./react-DlP5eolq.js";import{L as w}from"./loader-circle-CZQXsfz7.js";import{R as y}from"./refresh-ccw-CW2loqyz.js";import{Q as b}from"./qr-code-BqDQw03Z.js";import{E as k,a as L}from"./eye-DowB5M1R.js";import{C}from"./copy-D1OIgfLU.js";import{S as U}from"./shield-alert-5pYX52s1.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 S=j("Smartphone",[["rect",{width:"14",height:"20",x:"5",y:"2",rx:"2",ry:"2",key:"1yt0o3"}],["path",{d:"M12 18h.01",key:"mhygvu"}]]);function Q(){const{t:s}=g(["settings","common"]),[t,u]=c.useState(null),[r,d]=c.useState(!1),[o,p]=c.useState(""),l=N({mutationFn:()=>v.generateMobileQR(o.trim()?{host:o.trim()}:void 0),onSuccess:a=>{u(a),d(!1),i.success(s("mobile.generatedToast"))},onError:a=>i.error(a.message)});async function f(){if(t)try{await navigator.clipboard.writeText(t.loginUrl),i.success(s("mobile.copied"))}catch{i.error(s("mobile.copyFailed"))}}return e.jsxs("div",{className:"mx-auto flex max-w-4xl flex-col gap-6",children:[e.jsx("header",{className:"flex items-center gap-3",children:e.jsx("h1",{className:"text-xl font-semibold",children:s("mobile.title")})}),e.jsx("p",{className:"text-sm text-text-dim",children:s("mobile.subtitle")}),e.jsxs("section",{className:"rounded-md border border-border bg-surface p-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(S,{className:"h-4 w-4 text-text-dim"}),e.jsx("h2",{className:"text-sm font-semibold",children:s("mobile.generateCard")})]}),e.jsx("p",{className:"mt-1 text-xs text-text-dim",children:s("mobile.generateDesc")}),e.jsxs("div",{className:"mt-4 flex flex-col gap-2",children:[e.jsx(m,{className:"text-xs font-medium",children:s("mobile.hostLabel")}),e.jsx(x,{value:o,onChange:a=>p(a.target.value),placeholder:s("mobile.hostPlaceholder",{defaultValue:"auto-detect (leave blank)"}),className:"font-mono text-xs"}),e.jsx("p",{className:"text-[11px] text-text-dim",children:s("mobile.hostHint")})]}),e.jsxs("div",{className:"mt-4 flex items-center gap-2",children:[e.jsxs(n,{onClick:()=>l.mutate(),disabled:l.isPending,size:"sm",children:[l.isPending?e.jsx(w,{className:"h-4 w-4 animate-spin"}):t?e.jsx(y,{className:"h-4 w-4"}):e.jsx(b,{className:"h-4 w-4"}),e.jsx("span",{className:"ml-1",children:s(t?"mobile.regenerate":"mobile.generate")})]}),l.isPending&&e.jsx(h,{variant:"info",children:s("mobile.generating")})]})]}),t&&e.jsxs("section",{className:"rounded-md border border-border bg-surface p-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(b,{className:"h-4 w-4 text-text-dim"}),e.jsx("h2",{className:"text-sm font-semibold",children:s("mobile.scanCard")}),e.jsxs(h,{variant:"success",className:"ml-auto",children:[s("mobile.tokenLabel"),": ",e.jsx("span",{className:"ml-1 font-mono",children:t.label})]})]}),e.jsx("p",{className:"mt-1 text-xs text-text-dim",children:s("mobile.scanDesc")}),e.jsxs("div",{className:"mt-4 flex flex-col items-center gap-3 sm:flex-row sm:items-start",children:[e.jsx("div",{className:"shrink-0 rounded-md border border-border bg-white p-2",children:e.jsx("img",{src:t.qrDataUrl,alt:s("mobile.qrAlt",{defaultValue:"QR code for mobile chat"}),width:280,height:280,className:"block h-[280px] w-[280px]"})}),e.jsxs("div",{className:"flex w-full flex-col gap-3",children:[e.jsxs("div",{children:[e.jsx(m,{className:"text-xs font-medium",children:s("mobile.urlLabel")}),e.jsxs("div",{className:"mt-1 flex items-center gap-2",children:[e.jsx(x,{type:r?"text":"password",readOnly:!0,value:t.loginUrl,className:"font-mono text-[11px]"}),e.jsx(n,{size:"sm",variant:"ghost",onClick:()=>d(a=>!a),"aria-label":r?s("mobile.hideUrl",{defaultValue:"Hide URL"}):s("mobile.showUrl",{defaultValue:"Show URL"}),children:r?e.jsx(k,{className:"h-4 w-4"}):e.jsx(L,{className:"h-4 w-4"})}),e.jsx(n,{size:"sm",variant:"ghost",onClick:()=>void f(),"aria-label":s("mobile.copyUrl",{defaultValue:"Copy URL"}),children:e.jsx(C,{className:"h-4 w-4"})})]}),e.jsx("p",{className:"mt-1 text-[11px] text-text-dim",children:s("mobile.urlHint")})]}),e.jsxs("div",{children:[e.jsx(m,{className:"text-xs font-medium",children:s("mobile.tokenIdLabel")}),e.jsx("div",{className:"mt-1 font-mono text-xs",children:t.tokenId}),e.jsx("p",{className:"mt-1 text-[11px] text-text-dim",children:s("mobile.tokenIdHint")})]})]})]}),e.jsxs("div",{className:"mt-4 flex items-start gap-2 rounded-md border border-warning/40 bg-warning/5 p-3",children:[e.jsx(U,{className:"mt-0.5 h-4 w-4 shrink-0 text-warning"}),e.jsxs("div",{className:"text-xs",children:[e.jsx("div",{className:"font-medium",children:s("mobile.warningTitle")}),e.jsx("p",{className:"mt-1 text-text-dim",children:s("mobile.warningBody")}),e.jsx("a",{href:t.revokeHint,className:"mt-1 inline-block underline text-accent",children:s("mobile.revokeLink")})]})]})]})]})}export{Q as default};
|
|
7
|
-
//# sourceMappingURL=mobile-
|
|
7
|
+
//# sourceMappingURL=mobile-Crm0YJ36.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mobile-Duy_If5A.js","sources":["../../node_modules/lucide-react/dist/esm/icons/smartphone.js","../../src/routes/settings/mobile.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 Smartphone = createLucideIcon(\"Smartphone\", [\n [\"rect\", { width: \"14\", height: \"20\", x: \"5\", y: \"2\", rx: \"2\", ry: \"2\", key: \"1yt0o3\" }],\n [\"path\", { d: \"M12 18h.01\", key: \"mhygvu\" }]\n]);\n\nexport { Smartphone as default };\n//# sourceMappingURL=smartphone.js.map\n","/**\n * /settings/mobile — admin generates a QR an operator scans on a\n * phone to land directly inside /m/chat (v1.2.129).\n *\n * Flow:\n * 1. Click \"Generate QR\" → POST /api/mobile/qr → fresh role=user\n * token + QR PNG (data URL).\n * 2. Render QR, the embedded URL, and the token id.\n * 3. Phone scans → /m/login auto-submits the token cookie → /m/chat.\n *\n * Revoke: the link points the admin at /settings/security/tokens\n * where every token can be killed (the same UI works for the QR\n * tokens because they're stored in the same table with a\n * mobile-via-qr-* label).\n */\n\nimport { useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useMutation } from '@tanstack/react-query'\nimport { toast } from 'sonner'\nimport {\n Copy, Eye, EyeOff, Loader2, QrCode, RefreshCcw, ShieldAlert, Smartphone,\n} 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 { api } from '@/lib/api/endpoints'\nimport type { MobileQRResponse } from '@/types/api'\n\nexport default function SettingsMobileRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const [result, setResult] = useState<MobileQRResponse | null>(null)\n const [showUrl, setShowUrl] = useState(false)\n const [host, setHost] = useState('')\n\n const generate = useMutation<MobileQRResponse, Error>({\n mutationFn: () =>\n api.generateMobileQR(host.trim() ? { host: host.trim() } : undefined),\n onSuccess: (r) => {\n setResult(r)\n setShowUrl(false)\n toast.success(t('mobile.generatedToast'))\n },\n onError: (e) => toast.error(e.message),\n })\n\n async function copyUrl(): Promise<void> {\n if (!result) return\n try {\n await navigator.clipboard.writeText(result.loginUrl)\n toast.success(t('mobile.copied'))\n } catch {\n toast.error(t('mobile.copyFailed'))\n }\n }\n\n return (\n <div className=\"mx-auto flex max-w-4xl flex-col gap-6\">\n <header className=\"flex items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('mobile.title')}</h1>\n </header>\n <p className=\"text-sm text-text-dim\">{t('mobile.subtitle')}</p>\n\n <section className=\"rounded-md border border-border bg-surface p-4\">\n <div className=\"flex items-center gap-2\">\n <Smartphone className=\"h-4 w-4 text-text-dim\" />\n <h2 className=\"text-sm font-semibold\">{t('mobile.generateCard')}</h2>\n </div>\n <p className=\"mt-1 text-xs text-text-dim\">{t('mobile.generateDesc')}</p>\n\n <div className=\"mt-4 flex flex-col gap-2\">\n <Label className=\"text-xs font-medium\">{t('mobile.hostLabel')}</Label>\n <Input\n value={host}\n onChange={(e) => setHost(e.target.value)}\n placeholder={t('mobile.hostPlaceholder', { defaultValue: 'auto-detect (leave blank)' })}\n className=\"font-mono text-xs\"\n />\n <p className=\"text-[11px] text-text-dim\">{t('mobile.hostHint')}</p>\n </div>\n\n <div className=\"mt-4 flex items-center gap-2\">\n <Button\n onClick={() => generate.mutate()}\n disabled={generate.isPending}\n size=\"sm\"\n >\n {generate.isPending\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : result ? <RefreshCcw className=\"h-4 w-4\" /> : <QrCode className=\"h-4 w-4\" />}\n <span className=\"ml-1\">\n {result ? t('mobile.regenerate') : t('mobile.generate')}\n </span>\n </Button>\n {generate.isPending && (\n <Badge variant=\"info\">{t('mobile.generating')}</Badge>\n )}\n </div>\n </section>\n\n {result && (\n <section className=\"rounded-md border border-border bg-surface p-4\">\n <div className=\"flex items-center gap-2\">\n <QrCode className=\"h-4 w-4 text-text-dim\" />\n <h2 className=\"text-sm font-semibold\">{t('mobile.scanCard')}</h2>\n <Badge variant=\"success\" className=\"ml-auto\">\n {t('mobile.tokenLabel')}: <span className=\"ml-1 font-mono\">{result.label}</span>\n </Badge>\n </div>\n <p className=\"mt-1 text-xs text-text-dim\">{t('mobile.scanDesc')}</p>\n\n <div className=\"mt-4 flex flex-col items-center gap-3 sm:flex-row sm:items-start\">\n <div className=\"shrink-0 rounded-md border border-border bg-white p-2\">\n <img\n src={result.qrDataUrl}\n alt={t('mobile.qrAlt', { defaultValue: 'QR code for mobile chat' })}\n width={280}\n height={280}\n className=\"block h-[280px] w-[280px]\"\n />\n </div>\n <div className=\"flex w-full flex-col gap-3\">\n <div>\n <Label className=\"text-xs font-medium\">{t('mobile.urlLabel')}</Label>\n <div className=\"mt-1 flex items-center gap-2\">\n <Input\n type={showUrl ? 'text' : 'password'}\n readOnly\n value={result.loginUrl}\n className=\"font-mono text-[11px]\"\n />\n <Button\n size=\"sm\" variant=\"ghost\"\n onClick={() => setShowUrl((v) => !v)}\n aria-label={showUrl\n ? t('mobile.hideUrl', { defaultValue: 'Hide URL' })\n : t('mobile.showUrl', { defaultValue: 'Show URL' })}\n >\n {showUrl ? <EyeOff className=\"h-4 w-4\" /> : <Eye className=\"h-4 w-4\" />}\n </Button>\n <Button\n size=\"sm\" variant=\"ghost\"\n onClick={() => void copyUrl()}\n aria-label={t('mobile.copyUrl', { defaultValue: 'Copy URL' })}\n >\n <Copy className=\"h-4 w-4\" />\n </Button>\n </div>\n <p className=\"mt-1 text-[11px] text-text-dim\">{t('mobile.urlHint')}</p>\n </div>\n <div>\n <Label className=\"text-xs font-medium\">{t('mobile.tokenIdLabel')}</Label>\n <div className=\"mt-1 font-mono text-xs\">{result.tokenId}</div>\n <p className=\"mt-1 text-[11px] text-text-dim\">{t('mobile.tokenIdHint')}</p>\n </div>\n </div>\n </div>\n\n <div className=\"mt-4 flex items-start gap-2 rounded-md border border-warning/40 bg-warning/5 p-3\">\n <ShieldAlert className=\"mt-0.5 h-4 w-4 shrink-0 text-warning\" />\n <div className=\"text-xs\">\n <div className=\"font-medium\">{t('mobile.warningTitle')}</div>\n <p className=\"mt-1 text-text-dim\">{t('mobile.warningBody')}</p>\n <a\n href={result.revokeHint}\n className=\"mt-1 inline-block underline text-accent\"\n >\n {t('mobile.revokeLink')}\n </a>\n </div>\n </div>\n </section>\n )}\n </div>\n )\n}\n"],"names":["Smartphone","createLucideIcon","SettingsMobileRoute","t","useTranslation","result","setResult","useState","showUrl","setShowUrl","host","setHost","generate","useMutation","api","r","toast","e","copyUrl","jsxs","jsx","Label","Input","Button","Loader2","RefreshCcw","QrCode","Badge","v","EyeOff","Eye","Copy","ShieldAlert"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"mobile-Crm0YJ36.js","sources":["../../node_modules/lucide-react/dist/esm/icons/smartphone.js","../../src/routes/settings/mobile.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 Smartphone = createLucideIcon(\"Smartphone\", [\n [\"rect\", { width: \"14\", height: \"20\", x: \"5\", y: \"2\", rx: \"2\", ry: \"2\", key: \"1yt0o3\" }],\n [\"path\", { d: \"M12 18h.01\", key: \"mhygvu\" }]\n]);\n\nexport { Smartphone as default };\n//# sourceMappingURL=smartphone.js.map\n","/**\n * /settings/mobile — admin generates a QR an operator scans on a\n * phone to land directly inside /m/chat (v1.2.129).\n *\n * Flow:\n * 1. Click \"Generate QR\" → POST /api/mobile/qr → fresh role=user\n * token + QR PNG (data URL).\n * 2. Render QR, the embedded URL, and the token id.\n * 3. Phone scans → /m/login auto-submits the token cookie → /m/chat.\n *\n * Revoke: the link points the admin at /settings/security/tokens\n * where every token can be killed (the same UI works for the QR\n * tokens because they're stored in the same table with a\n * mobile-via-qr-* label).\n */\n\nimport { useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { useMutation } from '@tanstack/react-query'\nimport { toast } from 'sonner'\nimport {\n Copy, Eye, EyeOff, Loader2, QrCode, RefreshCcw, ShieldAlert, Smartphone,\n} 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 { api } from '@/lib/api/endpoints'\nimport type { MobileQRResponse } from '@/types/api'\n\nexport default function SettingsMobileRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const [result, setResult] = useState<MobileQRResponse | null>(null)\n const [showUrl, setShowUrl] = useState(false)\n const [host, setHost] = useState('')\n\n const generate = useMutation<MobileQRResponse, Error>({\n mutationFn: () =>\n api.generateMobileQR(host.trim() ? { host: host.trim() } : undefined),\n onSuccess: (r) => {\n setResult(r)\n setShowUrl(false)\n toast.success(t('mobile.generatedToast'))\n },\n onError: (e) => toast.error(e.message),\n })\n\n async function copyUrl(): Promise<void> {\n if (!result) return\n try {\n await navigator.clipboard.writeText(result.loginUrl)\n toast.success(t('mobile.copied'))\n } catch {\n toast.error(t('mobile.copyFailed'))\n }\n }\n\n return (\n <div className=\"mx-auto flex max-w-4xl flex-col gap-6\">\n <header className=\"flex items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('mobile.title')}</h1>\n </header>\n <p className=\"text-sm text-text-dim\">{t('mobile.subtitle')}</p>\n\n <section className=\"rounded-md border border-border bg-surface p-4\">\n <div className=\"flex items-center gap-2\">\n <Smartphone className=\"h-4 w-4 text-text-dim\" />\n <h2 className=\"text-sm font-semibold\">{t('mobile.generateCard')}</h2>\n </div>\n <p className=\"mt-1 text-xs text-text-dim\">{t('mobile.generateDesc')}</p>\n\n <div className=\"mt-4 flex flex-col gap-2\">\n <Label className=\"text-xs font-medium\">{t('mobile.hostLabel')}</Label>\n <Input\n value={host}\n onChange={(e) => setHost(e.target.value)}\n placeholder={t('mobile.hostPlaceholder', { defaultValue: 'auto-detect (leave blank)' })}\n className=\"font-mono text-xs\"\n />\n <p className=\"text-[11px] text-text-dim\">{t('mobile.hostHint')}</p>\n </div>\n\n <div className=\"mt-4 flex items-center gap-2\">\n <Button\n onClick={() => generate.mutate()}\n disabled={generate.isPending}\n size=\"sm\"\n >\n {generate.isPending\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : result ? <RefreshCcw className=\"h-4 w-4\" /> : <QrCode className=\"h-4 w-4\" />}\n <span className=\"ml-1\">\n {result ? t('mobile.regenerate') : t('mobile.generate')}\n </span>\n </Button>\n {generate.isPending && (\n <Badge variant=\"info\">{t('mobile.generating')}</Badge>\n )}\n </div>\n </section>\n\n {result && (\n <section className=\"rounded-md border border-border bg-surface p-4\">\n <div className=\"flex items-center gap-2\">\n <QrCode className=\"h-4 w-4 text-text-dim\" />\n <h2 className=\"text-sm font-semibold\">{t('mobile.scanCard')}</h2>\n <Badge variant=\"success\" className=\"ml-auto\">\n {t('mobile.tokenLabel')}: <span className=\"ml-1 font-mono\">{result.label}</span>\n </Badge>\n </div>\n <p className=\"mt-1 text-xs text-text-dim\">{t('mobile.scanDesc')}</p>\n\n <div className=\"mt-4 flex flex-col items-center gap-3 sm:flex-row sm:items-start\">\n <div className=\"shrink-0 rounded-md border border-border bg-white p-2\">\n <img\n src={result.qrDataUrl}\n alt={t('mobile.qrAlt', { defaultValue: 'QR code for mobile chat' })}\n width={280}\n height={280}\n className=\"block h-[280px] w-[280px]\"\n />\n </div>\n <div className=\"flex w-full flex-col gap-3\">\n <div>\n <Label className=\"text-xs font-medium\">{t('mobile.urlLabel')}</Label>\n <div className=\"mt-1 flex items-center gap-2\">\n <Input\n type={showUrl ? 'text' : 'password'}\n readOnly\n value={result.loginUrl}\n className=\"font-mono text-[11px]\"\n />\n <Button\n size=\"sm\" variant=\"ghost\"\n onClick={() => setShowUrl((v) => !v)}\n aria-label={showUrl\n ? t('mobile.hideUrl', { defaultValue: 'Hide URL' })\n : t('mobile.showUrl', { defaultValue: 'Show URL' })}\n >\n {showUrl ? <EyeOff className=\"h-4 w-4\" /> : <Eye className=\"h-4 w-4\" />}\n </Button>\n <Button\n size=\"sm\" variant=\"ghost\"\n onClick={() => void copyUrl()}\n aria-label={t('mobile.copyUrl', { defaultValue: 'Copy URL' })}\n >\n <Copy className=\"h-4 w-4\" />\n </Button>\n </div>\n <p className=\"mt-1 text-[11px] text-text-dim\">{t('mobile.urlHint')}</p>\n </div>\n <div>\n <Label className=\"text-xs font-medium\">{t('mobile.tokenIdLabel')}</Label>\n <div className=\"mt-1 font-mono text-xs\">{result.tokenId}</div>\n <p className=\"mt-1 text-[11px] text-text-dim\">{t('mobile.tokenIdHint')}</p>\n </div>\n </div>\n </div>\n\n <div className=\"mt-4 flex items-start gap-2 rounded-md border border-warning/40 bg-warning/5 p-3\">\n <ShieldAlert className=\"mt-0.5 h-4 w-4 shrink-0 text-warning\" />\n <div className=\"text-xs\">\n <div className=\"font-medium\">{t('mobile.warningTitle')}</div>\n <p className=\"mt-1 text-text-dim\">{t('mobile.warningBody')}</p>\n <a\n href={result.revokeHint}\n className=\"mt-1 inline-block underline text-accent\"\n >\n {t('mobile.revokeLink')}\n </a>\n </div>\n </div>\n </section>\n )}\n </div>\n )\n}\n"],"names":["Smartphone","createLucideIcon","SettingsMobileRoute","t","useTranslation","result","setResult","useState","showUrl","setShowUrl","host","setHost","generate","useMutation","api","r","toast","e","copyUrl","jsxs","jsx","Label","Input","Button","Loader2","RefreshCcw","QrCode","Badge","v","EyeOff","Eye","Copy","ShieldAlert"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{o as e}from"./index-
|
|
1
|
+
import{o as e}from"./index-DvWldAJY.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-BYbGwOEp.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"network-
|
|
1
|
+
{"version":3,"file":"network-BYbGwOEp.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{o as L,b as C,d as m,a as E,e as P,u as A,f as D,j as t,B as j,R as M,L as N,S as F,g as q,h as B,i as Q,k as y,I as K,m as v,n as V,c as z}from"./index-
|
|
1
|
+
import{o as L,b as C,d as m,a as E,e as P,u as A,f as D,j as t,B as j,R as M,L as N,S as F,g as q,h as B,i as Q,k as y,I as K,m as v,n as V,c as z}from"./index-DvWldAJY.js";import{r as w}from"./react-DlP5eolq.js";import{D as J}from"./data-table-BYJ2qMyY.js";import{E as U}from"./empty-state-De5ls0uC.js";import{S as $}from"./status-badge-W8PRNBT2.js";import{C as H}from"./confirm-dialog-C2melodU.js";import{L as Y}from"./loader-circle-CZQXsfz7.js";import{R as G}from"./refresh-ccw-CW2loqyz.js";import"./table-B695Fh_p.js";import"./arrow-up-DZLw3qr1.js";import"./arrow-down-Bhl7hNwa.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 pe(){const{t:e}=A(["tasks","common"]),[a,r]=D(),n=a.get("status")??null,i=a.get("thread")??"",{data:_,isLoading:O,isFetching:f,refetch:k}=X({...n?{status:n}:{},...i?{thread:i}:{},limit:200}),I=_?.rows??[],o=Z().data,c=ee(),[d,p]=w.useState(null);function b(s){const l=new URLSearchParams(a);for(const[g,u]of Object.entries(s))u==null||u===""?l.delete(g):l.set(g,u);r(l,{replace:!0})}async function R(){if(d!=null)try{await c.mutateAsync(d),v.success(e("states.saved",{ns:"common"}))}catch(s){const{message:l}=V(s,e);throw v.error(l),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:l=>{l.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(F,{value:n??"__any__",onValueChange:s=>b({status:s==="__any__"?null:s}),children:[t.jsx(q,{id:"status-filter",className:"w-[160px]",children:t.jsx(B,{})}),t.jsxs(Q,{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(K,{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:z("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),n=r.text??r.message??r.title??r.body??null;return typeof n=="string"&&n.length>0?n: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{pe as default};
|
|
7
|
-
//# sourceMappingURL=outbox-
|
|
7
|
+
//# sourceMappingURL=outbox-D7xZ5y2T.js.map
|