@nextclaw/ui 0.19.2 → 0.19.4
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 +20 -1
- package/dist/assets/{abnfDiagram-VRR7QNED-DvTjgVMf.js → abnfDiagram-VRR7QNED-DrbfiNNF.js} +1 -1
- package/dist/assets/{aiden0z-pptx-renderer.es-C1nfBAXR.js → aiden0z-pptx-renderer.es-DdLb2IVc.js} +1 -1
- package/dist/assets/{api-BH6Oslx4.js → api-CUSlBpt_.js} +3 -3
- package/dist/assets/{appearance-settings-page-zhgfcGgW.js → appearance-settings-page-cTuZdROP.js} +1 -1
- package/dist/assets/{arc-BvhODBXv.js → arc-BXlMc9B0.js} +1 -1
- package/dist/assets/architecture-TIHT7OUA-Bq0i9WiE.js +1 -0
- package/dist/assets/{architectureDiagram-ZJ3FMSHR-BKO9RgNS.js → architectureDiagram-ZJ3FMSHR-DXAJxxO0.js} +1 -1
- package/dist/assets/{blockDiagram-677ZJIJ3-DHpDXy7D.js → blockDiagram-677ZJIJ3-i4Kz7zU0.js} +1 -1
- package/dist/assets/{book-open-DGTS6oEO.js → book-open-BJ-xAIp9.js} +1 -1
- package/dist/assets/{c4Diagram-LMCZKHZV-BG_iQnDr.js → c4Diagram-LMCZKHZV-BDc0TkPd.js} +1 -1
- package/dist/assets/channel-iCaZQ87u.js +1 -0
- package/dist/assets/{channels-list-page-3D5lhZoT.js → channels-list-page-nRHOasWA.js} +2 -2
- package/dist/assets/chunk-2Q5K7J3B-DFQtlnJS.js +1 -0
- package/dist/assets/{chunk-32BRIVSS-DR9M0LLx.js → chunk-32BRIVSS-DuReei0Z.js} +1 -1
- package/dist/assets/{chunk-52WLFC77-698iC3BB.js → chunk-52WLFC77-D8APq0tm.js} +1 -1
- package/dist/assets/{chunk-5FCAYU7R-DikTj9Ey.js → chunk-5FCAYU7R-BsPrNXNS.js} +1 -1
- package/dist/assets/{chunk-5HE753X5-ko0o7_q0.js → chunk-5HE753X5-BRtkOPoJ.js} +1 -1
- package/dist/assets/{chunk-5JV3BV7I-CEHufhgo.js → chunk-5JV3BV7I-ChPc8e8U.js} +1 -1
- package/dist/assets/{chunk-5TONJI2A-CGgno1cu.js → chunk-5TONJI2A-CzTjlJGb.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-DkiB4cUQ.js → chunk-5VM5RSS4-xsv_22jR.js} +1 -1
- package/dist/assets/{chunk-7BUUIJ7U-DzptcytQ.js → chunk-7BUUIJ7U-CwECujme.js} +1 -1
- package/dist/assets/{chunk-BIQX33UG-DMRSQJvT.js → chunk-BIQX33UG-DQAm173p.js} +1 -1
- package/dist/assets/{chunk-C7G6YPKG-Bw1BwwuY.js → chunk-C7G6YPKG-BkpajeQb.js} +1 -1
- package/dist/assets/{chunk-CQNSW5MT-C0z6eHBk.js → chunk-CQNSW5MT-ND65pWRA.js} +1 -1
- package/dist/assets/{chunk-CYSBUYHQ-ByPyAouO.js → chunk-CYSBUYHQ-vMu6ijxG.js} +1 -1
- package/dist/assets/{chunk-EMLP6XTP-CJlAXWZg.js → chunk-EMLP6XTP-CEaeW3gH.js} +1 -1
- package/dist/assets/{chunk-EX3LRPZG-Dqq4zKJu.js → chunk-EX3LRPZG-a4ER-HDr.js} +1 -1
- package/dist/assets/{chunk-FWX5IMBZ-B0SNoCmi.js → chunk-FWX5IMBZ-C_8fQssn.js} +2 -2
- package/dist/assets/{chunk-HOUHSVGY-DG_GJih_.js → chunk-HOUHSVGY-CEvw-PEd.js} +1 -1
- package/dist/assets/{chunk-ICXQ74PX-Drxk_6bE.js → chunk-ICXQ74PX-BEtF0fGY.js} +1 -1
- package/dist/assets/{chunk-JG7HCLWE-DdLFPpnd.js → chunk-JG7HCLWE-DGRrVp8-.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-B8M4G76F.js → chunk-JWPE2WC7-DRqpp_nM.js} +1 -1
- package/dist/assets/{chunk-MOJQB5TN-XP6FJHY_.js → chunk-MOJQB5TN-BDEriOXs.js} +1 -1
- package/dist/assets/{chunk-MOZMSUNE-C_6x18Qw.js → chunk-MOZMSUNE-JWRNzdnw.js} +1 -1
- package/dist/assets/{chunk-OGEWGWER-N25BzCmG.js → chunk-OGEWGWER-DS2VTgCx.js} +1 -1
- package/dist/assets/{chunk-OSBZ3O6U-ASDEm7y0.js → chunk-OSBZ3O6U-3LiYTBUB.js} +1 -1
- package/dist/assets/{chunk-PUDLZKDR-CTlvAcn7.js → chunk-PUDLZKDR-o9M2s_SO.js} +1 -1
- package/dist/assets/{chunk-Q4XR5HBZ-Da9BWfB6.js → chunk-Q4XR5HBZ-DTB7Ma2N.js} +1 -1
- package/dist/assets/{chunk-QBLGF6JB-Bi6RpTJO.js → chunk-QBLGF6JB-DpkxZJL5.js} +1 -1
- package/dist/assets/{chunk-R7FJI6CG-DkMsSPvK.js → chunk-R7FJI6CG-CRejkHJU.js} +1 -1
- package/dist/assets/{chunk-RYQCIY6F-DZp0eU-j.js → chunk-RYQCIY6F-B1boBjLt.js} +1 -1
- package/dist/assets/{chunk-U6XO7XAA-vfinDSrj.js → chunk-U6XO7XAA-DgKa97bj.js} +1 -1
- package/dist/assets/{chunk-V7JOEXUC-C9Nksccs.js → chunk-V7JOEXUC-DE56eh0N.js} +1 -1
- package/dist/assets/chunk-VAUOI2AC-CF9A-TeE.js +1 -0
- package/dist/assets/{chunk-VR4S4FIN-Xv6zfwXs.js → chunk-VR4S4FIN-BzomPZq2.js} +1 -1
- package/dist/assets/{chunk-WYO6CB5R-mOJNzbWl.js → chunk-WYO6CB5R-C6gy8rSd.js} +2 -2
- package/dist/assets/chunk-XXDRQBXY-BRxdfVCU.js +1 -0
- package/dist/assets/{chunk-YOTPTUD7-1-aKSu4o.js → chunk-YOTPTUD7-BK98yfl9.js} +1 -1
- package/dist/assets/{chunk-ZGVPDNZ5-OJ8veMpK.js → chunk-ZGVPDNZ5-DFXAhwUT.js} +1 -1
- package/dist/assets/{chunk-ZIRB5QZD-SR_Nq_PP.js → chunk-ZIRB5QZD-Bbu6BiNC.js} +1 -1
- package/dist/assets/classDiagram-OUVF2IWQ-Bo28fPi-.js +1 -0
- package/dist/assets/classDiagram-v2-EOCWNBFH-BOVN9wUz.js +1 -0
- package/dist/assets/{config-split-page-B55XD_ZY.js → config-split-page-DO1Oyb-r.js} +1 -1
- package/dist/assets/{confirm-dialog-BCCreI_f.js → confirm-dialog-CCae9Fr4.js} +1 -1
- package/dist/assets/{cose-bilkent-JH36ORCC-NjVgz2Bw.js → cose-bilkent-JH36ORCC-BV8KR4uF.js} +1 -1
- package/dist/assets/cynefin-VYW2F7L2-B7rF3JRp.js +1 -0
- package/dist/assets/{cynefinDiagram-TSTJHNR4-B_17LDqD.js → cynefinDiagram-TSTJHNR4-Ckd6nU9t.js} +1 -1
- package/dist/assets/{dagre-CMe101gk.js → dagre-D_T-FW5i.js} +1 -1
- package/dist/assets/{dagre-VKFMJZFB-qo8nLb3B.js → dagre-VKFMJZFB-CyDaQpD4.js} +1 -1
- package/dist/assets/desktop-update-config-XSV-DjJW.js +1 -0
- package/dist/assets/{diagram-FQU43EPY-Ba3XIklC.js → diagram-FQU43EPY-CghnwS0H.js} +1 -1
- package/dist/assets/{diagram-G47NLZAW-CG45TcUx.js → diagram-G47NLZAW-DK4DJ3Kx.js} +1 -1
- package/dist/assets/{diagram-NH7WQ7WH-2F2HrwV-.js → diagram-NH7WQ7WH-CUgDkZCJ.js} +1 -1
- package/dist/assets/{diagram-OA4YK3LP-CXfWH9NZ.js → diagram-OA4YK3LP-vO2gyH6n.js} +1 -1
- package/dist/assets/{diagram-WEI45ONY-CH_4yepc.js → diagram-WEI45ONY-DbSBRDSr.js} +1 -1
- package/dist/assets/{dist-IRWcJpfm.js → dist-1N9UpL3c.js} +1 -1
- package/dist/assets/{dist-BYSUQaO2.js → dist-C-2H76Cv.js} +1 -1
- package/dist/assets/doc-browser-BHFCZIoL.js +1 -0
- package/dist/assets/{doc-browser-D8rNrWHk.js → doc-browser-CRlpqMwH.js} +1 -1
- package/dist/assets/{doc-browser-context-DjTbIbQc.js → doc-browser-context-C0Bns1J6.js} +1 -1
- package/dist/assets/{docx-preview-CoM4JK7_.js → docx-preview-DfxIm9IB.js} +1 -1
- package/dist/assets/{ebnfDiagram-CCIWWBDH-BwiG4Ea1.js → ebnfDiagram-CCIWWBDH-W7CAcK7r.js} +1 -1
- package/dist/assets/{erDiagram-Q63AITRT-BML3hpnQ.js → erDiagram-Q63AITRT-LA0JWL8-.js} +1 -1
- package/dist/assets/eventmodeling-45OFAUF4-DzQLXa3s.js +1 -0
- package/dist/assets/flowDiagram-23GEKE2U-C81eexJZ.js +1 -0
- package/dist/assets/{form-actions-C8hazgNP.js → form-actions-CMxhPact.js} +1 -1
- package/dist/assets/{ganttDiagram-NO4QXBWP-80enfWbD.js → ganttDiagram-NO4QXBWP-_PiTPavJ.js} +1 -1
- package/dist/assets/gitGraph-TEB2WS4Q-Dt3ZqpFD.js +1 -0
- package/dist/assets/{gitGraphDiagram-IHSO6WYX-CVLqXr-b.js → gitGraphDiagram-IHSO6WYX-DsRB1ZMU.js} +1 -1
- package/dist/assets/index-DdYOaKm7.js +109 -0
- package/dist/assets/index-DxCGKhAw.css +1 -0
- package/dist/assets/info-DKCQHKI2-CCCE7dXC.js +1 -0
- package/dist/assets/{infoDiagram-FWYZ7A6U-Dyvs2t0i.js → infoDiagram-FWYZ7A6U-wIRraYx5.js} +1 -1
- package/dist/assets/{ishikawaDiagram-FXEZZL3T-sSnxDKfh.js → ishikawaDiagram-FXEZZL3T-CNzsrcrh.js} +1 -1
- package/dist/assets/{journeyDiagram-5HDEW3XC-D22V71Mf.js → journeyDiagram-5HDEW3XC-Dy9huHxy.js} +1 -1
- package/dist/assets/{kanban-definition-HUTT4EX6-D3ds0p-g.js → kanban-definition-HUTT4EX6-BOCIN365.js} +1 -1
- package/dist/assets/{line-CbyFs065.js → line-BxsizOTs.js} +1 -1
- package/dist/assets/{linear-4DKtnZBS.js → linear-C_YHf92I.js} +1 -1
- package/dist/assets/loader-circle-B-UdXjl4.js +1 -0
- package/dist/assets/{map-CcZzEoz6.js → map-CobcjgZ8.js} +1 -1
- package/dist/assets/mcp-marketplace-page-BUIGtSda.js +1 -0
- package/dist/assets/mcp-marketplace-page-CStb8ml2.js +9 -0
- package/dist/assets/{mermaid-parser.core-DPmMOjXD.js → mermaid-parser.core-D7lu2RbA.js} +2 -2
- package/dist/assets/{mermaid.core-BSf-ddRa.js → mermaid.core-CbfW2Rk8.js} +3 -3
- package/dist/assets/{mindmap-definition-LN4V7U3C-BUTwWPyx.js → mindmap-definition-LN4V7U3C-DUjGXlIC.js} +1 -1
- package/dist/assets/model-config-page-BkfUYm95.js +1 -0
- package/dist/assets/{navigation-link-kGAcL2N2.js → navigation-link-v3FaWcIr.js} +1 -1
- package/dist/assets/{ordinal-BgLYtOZE.js → ordinal-CjoUCHto.js} +1 -1
- package/dist/assets/packet-7NZHBO7P-D19yoxFV.js +1 -0
- package/dist/assets/{pegDiagram-2B236MQR-BEu_ZBjc.js → pegDiagram-2B236MQR-BQY2DgiP.js} +1 -1
- package/dist/assets/pie-RZYD4A2V-hMaJbLrn.js +1 -0
- package/dist/assets/{pieDiagram-ENE6RG2P-CAwAwuBd.js → pieDiagram-ENE6RG2P-D18owe4D.js} +1 -1
- package/dist/assets/plus-Dw9QFnKr.js +1 -0
- package/dist/assets/{privacy-settings-page-v9LTFvJe.js → privacy-settings-page-CYM1Dxwo.js} +1 -1
- package/dist/assets/providers-config-page-fxL4I4bz.js +1 -0
- package/dist/assets/{quadrantDiagram-ABIIQ3AL-CwE6F-_2.js → quadrantDiagram-ABIIQ3AL-B8F7YoTA.js} +1 -1
- package/dist/assets/radar-I7S5WNFK-C8BkvScA.js +1 -0
- package/dist/assets/railroad-3IZDKUUU-CozZOitC.js +1 -0
- package/dist/assets/railroad-abnf-AHOZXSZD-BqIoFXFi.js +1 -0
- package/dist/assets/railroad-ebnf-EBAXGLYW-CD2e3dng.js +1 -0
- package/dist/assets/railroad-peg-LSFZ7HO6-DoKlRUOF.js +1 -0
- package/dist/assets/{railroadDiagram-RFXS5EU6-xgLekU3B.js → railroadDiagram-RFXS5EU6-RU8GpxN5.js} +1 -1
- package/dist/assets/{react-Dwvp5yeX.js → react-Dlz_IxoP.js} +1 -1
- package/dist/assets/{refresh-cw-C_oj_h_s.js → refresh-cw-CK4I5UFv.js} +1 -1
- package/dist/assets/remote-B0pPgtC6.js +1 -0
- package/dist/assets/{requirementDiagram-TGXJPOKE-CyVUzEX5.js → requirementDiagram-TGXJPOKE-ubPOmmNi.js} +1 -1
- package/dist/assets/rotate-cw-Z48dmh13.js +1 -0
- package/dist/assets/runtime-config-page-C7vksFVD.js +1 -0
- package/dist/assets/{sankeyDiagram-HTMAVEWB-JK6bFmYB.js → sankeyDiagram-HTMAVEWB-8L_hXJWW.js} +1 -1
- package/dist/assets/{save-BZE6H02N.js → save-Bo37cIFb.js} +1 -1
- package/dist/assets/{search-C7Tj40kC.js → search-CZiEm7YD.js} +1 -1
- package/dist/assets/search-config-page-DKdEf7m9.js +1 -0
- package/dist/assets/{secrets-config-page-B__VLAEQ.js → secrets-config-page-COlMqSfL.js} +2 -2
- package/dist/assets/security-config-CitLihXA.js +1 -0
- package/dist/assets/{select-fZ5tifar.js → select-BACzapV3.js} +1 -1
- package/dist/assets/{sequenceDiagram-DBY2YBRQ-BR5IokXV.js → sequenceDiagram-DBY2YBRQ-Dom6Qor5.js} +1 -1
- package/dist/assets/{sizeCapture-X5ZJPWSS-SxG_YnMA.js → sizeCapture-X5ZJPWSS-cZcFSpLJ.js} +1 -1
- package/dist/assets/skeleton-B2PCAZJG.js +1 -0
- package/dist/assets/{src-vgz8E_-O.js → src-BE9E1xcR.js} +1 -1
- package/dist/assets/{stateDiagram-2N3HPSRC-DD4OoYhn.js → stateDiagram-2N3HPSRC-CHrpxmGO.js} +1 -1
- package/dist/assets/stateDiagram-v2-6OUMAXLB-b1pZQlDD.js +1 -0
- package/dist/assets/{swimlanes-5IMT3BWC-BWkFeyCT.js → swimlanes-5IMT3BWC-D6nJS2xQ.js} +2 -2
- package/dist/assets/swimlanesDiagram-G3AALYLV-CowxgWVn.js +8 -0
- package/dist/assets/{tag-chip-CwYZcRoe.js → tag-chip-BnamTQVX.js} +1 -1
- package/dist/assets/{timeline-definition-FHXFAJF6-VTRPy6KA.js → timeline-definition-FHXFAJF6-DJNn-HQO.js} +1 -1
- package/dist/assets/treeView-QDETBFTQ-BQlYkJbz.js +1 -0
- package/dist/assets/treemap-6X3UGDF4-DzTOd1bd.js +1 -0
- package/dist/assets/{vennDiagram-L72KCM5P-Bvk42Pek.js → vennDiagram-L72KCM5P-CCEzHoXt.js} +1 -1
- package/dist/assets/wardley-OPB4EBWU-D80jQc0y.js +1 -0
- package/dist/assets/{wardleyDiagram-EHGQE667-DOFjx2s3.js → wardleyDiagram-EHGQE667-BhyVxVXt.js} +1 -1
- package/dist/assets/x-BzYEzkLA.js +1 -0
- package/dist/assets/{xychartDiagram-FW5EYKEG-DY5yRTUc.js → xychartDiagram-FW5EYKEG-CacW_246.js} +1 -1
- package/dist/index.html +70 -22
- package/index.html +49 -1
- package/package.json +8 -8
- package/src/app/index.tsx +1 -3
- package/src/app/managers/__tests__/viewport-layout.manager.test.ts +12 -0
- package/src/app/managers/viewport-layout.manager.ts +12 -0
- package/src/app/stores/viewport-layout.store.ts +23 -11
- package/src/features/apps/components/__tests__/app-marketplace-catalog.test.tsx +161 -0
- package/src/features/apps/components/app-marketplace-catalog.tsx +36 -7
- package/src/features/apps/components/app-marketplace-detail.tsx +29 -6
- package/src/features/apps/components/app-marketplace-dialog.tsx +71 -55
- package/src/features/apps/components/app-marketplace-operation.tsx +128 -16
- package/src/features/apps/components/app-packages-panel.tsx +1 -0
- package/src/features/apps/utils/app-marketplace-platform.utils.test.ts +59 -0
- package/src/features/apps/utils/app-marketplace-platform.utils.ts +33 -0
- package/src/features/chat/features/conversation/components/__tests__/session-conversation-area.test.tsx +6 -0
- package/src/features/chat/features/conversation/components/__tests__/session-conversation-input.streaming.test.tsx +6 -2
- package/src/features/chat/features/conversation/components/__tests__/session-queued-input-rows.test.tsx +46 -0
- package/src/features/chat/features/conversation/components/session-conversation-area.tsx +15 -2
- package/src/features/chat/features/conversation/components/session-conversation-input.tsx +5 -3
- package/src/features/chat/features/conversation/components/session-queued-input-rows.tsx +59 -5
- package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-controller.test.tsx +35 -1
- package/src/features/chat/features/conversation/hooks/__tests__/use-session-run-queue.test.tsx +25 -19
- package/src/features/chat/features/conversation/hooks/use-session-conversation-controller.ts +148 -134
- package/src/features/chat/features/conversation/hooks/use-session-pending-input-actions.ts +135 -0
- package/src/features/chat/features/conversation/hooks/use-session-run-queue.ts +19 -4
- package/src/features/chat/features/conversation/utils/__tests__/session-queued-input.utils.test.ts +52 -2
- package/src/features/chat/features/conversation/utils/session-queued-input.utils.ts +46 -5
- package/src/features/chat/features/message/utils/chat-message-texts.utils.ts +1 -0
- package/src/features/chat/features/ncp/hooks/__tests__/use-hydrated-ncp-agent.test.tsx +102 -0
- package/src/features/chat/features/ncp/hooks/__tests__/use-ncp-session-conversation.test.tsx +117 -1
- package/src/features/chat/features/ncp/hooks/use-ncp-session-conversation.ts +2 -2
- package/src/features/chat/features/ncp/hooks/use-ncp-session-message-history.ts +31 -81
- package/src/features/chat/features/ncp/hooks/use-ncp-session-seed-loader.ts +134 -0
- package/src/features/chat/features/session/utils/ncp-session-adapter.utils.ts +1 -6
- package/src/features/panel-apps/components/__tests__/panel-app-list-item.test.tsx +8 -0
- package/src/features/panel-apps/components/__tests__/panel-app-main-sidebar-nav.test.tsx +99 -13
- package/src/features/panel-apps/components/panel-app-main-sidebar-menu-item.tsx +4 -0
- package/src/features/panel-apps/components/panel-app-main-sidebar-nav.tsx +166 -31
- package/src/shared/lib/api/utils/ncp-attachments.utils.ts +8 -1
- package/src/shared/lib/api/utils/ncp-session.utils.ts +1 -0
- package/src/shared/lib/i18n/locales/en-US/chat.json +3 -0
- package/src/shared/lib/i18n/locales/en-US/doc-browser.json +11 -1
- package/src/shared/lib/i18n/locales/zh-CN/chat.json +3 -0
- package/src/shared/lib/i18n/locales/zh-CN/doc-browser.json +11 -1
- package/src/vite-env.d.ts +9 -0
- package/dist/assets/architecture-TIHT7OUA-Bjp9jf0h.js +0 -1
- package/dist/assets/channel-5T3pdR-s.js +0 -1
- package/dist/assets/chat-page-BXu3hnOK.js +0 -1
- package/dist/assets/chunk-2Q5K7J3B-DTZ3tGfE.js +0 -1
- package/dist/assets/chunk-VAUOI2AC-HLGIHQ6k.js +0 -1
- package/dist/assets/chunk-XXDRQBXY-Dl0m6Ni-.js +0 -1
- package/dist/assets/classDiagram-OUVF2IWQ-DcDnzGNX.js +0 -1
- package/dist/assets/classDiagram-v2-EOCWNBFH-BKXKMzKM.js +0 -1
- package/dist/assets/cynefin-VYW2F7L2-BWg7U2UD.js +0 -1
- package/dist/assets/desktop-update-config-Blol-Umu.js +0 -1
- package/dist/assets/doc-browser-BExPq1Hk.js +0 -1
- package/dist/assets/eventmodeling-45OFAUF4-SB-J4tpq.js +0 -1
- package/dist/assets/flowDiagram-23GEKE2U-BQ_u-eLM.js +0 -1
- package/dist/assets/gitGraph-TEB2WS4Q-DPxNwsFd.js +0 -1
- package/dist/assets/index-Btj8yN4T.css +0 -1
- package/dist/assets/index-CHcGqqBe.js +0 -109
- package/dist/assets/info-DKCQHKI2-DNlNGH90.js +0 -1
- package/dist/assets/loader-circle-C75DUmmm.js +0 -1
- package/dist/assets/mcp-marketplace-page-CIMRYgOY.js +0 -9
- package/dist/assets/mcp-marketplace-page-D2NlhG1k.js +0 -1
- package/dist/assets/model-config-page-ChR-ENjp.js +0 -1
- package/dist/assets/packet-7NZHBO7P-BpeiqkBZ.js +0 -1
- package/dist/assets/pie-RZYD4A2V-Cy1yxsPd.js +0 -1
- package/dist/assets/plus-TzSIMKWW.js +0 -1
- package/dist/assets/provider-scoped-model-input-DiSpKSk0.js +0 -1
- package/dist/assets/providers-config-page-BvXa03cp.js +0 -1
- package/dist/assets/radar-I7S5WNFK-CEcPKCj8.js +0 -1
- package/dist/assets/railroad-3IZDKUUU-CW38eNDs.js +0 -1
- package/dist/assets/railroad-abnf-AHOZXSZD-ByrylcXf.js +0 -1
- package/dist/assets/railroad-ebnf-EBAXGLYW-CNB6GwP-.js +0 -1
- package/dist/assets/railroad-peg-LSFZ7HO6-x6hnqlBG.js +0 -1
- package/dist/assets/remote-BgYduCQR.js +0 -1
- package/dist/assets/rotate-cw-BT8HxlcB.js +0 -1
- package/dist/assets/runtime-config-page-BuYof2Ty.js +0 -1
- package/dist/assets/search-config-page-CQTJOsOf.js +0 -1
- package/dist/assets/security-config-CtJqaPVL.js +0 -1
- package/dist/assets/settings-2-BHGgNlOH.js +0 -1
- package/dist/assets/skeleton-CJLc1CWn.js +0 -1
- package/dist/assets/stateDiagram-v2-6OUMAXLB-ZC6dFORv.js +0 -1
- package/dist/assets/swimlanesDiagram-G3AALYLV-CRkh51Im.js +0 -8
- package/dist/assets/treeView-QDETBFTQ-Bw0DSCH7.js +0 -1
- package/dist/assets/treemap-6X3UGDF4-DFWBFcfh.js +0 -1
- package/dist/assets/wardley-OPB4EBWU-CoWturk0.js +0 -1
- package/dist/assets/x-BMl7cucN.js +0 -1
- /package/dist/assets/{array-NADKd9aU.js → array-COEOjKUv.js} +0 -0
- /package/dist/assets/{chunk-KEIR6QF5-BuyuzJJL.js → chunk-KEIR6QF5-D7oHAcry.js} +0 -0
- /package/dist/assets/{chunk-Y2CYZVJY-D_B2ZRNt.js → chunk-Y2CYZVJY-08IUpgTP.js} +0 -0
- /package/dist/assets/{config-hints-BcfVUMij.js → config-hints-BoE41XDI.js} +0 -0
- /package/dist/assets/{cytoscape.esm-BANTlgza.js → cytoscape.esm-HifWufkp.js} +0 -0
- /package/dist/assets/{defaultLocale-C4_L0aEs.js → defaultLocale-CA-_SsC1.js} +0 -0
- /package/dist/assets/{dist-DAPEIJbz.js → dist-C60rvfy8.js} +0 -0
- /package/dist/assets/{graphlib-ChqXg0dI.js → graphlib-CGYCNsoJ.js} +0 -0
- /package/dist/assets/{host-capabilities-D9C4CBK5.js → host-capabilities-DPNRAjIj.js} +0 -0
- /package/dist/assets/{init-D8wZg9xq.js → init-C3plFVsG.js} +0 -0
- /package/dist/assets/{jszip.min-CkbBfwAQ.js → jszip.min-CeYs17Gn.js} +0 -0
- /package/dist/assets/{katex-TZJFa0J_.js → katex-DRThweSG.js} +0 -0
- /package/dist/assets/{middleware-B3k-TSmZ.js → middleware-D05fK5Sb.js} +0 -0
- /package/dist/assets/{path-DodfxcX7.js → path-BKtKxQ6Y.js} +0 -0
- /package/dist/assets/{rough.esm-CUaa1Rbe.js → rough.esm-DurL7-u7.js} +0 -0
- /package/dist/assets/{xlsx-CxByi7bR.js → xlsx-Sg8fZ6nH.js} +0 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { fireEvent, render, screen } from '@testing-library/react';
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { AppMarketplaceCatalog } from '@/features/apps/components/app-marketplace-catalog';
|
|
4
|
+
import type { AppMarketplaceItemView } from '@/features/apps/types/app-marketplace.types';
|
|
5
|
+
import { Dialog } from '@/shared/components/ui/dialog';
|
|
6
|
+
import { TooltipProvider } from '@/shared/components/ui/tooltip';
|
|
7
|
+
import { setLanguage } from '@/shared/lib/i18n';
|
|
8
|
+
|
|
9
|
+
const LINUX_ONLY_APP: AppMarketplaceItemView = {
|
|
10
|
+
id: 'rust-todo',
|
|
11
|
+
slug: 'rust-todo',
|
|
12
|
+
appId: 'peiiii.rust-todo',
|
|
13
|
+
name: 'Rust Todo',
|
|
14
|
+
summary: '轻量待办应用',
|
|
15
|
+
summaryI18n: {},
|
|
16
|
+
tags: ['todo'],
|
|
17
|
+
latestVersion: '0.1.0',
|
|
18
|
+
featured: false,
|
|
19
|
+
availability: {
|
|
20
|
+
mode: 'targeted',
|
|
21
|
+
targets: ['linux-x64-gnu'],
|
|
22
|
+
operatingSystems: ['linux'],
|
|
23
|
+
},
|
|
24
|
+
publisher: { id: 'peiiii', name: 'peiiii' },
|
|
25
|
+
install: {
|
|
26
|
+
kind: 'registry',
|
|
27
|
+
spec: 'peiiii.rust-todo',
|
|
28
|
+
registry: 'https://apps-registry.nextclaw.io',
|
|
29
|
+
},
|
|
30
|
+
webUrl: 'https://nextclaw.io/apps/rust-todo',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
describe('AppMarketplaceCatalog compatibility actions', () => {
|
|
34
|
+
it('keeps an incompatible app discoverable but disables installation and hides stale failures', () => {
|
|
35
|
+
setLanguage('zh');
|
|
36
|
+
const onInstall = vi.fn();
|
|
37
|
+
const onSelect = vi.fn();
|
|
38
|
+
|
|
39
|
+
render(
|
|
40
|
+
<TooltipProvider>
|
|
41
|
+
<Dialog>
|
|
42
|
+
<AppMarketplaceCatalog
|
|
43
|
+
error={null}
|
|
44
|
+
filter="all"
|
|
45
|
+
hostTarget={{
|
|
46
|
+
key: 'darwin-arm64',
|
|
47
|
+
operatingSystem: 'darwin',
|
|
48
|
+
architecture: 'arm64',
|
|
49
|
+
}}
|
|
50
|
+
installedById={new Map()}
|
|
51
|
+
isError={false}
|
|
52
|
+
isFetchingNextPage={false}
|
|
53
|
+
isLoading={false}
|
|
54
|
+
isStarting={false}
|
|
55
|
+
items={[LINUX_ONLY_APP]}
|
|
56
|
+
localeFallbacks={['zh-CN']}
|
|
57
|
+
onFilterChange={vi.fn()}
|
|
58
|
+
onInstall={onInstall}
|
|
59
|
+
onLoadMore={vi.fn()}
|
|
60
|
+
onSearchChange={vi.fn()}
|
|
61
|
+
onSelect={onSelect}
|
|
62
|
+
onUpdate={vi.fn()}
|
|
63
|
+
operations={[{
|
|
64
|
+
id: 'failed-install',
|
|
65
|
+
action: 'install',
|
|
66
|
+
appId: 'peiiii.rust-todo',
|
|
67
|
+
source: 'peiiii.rust-todo',
|
|
68
|
+
status: 'failed',
|
|
69
|
+
completedSteps: 0,
|
|
70
|
+
totalSteps: 1,
|
|
71
|
+
createdAt: '2026-08-20T00:00:00.000Z',
|
|
72
|
+
updatedAt: '2026-08-20T00:00:00.000Z',
|
|
73
|
+
error: 'raw registry failure',
|
|
74
|
+
}]}
|
|
75
|
+
hasNextPage={false}
|
|
76
|
+
search=""
|
|
77
|
+
/>
|
|
78
|
+
</Dialog>
|
|
79
|
+
</TooltipProvider>,
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
expect(screen.getByText('仅支持 Linux')).toBeTruthy();
|
|
83
|
+
expect(screen.getByText('这台设备无法安装')).toBeTruthy();
|
|
84
|
+
const installButton = screen.getByRole('button', { name: '无法安装' });
|
|
85
|
+
expect((installButton as HTMLButtonElement).disabled).toBe(true);
|
|
86
|
+
expect(screen.queryByText('raw registry failure')).toBeNull();
|
|
87
|
+
|
|
88
|
+
fireEvent.click(installButton);
|
|
89
|
+
expect(onInstall).not.toHaveBeenCalled();
|
|
90
|
+
|
|
91
|
+
fireEvent.click(screen.getAllByRole('button', { name: /Rust Todo/ })[0]);
|
|
92
|
+
expect(onSelect).toHaveBeenCalledWith('rust-todo');
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('does not project a persisted terminal failure back into a compatible card', () => {
|
|
96
|
+
setLanguage('zh');
|
|
97
|
+
const onInstall = vi.fn();
|
|
98
|
+
|
|
99
|
+
render(
|
|
100
|
+
<TooltipProvider>
|
|
101
|
+
<Dialog>
|
|
102
|
+
<AppMarketplaceCatalog
|
|
103
|
+
error={null}
|
|
104
|
+
filter="all"
|
|
105
|
+
hostTarget={{
|
|
106
|
+
key: 'darwin-arm64',
|
|
107
|
+
operatingSystem: 'darwin',
|
|
108
|
+
architecture: 'arm64',
|
|
109
|
+
}}
|
|
110
|
+
installedById={new Map()}
|
|
111
|
+
isError={false}
|
|
112
|
+
isFetchingNextPage={false}
|
|
113
|
+
isLoading={false}
|
|
114
|
+
isStarting={false}
|
|
115
|
+
items={[{
|
|
116
|
+
...LINUX_ONLY_APP,
|
|
117
|
+
availability: {
|
|
118
|
+
mode: 'universal',
|
|
119
|
+
targets: [],
|
|
120
|
+
operatingSystems: [],
|
|
121
|
+
},
|
|
122
|
+
}]}
|
|
123
|
+
localeFallbacks={['zh-CN']}
|
|
124
|
+
onFilterChange={vi.fn()}
|
|
125
|
+
onInstall={onInstall}
|
|
126
|
+
onLoadMore={vi.fn()}
|
|
127
|
+
onSearchChange={vi.fn()}
|
|
128
|
+
onSelect={vi.fn()}
|
|
129
|
+
onUpdate={vi.fn()}
|
|
130
|
+
operations={[{
|
|
131
|
+
id: 'persisted-failure',
|
|
132
|
+
action: 'install',
|
|
133
|
+
appId: 'peiiii.rust-todo',
|
|
134
|
+
source: 'peiiii.rust-todo',
|
|
135
|
+
status: 'failed',
|
|
136
|
+
completedSteps: 0,
|
|
137
|
+
totalSteps: 1,
|
|
138
|
+
createdAt: '2026-08-19T00:00:00.000Z',
|
|
139
|
+
updatedAt: '2026-08-19T00:00:01.000Z',
|
|
140
|
+
completedAt: '2026-08-19T00:00:01.000Z',
|
|
141
|
+
error: 'persisted registry failure',
|
|
142
|
+
}]}
|
|
143
|
+
hasNextPage={false}
|
|
144
|
+
search=""
|
|
145
|
+
/>
|
|
146
|
+
</Dialog>
|
|
147
|
+
</TooltipProvider>,
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
expect(screen.queryByText('persisted registry failure')).toBeNull();
|
|
151
|
+
expect(screen.queryByRole('button', { name: '重试' })).toBeNull();
|
|
152
|
+
const installButton = screen.getByRole('button', { name: '安装应用' });
|
|
153
|
+
expect((installButton as HTMLButtonElement).disabled).toBe(false);
|
|
154
|
+
|
|
155
|
+
fireEvent.click(installButton);
|
|
156
|
+
expect(onInstall).toHaveBeenCalledWith(
|
|
157
|
+
'peiiii.rust-todo',
|
|
158
|
+
'https://apps-registry.nextclaw.io',
|
|
159
|
+
);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
-
import type { AppPackageOperationView, AppPackageView } from '@nextclaw/client-sdk';
|
|
1
|
+
import type { AppPackageHostTarget, AppPackageOperationView, AppPackageView } from '@nextclaw/client-sdk';
|
|
2
2
|
import { ChevronRight, Search, Sparkles } from 'lucide-react';
|
|
3
3
|
import { AppArtwork } from '@/features/apps/components/app-artwork';
|
|
4
4
|
import { AppMarketplaceCover } from '@/features/apps/components/app-marketplace-cover';
|
|
5
5
|
import {
|
|
6
6
|
findLatestAppPackageOperation,
|
|
7
|
+
MarketplaceCompatibilityBadge,
|
|
8
|
+
MarketplaceCompatibilityStatus,
|
|
7
9
|
MarketplaceInstallButton,
|
|
8
10
|
OperationProgress,
|
|
11
|
+
readMarketplaceCompatibilityPresentation,
|
|
9
12
|
} from '@/features/apps/components/app-marketplace-operation';
|
|
10
13
|
import { isAppPackageOperationActive } from '@/features/apps/hooks/use-app-packages';
|
|
11
14
|
import type { AppMarketplaceItemView } from '@/features/apps/types/app-marketplace.types';
|
|
12
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
formatAppMarketplacePlatforms,
|
|
17
|
+
resolveAppMarketplaceInstallability,
|
|
18
|
+
} from '@/features/apps/utils/app-marketplace-platform.utils';
|
|
13
19
|
import { pickLocalizedText } from '@/features/marketplace';
|
|
14
20
|
import {
|
|
15
21
|
DialogDescription,
|
|
@@ -26,6 +32,7 @@ export type MarketplaceFilter = 'all' | 'featured' | 'personal' | 'local';
|
|
|
26
32
|
export function AppMarketplaceCatalog({
|
|
27
33
|
error,
|
|
28
34
|
filter,
|
|
35
|
+
hostTarget,
|
|
29
36
|
installedById,
|
|
30
37
|
isError,
|
|
31
38
|
isFetchingNextPage,
|
|
@@ -46,6 +53,7 @@ export function AppMarketplaceCatalog({
|
|
|
46
53
|
}: {
|
|
47
54
|
error: Error | null;
|
|
48
55
|
filter: MarketplaceFilter;
|
|
56
|
+
hostTarget?: AppPackageHostTarget;
|
|
49
57
|
installedById: Map<string, AppPackageView>;
|
|
50
58
|
isError: boolean;
|
|
51
59
|
isFetchingNextPage: boolean;
|
|
@@ -80,6 +88,7 @@ export function AppMarketplaceCatalog({
|
|
|
80
88
|
) : null}
|
|
81
89
|
<MarketplaceCatalogContent
|
|
82
90
|
installedById={installedById}
|
|
91
|
+
hostTarget={hostTarget}
|
|
83
92
|
isError={isError}
|
|
84
93
|
isFetchingNextPage={isFetchingNextPage}
|
|
85
94
|
isLoading={isLoading}
|
|
@@ -158,6 +167,7 @@ function MarketplaceCatalogHeader({
|
|
|
158
167
|
|
|
159
168
|
function MarketplaceCatalogContent({
|
|
160
169
|
installedById,
|
|
170
|
+
hostTarget,
|
|
161
171
|
isError,
|
|
162
172
|
isFetchingNextPage,
|
|
163
173
|
isLoading,
|
|
@@ -173,6 +183,7 @@ function MarketplaceCatalogContent({
|
|
|
173
183
|
startingSource,
|
|
174
184
|
}: {
|
|
175
185
|
installedById: Map<string, AppPackageView>;
|
|
186
|
+
hostTarget?: AppPackageHostTarget;
|
|
176
187
|
isError: boolean;
|
|
177
188
|
isFetchingNextPage: boolean;
|
|
178
189
|
isLoading: boolean;
|
|
@@ -221,6 +232,7 @@ function MarketplaceCatalogContent({
|
|
|
221
232
|
<MarketplaceCatalogCard
|
|
222
233
|
key={item.id}
|
|
223
234
|
installedPackage={installedById.get(item.appId)}
|
|
235
|
+
hostTarget={hostTarget}
|
|
224
236
|
isStarting={isStarting && startingSource === item.install.spec}
|
|
225
237
|
item={item}
|
|
226
238
|
localeFallbacks={localeFallbacks}
|
|
@@ -249,6 +261,7 @@ function MarketplaceCatalogContent({
|
|
|
249
261
|
|
|
250
262
|
function MarketplaceCatalogCard({
|
|
251
263
|
installedPackage,
|
|
264
|
+
hostTarget,
|
|
252
265
|
isStarting,
|
|
253
266
|
item,
|
|
254
267
|
localeFallbacks,
|
|
@@ -258,6 +271,7 @@ function MarketplaceCatalogCard({
|
|
|
258
271
|
operation,
|
|
259
272
|
}: {
|
|
260
273
|
installedPackage?: AppPackageView;
|
|
274
|
+
hostTarget?: AppPackageHostTarget;
|
|
261
275
|
isStarting: boolean;
|
|
262
276
|
item: AppMarketplaceItemView;
|
|
263
277
|
localeFallbacks: string[];
|
|
@@ -271,10 +285,18 @@ function MarketplaceCatalogCard({
|
|
|
271
285
|
: item.name;
|
|
272
286
|
const summary = pickLocalizedText(item.summaryI18n, item.summary, localeFallbacks);
|
|
273
287
|
const active = operation ? isAppPackageOperationActive(operation.status) : false;
|
|
274
|
-
const failed = operation?.status === 'failed' || operation?.status === 'interrupted';
|
|
275
288
|
const canUpdate = Boolean(
|
|
276
289
|
installedPackage && installedPackage.activeVersion !== item.latestVersion,
|
|
277
290
|
);
|
|
291
|
+
const supportedPlatforms = formatAppMarketplacePlatforms(
|
|
292
|
+
item.availability,
|
|
293
|
+
t('appPackagesAllPlatforms'),
|
|
294
|
+
);
|
|
295
|
+
const compatibility = readMarketplaceCompatibilityPresentation(
|
|
296
|
+
resolveAppMarketplaceInstallability(item.availability, hostTarget),
|
|
297
|
+
supportedPlatforms,
|
|
298
|
+
);
|
|
299
|
+
const blockAction = Boolean(compatibility && (!installedPackage || canUpdate));
|
|
278
300
|
return (
|
|
279
301
|
<article className="group relative overflow-hidden rounded-2xl border border-border/60 bg-card shadow-sm transition duration-200 hover:-translate-y-0.5 hover:border-border hover:shadow-lg">
|
|
280
302
|
<button
|
|
@@ -296,32 +318,39 @@ function MarketplaceCatalogCard({
|
|
|
296
318
|
<span className="truncate text-sm font-semibold text-foreground">{displayName}</span>
|
|
297
319
|
{item.featured ? <Sparkles className="h-3.5 w-3.5 shrink-0 text-amber-500" aria-label={t('appPackagesMarketplaceFeatured')} /> : null}
|
|
298
320
|
</span>
|
|
321
|
+
<MarketplaceCompatibilityBadge presentation={compatibility} />
|
|
299
322
|
<span className="mt-1 line-clamp-2 block min-h-10 text-xs leading-5 text-muted-foreground">{summary}</span>
|
|
300
323
|
<span className="mt-2 flex items-center gap-1.5 text-[11px] text-muted-foreground/75">
|
|
301
324
|
<span>{item.publisher.name}</span>
|
|
302
325
|
<span aria-hidden="true">·</span>
|
|
303
326
|
<span>v{item.latestVersion}</span>
|
|
304
327
|
<span aria-hidden="true">·</span>
|
|
305
|
-
<span>{
|
|
328
|
+
<span>{supportedPlatforms}</span>
|
|
306
329
|
<ChevronRight className="ml-0.5 h-3 w-3 opacity-0 transition-opacity group-hover:opacity-60" />
|
|
307
330
|
</span>
|
|
308
331
|
</button>
|
|
309
332
|
</div>
|
|
310
|
-
<div className="mt-3 flex items-center justify-
|
|
333
|
+
<div className="mt-3 flex items-center justify-between gap-3 border-t border-border/50 pt-3">
|
|
334
|
+
<MarketplaceCompatibilityStatus
|
|
335
|
+
blocked={blockAction}
|
|
336
|
+
presentation={compatibility}
|
|
337
|
+
className="min-w-0 text-[11px] font-medium text-muted-foreground"
|
|
338
|
+
/>
|
|
311
339
|
<MarketplaceInstallButton
|
|
312
340
|
active={active}
|
|
313
341
|
canUpdate={canUpdate}
|
|
314
|
-
failed={failed}
|
|
315
342
|
installed={Boolean(installedPackage)}
|
|
316
343
|
isStarting={isStarting}
|
|
317
344
|
onAction={() => canUpdate
|
|
318
345
|
? onUpdate(item.appId)
|
|
319
346
|
: onInstall(item.install.spec, item.install.registry)}
|
|
320
347
|
operation={operation}
|
|
348
|
+
unavailableLabel={blockAction ? compatibility?.actionLabel : undefined}
|
|
349
|
+
unavailableReason={blockAction ? compatibility?.reason : undefined}
|
|
321
350
|
/>
|
|
322
351
|
</div>
|
|
323
352
|
</div>
|
|
324
|
-
{operation &&
|
|
353
|
+
{operation && !blockAction && active ? <div className="px-4 pb-4"><OperationProgress operation={operation} /></div> : null}
|
|
325
354
|
</article>
|
|
326
355
|
);
|
|
327
356
|
}
|
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
import type { AppPackageOperationView, AppPackageView } from '@nextclaw/client-sdk';
|
|
1
|
+
import type { AppPackageHostTarget, AppPackageOperationView, AppPackageView } from '@nextclaw/client-sdk';
|
|
2
2
|
import { ExternalLink, FileText, Monitor, Server, ShieldAlert, ShieldCheck, type LucideIcon } from 'lucide-react';
|
|
3
3
|
import { AppArtwork } from '@/features/apps/components/app-artwork';
|
|
4
4
|
import { AppMarketplaceCover } from '@/features/apps/components/app-marketplace-cover';
|
|
5
5
|
import {
|
|
6
|
+
MarketplaceCompatibilityBadge,
|
|
7
|
+
MarketplaceCompatibilityStatus,
|
|
6
8
|
MarketplaceInstallButton,
|
|
7
9
|
OperationProgress,
|
|
10
|
+
readMarketplaceCompatibilityPresentation,
|
|
8
11
|
} from '@/features/apps/components/app-marketplace-operation';
|
|
9
12
|
import { isAppPackageOperationActive } from '@/features/apps/hooks/use-app-packages';
|
|
10
13
|
import type { AppMarketplaceDetailView } from '@/features/apps/types/app-marketplace.types';
|
|
11
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
formatAppMarketplacePlatforms,
|
|
16
|
+
resolveAppMarketplaceInstallability,
|
|
17
|
+
} from '@/features/apps/utils/app-marketplace-platform.utils';
|
|
12
18
|
import { pickLocalizedText } from '@/features/marketplace';
|
|
13
19
|
import { Skeleton } from '@/shared/components/ui/skeleton';
|
|
14
20
|
import { t } from '@/shared/lib/i18n';
|
|
@@ -16,6 +22,7 @@ import { t } from '@/shared/lib/i18n';
|
|
|
16
22
|
export function MarketplaceDetail({
|
|
17
23
|
detail,
|
|
18
24
|
error,
|
|
25
|
+
hostTarget,
|
|
19
26
|
installedPackage,
|
|
20
27
|
isLoading,
|
|
21
28
|
isStarting,
|
|
@@ -26,6 +33,7 @@ export function MarketplaceDetail({
|
|
|
26
33
|
}: {
|
|
27
34
|
detail?: AppMarketplaceDetailView;
|
|
28
35
|
error: Error | null;
|
|
36
|
+
hostTarget?: AppPackageHostTarget;
|
|
29
37
|
installedPackage?: AppPackageView;
|
|
30
38
|
isLoading: boolean;
|
|
31
39
|
isStarting: boolean;
|
|
@@ -43,7 +51,6 @@ export function MarketplaceDetail({
|
|
|
43
51
|
const summary = pickLocalizedText(detail.summaryI18n, detail.summary, localeFallbacks);
|
|
44
52
|
const description = pickLocalizedText(detail.descriptionI18n, detail.description ?? summary, localeFallbacks);
|
|
45
53
|
const active = operation ? isAppPackageOperationActive(operation.status) : false;
|
|
46
|
-
const failed = operation?.status === 'failed' || operation?.status === 'interrupted';
|
|
47
54
|
const components = detail.manifest.components ?? [];
|
|
48
55
|
const panelCount = components.filter((entry) => entry.kind === 'panel').length;
|
|
49
56
|
const serviceCount = components.filter((entry) => entry.kind === 'service').length;
|
|
@@ -52,6 +59,15 @@ export function MarketplaceDetail({
|
|
|
52
59
|
const canUpdate = Boolean(
|
|
53
60
|
installedPackage && installedPackage.activeVersion !== detail.latestVersion,
|
|
54
61
|
);
|
|
62
|
+
const supportedPlatforms = formatAppMarketplacePlatforms(
|
|
63
|
+
detail.availability,
|
|
64
|
+
t('appPackagesAllPlatforms'),
|
|
65
|
+
);
|
|
66
|
+
const compatibility = readMarketplaceCompatibilityPresentation(
|
|
67
|
+
resolveAppMarketplaceInstallability(detail.availability, hostTarget),
|
|
68
|
+
supportedPlatforms,
|
|
69
|
+
);
|
|
70
|
+
const blockAction = Boolean(compatibility && (!installedPackage || canUpdate));
|
|
55
71
|
return (
|
|
56
72
|
<div className="mx-auto w-full max-w-3xl px-5 py-5 sm:px-7 sm:py-6">
|
|
57
73
|
<div className="grid items-stretch gap-5 sm:grid-cols-[minmax(0,1.18fr)_minmax(240px,0.82fr)]">
|
|
@@ -61,6 +77,7 @@ export function MarketplaceDetail({
|
|
|
61
77
|
<AppArtwork icon={detail.iconUrl ?? installedPackage?.icon} name={detail.name} className="h-14 w-14 rounded-2xl" />
|
|
62
78
|
<div className="min-w-0 flex-1">
|
|
63
79
|
<h2 className="text-lg font-semibold tracking-tight text-foreground">{detail.name}</h2>
|
|
80
|
+
<MarketplaceCompatibilityBadge presentation={compatibility} />
|
|
64
81
|
<div className="mt-1.5 flex flex-wrap items-center gap-2 text-[11px] text-muted-foreground">
|
|
65
82
|
<span className="inline-flex items-center gap-1"><ShieldCheck className="h-3.5 w-3.5" />{detail.publisher.name}</span>
|
|
66
83
|
<span>v{detail.latestVersion}</span>
|
|
@@ -69,21 +86,27 @@ export function MarketplaceDetail({
|
|
|
69
86
|
</div>
|
|
70
87
|
<p className="mt-3 text-sm leading-6 text-muted-foreground">{summary}</p>
|
|
71
88
|
<div className="mt-auto pt-4">
|
|
89
|
+
<MarketplaceCompatibilityStatus
|
|
90
|
+
blocked={blockAction}
|
|
91
|
+
presentation={compatibility}
|
|
92
|
+
className="mb-2 text-xs font-medium text-muted-foreground"
|
|
93
|
+
/>
|
|
72
94
|
<MarketplaceInstallButton
|
|
73
95
|
active={active}
|
|
74
96
|
canUpdate={canUpdate}
|
|
75
|
-
failed={failed}
|
|
76
97
|
installed={Boolean(installedPackage)}
|
|
77
98
|
isStarting={isStarting}
|
|
78
99
|
onAction={() => canUpdate
|
|
79
100
|
? onUpdate(detail.appId)
|
|
80
101
|
: onInstall(detail.install.spec, detail.install.registry)}
|
|
81
102
|
operation={operation}
|
|
103
|
+
unavailableLabel={blockAction ? compatibility?.actionLabel : undefined}
|
|
104
|
+
unavailableReason={blockAction ? compatibility?.reason : undefined}
|
|
82
105
|
/>
|
|
83
106
|
</div>
|
|
84
107
|
</div>
|
|
85
108
|
</div>
|
|
86
|
-
{operation &&
|
|
109
|
+
{operation && !blockAction && active ? <OperationProgress operation={operation} /> : null}
|
|
87
110
|
|
|
88
111
|
<section className="mt-7">
|
|
89
112
|
<h3 className="text-sm font-semibold text-foreground">{t('appPackagesAboutApp')}</h3>
|
|
@@ -94,7 +117,7 @@ export function MarketplaceDetail({
|
|
|
94
117
|
<DetailFact
|
|
95
118
|
icon={Monitor}
|
|
96
119
|
label={t('appPackagesPlatformsLabel')}
|
|
97
|
-
value={
|
|
120
|
+
value={supportedPlatforms}
|
|
98
121
|
/>
|
|
99
122
|
<DetailFact icon={FileText} label={t('appPackagesPanelsAdded')} value={panelCount > 0 ? String(panelCount) : t('appPackagesNone')} />
|
|
100
123
|
<DetailFact icon={Server} label={t('appPackagesServicesAdded')} value={serviceCount > 0 ? String(serviceCount) : t('appPackagesNone')} />
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useEffect, useMemo, useState } from 'react';
|
|
2
|
-
import type { AppPackageOperationView, AppPackageView } from '@nextclaw/client-sdk';
|
|
2
|
+
import type { AppPackageHostTarget, AppPackageOperationView, AppPackageView } from '@nextclaw/client-sdk';
|
|
3
3
|
import { ArrowLeft, ShieldCheck } from 'lucide-react';
|
|
4
4
|
import {
|
|
5
5
|
AppMarketplaceCatalog,
|
|
@@ -12,10 +12,15 @@ import {
|
|
|
12
12
|
useAppMarketplaceDetail,
|
|
13
13
|
} from '@/features/apps/hooks/use-app-marketplace';
|
|
14
14
|
import { buildLocaleFallbacks } from '@/features/marketplace';
|
|
15
|
+
import {
|
|
16
|
+
getAppMarketplaceInstallabilityRank,
|
|
17
|
+
resolveAppMarketplaceInstallability,
|
|
18
|
+
} from '@/features/apps/utils/app-marketplace-platform.utils';
|
|
15
19
|
import {
|
|
16
20
|
Dialog,
|
|
17
21
|
DialogContent,
|
|
18
22
|
} from '@/shared/components/ui/dialog';
|
|
23
|
+
import { TooltipProvider } from '@/shared/components/ui/tooltip';
|
|
19
24
|
import { getLanguage, t } from '@/shared/lib/i18n';
|
|
20
25
|
|
|
21
26
|
const HIDDEN_ENGINEERING_APPS = new Set([
|
|
@@ -25,6 +30,7 @@ const HIDDEN_ENGINEERING_APPS = new Set([
|
|
|
25
30
|
|
|
26
31
|
export function AppMarketplaceDialog({
|
|
27
32
|
error,
|
|
33
|
+
hostTarget,
|
|
28
34
|
installedPackages,
|
|
29
35
|
isStarting,
|
|
30
36
|
onInstall,
|
|
@@ -35,6 +41,7 @@ export function AppMarketplaceDialog({
|
|
|
35
41
|
startingSource,
|
|
36
42
|
}: {
|
|
37
43
|
error: Error | null;
|
|
44
|
+
hostTarget?: AppPackageHostTarget;
|
|
38
45
|
installedPackages: AppPackageView[];
|
|
39
46
|
isStarting: boolean;
|
|
40
47
|
onInstall: (source: string, registryUrl: string) => void;
|
|
@@ -70,12 +77,17 @@ export function AppMarketplaceDialog({
|
|
|
70
77
|
[installedPackages],
|
|
71
78
|
);
|
|
72
79
|
const localeFallbacks = buildLocaleFallbacks(getLanguage() === 'zh' ? 'zh-CN' : 'en-US');
|
|
73
|
-
const items = useMemo(
|
|
74
|
-
() => (
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
const items = useMemo(() => (marketplace.data?.items ?? [])
|
|
81
|
+
.filter((item) => !HIDDEN_ENGINEERING_APPS.has(item.appId))
|
|
82
|
+
.map((item, index) => ({
|
|
83
|
+
item,
|
|
84
|
+
index,
|
|
85
|
+
rank: getAppMarketplaceInstallabilityRank(
|
|
86
|
+
resolveAppMarketplaceInstallability(item.availability, hostTarget),
|
|
87
|
+
),
|
|
88
|
+
}))
|
|
89
|
+
.sort((left, right) => left.rank - right.rank || left.index - right.index)
|
|
90
|
+
.map(({ item }) => item), [hostTarget, marketplace.data?.items]);
|
|
79
91
|
|
|
80
92
|
const closeDialog = (nextOpen: boolean) => {
|
|
81
93
|
if (!nextOpen) setSelectedSlug(null);
|
|
@@ -84,54 +96,58 @@ export function AppMarketplaceDialog({
|
|
|
84
96
|
|
|
85
97
|
return (
|
|
86
98
|
<Dialog open={open} onOpenChange={closeDialog}>
|
|
87
|
-
<
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
<
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
99
|
+
<TooltipProvider>
|
|
100
|
+
<DialogContent className="flex h-dvh w-screen max-w-none flex-col gap-0 overflow-hidden rounded-none border-0 bg-background/95 p-0 shadow-[0_32px_100px_rgba(0,0,0,0.24)] backdrop-blur-xl [&>button.absolute]:top-[max(1rem,env(safe-area-inset-top))] sm:h-[min(680px,calc(100dvh-4rem))] sm:w-[min(920px,calc(100vw-3rem))] sm:max-w-none sm:rounded-2xl sm:border sm:border-border/55">
|
|
101
|
+
{selectedSlug ? (
|
|
102
|
+
<>
|
|
103
|
+
<MarketplaceDetailHeader onBack={() => setSelectedSlug(null)} />
|
|
104
|
+
<div className="custom-scrollbar min-h-0 flex-1 overflow-y-auto bg-background">
|
|
105
|
+
<MarketplaceDetail
|
|
106
|
+
detail={detail.data}
|
|
107
|
+
error={detail.error instanceof Error ? detail.error : null}
|
|
108
|
+
installedPackage={detail.data ? installedById.get(detail.data.appId) : undefined}
|
|
109
|
+
hostTarget={hostTarget}
|
|
110
|
+
isLoading={detail.isLoading}
|
|
111
|
+
isStarting={isStarting && detail.data?.install.spec === startingSource}
|
|
112
|
+
localeFallbacks={localeFallbacks}
|
|
113
|
+
onInstall={onInstall}
|
|
114
|
+
onUpdate={onUpdate}
|
|
115
|
+
operation={detail.data
|
|
116
|
+
? findLatestAppPackageOperation(operations, detail.data.appId, detail.data.install.spec)
|
|
117
|
+
: undefined}
|
|
118
|
+
/>
|
|
119
|
+
</div>
|
|
120
|
+
</>
|
|
121
|
+
) : (
|
|
122
|
+
<AppMarketplaceCatalog
|
|
123
|
+
error={error}
|
|
124
|
+
filter={filter}
|
|
125
|
+
installedById={installedById}
|
|
126
|
+
hostTarget={hostTarget}
|
|
127
|
+
isError={marketplace.isError}
|
|
128
|
+
isFetchingNextPage={marketplace.isFetchingNextPage}
|
|
129
|
+
isLoading={marketplace.isLoading}
|
|
130
|
+
isStarting={isStarting}
|
|
131
|
+
items={items}
|
|
132
|
+
localeFallbacks={localeFallbacks}
|
|
133
|
+
onFilterChange={setFilter}
|
|
134
|
+
onInstall={onInstall}
|
|
135
|
+
onLoadMore={() => void marketplace.fetchNextPage()}
|
|
136
|
+
onSearchChange={setSearch}
|
|
137
|
+
onSelect={setSelectedSlug}
|
|
138
|
+
onUpdate={onUpdate}
|
|
139
|
+
operations={operations}
|
|
140
|
+
hasNextPage={marketplace.hasNextPage}
|
|
141
|
+
search={search}
|
|
142
|
+
startingSource={startingSource}
|
|
143
|
+
/>
|
|
144
|
+
)}
|
|
145
|
+
<div className="flex items-start gap-2 border-t border-border/60 bg-muted/25 px-5 pb-[max(.75rem,env(safe-area-inset-bottom))] pt-3 text-[11px] leading-4 text-muted-foreground sm:px-6 sm:pb-3">
|
|
146
|
+
<ShieldCheck className="mt-0.5 h-3.5 w-3.5 shrink-0" />
|
|
147
|
+
<span>{t('appPackagesMarketplaceTrustHint')}</span>
|
|
148
|
+
</div>
|
|
149
|
+
</DialogContent>
|
|
150
|
+
</TooltipProvider>
|
|
135
151
|
</Dialog>
|
|
136
152
|
);
|
|
137
153
|
}
|