@nextclaw/ui 0.26.4 → 0.27.0

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.
Files changed (376) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/dist/.vite/manifest.json +1271 -1227
  3. package/dist/assets/{abnfDiagram-VRR7QNED-Dcw10Yt1.js → abnfDiagram-VRR7QNED-DmeCRAkd.js} +1 -1
  4. package/dist/assets/account-panel-BYxGT4m4.js +1 -0
  5. package/dist/assets/{aiden0z-pptx-renderer.es--oNqetPA.js → aiden0z-pptx-renderer.es-ChX5DHqP.js} +1 -1
  6. package/dist/assets/api-CG22BskB.js +20 -0
  7. package/dist/assets/app-presenter-provider-CJFjhVYI.js +28 -0
  8. package/dist/assets/app-presenter-provider-D3BuuOyZ.css +1 -0
  9. package/dist/assets/appearance-settings-page-BcXr0vHp.js +1 -0
  10. package/dist/assets/{arc-DBRedCax.js → arc-Cu6Ols44.js} +1 -1
  11. package/dist/assets/architecture-TIHT7OUA-CLjV_xu4.js +1 -0
  12. package/dist/assets/{architectureDiagram-ZJ3FMSHR-Dufhtuv-.js → architectureDiagram-ZJ3FMSHR-DrNB0eLE.js} +1 -1
  13. package/dist/assets/{blockDiagram-677ZJIJ3-BUk0vtJ7.js → blockDiagram-677ZJIJ3-08rHt6DJ.js} +1 -1
  14. package/dist/assets/{book-open-CmRdT3N1.js → book-open-ClbJmmxP.js} +1 -1
  15. package/dist/assets/{c4Diagram-LMCZKHZV-CxDcVE9p.js → c4Diagram-LMCZKHZV-CCVgRG-u.js} +1 -1
  16. package/dist/assets/{card-CdRBL1E0.js → card-BdC01NFF.js} +1 -1
  17. package/dist/assets/channel-BgpbPyEH.js +1 -0
  18. package/dist/assets/channels-list-page-BrIvJlop.js +8 -0
  19. package/dist/assets/chunk-2Q5K7J3B-DjhMPqAC.js +1 -0
  20. package/dist/assets/{chunk-32BRIVSS-DSF3KElA.js → chunk-32BRIVSS-BeCaI-JN.js} +1 -1
  21. package/dist/assets/{chunk-52WLFC77-Costxzr3.js → chunk-52WLFC77-ZXIcYPYs.js} +1 -1
  22. package/dist/assets/{chunk-5FCAYU7R-rhqzGGZo.js → chunk-5FCAYU7R-DDwTPcy8.js} +1 -1
  23. package/dist/assets/{chunk-5HE753X5-BsEsmIao.js → chunk-5HE753X5-WygrMYPL.js} +1 -1
  24. package/dist/assets/{chunk-5JV3BV7I-Dqw_DCoN.js → chunk-5JV3BV7I-o8T3KZgk.js} +1 -1
  25. package/dist/assets/{chunk-5TONJI2A-Cft82fp8.js → chunk-5TONJI2A-BKFbUT7J.js} +1 -1
  26. package/dist/assets/{chunk-5VM5RSS4-DqNHn9Dl.js → chunk-5VM5RSS4-DYxCRV86.js} +1 -1
  27. package/dist/assets/{chunk-7BUUIJ7U-A5SBEMYY.js → chunk-7BUUIJ7U-CvSeJlKZ.js} +1 -1
  28. package/dist/assets/{chunk-BIQX33UG-1Ng3mTrH.js → chunk-BIQX33UG-BhH3RHCY.js} +1 -1
  29. package/dist/assets/{chunk-C7G6YPKG-DRJEy8ZI.js → chunk-C7G6YPKG-BTL0-xL3.js} +1 -1
  30. package/dist/assets/{chunk-CQNSW5MT-Bydv_J3J.js → chunk-CQNSW5MT-DWAU4QaD.js} +1 -1
  31. package/dist/assets/{chunk-CYSBUYHQ-HkMIg12u.js → chunk-CYSBUYHQ-B7ZBMXTx.js} +1 -1
  32. package/dist/assets/{chunk-EMLP6XTP-C5ndDvm3.js → chunk-EMLP6XTP-D92HvnHE.js} +1 -1
  33. package/dist/assets/{chunk-EX3LRPZG-DzeloZRo.js → chunk-EX3LRPZG-DfOGKwW8.js} +1 -1
  34. package/dist/assets/{chunk-FWX5IMBZ-n_2_CLTQ.js → chunk-FWX5IMBZ-DUuJUrXJ.js} +2 -2
  35. package/dist/assets/{chunk-HOUHSVGY-kx_slvu3.js → chunk-HOUHSVGY-i3MDyUY5.js} +1 -1
  36. package/dist/assets/{chunk-ICXQ74PX-sQLMURqL.js → chunk-ICXQ74PX-F_pmNX6t.js} +1 -1
  37. package/dist/assets/{chunk-JG7HCLWE-CMUn5Elc.js → chunk-JG7HCLWE-DygOelrU.js} +1 -1
  38. package/dist/assets/{chunk-JWPE2WC7-Cra3s-Uk.js → chunk-JWPE2WC7-BpiZMeRl.js} +1 -1
  39. package/dist/assets/{chunk-MOJQB5TN-umcrg5Bi.js → chunk-MOJQB5TN-CV10sB1I.js} +1 -1
  40. package/dist/assets/{chunk-MOZMSUNE-BnljD1ig.js → chunk-MOZMSUNE-Cf1WZNm0.js} +1 -1
  41. package/dist/assets/{chunk-OGEWGWER-BXx5pQjU.js → chunk-OGEWGWER-DuSw54VR.js} +1 -1
  42. package/dist/assets/{chunk-OSBZ3O6U-D-1qfdWu.js → chunk-OSBZ3O6U-_rt_XKSZ.js} +1 -1
  43. package/dist/assets/{chunk-PUDLZKDR-DLzX78LC.js → chunk-PUDLZKDR-BFPaAGNW.js} +1 -1
  44. package/dist/assets/{chunk-Q4XR5HBZ-DTK-rtW6.js → chunk-Q4XR5HBZ-GE0v_E5y.js} +1 -1
  45. package/dist/assets/{chunk-QBLGF6JB-CsFeIGfr.js → chunk-QBLGF6JB-BK_FpnlJ.js} +1 -1
  46. package/dist/assets/{chunk-R7FJI6CG-4xNYUeng.js → chunk-R7FJI6CG-CpYh6rGo.js} +1 -1
  47. package/dist/assets/{chunk-RYQCIY6F-DJiHiTE5.js → chunk-RYQCIY6F-htnxL_Cl.js} +1 -1
  48. package/dist/assets/{chunk-U6XO7XAA-BVYkauHz.js → chunk-U6XO7XAA-wDbE4BZ7.js} +1 -1
  49. package/dist/assets/{chunk-V7JOEXUC-BsazE8cS.js → chunk-V7JOEXUC-DDRSVFTB.js} +1 -1
  50. package/dist/assets/chunk-VAUOI2AC-GYimZYx9.js +1 -0
  51. package/dist/assets/{chunk-VR4S4FIN-7RoZQffO.js → chunk-VR4S4FIN-COdhHR1o.js} +1 -1
  52. package/dist/assets/{chunk-WYO6CB5R-DEuS6N1R.js → chunk-WYO6CB5R-DPDGhyF6.js} +3 -3
  53. package/dist/assets/chunk-XXDRQBXY-KKCf0HV5.js +1 -0
  54. package/dist/assets/{chunk-YOTPTUD7-9KBrosZL.js → chunk-YOTPTUD7-D8ir9Nx5.js} +1 -1
  55. package/dist/assets/{chunk-ZGVPDNZ5-IYgN9f5A.js → chunk-ZGVPDNZ5-BuNKD836.js} +1 -1
  56. package/dist/assets/{chunk-ZIRB5QZD-BUo0-zcp.js → chunk-ZIRB5QZD-DyHzq8jH.js} +1 -1
  57. package/dist/assets/{circle-dashed-HOgt3gIJ.js → circle-dashed-nDaMRmP-.js} +1 -1
  58. package/dist/assets/classDiagram-OUVF2IWQ-iRMPRR8M.js +1 -0
  59. package/dist/assets/classDiagram-v2-EOCWNBFH-BguFy_wj.js +1 -0
  60. package/dist/assets/{client-DKKbdJ6Q.js → client-DlFB5dW5.js} +1 -1
  61. package/dist/assets/config-split-page-C06fU9OQ.js +1 -0
  62. package/dist/assets/confirm-dialog-DpcmlXhd.js +1 -0
  63. package/dist/assets/{app-presenter-provider-jNGlmBLe.css → context-menu-DEcVZfaU.css} +1 -1
  64. package/dist/assets/context-menu-DKIEaY7f.js +211 -0
  65. package/dist/assets/{cose-bilkent-JH36ORCC-DhqbC1fR.js → cose-bilkent-JH36ORCC-B1I1_P6a.js} +1 -1
  66. package/dist/assets/{createLucideIcon-DE0sB9Nu.js → createLucideIcon-Lnt-4LMC.js} +1 -1
  67. package/dist/assets/cynefin-VYW2F7L2-CtbjXuCW.js +1 -0
  68. package/dist/assets/{cynefinDiagram-TSTJHNR4-C-TBRi5V.js → cynefinDiagram-TSTJHNR4-DcOnhnCo.js} +1 -1
  69. package/dist/assets/{dagre-VKFMJZFB-BmafJymp.js → dagre-VKFMJZFB-hAX89lg3.js} +1 -1
  70. package/dist/assets/{dagre-CrgsRasE.js → dagre-nSYhf9yY.js} +1 -1
  71. package/dist/assets/{desktop-capabilities-page-B9-B9k1A.js → desktop-capabilities-page-DPORyZAu.js} +1 -1
  72. package/dist/assets/desktop-update-config-BMTeWZmn.js +1 -0
  73. package/dist/assets/{diagram-FQU43EPY-BoOMwa6D.js → diagram-FQU43EPY-C1mRMD2k.js} +1 -1
  74. package/dist/assets/{diagram-G47NLZAW-Le7N6Uym.js → diagram-G47NLZAW-D2XBn5al.js} +1 -1
  75. package/dist/assets/{diagram-NH7WQ7WH-Fbpj3-MO.js → diagram-NH7WQ7WH-3LmRsmkC.js} +1 -1
  76. package/dist/assets/{diagram-OA4YK3LP-D3QuGGuu.js → diagram-OA4YK3LP-CFWn-osC.js} +1 -1
  77. package/dist/assets/{diagram-WEI45ONY-Cxu1uiN6.js → diagram-WEI45ONY-BqNRbUvU.js} +1 -1
  78. package/dist/assets/dialog-BNXSPMX_.js +1 -0
  79. package/dist/assets/dist-Cuiqqp1O.js +41 -0
  80. package/dist/assets/doc-browser-CDEapjmj.js +1 -0
  81. package/dist/assets/{doc-browser-context-ClLgMbxd.js → doc-browser-context-0QDWYorh.js} +1 -1
  82. package/dist/assets/{docx-preview-CkU2psnd.js → docx-preview-CunAATyC.js} +1 -1
  83. package/dist/assets/{download-CKqS1Ksj.js → download-f_sPcoLZ.js} +1 -1
  84. package/dist/assets/{ebnfDiagram-CCIWWBDH-CCAjuQM6.js → ebnfDiagram-CCIWWBDH-CYb8IwqD.js} +1 -1
  85. package/dist/assets/{erDiagram-Q63AITRT-BuzUAq-d.js → erDiagram-Q63AITRT-H47mUoeK.js} +1 -1
  86. package/dist/assets/eventmodeling-45OFAUF4-Djd6id_u.js +1 -0
  87. package/dist/assets/extensions-B-0xQz3L.js +1 -0
  88. package/dist/assets/external-link-CbVlnlNy.js +1 -0
  89. package/dist/assets/flowDiagram-23GEKE2U-DUrsM_ZL.js +1 -0
  90. package/dist/assets/{form-actions-CCoxz33Q.js → form-actions-BoTqELHB.js} +1 -1
  91. package/dist/assets/{ganttDiagram-NO4QXBWP-cJmWVY8F.js → ganttDiagram-NO4QXBWP-hSX45zfV.js} +1 -1
  92. package/dist/assets/gitGraph-TEB2WS4Q-CU6P_2Cm.js +1 -0
  93. package/dist/assets/{gitGraphDiagram-IHSO6WYX-F58o-vtP.js → gitGraphDiagram-IHSO6WYX-Br0UW2qg.js} +1 -1
  94. package/dist/assets/{i18n-OGmF0Ws_.js → i18n-B0V5NkFj.js} +2 -2
  95. package/dist/assets/inbox-Bna8iUy0.js +1 -0
  96. package/dist/assets/info-DKCQHKI2-Bj2P_7RC.js +1 -0
  97. package/dist/assets/{infoDiagram-FWYZ7A6U-Gt59b83C.js → infoDiagram-FWYZ7A6U-DQmP_67w.js} +1 -1
  98. package/dist/assets/{ishikawaDiagram-FXEZZL3T-1u4IAj1I.js → ishikawaDiagram-FXEZZL3T-BHAV2oes.js} +1 -1
  99. package/dist/assets/{journeyDiagram-5HDEW3XC-CCQsfV-5.js → journeyDiagram-5HDEW3XC-CFHax4_d.js} +1 -1
  100. package/dist/assets/{kanban-definition-HUTT4EX6-vlB6O_Zn.js → kanban-definition-HUTT4EX6-B4ZA9rp5.js} +1 -1
  101. package/dist/assets/katex-BprZ-Wwb.js +1 -0
  102. package/dist/assets/{keyboard-shortcuts-settings-page-D8rosOVh.js → keyboard-shortcuts-settings-page-BluWKrSo.js} +1 -1
  103. package/dist/assets/{line-D_bHubTL.js → line-BboM0HLF.js} +1 -1
  104. package/dist/assets/{linear-ChlwuS5y.js → linear-4K_M1oYM.js} +1 -1
  105. package/dist/assets/login-page-BMHW0Hh0.js +1 -0
  106. package/dist/assets/{login-page-BT3GV3Sb.js → login-page-JNr5JCEw.js} +1 -1
  107. package/dist/assets/main-BCX_Untx.css +1 -0
  108. package/dist/assets/main-C5kbmGUV.js +2 -0
  109. package/dist/assets/main-i18n-catalog.config-DO4wNT7T.js +1 -0
  110. package/dist/assets/{map-oGHTsIu8.js → map-26GpO1wn.js} +1 -1
  111. package/dist/assets/mcp-marketplace-page-CV-PHKTN.js +1 -0
  112. package/dist/assets/{mermaid-parser.core-CuRe1ZG4.js → mermaid-parser.core-BTJFnvRC.js} +2 -2
  113. package/dist/assets/{mermaid.core-u4YCFKRf.js → mermaid.core-B7ufoXgq.js} +3 -3
  114. package/dist/assets/{mindmap-definition-LN4V7U3C-DeJAQYTu.js → mindmap-definition-LN4V7U3C-BHyru6KE.js} +1 -1
  115. package/dist/assets/model-config-page-C-wbM6Fe.js +1 -0
  116. package/dist/assets/{navigation-link-DC-Pku0Y.js → navigation-link-DFLSVIut.js} +2 -2
  117. package/dist/assets/{ordinal-C6JFfkKN.js → ordinal-BqFe2ePF.js} +1 -1
  118. package/dist/assets/packet-7NZHBO7P-ti5ge2jr.js +1 -0
  119. package/dist/assets/panel-app-CSQmm_7E.js +1 -0
  120. package/dist/assets/panel-app-i18n-catalog.config-Bo52dPuF.js +1 -0
  121. package/dist/assets/panelStandalone-PuuMF65O.js +2 -0
  122. package/dist/assets/panelStandalone-XRlWxbRS.css +1 -0
  123. package/dist/assets/{pegDiagram-2B236MQR-nVMkxShH.js → pegDiagram-2B236MQR-PVTatU5j.js} +1 -1
  124. package/dist/assets/pie-RZYD4A2V-Bnep8TyV.js +1 -0
  125. package/dist/assets/{pieDiagram-ENE6RG2P-8aUH44QZ.js → pieDiagram-ENE6RG2P-CGc-QCc7.js} +1 -1
  126. package/dist/assets/plus-CywSlIbG.js +1 -0
  127. package/dist/assets/privacy-settings-page-CPdEiouE.js +1 -0
  128. package/dist/assets/projects-D_cd_t4G.js +1 -0
  129. package/dist/assets/provider-models-XRArsply.js +1 -0
  130. package/dist/assets/provider-scoped-model-input-C8JI-hus.js +1 -0
  131. package/dist/assets/providers-config-page-fyMlVgvq.js +1 -0
  132. package/dist/assets/puzzle-Bk3ud1KI.js +1 -0
  133. package/dist/assets/pwa-Cx6Fnox4.js +1 -0
  134. package/dist/assets/{quadrantDiagram-ABIIQ3AL-EY8hpFv8.js → quadrantDiagram-ABIIQ3AL-DGL36riv.js} +1 -1
  135. package/dist/assets/radar-I7S5WNFK-BYg-icAP.js +1 -0
  136. package/dist/assets/railroad-3IZDKUUU-_CHO-Fi1.js +1 -0
  137. package/dist/assets/railroad-abnf-AHOZXSZD-hbQDevHe.js +1 -0
  138. package/dist/assets/railroad-ebnf-EBAXGLYW-v4RZkOfi.js +1 -0
  139. package/dist/assets/railroad-peg-LSFZ7HO6-bC9BqkI5.js +1 -0
  140. package/dist/assets/{railroadDiagram-RFXS5EU6-CNhcIeji.js → railroadDiagram-RFXS5EU6-CyNwvhSb.js} +1 -1
  141. package/dist/assets/{refresh-cw-BG8VfcdA.js → refresh-cw-Ca2napNx.js} +1 -1
  142. package/dist/assets/remote-D5MBQNZE.js +1 -0
  143. package/dist/assets/{requirementDiagram-TGXJPOKE-D8Dcs-Rt.js → requirementDiagram-TGXJPOKE-C31NMKJ0.js} +1 -1
  144. package/dist/assets/{rotate-cw-DPEegUU2.js → rotate-cw-DXg7sNUE.js} +1 -1
  145. package/dist/assets/runtime-config-page--ivCxBT4.js +1 -0
  146. package/dist/assets/{sankeyDiagram-HTMAVEWB-HTrb6aa-.js → sankeyDiagram-HTMAVEWB-CwrQ_7PA.js} +1 -1
  147. package/dist/assets/{save-CPlctBjT.js → save-DNigywZ9.js} +1 -1
  148. package/dist/assets/search-U9C0oTQJ.js +1 -0
  149. package/dist/assets/search-config-page-Bdx_RR1q.js +1 -0
  150. package/dist/assets/secrets-config-page-CvMIcsfJ.js +3 -0
  151. package/dist/assets/security-config-CQmMqQ8v.js +1 -0
  152. package/dist/assets/select-DxwDeKUR.js +1 -0
  153. package/dist/assets/{sequenceDiagram-DBY2YBRQ-6f_4X16Y.js → sequenceDiagram-DBY2YBRQ-EFD482_y.js} +1 -1
  154. package/dist/assets/service-apps-panel-CiYO1Be4.js +1 -0
  155. package/dist/assets/{settings-2-CrGx9_De.js → settings-2-BrBUdRoY.js} +1 -1
  156. package/dist/assets/{sizeCapture-X5ZJPWSS-Ck9rsuwL.js → sizeCapture-X5ZJPWSS-TDvULTE1.js} +1 -1
  157. package/dist/assets/{src-C8AUg09O.js → src-CI2AvEMj.js} +1 -1
  158. package/dist/assets/{stateDiagram-2N3HPSRC-Cm33MLHu.js → stateDiagram-2N3HPSRC-JdPsIYHo.js} +1 -1
  159. package/dist/assets/stateDiagram-v2-6OUMAXLB-4_aAQfB_.js +1 -0
  160. package/dist/assets/{status-dot-Cb8ewlUr.js → status-dot-BbGsrkIX.js} +1 -1
  161. package/dist/assets/{swimlanes-5IMT3BWC-B107vmvM.js → swimlanes-5IMT3BWC-BnxpKeK_.js} +2 -2
  162. package/dist/assets/swimlanesDiagram-G3AALYLV-wCqfwsw-.js +8 -0
  163. package/dist/assets/tag-chip-BDbxcf6P.js +1 -0
  164. package/dist/assets/theme-provider-D98XGa-c.js +1 -0
  165. package/dist/assets/{timeline-definition-FHXFAJF6-CJEoAj33.js → timeline-definition-FHXFAJF6-2IL22-uC.js} +1 -1
  166. package/dist/assets/trash-2-DwSkRfeB.js +1 -0
  167. package/dist/assets/treeView-QDETBFTQ-BAyOb14Z.js +1 -0
  168. package/dist/assets/treemap-6X3UGDF4-DgPDM0zS.js +1 -0
  169. package/dist/assets/{use-config-BM5jC65L.js → use-config-D3cNzk2k.js} +1 -1
  170. package/dist/assets/{use-desktop-capabilities-ezKJwKqg.js → use-desktop-capabilities-D7odgaTB.js} +1 -1
  171. package/dist/assets/use-viewport-layout-BANU5E1t.js +1 -0
  172. package/dist/assets/{vennDiagram-L72KCM5P-DzsUHk5I.js → vennDiagram-L72KCM5P-Cjf6n5Va.js} +1 -1
  173. package/dist/assets/wardley-OPB4EBWU-eCElh8z5.js +1 -0
  174. package/dist/assets/{wardleyDiagram-EHGQE667-1NfFs5ua.js → wardleyDiagram-EHGQE667-yv4qKbBO.js} +1 -1
  175. package/dist/assets/x-BqGj6_Vq.js +1 -0
  176. package/dist/assets/{xychartDiagram-FW5EYKEG-Ci8AI3Qo.js → xychartDiagram-FW5EYKEG-Bmp8Ck8X.js} +1 -1
  177. package/dist/index.html +43 -106
  178. package/dist/panel-standalone.html +18 -12
  179. package/index.html +15 -66
  180. package/package.json +5 -5
  181. package/src/app/configs/__tests__/app-navigation.config.test.ts +4 -2
  182. package/src/app/configs/app-navigation.config.ts +7 -2
  183. package/src/app/styles/design-system.css +85 -1
  184. package/src/app/styles/island-theme.css +8 -6
  185. package/src/features/agents/components/agent-details-dialog.tsx +5 -3
  186. package/src/features/app-data/components/app-retained-data-section.tsx +2 -2
  187. package/src/features/apps/components/__tests__/app-marketplace-catalog.test.tsx +2 -2
  188. package/src/features/apps/components/__tests__/app-packages-panel.test.tsx +94 -23
  189. package/src/features/apps/components/__tests__/apps-panel.test.tsx +5 -3
  190. package/src/features/apps/components/app-document-access-section.tsx +17 -14
  191. package/src/features/apps/components/app-marketplace-catalog.tsx +66 -39
  192. package/src/features/apps/components/app-marketplace-cover.tsx +5 -2
  193. package/src/features/apps/components/app-marketplace-detail.tsx +9 -6
  194. package/src/features/apps/components/app-marketplace-operation.tsx +8 -3
  195. package/src/features/apps/components/app-marketplace-panel.tsx +168 -0
  196. package/src/features/apps/components/app-package-card.tsx +224 -147
  197. package/src/features/apps/components/app-package-details-dialog.tsx +103 -0
  198. package/src/features/apps/components/app-packages-panel.tsx +159 -144
  199. package/src/features/apps/components/apps-panel.tsx +40 -11
  200. package/src/features/chat/components/conversation/chat-conversation-header-section.tsx +1 -1
  201. package/src/features/chat/components/conversation/chat-conversation-header.tsx +1 -1
  202. package/src/features/chat/components/layout/chat-sidebar-toolbar.tsx +2 -2
  203. package/src/features/chat/components/layout/chat-sidebar-utility-menu.tsx +9 -7
  204. package/src/features/chat/features/conversation/components/floating-session-conversation.tsx +2 -3
  205. package/src/features/chat/features/conversation/components/session-conversation-area.tsx +1 -0
  206. package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-input-state.test.tsx +33 -0
  207. package/src/features/chat/features/message/components/chat-message-list.container.tsx +0 -2
  208. package/src/features/chat/features/message/utils/__tests__/chat-message-process-summary.utils.test.ts +4 -6
  209. package/src/features/chat/features/message/utils/chat-message-execution-summary.utils.ts +3 -0
  210. package/src/features/chat/features/message/utils/chat-message-process-summary.utils.ts +2 -10
  211. package/src/features/chat/features/message/utils/chat-message-texts.utils.ts +2 -0
  212. package/src/features/chat/features/message/utils/chat-message-trigger-details.utils.ts +3 -0
  213. package/src/features/chat/features/session/components/chat-sidebar-project-groups.tsx +2 -1
  214. package/src/features/chat/features/session/components/session-header/chat-session-metadata-dialog.tsx +1 -1
  215. package/src/features/chat/features/session/components/session-header/chat-session-project-badge.tsx +2 -2
  216. package/src/features/chat/features/welcome/components/__tests__/chat-welcome.test.tsx +31 -6
  217. package/src/features/chat/features/welcome/components/chat-conversation-welcome.tsx +13 -1
  218. package/src/features/chat/features/welcome/components/chat-welcome-agent-picker.tsx +1 -1
  219. package/src/features/chat/features/welcome/components/chat-welcome-project-picker.tsx +1 -1
  220. package/src/features/chat/features/welcome/components/chat-welcome-prompt-suggestions.tsx +56 -13
  221. package/src/features/chat/features/welcome/components/chat-welcome-session-type-picker.tsx +3 -3
  222. package/src/features/chat/features/welcome/components/chat-welcome.tsx +14 -4
  223. package/src/features/chat/features/welcome/utils/__tests__/chat-welcome-continuation.utils.test.ts +40 -0
  224. package/src/features/chat/features/welcome/utils/chat-welcome-continuation.utils.ts +21 -0
  225. package/src/features/chat/features/workspace/components/chat-session-workspace-directory-browser.tsx +1 -1
  226. package/src/features/chat/features/workspace/components/chat-session-workspace-file-breadcrumbs.tsx +5 -9
  227. package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx +6 -4
  228. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +27 -27
  229. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-nav.tsx +1 -1
  230. package/src/features/chat/features/workspace/components/overview/chat-session-continuous-attention.tsx +11 -11
  231. package/src/features/chat/features/workspace/components/overview/chat-session-token-usage.tsx +15 -15
  232. package/src/features/chat/features/workspace/components/project-files/workspace-directory-tree.tsx +2 -2
  233. package/src/features/chat/features/workspace/components/project-files/workspace-new-folder-tree-item.tsx +1 -1
  234. package/src/features/chat/features/workspace/components/project-files/workspace-project-files-toolbar.tsx +2 -2
  235. package/src/features/chat/features/workspace/components/session-cron-job-content.tsx +7 -4
  236. package/src/features/cron/components/cron-job-row.tsx +5 -4
  237. package/src/features/desktop-capabilities/components/desktop-authorization-dialog.tsx +5 -5
  238. package/src/features/inbox/components/inbox-reader-dialog.test.tsx +46 -6
  239. package/src/features/inbox/components/inbox-reader-dialog.tsx +38 -29
  240. package/src/features/inbox/managers/inbox.manager.test.ts +28 -0
  241. package/src/features/inbox/managers/inbox.manager.ts +18 -4
  242. package/src/features/inbox/pages/inbox-page.test.ts +16 -5
  243. package/src/features/inbox/pages/inbox-page.tsx +37 -29
  244. package/src/features/panel-apps/components/panel-app-list-item.tsx +4 -3
  245. package/src/features/panel-apps/components/panel-app-service-action-authorization-dialog.tsx +2 -2
  246. package/src/features/panel-apps/utils/panel-app-doc-browser.utils.tsx +5 -24
  247. package/src/features/projects/components/work/project-work-items.tsx +1 -1
  248. package/src/features/projects/pages/project-home-page.tsx +4 -2
  249. package/src/features/pwa/managers/__tests__/pwa-shell-theme.manager.test.ts +3 -3
  250. package/src/features/pwa/managers/pwa-shell-theme.manager.ts +8 -3
  251. package/src/features/right-panel-resources/components/__tests__/page-resource-icon.test.tsx +13 -2
  252. package/src/features/right-panel-resources/components/page-resource-icon.tsx +15 -7
  253. package/src/features/right-panel-resources/configs/right-panel-resource-routes.config.ts +1 -1
  254. package/src/features/right-panel-resources/index.ts +3 -0
  255. package/src/features/right-panel-resources/utils/__tests__/right-panel-resource-route-resolver.utils.test.ts +5 -0
  256. package/src/features/right-panel-resources/utils/right-panel-resource-uri.utils.ts +3 -2
  257. package/src/features/service-apps/components/service-action-row.tsx +4 -3
  258. package/src/features/service-apps/components/service-app-delete-dialog.tsx +2 -2
  259. package/src/features/service-apps/components/service-app-list-item.tsx +5 -4
  260. package/src/features/settings/components/config/provider-model-suggestions-panel.tsx +1 -1
  261. package/src/features/settings/pages/providers-config-page.tsx +3 -2
  262. package/src/index.css +42 -8
  263. package/src/platforms/mobile/components/__tests__/mobile-app-shell.test.tsx +9 -0
  264. package/src/platforms/mobile/components/mobile-app-shell.tsx +4 -2
  265. package/src/platforms/mobile/components/mobile-topbar.tsx +2 -2
  266. package/src/shared/components/doc-browser/doc-browser-tab-strip.tsx +2 -2
  267. package/src/shared/components/path-picker/server-path-picker-dialog.tsx +5 -3
  268. package/src/shared/components/ui/__tests__/dialog.test.tsx +37 -1
  269. package/src/shared/components/ui/actions/action-feedback.ts +1 -8
  270. package/src/shared/components/ui/actions/icon-action-button.tsx +1 -1
  271. package/src/shared/components/ui/confirm-dialog.tsx +1 -2
  272. package/src/shared/components/ui/context-menu/context-menu-items.tsx +2 -2
  273. package/src/shared/components/ui/dialog.tsx +29 -7
  274. package/src/shared/components/ui/popover.tsx +14 -3
  275. package/src/shared/components/ui/tab-strip/compact-tab-strip.tsx +5 -5
  276. package/src/shared/components/ui/tooltip.tsx +2 -1
  277. package/src/shared/components/workbench/__tests__/workbench-surface.test.tsx +21 -0
  278. package/src/shared/components/workbench/workbench-surface-toolbar.tsx +4 -0
  279. package/src/shared/components/workbench/workbench-surface.tsx +5 -2
  280. package/src/shared/lib/i18n/locales/en-US/chat.json +14 -9
  281. package/src/shared/lib/i18n/locales/en-US/core.json +5 -1
  282. package/src/shared/lib/i18n/locales/en-US/doc-browser.json +10 -5
  283. package/src/shared/lib/i18n/locales/en-US/inbox.json +1 -0
  284. package/src/shared/lib/i18n/locales/zh-CN/chat.json +14 -9
  285. package/src/shared/lib/i18n/locales/zh-CN/core.json +5 -1
  286. package/src/shared/lib/i18n/locales/zh-CN/doc-browser.json +11 -6
  287. package/src/shared/lib/i18n/locales/zh-CN/inbox.json +1 -0
  288. package/src/shared/lib/theme/index.test.ts +28 -1
  289. package/src/shared/lib/theme/index.ts +14 -3
  290. package/dist/assets/account-panel-DVi_jhkG.js +0 -1
  291. package/dist/assets/api-BZvNpFOS.js +0 -20
  292. package/dist/assets/app-presenter-provider-BcYL-VNe.js +0 -124
  293. package/dist/assets/appearance-settings-page-AZNBzLmT.js +0 -1
  294. package/dist/assets/architecture-TIHT7OUA-CvnC-LeA.js +0 -1
  295. package/dist/assets/channel-CpMstUPF.js +0 -1
  296. package/dist/assets/channels-list-page-eZN74FN3.js +0 -8
  297. package/dist/assets/chunk-2Q5K7J3B-Djp3VF0s.js +0 -1
  298. package/dist/assets/chunk-VAUOI2AC-BrbiIC1Q.js +0 -1
  299. package/dist/assets/chunk-XXDRQBXY-Cx9N40wF.js +0 -1
  300. package/dist/assets/classDiagram-OUVF2IWQ-DFN1v3PQ.js +0 -1
  301. package/dist/assets/classDiagram-v2-EOCWNBFH-DRvglADa.js +0 -1
  302. package/dist/assets/config-split-page-BA3V6b3Q.js +0 -1
  303. package/dist/assets/confirm-dialog-8vqYZ0wy.js +0 -1
  304. package/dist/assets/context-menu-DHVVdHzN.js +0 -1
  305. package/dist/assets/cynefin-VYW2F7L2-DXUGnpJH.js +0 -1
  306. package/dist/assets/desktop-update-config-Cfr3IRUe.js +0 -1
  307. package/dist/assets/dialog-BUfWO8hr.js +0 -5
  308. package/dist/assets/doc-browser-w8q1j0jL.js +0 -1
  309. package/dist/assets/es2015-BiB05Sav.js +0 -41
  310. package/dist/assets/eventmodeling-45OFAUF4-ZBfVS3ZC.js +0 -1
  311. package/dist/assets/extensions-vPD4dGqt.js +0 -1
  312. package/dist/assets/eye-bKzylu3p.js +0 -1
  313. package/dist/assets/flowDiagram-23GEKE2U-CqdsKk6x.js +0 -1
  314. package/dist/assets/gitGraph-TEB2WS4Q-fHYFd9Es.js +0 -1
  315. package/dist/assets/info-DKCQHKI2-CSaOL_bb.js +0 -1
  316. package/dist/assets/katex-B4FQSo9k.js +0 -1
  317. package/dist/assets/loader-circle-Clq1Gtb1.js +0 -1
  318. package/dist/assets/login-page-DKId3By8.js +0 -1
  319. package/dist/assets/main-bEWCGDHr.js +0 -2
  320. package/dist/assets/main-i18n-catalog.config-Bpu5GcwF.js +0 -1
  321. package/dist/assets/main-kqMRTwOs.css +0 -1
  322. package/dist/assets/mcp-marketplace-page-CZIP6j3L.js +0 -1
  323. package/dist/assets/model-config-page-D21a-BO0.js +0 -1
  324. package/dist/assets/packet-7NZHBO7P-D-YFTczs.js +0 -1
  325. package/dist/assets/panel-app-BYfQu_TS.js +0 -1
  326. package/dist/assets/panel-app-i18n-catalog.config-D44qmtfk.js +0 -1
  327. package/dist/assets/panelStandalone-BRg7B1EI.css +0 -1
  328. package/dist/assets/panelStandalone-CX8X2hjh.js +0 -2
  329. package/dist/assets/pie-RZYD4A2V-VEnYu9s5.js +0 -1
  330. package/dist/assets/privacy-settings-page-e0LFHZJm.js +0 -1
  331. package/dist/assets/projects-Rki7Fmth.js +0 -1
  332. package/dist/assets/provider-models-DFQgF4hS.js +0 -1
  333. package/dist/assets/provider-scoped-model-input-DaONL0j_.js +0 -1
  334. package/dist/assets/providers-config-page-CEOhQlMe.js +0 -1
  335. package/dist/assets/puzzle-D_TiFXOv.js +0 -1
  336. package/dist/assets/pwa-C9ac_1dg.js +0 -1
  337. package/dist/assets/radar-I7S5WNFK-BFNIekC1.js +0 -1
  338. package/dist/assets/railroad-3IZDKUUU-lVqJ3Hak.js +0 -1
  339. package/dist/assets/railroad-abnf-AHOZXSZD-DYaefdFC.js +0 -1
  340. package/dist/assets/railroad-ebnf-EBAXGLYW-CTAk6lVq.js +0 -1
  341. package/dist/assets/railroad-peg-LSFZ7HO6-Cob294tg.js +0 -1
  342. package/dist/assets/remote-DkSx5x4R.js +0 -1
  343. package/dist/assets/runtime-config-page-DDT1dVLt.js +0 -1
  344. package/dist/assets/search-config-page-CDwmd6eX.js +0 -1
  345. package/dist/assets/secrets-config-page-1OvgmwPv.js +0 -3
  346. package/dist/assets/security-config-Pv4CM-kw.js +0 -1
  347. package/dist/assets/select-Y9IEbx9x.js +0 -1
  348. package/dist/assets/service-apps-panel-DPrLeF3N.js +0 -1
  349. package/dist/assets/stateDiagram-v2-6OUMAXLB-BrNv-raG.js +0 -1
  350. package/dist/assets/swimlanesDiagram-G3AALYLV-ntcxaPXp.js +0 -8
  351. package/dist/assets/tag-chip-D-6aPuuh.js +0 -1
  352. package/dist/assets/theme-provider-BjF1Eowc.js +0 -1
  353. package/dist/assets/trash-2-DER2EJKK.js +0 -1
  354. package/dist/assets/treeView-QDETBFTQ-DbFmr-gw.js +0 -1
  355. package/dist/assets/treemap-6X3UGDF4-C8aY96pi.js +0 -1
  356. package/dist/assets/use-viewport-layout-vmbQUNT6.js +0 -1
  357. package/dist/assets/wardley-OPB4EBWU-D8d6DbbJ.js +0 -1
  358. package/dist/assets/x-DSz9cGhy.js +0 -1
  359. package/src/features/apps/components/app-marketplace-dialog.tsx +0 -168
  360. /package/dist/assets/{array-BV9OtnO8.js → array-DstOKG9P.js} +0 -0
  361. /package/dist/assets/{chunk-KEIR6QF5-Cx-8EJ4_.js → chunk-KEIR6QF5-0TA8nwgf.js} +0 -0
  362. /package/dist/assets/{chunk-Y2CYZVJY-Dy1ufvjf.js → chunk-Y2CYZVJY-rfGCG6pM.js} +0 -0
  363. /package/dist/assets/{config-hints-DbmiyTKg.js → config-hints-BfGoD7-o.js} +0 -0
  364. /package/dist/assets/{cytoscape.esm-CSCjuT4Z.js → cytoscape.esm-DdIcNEda.js} +0 -0
  365. /package/dist/assets/{defaultLocale-DWTiNsbT.js → defaultLocale-CzXix2iJ.js} +0 -0
  366. /package/dist/assets/{dist-BVCSkfWY.js → dist-D5dwMwKA.js} +0 -0
  367. /package/dist/assets/{graphlib-B1yb1Wl8.js → graphlib-BKOe0eFe.js} +0 -0
  368. /package/dist/assets/{host-capabilities-DuIFVsvM.js → host-capabilities-CnSVTaot.js} +0 -0
  369. /package/dist/assets/{init-BF6GH5oe.js → init-OCFb3zgY.js} +0 -0
  370. /package/dist/assets/{jszip.min-D12teKzP.js → jszip.min-B2uhSxvV.js} +0 -0
  371. /package/dist/assets/{katex-CsAM73R9.js → katex-dBrYsE7B.js} +0 -0
  372. /package/dist/assets/{middleware-B--6mAUM.js → middleware-CAXxl-af.js} +0 -0
  373. /package/dist/assets/{path-C56XkznJ.js → path-T5eoIRSJ.js} +0 -0
  374. /package/dist/assets/{preload-helper-ca-nBW7U.js → preload-helper-DWTEM3RW.js} +0 -0
  375. /package/dist/assets/{rough.esm-CGfeEbtE.js → rough.esm-DmGXmZEB.js} +0 -0
  376. /package/dist/assets/{xlsx-sds5nUpL.js → xlsx-CoYacou7.js} +0 -0
@@ -4,7 +4,8 @@ import { useRef, useState } from "react";
4
4
  import { ChevronLeft, ChevronRight, Inbox } from "lucide-react";
5
5
  import { useNavigate } from "react-router-dom";
6
6
  import { useAppPresenter } from "@/app/components/app-presenter-provider";
7
- import { CHAT_DRAFT_SESSION_PATH } from "@/features/chat";
7
+ import { useViewportLayout } from "@/app/hooks/use-viewport-layout";
8
+ import { buildSessionPath, CHAT_DRAFT_SESSION_PATH } from "@/features/chat";
8
9
  import { InboxDeliveryContent } from "@/features/inbox/components/inbox-delivery-content";
9
10
  import { useInboxDeliveries } from "@/features/inbox/hooks/use-inbox-deliveries";
10
11
  import { useInboxStore } from "@/features/inbox/stores/inbox.store";
@@ -13,6 +14,7 @@ import {
13
14
  Dialog,
14
15
  DialogContent,
15
16
  DialogDescription,
17
+ DialogHeader,
16
18
  DialogTitle,
17
19
  } from "@/shared/components/ui/dialog";
18
20
  import { IconActionButton } from "@/shared/components/ui/actions/icon-action-button";
@@ -28,7 +30,8 @@ function formatPosition(current: number, total: number): string {
28
30
  export function InboxReaderDialog() {
29
31
  const titleRef = useRef<HTMLHeadingElement>(null);
30
32
  const navigate = useNavigate();
31
- const { chatDraftIntentManager, inboxManager } = useAppPresenter();
33
+ const { chatComposerIntentManager, docBrowserManager, inboxManager } = useAppPresenter();
34
+ const { isMobile } = useViewportLayout();
32
35
  const { data } = useInboxDeliveries();
33
36
  const { activeDeliveryId, readerOpen } = useInboxStore((state) => state.snapshot);
34
37
  const [pendingAction, setPendingAction] = useState<string | null>(null);
@@ -77,9 +80,10 @@ export function InboxReaderDialog() {
77
80
  return;
78
81
  }
79
82
  void runAction("continue", async () => {
80
- const { reference } = await inboxManager.prepareChatReference(activeDelivery.id);
81
- chatDraftIntentManager.requestSystemObjectReference(reference);
82
- navigate(CHAT_DRAFT_SESSION_PATH);
83
+ const { reference, targetSessionKey } = await inboxManager.prepareChatReference(activeDelivery.id);
84
+ chatComposerIntentManager.requestSystemObjectReference({ targetSessionKey, reference });
85
+ if (isMobile) docBrowserManager.close();
86
+ navigate(targetSessionKey ? buildSessionPath(targetSessionKey) : CHAT_DRAFT_SESSION_PATH);
83
87
  });
84
88
  };
85
89
 
@@ -96,15 +100,18 @@ export function InboxReaderDialog() {
96
100
  const positionControls = unreadDeliveries.length > 1 ? (
97
101
  <div className="flex shrink-0 items-center gap-1 pr-1">
98
102
  <span className="mr-1 text-[11px] tabular-nums text-muted-foreground">
99
- {formatPosition(activeIndex + 1, unreadDeliveries.length)}
103
+ <span className="hidden md:inline">{formatPosition(activeIndex + 1, unreadDeliveries.length)}</span>
104
+ <span className="md:hidden" aria-label={formatPosition(activeIndex + 1, unreadDeliveries.length)}>{activeIndex + 1}/{unreadDeliveries.length}</span>
100
105
  </span>
101
106
  <IconActionButton
107
+ size="sm"
102
108
  icon={<ChevronLeft className="h-4 w-4" />}
103
109
  label={t("inboxPrevious")}
104
110
  disabled={activeIndex <= 0 || pendingAction === "select"}
105
111
  onClick={() => selectAt(activeIndex - 1)}
106
112
  />
107
113
  <IconActionButton
114
+ size="sm"
108
115
  icon={<ChevronRight className="h-4 w-4" />}
109
116
  label={t("inboxNext")}
110
117
  disabled={activeIndex >= unreadDeliveries.length - 1 || pendingAction === "select"}
@@ -123,7 +130,7 @@ export function InboxReaderDialog() {
123
130
  }}
124
131
  >
125
132
  <DialogContent
126
- className="flex h-[min(82vh,760px)] w-[calc(100vw-2rem)] max-w-[820px] flex-col gap-0 overflow-hidden rounded-[24px] border-border/70 bg-background p-0 shadow-[0_20px_55px_-22px_rgba(15,23,42,0.32)] max-sm:h-[100dvh] max-sm:max-h-none max-sm:w-screen max-sm:rounded-none max-sm:border-0"
133
+ className="flex h-[min(82vh,760px)] w-[calc(100vw-2rem)] max-w-[820px] flex-col gap-0 overflow-hidden rounded-[24px] border-border/70 bg-background p-0 shadow-[0_20px_55px_-22px_rgba(15,23,42,0.32)] max-md:h-[100dvh] max-md:max-h-[100dvh] max-md:w-screen max-md:max-w-none max-md:rounded-none max-md:border-0 max-md:pt-[env(safe-area-inset-top,0px)] max-md:pb-[env(safe-area-inset-bottom,0px)]"
127
134
  onOpenAutoFocus={(event) => {
128
135
  event.preventDefault();
129
136
  titleRef.current?.focus();
@@ -131,10 +138,15 @@ export function InboxReaderDialog() {
131
138
  >
132
139
  {activeDelivery ? (
133
140
  <>
134
- <header className="shrink-0 border-b border-border/50 px-5 py-3 pr-14 sm:px-6">
135
- <div className="flex min-h-7 items-center justify-between gap-3">
141
+ <DialogHeader
142
+ className="items-center gap-1 border-b border-border/50 px-3 py-2 md:gap-3 md:px-6 md:py-3"
143
+ actions={<>
144
+ {positionControls}
145
+ <PageResourceActionsMenu page={pageResourceFromSystemObject("inbox-delivery", activeDelivery.id, activeDelivery.title)} />
146
+ </>}
147
+ >
136
148
  <div className="flex min-w-0 items-center gap-2">
137
- <span className="flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-muted/70 text-muted-foreground">
149
+ <span className="hidden h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-muted/70 text-muted-foreground md:flex">
138
150
  <Inbox className="h-3.5 w-3.5" />
139
151
  </span>
140
152
  <DialogTitle
@@ -145,29 +157,24 @@ export function InboxReaderDialog() {
145
157
  >
146
158
  {activeDelivery.title}
147
159
  </DialogTitle>
148
- <span className="hidden shrink-0 text-muted-foreground sm:inline" aria-hidden="true">·</span>
160
+ <span className="hidden shrink-0 text-muted-foreground md:inline" aria-hidden="true">·</span>
149
161
  <time
150
- className="hidden shrink-0 text-[11px] tabular-nums text-muted-foreground sm:block"
162
+ className="hidden shrink-0 text-[11px] tabular-nums text-muted-foreground md:block"
151
163
  dateTime={activeDelivery.createdAt}
152
164
  >
153
165
  {formatDateTime(activeDelivery.createdAt)}
154
166
  </time>
155
167
  </div>
156
- <div className="flex shrink-0 items-center gap-1">
157
- {positionControls}
158
- <PageResourceActionsMenu page={pageResourceFromSystemObject("inbox-delivery", activeDelivery.id, activeDelivery.title)} />
159
- </div>
160
- </div>
161
168
  <DialogDescription className="sr-only">
162
169
  {activeDelivery.summary ?? t("inboxNoSummary")}
163
170
  </DialogDescription>
164
- </header>
171
+ </DialogHeader>
165
172
 
166
173
  <div className={cn(
167
174
  "min-h-0 flex-1",
168
175
  isHtml
169
- ? "p-3 sm:p-4"
170
- : "custom-scrollbar overflow-y-auto px-6 py-5 sm:px-8 sm:py-6",
176
+ ? "p-0 md:p-4"
177
+ : "custom-scrollbar overflow-y-auto overscroll-contain px-4 py-3 md:px-8 md:py-6",
171
178
  )}>
172
179
  <InboxDeliveryContent
173
180
  className={isHtml ? "h-full" : undefined}
@@ -178,24 +185,26 @@ export function InboxReaderDialog() {
178
185
  />
179
186
  </div>
180
187
 
181
- <footer className="shrink-0 border-t border-border/50 bg-background px-5 py-3 sm:px-6">
188
+ <footer className="shrink-0 border-t border-border/50 bg-background px-3 py-2 md:px-6 md:py-3">
182
189
  {error ? (
183
190
  <p role="alert" className="mb-3 text-sm text-destructive">{error}</p>
184
191
  ) : null}
185
- <div className="flex flex-col-reverse gap-2 sm:flex-row sm:items-center sm:justify-between">
186
- <div className="flex flex-col-reverse gap-1 sm:flex-row sm:flex-wrap">
187
- <Button size="sm" variant="ghost" onClick={inboxManager.closeReader}>
192
+ <div className="flex items-center justify-between gap-2 [--control-touch-size:2rem]">
193
+ <div className="flex items-center gap-1">
194
+ <Button size="sm" className="px-2 md:px-3" variant="ghost" onClick={inboxManager.closeReader}>
188
195
  {t("inboxReadLater")}
189
196
  </Button>
190
- <Button size="sm" variant="outline" disabled={pendingAction !== null} onClick={markRead}>
197
+ <Button size="sm" className="px-2 md:px-3" variant="outline" disabled={pendingAction !== null} onClick={markRead}>
191
198
  {t("inboxMarkRead")}
192
199
  </Button>
193
- <Button size="sm" variant="ghost" disabled={pendingAction !== null} onClick={openInbox}>
194
- {t("inboxOpenInbox")}
200
+ <Button size="sm" className="px-2 md:px-3" variant="ghost" aria-label={t("inboxOpenInbox")} disabled={pendingAction !== null} onClick={openInbox}>
201
+ <span className="md:hidden">{t("inboxTitle")}</span>
202
+ <span className="hidden md:inline">{t("inboxOpenInbox")}</span>
195
203
  </Button>
196
204
  </div>
197
- <Button size="sm" disabled={pendingAction !== null} onClick={continueInChat}>
198
- {t("inboxContinueChat")}
205
+ <Button size="sm" className="px-2 md:px-3" aria-label={t("inboxContinueChat")} disabled={pendingAction !== null} onClick={continueInChat}>
206
+ <span className="md:hidden">{t("inboxContinueChatCompact")}</span>
207
+ <span className="hidden md:inline">{t("inboxContinueChat")}</span>
199
208
  </Button>
200
209
  </div>
201
210
  </footer>
@@ -1,10 +1,13 @@
1
1
  import { QueryClient } from "@tanstack/react-query";
2
2
  import { beforeEach, describe, expect, it, vi } from "vitest";
3
3
  import type { InboxDelivery } from "@nextclaw/shared";
4
+ import { NextClawClientError } from "@nextclaw/client-sdk";
4
5
  import { InboxManager } from "@/features/inbox/managers/inbox.manager";
5
6
  import { useInboxStore } from "@/features/inbox/stores/inbox.store";
6
7
 
7
8
  const mocks = vi.hoisted(() => ({
9
+ getDelivery: vi.fn(),
10
+ getSession: vi.fn(),
8
11
  delete: vi.fn(),
9
12
  resolveReference: vi.fn(),
10
13
  list: vi.fn(),
@@ -16,6 +19,7 @@ vi.mock("@/shared/lib/api", () => ({
16
19
  nextclawClient: {
17
20
  eventBus: { on: mocks.on },
18
21
  inboxDeliveries: {
22
+ get: mocks.getDelivery,
19
23
  delete: mocks.delete,
20
24
  list: mocks.list,
21
25
  updateState: mocks.updateState,
@@ -23,6 +27,7 @@ vi.mock("@/shared/lib/api", () => ({
23
27
  systemObjectReferences: {
24
28
  resolve: mocks.resolveReference,
25
29
  },
30
+ sessions: { get: mocks.getSession },
26
31
  },
27
32
  }));
28
33
 
@@ -43,6 +48,8 @@ const delivery: InboxDelivery = {
43
48
  describe("InboxManager", () => {
44
49
  beforeEach(() => {
45
50
  vi.clearAllMocks();
51
+ mocks.getDelivery.mockResolvedValue(delivery);
52
+ mocks.getSession.mockResolvedValue({ sessionId: "source-session" });
46
53
  Object.defineProperty(document, "visibilityState", { configurable: true, value: "visible" });
47
54
  useInboxStore.setState({
48
55
  snapshot: { readerOpen: false, activeDeliveryId: null },
@@ -107,5 +114,26 @@ describe("InboxManager", () => {
107
114
  );
108
115
  expect(mocks.updateState).toHaveBeenCalledWith(delivery.id, "read");
109
116
  expect(result.reference.assetUri).toBe("asset://store/report");
117
+ expect(result.targetSessionKey).toBeNull();
118
+ });
119
+
120
+ it("targets the original report session", async () => {
121
+ mocks.getDelivery.mockResolvedValue({ ...delivery, source: { ...delivery.source, sessionId: "source-session" } });
122
+ const result = await new InboxManager(new QueryClient()).prepareChatReference(delivery.id);
123
+ expect(mocks.getSession).toHaveBeenCalledWith("source-session");
124
+ expect(result.targetSessionKey).toBe("source-session");
125
+ });
126
+
127
+ it("falls back to a draft only when the source session was deleted", async () => {
128
+ mocks.getDelivery.mockResolvedValue({ ...delivery, source: { ...delivery.source, sessionId: "deleted" } });
129
+ mocks.getSession.mockRejectedValueOnce(new NextClawClientError({ message: "Missing", status: 404 }));
130
+ expect((await new InboxManager(new QueryClient()).prepareChatReference(delivery.id)).targetSessionKey).toBeNull();
131
+ });
132
+
133
+ it("keeps the report unread when the source session lookup fails", async () => {
134
+ mocks.getDelivery.mockResolvedValue({ ...delivery, source: { ...delivery.source, sessionId: "source-session" } });
135
+ mocks.getSession.mockRejectedValueOnce(new NextClawClientError({ message: "Offline", status: 503 }));
136
+ await expect(new InboxManager(new QueryClient()).prepareChatReference(delivery.id)).rejects.toThrow("Offline");
137
+ expect(mocks.updateState).not.toHaveBeenCalled();
110
138
  });
111
139
  });
@@ -13,6 +13,7 @@ import {
13
13
  import { appQueryClient } from "@/app-query-client";
14
14
  import { useInboxStore } from "@/features/inbox/stores/inbox.store";
15
15
  import { nextclawClient } from "@/shared/lib/api";
16
+ import { NextClawClientError } from "@nextclaw/client-sdk";
16
17
 
17
18
  export const INBOX_DELIVERIES_QUERY_KEY = ["inbox-deliveries"] as const;
18
19
 
@@ -112,13 +113,26 @@ export class InboxManager {
112
113
  prepareChatReference = async (deliveryId: string): Promise<{
113
114
  delivery: InboxDelivery;
114
115
  reference: SystemObjectResolvedReference;
116
+ targetSessionKey: string | null;
115
117
  }> => {
116
- const reference = await nextclawClient.systemObjectReferences.resolve(
117
- createSystemObjectReferenceUri(SYSTEM_OBJECT_TYPE_INBOX_DELIVERY, deliveryId),
118
- );
118
+ const [reference, sourceDelivery] = await Promise.all([
119
+ nextclawClient.systemObjectReferences.resolve(
120
+ createSystemObjectReferenceUri(SYSTEM_OBJECT_TYPE_INBOX_DELIVERY, deliveryId),
121
+ ),
122
+ nextclawClient.inboxDeliveries.get(deliveryId),
123
+ ]);
124
+ let targetSessionKey = sourceDelivery.source.sessionId?.trim() || null;
125
+ if (targetSessionKey) {
126
+ try {
127
+ await nextclawClient.sessions.get(targetSessionKey);
128
+ } catch (error) {
129
+ if (!(error instanceof NextClawClientError) || error.status !== 404) throw error;
130
+ targetSessionKey = null;
131
+ }
132
+ }
119
133
  const delivery = await this.updateState(deliveryId, "read");
120
134
  this.closeReader();
121
- return { delivery, reference };
135
+ return { delivery, reference, targetSessionKey };
122
136
  };
123
137
 
124
138
  private updateState = async (
@@ -7,13 +7,15 @@ import { InboxPage, resolveInboxFilter } from "@/features/inbox/pages/inbox-page
7
7
  import { t } from "@/shared/lib/i18n";
8
8
 
9
9
  const mocks = vi.hoisted(() => ({
10
+ isMobile: false,
10
11
  prepareChatReference: vi.fn(),
11
12
  requestSystemObjectReference: vi.fn(),
12
13
  }));
13
14
 
14
15
  vi.mock("@/app/components/app-presenter-provider", () => ({
15
16
  useAppPresenter: () => ({
16
- chatDraftIntentManager: {
17
+ docBrowserManager: { close: vi.fn() },
18
+ chatComposerIntentManager: {
17
19
  requestSystemObjectReference: mocks.requestSystemObjectReference,
18
20
  },
19
21
  inboxManager: {
@@ -28,7 +30,7 @@ vi.mock("@/app/components/app-presenter-provider", () => ({
28
30
  }));
29
31
 
30
32
  vi.mock("@/app/hooks/use-viewport-layout", () => ({
31
- useViewportLayout: () => ({ isMobile: false }),
33
+ useViewportLayout: () => ({ isMobile: mocks.isMobile }),
32
34
  }));
33
35
 
34
36
  vi.mock("@/features/inbox/hooks/use-inbox-deliveries", () => ({
@@ -101,7 +103,9 @@ describe("resolveInboxFilter", () => {
101
103
  describe("InboxPage", () => {
102
104
  beforeEach(() => {
103
105
  vi.clearAllMocks();
106
+ mocks.isMobile = false;
104
107
  mocks.prepareChatReference.mockResolvedValue({
108
+ targetSessionKey: null,
105
109
  reference: {
106
110
  uri: "nextclaw://objects/inbox-delivery/delivery-1",
107
111
  label: "A considered report",
@@ -109,7 +113,8 @@ describe("InboxPage", () => {
109
113
  });
110
114
  });
111
115
 
112
- it("opens a draft with the same visible system object intent as the reader dialog", async () => {
116
+ it.each([false, true])("opens a draft with the same system object intent (mobile=%s)", async (isMobile) => {
117
+ mocks.isMobile = isMobile;
113
118
  render(
114
119
  createElement(
115
120
  MemoryRouter,
@@ -134,14 +139,20 @@ describe("InboxPage", () => {
134
139
  ),
135
140
  );
136
141
 
137
- fireEvent.click(screen.getByRole("button", { name: t("inboxContinueChat") }));
142
+ const continueButton = screen.getByRole("button", { name: t("inboxContinueChat") });
143
+ if (isMobile) {
144
+ const moreButton = screen.getByRole("button", { name: t("more") });
145
+ expect(continueButton.compareDocumentPosition(moreButton) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
146
+ expect(screen.getByRole("button", { name: t("inboxTitle") })).toBeTruthy();
147
+ }
148
+ fireEvent.click(continueButton);
138
149
 
139
150
  await waitFor(() => {
140
151
  expect(screen.getByTestId("current-path").textContent).toBe(CHAT_DRAFT_SESSION_PATH);
141
152
  });
142
153
  expect(mocks.prepareChatReference).toHaveBeenCalledWith("delivery-1");
143
154
  expect(mocks.requestSystemObjectReference).toHaveBeenCalledWith(
144
- expect.objectContaining({ uri: "nextclaw://objects/inbox-delivery/delivery-1" }),
155
+ { targetSessionKey: null, reference: expect.objectContaining({ uri: "nextclaw://objects/inbox-delivery/delivery-1" }) },
145
156
  );
146
157
  });
147
158
  });
@@ -2,14 +2,14 @@ import { PageResourceActionsMenu } from '@/features/right-panel-resources';
2
2
  import { pageResourceFromSystemObject } from '@/features/right-panel-resources';
3
3
  import { useEffect, useMemo, useState } from "react";
4
4
  import type { InboxDelivery } from "@nextclaw/shared";
5
- import { Archive, Inbox, MessageCircle, MoreVertical, RotateCcw, Trash2 } from "lucide-react";
5
+ import { Archive, ArrowLeft, Inbox, MessageCircle, MoreVertical, RotateCcw, Trash2 } from "lucide-react";
6
6
  import { ContextMenu, ContextMenuTrigger } from '@/shared/components/ui/context-menu/context-menu';
7
7
  import { IconActionButton } from '@/shared/components/ui/actions/icon-action-button';
8
8
  import { Link, useNavigate, useParams } from "react-router-dom";
9
9
  import { useAppPresenter } from "@/app/components/app-presenter-provider";
10
10
  import { PageHeader } from "@/app/components/layout/page-layout";
11
11
  import { useViewportLayout } from "@/app/hooks/use-viewport-layout";
12
- import { CHAT_DRAFT_SESSION_PATH } from "@/features/chat";
12
+ import { buildSessionPath, CHAT_DRAFT_SESSION_PATH } from "@/features/chat";
13
13
  import { InboxDeliveryContent } from "@/features/inbox/components/inbox-delivery-content";
14
14
  import { useInboxDeliveries } from "@/features/inbox/hooks/use-inbox-deliveries";
15
15
  import { Button } from "@/shared/components/ui/button";
@@ -167,6 +167,7 @@ function InboxListPane({
167
167
 
168
168
  function InboxDetailPane({
169
169
  delivery,
170
+ isMobile,
170
171
  error,
171
172
  pending,
172
173
  onArchiveToggle,
@@ -175,6 +176,7 @@ function InboxDetailPane({
175
176
  onReadToggle,
176
177
  }: {
177
178
  delivery: InboxDelivery | null;
179
+ isMobile: boolean;
178
180
  error: string | null;
179
181
  pending: boolean;
180
182
  onArchiveToggle: () => void;
@@ -182,38 +184,52 @@ function InboxDetailPane({
182
184
  onDelete: () => void;
183
185
  onReadToggle: () => void;
184
186
  }) {
187
+ const navigate = useNavigate();
188
+ const backButton = <IconActionButton size="sm" icon={<ArrowLeft className="h-4 w-4" />} label={t("inboxTitle")} onClick={() => navigate('/inbox')} />;
185
189
  const scrollRestoration = useScrollRestoration<HTMLDivElement>({
186
190
  restorationKey: delivery ? `inbox:delivery:${delivery.id}` : null,
187
191
  });
188
192
  const { onScroll, scrollRef } = scrollRestoration;
189
193
  if (!delivery) {
190
- return <main className="flex min-h-0 flex-col"><InboxEmptyState selection /></main>;
194
+ return <main className="flex min-h-0 flex-col"><div className="md:hidden">{backButton}</div><InboxEmptyState selection /></main>;
191
195
  }
192
196
  const isHtml = delivery.contentType === "html";
193
197
  return (
194
- <main className="flex min-h-0 flex-col">
195
- <div className="shrink-0 px-4 py-2 md:border-b md:border-border/50 md:px-6 md:py-3">
196
- <div className="flex min-h-7 min-w-0 items-center gap-2">
198
+ <main className="flex min-h-0 min-w-0 flex-col max-md:pt-[env(safe-area-inset-top,0px)] max-md:pb-[env(safe-area-inset-bottom,0px)]">
199
+ <div className="shrink-0 border-b border-border/50 px-2 py-2 md:px-6 md:py-3">
200
+ <div className="flex min-h-7 min-w-0 items-center gap-1">
201
+ <div className="md:hidden">{backButton}</div>
197
202
  <h2
198
203
  title={delivery.title}
199
- className="min-w-0 truncate text-sm font-medium text-foreground"
204
+ className="min-w-0 flex-1 truncate text-sm font-medium text-foreground md:flex-none"
200
205
  >
201
206
  {delivery.title}
202
207
  </h2>
203
- <span className="hidden shrink-0 text-muted-foreground sm:inline" aria-hidden="true">·</span>
208
+ <span className="hidden shrink-0 text-muted-foreground md:inline" aria-hidden="true">·</span>
204
209
  <time
205
- className="hidden shrink-0 text-[11px] tabular-nums text-muted-foreground sm:block"
210
+ className="hidden shrink-0 text-[11px] tabular-nums text-muted-foreground md:block"
206
211
  dateTime={delivery.createdAt}
207
212
  >
208
213
  {formatDateTime(delivery.createdAt)}
209
214
  </time>
215
+ {isMobile ? <div className="flex shrink-0 items-center">
216
+ <IconActionButton size="sm" icon={<MessageCircle className="h-4 w-4" />} label={t('inboxContinueChat')} disabled={pending} onClick={onContinue} />
217
+ <ContextMenu label={t('inboxTitle')} groups={[{ key: 'delivery', items: [
218
+ { key: 'read', label: delivery.readAt ? t('inboxMarkUnread') : t('inboxMarkRead'), disabled: pending, onSelect: onReadToggle },
219
+ { key: 'archive', label: delivery.archivedAt ? t('inboxRestore') : t('inboxArchive'), icon: <Archive className="h-4 w-4" />, disabled: pending, onSelect: onArchiveToggle },
220
+ { key: 'delete', label: t('inboxDelete'), icon: <Trash2 className="h-4 w-4" />, destructive: true, disabled: pending, onSelect: onDelete },
221
+ ] }]}>
222
+ <div><ContextMenuTrigger><IconActionButton size="sm" icon={<MoreVertical className="h-4 w-4" />} label={t('more')} /></ContextMenuTrigger></div>
223
+ </ContextMenu>
224
+ </div> : null}
210
225
  </div>
211
226
  </div>
227
+ {error ? <p role="alert" className="shrink-0 px-4 py-2 text-sm text-destructive">{error}</p> : null}
212
228
  <div className={cn(
213
229
  "min-h-0 flex-1",
214
230
  isHtml
215
231
  ? "p-0 md:p-4"
216
- : "custom-scrollbar overflow-y-auto px-5 py-5 sm:px-6 sm:py-6",
232
+ : "custom-scrollbar overflow-y-auto overscroll-contain px-4 py-4 sm:px-6 sm:py-6",
217
233
  )}
218
234
  ref={scrollRef}
219
235
  onScroll={onScroll}
@@ -228,8 +244,7 @@ function InboxDetailPane({
228
244
  />
229
245
  </div>
230
246
  </div>
231
- <div className="shrink-0 border-t border-border/50 px-4 py-2 md:px-6 md:py-3">
232
- {error ? <p role="alert" className="mb-2 text-sm text-destructive">{error}</p> : null}
247
+ {!isMobile ? <div className="shrink-0 border-t border-border/50 px-6 py-3">
233
248
  <div className="flex items-center justify-between gap-2">
234
249
  <div className="hidden md:flex flex-wrap items-center gap-1">
235
250
  <Button size="sm" variant="outline" disabled={pending} onClick={onReadToggle}>
@@ -246,21 +261,12 @@ function InboxDetailPane({
246
261
  {t("inboxDelete")}
247
262
  </Button>
248
263
  </div>
249
- <div className="md:hidden">
250
- <ContextMenu label={t('inboxTitle')} groups={[{ key: 'delivery', items: [
251
- { key: 'read', label: delivery.readAt ? t('inboxMarkUnread') : t('inboxMarkRead'), disabled: pending, onSelect: onReadToggle },
252
- { key: 'archive', label: delivery.archivedAt ? t('inboxRestore') : t('inboxArchive'), icon: <Archive className="h-4 w-4" />, disabled: pending, onSelect: onArchiveToggle },
253
- { key: 'delete', label: t('inboxDelete'), icon: <Trash2 className="h-4 w-4" />, destructive: true, disabled: pending, onSelect: onDelete },
254
- ] }]}>
255
- <div><ContextMenuTrigger><IconActionButton icon={<MoreVertical className="h-4 w-4" />} label={t('more')} /></ContextMenuTrigger></div>
256
- </ContextMenu>
257
- </div>
258
264
  <Button size="sm" disabled={pending} onClick={onContinue}>
259
265
  <MessageCircle className="mr-2 h-4 w-4" />
260
266
  {t("inboxContinueChat")}
261
267
  </Button>
262
268
  </div>
263
- </div>
269
+ </div> : null}
264
270
  </main>
265
271
  );
266
272
  }
@@ -269,7 +275,7 @@ export function InboxPage() {
269
275
  const navigate = useNavigate();
270
276
  const { deliveryId } = useParams<{ deliveryId?: string }>();
271
277
  const { isMobile } = useViewportLayout();
272
- const { chatDraftIntentManager, inboxManager } = useAppPresenter();
278
+ const { chatComposerIntentManager, docBrowserManager, inboxManager } = useAppPresenter();
273
279
  const deliveriesQuery = useInboxDeliveries();
274
280
  const { confirm, ConfirmDialog } = useConfirmDialog();
275
281
  const [selectedFilter, setSelectedFilter] = useState<InboxFilter | null>(null);
@@ -310,9 +316,10 @@ export function InboxPage() {
310
316
  return;
311
317
  }
312
318
  void runAction("continue", async () => {
313
- const { reference } = await inboxManager.prepareChatReference(activeDelivery.id);
314
- chatDraftIntentManager.requestSystemObjectReference(reference);
315
- navigate(CHAT_DRAFT_SESSION_PATH);
319
+ const { reference, targetSessionKey } = await inboxManager.prepareChatReference(activeDelivery.id);
320
+ chatComposerIntentManager.requestSystemObjectReference({ targetSessionKey, reference });
321
+ if (isMobile) docBrowserManager.close();
322
+ navigate(targetSessionKey ? buildSessionPath(targetSessionKey) : CHAT_DRAFT_SESSION_PATH);
316
323
  });
317
324
  };
318
325
 
@@ -359,8 +366,8 @@ export function InboxPage() {
359
366
  });
360
367
  };
361
368
 
362
- const showList = !isMobile || !activeDelivery;
363
- const showDetail = !isMobile || Boolean(activeDelivery);
369
+ const showList = !isMobile || !deliveryId;
370
+ const showDetail = !isMobile || Boolean(deliveryId);
364
371
 
365
372
  return (
366
373
  <div className="flex h-full min-h-0 flex-col md:gap-6">
@@ -372,7 +379,7 @@ export function InboxPage() {
372
379
 
373
380
  <div className="min-h-0 flex-1 overflow-hidden bg-background md:rounded-2xl md:border md:border-border/60">
374
381
  {deliveriesQuery.isError ? (
375
- <div role="alert" className="p-6 text-sm text-destructive">{t("inboxLoadError")}</div>
382
+ <div className="p-4">{isMobile && deliveryId ? <IconActionButton icon={<ArrowLeft className="h-4 w-4" />} label={t("inboxTitle")} onClick={() => navigate('/inbox')} /> : null}<p role="alert" className="text-sm text-destructive">{t("inboxLoadError")}</p></div>
376
383
  ) : (
377
384
  <div className="grid h-full min-h-0 grid-cols-1 md:grid-cols-[300px_minmax(0,1fr)]">
378
385
  {showList ? <InboxListPane
@@ -383,6 +390,7 @@ export function InboxPage() {
383
390
  /> : null}
384
391
  {showDetail ? <InboxDetailPane
385
392
  delivery={activeDelivery}
393
+ isMobile={isMobile}
386
394
  error={error}
387
395
  pending={pendingAction !== null}
388
396
  onArchiveToggle={toggleArchive}
@@ -1,3 +1,4 @@
1
+ import { ACTION_FEEDBACK, ACTION_MENU_ITEM_CLASS } from '@/shared/components/ui/actions/action-feedback';
1
2
  import { useState, type MouseEvent } from 'react';
2
3
  import { MoreVertical, Star, Trash2, type LucideIcon } from 'lucide-react';
3
4
  import type { PanelAppEntryView } from '@/shared/lib/api';
@@ -127,13 +128,13 @@ function PanelAppMenuItem({
127
128
  <button
128
129
  type="button"
129
130
  className={cn(
130
- 'flex w-full items-center gap-2 rounded-lg px-2.5 py-2 text-left text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-50',
131
- destructive ? 'text-destructive hover:bg-destructive/10' : 'text-muted-foreground hover:bg-[var(--interaction-hover)] hover:text-accent-foreground',
131
+ ACTION_MENU_ITEM_CLASS,
132
+ destructive ? ACTION_FEEDBACK.destructive : `text-foreground ${ACTION_FEEDBACK.item}`,
132
133
  )}
133
134
  disabled={disabled}
134
135
  onClick={onClick}
135
136
  >
136
- <Icon className="h-4 w-4 shrink-0" />
137
+ <Icon className={cn("h-4 w-4 shrink-0", !destructive && "text-muted-foreground")} />
137
138
  <span>{label}</span>
138
139
  </button>
139
140
  );
@@ -26,8 +26,8 @@ export function PanelAppServiceActionAuthorizationDialog() {
26
26
  }
27
27
  }}
28
28
  >
29
- <DialogContent className="[&>:last-child]:hidden">
30
- <DialogHeader>
29
+ <DialogContent>
30
+ <DialogHeader showClose={false}>
31
31
  <DialogTitle className="flex items-center gap-2">
32
32
  <ShieldAlert className="h-4 w-4 text-amber-600" />
33
33
  {t('serviceActionAuthorizationTitle')}
@@ -2,16 +2,15 @@ import { AppWindow, Boxes } from 'lucide-react';
2
2
  import type { DocBrowserContextValue } from '@/shared/components/doc-browser/doc-browser-context';
3
3
  import type { DocBrowserCustomTabRenderers } from '@/shared/components/doc-browser/doc-browser-renderer.types';
4
4
  import { getPresenter } from '@/app/presenters/app.presenter';
5
- import { AppsPanel, type AppsPanelTab } from '@/features/apps';
5
+ import { AppsPanel } from '@/features/apps';
6
6
  import { PanelAppDocBrowserToolbar } from '@/features/panel-apps/components/panel-app-toolbar';
7
7
  import {
8
8
  createPanelAppRightPanelResourceTarget,
9
9
  RIGHT_PANEL_APPS_TAB_KIND,
10
- RIGHT_PANEL_APPS_URL,
10
+ createRightPanelAppsUrl,
11
+ getRightPanelAppsTabFromUrl,
11
12
  RIGHT_PANEL_HOME_TAB_KIND,
12
13
  RIGHT_PANEL_PANEL_APP_TAB_KIND,
13
- RIGHT_PANEL_PANEL_APPS_URL,
14
- RIGHT_PANEL_SERVICE_APPS_URL,
15
14
  RightPanelResourceHomePage,
16
15
  } from '@/features/right-panel-resources';
17
16
  import { t } from '@/shared/lib/i18n';
@@ -19,26 +18,8 @@ import { PANEL_APP_IFRAME_SANDBOX, focusPanelAppIframe } from './panel-app-ifram
19
18
 
20
19
  export const APPS_TAB_KIND = RIGHT_PANEL_APPS_TAB_KIND;
21
20
  export const PANEL_APP_TAB_KIND = RIGHT_PANEL_PANEL_APP_TAB_KIND;
22
- const DEFAULT_APPS_PANEL_TAB: AppsPanelTab = 'apps';
23
-
24
- function isAppsPanelTab(value: unknown): value is AppsPanelTab {
25
- return value === 'apps' || value === 'panel-apps' || value === 'service-apps';
26
- }
27
-
28
- export function createAppsPanelUrl(tab: AppsPanelTab = DEFAULT_APPS_PANEL_TAB): string {
29
- if (tab === 'panel-apps') return RIGHT_PANEL_PANEL_APPS_URL;
30
- if (tab === 'service-apps') return RIGHT_PANEL_SERVICE_APPS_URL;
31
- return RIGHT_PANEL_APPS_URL;
32
- }
33
-
34
- export function getAppsPanelTabFromUrl(url: string): AppsPanelTab {
35
- try {
36
- const tab = new URL(url).searchParams.get('tab');
37
- return isAppsPanelTab(tab) ? tab : DEFAULT_APPS_PANEL_TAB;
38
- } catch {
39
- return DEFAULT_APPS_PANEL_TAB;
40
- }
41
- }
21
+ export const createAppsPanelUrl = createRightPanelAppsUrl;
22
+ export const getAppsPanelTabFromUrl = getRightPanelAppsTabFromUrl;
42
23
 
43
24
  export function openApps(docBrowser: Pick<DocBrowserContextValue, 'open'>): void {
44
25
  docBrowser.open(createAppsPanelUrl(), {
@@ -255,7 +255,7 @@ function ProjectWorkStateGroup({
255
255
  <div
256
256
  className={
257
257
  view === "board"
258
- ? "min-h-0 flex-1 space-y-2 overflow-y-auto overscroll-contain px-1 pb-3"
258
+ ? "min-h-0 flex-1 space-y-2 overflow-y-auto px-1 pb-3"
259
259
  : "space-y-2 px-1 pb-3"
260
260
  }
261
261
  >
@@ -1,5 +1,5 @@
1
1
  import { useState } from "react";
2
- import { useNavigate, useParams } from "react-router-dom";
2
+ import { useLocation, useNavigate, useParams } from "react-router-dom";
3
3
  import { useProjects } from "@/shared/hooks/use-projects";
4
4
  import { useViewportLayout } from "@/app/hooks/use-viewport-layout";
5
5
  import { t } from "@/shared/lib/i18n";
@@ -43,6 +43,7 @@ export function ProjectsPage() {
43
43
  tab?: string;
44
44
  }>();
45
45
  const navigate = useNavigate();
46
+ const { state } = useLocation();
46
47
  const presenter = usePresenter();
47
48
  const { isMobile } = useViewportLayout();
48
49
  const projects = useProjects();
@@ -86,7 +87,7 @@ export function ProjectsPage() {
86
87
  <select
87
88
  id="project-home-selection"
88
89
  value=""
89
- onChange={(event) => navigate(`/projects/${encodeURIComponent(event.target.value)}/overview`)}
90
+ onChange={(event) => navigate(`/projects/${encodeURIComponent(event.target.value)}/overview`, { state })}
90
91
  className="min-h-11 w-full rounded-xl border border-border bg-card px-3 text-base text-foreground"
91
92
  >
92
93
  <option value="" disabled>{t("projectsChoose")}</option>
@@ -117,6 +118,7 @@ export function ProjectsPage() {
117
118
  onValueChange={(value) =>
118
119
  navigate(
119
120
  `/projects/${encodeURIComponent(selectedProject.id)}/${value}`,
121
+ { state },
120
122
  )
121
123
  }
122
124
  >