collabmd 0.1.48 → 0.1.49
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/README.md +61 -5
- package/bin/collabmd.js +3 -0
- package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-C-nmgL5g.js +1 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-CdVZqicp.js +1 -0
- package/dist/client/assets/{architectureDiagram-5GKGNRK7-I39sYjHI.js → architectureDiagram-5GKGNRK7-wUo0bXif.js} +3 -3
- package/dist/client/assets/{blockDiagram-NRAW4CY4-C6DtJy5Y.js → blockDiagram-I7D4REHJ-BRSK3m49.js} +4 -4
- package/dist/client/assets/browser-utils-DbXSMI-6.js +1 -0
- package/dist/client/assets/{c4Diagram-UCG6FXSJ-CtWtxS9_.js → c4Diagram-7LVT6UL2-yD2poxqw.js} +1 -1
- package/dist/client/assets/channel-Fa4GS_-F.js +1 -0
- package/dist/client/assets/chunk-2E4U76K2-BPnTT-J3.js +2 -0
- package/dist/client/assets/{chunk-TEH6E4GO-DVayPj-q.js → chunk-4HAMMTFA-DStbIfJ1.js} +20 -20
- package/dist/client/assets/{chunk-75Z2AOVW-CdFSaPjz.js → chunk-75Z2AOVW-C5pGd3W9.js} +1 -1
- package/dist/client/assets/{chunk-CLGD4ZFX-DQLgbQrv.js → chunk-CLGD4ZFX-BMeArk03.js} +1 -1
- package/dist/client/assets/chunk-DU6HZSFF-Zkp69c6c.js +127 -0
- package/dist/client/assets/{chunk-F27PBJKO-CNHIFhjo.js → chunk-F27PBJKO-D4xNct1r.js} +1 -1
- package/dist/client/assets/{chunk-GMAD6QVW-CbcBqPM5.js → chunk-GMAD6QVW-NZ6WpDb8.js} +1 -1
- package/dist/client/assets/{chunk-OBVCFTLP-BJR7u1jh.js → chunk-GVQU2GXP-D8SDprfX.js} +1 -1
- package/dist/client/assets/{chunk-G27WJ6UU-D9-eg537.js → chunk-IMKFNOWR-D8jEuU3Q.js} +2 -2
- package/dist/client/assets/{chunk-JQ64N6SF-DSFNH4bh.js → chunk-L3NEJ4N5-aijKP-eh.js} +1 -1
- package/dist/client/assets/chunk-OSK3NFVY-CCbLQAMa.js +10 -0
- package/dist/client/assets/{chunk-P2QGCYS3-BRpqY32H.js → chunk-P2QGCYS3-Oag_FdCq.js} +1 -1
- package/dist/client/assets/{chunk-POPQ4Y6H-Cb4SlVZF.js → chunk-POPQ4Y6H-CYnpIgXT.js} +1 -1
- package/dist/client/assets/{chunk-PWAF6VOD-Cz8IwBB5.js → chunk-PWAF6VOD-JSNrcBmP.js} +1 -1
- package/dist/client/assets/{chunk-RM4UPSZO-CWRwxNWJ.js → chunk-RM4UPSZO-DOWllDY8.js} +4 -4
- package/dist/client/assets/{chunk-RHFEMEQ7-CWY8cf4H.js → chunk-SHT3W25Y-BiQGljao.js} +5 -5
- package/dist/client/assets/{chunk-SVP7TREG-CyHOmcac.js → chunk-SVP7TREG-DB485R5x.js} +1 -1
- package/dist/client/assets/{chunk-LCL6LL3I-DmDkVukh.js → chunk-TICWLB2K-8rAVvoS3.js} +4 -4
- package/dist/client/assets/{chunk-CKBBP62Z-DG26UiBv.js → chunk-TLUHSLCS-DTY5v0aj.js} +2 -2
- package/dist/client/assets/classDiagram-ZZMXUADV-BsQWoR3Q.js +1 -0
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-BsQWoR3Q.js +1 -0
- package/dist/client/assets/{comment-thread-store-CdcwrObc.js → comment-thread-store-CX98zR6q.js} +1 -1
- package/dist/client/assets/comment-threads-BnRwo5B9.js +4 -0
- package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-CdTPi2yO.js → cynefinDiagram-5FMLGOSQ-rTz9RhFH.js} +1 -1
- package/dist/client/assets/{dagre-3AP2YEHR-5gtJtd0O.js → dagre-GXQ25YYZ-Cr67wLpQ.js} +2 -2
- package/dist/client/assets/{diagram-S7CK7UJ4-BudWz9WU.js → diagram-S7CK7UJ4-DywERe__.js} +2 -2
- package/dist/client/assets/{diagram-UQ7AKVKN-3v4rbH-s.js → diagram-UQ7AKVKN-CNYlXtu4.js} +1 -1
- package/dist/client/assets/diagram-VSXAHHWV-0H1a61Bn.js +3 -0
- package/dist/client/assets/{diagram-VX7I27RA-C_-rj0sw.js → diagram-VX7I27RA-CsJbsx5F.js} +1 -1
- package/dist/client/assets/{diagram-Z3DM3KII-B4yxavgj.js → diagram-Z3DM3KII-D0mLxEgI.js} +1 -1
- package/dist/client/assets/dist--hk9I5HQ.js +1 -0
- package/dist/client/assets/{dist-DutPuFmC.js → dist-B1XEa-Zs.js} +1 -1
- package/dist/client/assets/dist-Bd1JucQF.js +1 -0
- package/dist/client/assets/{dist-DZAAWTG-.js → dist-C0G3AaXG.js} +1 -1
- package/dist/client/assets/dist-Dm4w5UId.js +1 -0
- package/dist/client/assets/{dist-B_yQaEv_.js → dist-DpYDHR9p.js} +1 -1
- package/dist/client/assets/{dist-CietwTVS.js → dist-DzNmC81X.js} +1 -1
- package/dist/client/assets/{dist-DDUn5zTz.js → dist-GvvCNBe4.js} +1 -1
- package/dist/client/assets/dist-JaU3aRlD.js +19 -0
- package/dist/client/assets/{dist-Bw3VIE_v.js → dist-TW8iFRyW.js} +1 -1
- package/dist/client/assets/{dist-Dir5dDKZ.js → dist-jVU5Be5P.js} +1 -1
- package/dist/client/assets/document-formatter-rDDjRfZ2.js +2 -0
- package/dist/client/assets/drawioEditor-JubEEha7.js +9 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-HeTxHpCU.js +1 -0
- package/dist/client/assets/editor-session-Bk6oIvSr.js +54 -0
- package/dist/client/assets/{embedded-editor-base-B3l6Xy65.css → embedded-editor-base-BlCgz6mw.css} +1 -1
- package/dist/client/assets/{erDiagram-SSCWMZ5O-C-iy6VkX.js → erDiagram-RLTQ6QDP-CbrDdd5P.js} +2 -2
- package/dist/client/assets/{vault-utils-DvoSftJT.js → es-Bfdp096f.js} +13 -13
- package/dist/client/assets/excalidraw-element-link-YLIaTnVF.js +7 -0
- package/dist/client/assets/{excalidraw-scene-BOben2gr.js → excalidraw-scene-6uROebca.js} +1 -1
- package/dist/client/assets/excalidrawEditor-dBMbRX_S.js +9 -0
- package/dist/client/assets/export-page-CRRQ2NEl.js +57 -0
- package/dist/client/assets/exportDocument-BlQRd9_m.js +2 -0
- package/dist/client/assets/exportDocument-CNSbjZwu.css +1 -0
- package/dist/client/assets/flowDiagram-HODETNUW-D5Gy0wmg.js +1 -0
- package/dist/client/assets/{ganttDiagram-EL5Y4UJY-DtKHAbez.js → ganttDiagram-EL5Y4UJY-BHgOYiZz.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-oue8fQ5o.js → gitGraphDiagram-WWUBYQGX-Dl__X3Sk.js} +1 -1
- package/dist/client/assets/image-ZVKINSPA-DgzW5zAy.js +1 -0
- package/dist/client/assets/index-D3RER1SZ.js +1023 -0
- package/dist/client/assets/index-DREVKl_K.css +1 -0
- package/dist/client/assets/{infoDiagram-RXCK75RN-BMzo6KIn.js → infoDiagram-27XIBGKW-DBpoANC9.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-5VMMS53U-BIM3h287.js → ishikawaDiagram-5VMMS53U-BMPC6hfp.js} +1 -1
- package/dist/client/assets/{journeyDiagram-EYS64GPL-mF6Lh8O-.js → journeyDiagram-3NMN7TZE-B1sApUmM.js} +2 -2
- package/dist/client/assets/{kanban-definition-3QL26DDD-DLN2NyoR.js → kanban-definition-UXKFOSKX-C9yP4td1.js} +4 -4
- package/dist/client/assets/{line-BfTWJmgf.js → line-BFl3ujec.js} +1 -1
- package/dist/client/assets/mermaid.core-BrY09czX.js +11 -0
- package/dist/client/assets/mermaid.core-DfcNfOTv.js +1 -0
- package/dist/client/assets/{mindmap-definition-FBJOCRG2-CRyHaHTk.js → mindmap-definition-YA3MSWOX-BUQHcYbK.js} +8 -8
- package/dist/client/assets/pegDiagram-XKGWAZYB-Bi2Iml7Z.js +1 -0
- package/dist/client/assets/{pieDiagram-E7YTZNPT-B5OZPb88.js → pieDiagram-E7YTZNPT-_gYXnMoi.js} +1 -1
- package/dist/client/assets/preview-render-compiler-CfxJYldJ.js +41 -0
- package/dist/client/assets/preview-render-compiler-Cu8_i9iS.js +1 -0
- package/dist/client/assets/{preview-render-worker-_QTxqKvP.js → preview-render-worker-c4Yi93qW.js} +41 -35
- package/dist/client/assets/prod-BiJL30sl.js +1 -0
- package/dist/client/assets/prod-qAk7rHa4.js +177 -0
- package/dist/client/assets/{quadrantDiagram-AXDQQJYC-Drrw14YH.js → quadrantDiagram-AXDQQJYC-DwexhEhd.js} +1 -1
- package/dist/client/assets/quick-switcher-controller-BoIK_wuG.js +1 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-BVA5UbMu.js +1 -0
- package/dist/client/assets/{requirementDiagram-EFPCY7ZU-CRZG6mRB.js → requirementDiagram-BXWQKSXE-C4cKwiIw.js} +2 -2
- package/dist/client/assets/runtime-config-DcmnGcXU.js +1 -0
- package/dist/client/assets/{sankeyDiagram-P5KCCOFB-DvarEJpo.js → sankeyDiagram-P5KCCOFB-B5HHkRT2.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-B4oWlb-w.js → sequenceDiagram-WJ2MYXX4-BX6jqJFD.js} +6 -6
- package/dist/client/assets/{stateDiagram-HBIQ2CUA-qbHIIqRZ.js → stateDiagram-D77RDMKH-CmqxyRGx.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-zoLLQVyh.js +1 -0
- package/dist/client/assets/{swimlanes-XN3QIQJK-xB6CtUGj.js → swimlanes-42K2YHIH-Bmgb9Zld.js} +1 -1
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-DS-KQN37.js +8 -0
- package/dist/client/assets/{timeline-definition-24CTP7MA-Lj_yTNlY.js → timeline-definition-24CTP7MA-BA-lVH6P.js} +1 -1
- package/dist/client/assets/vault-api-client-iZLhMJKe.js +6 -0
- package/dist/client/assets/{vennDiagram-4TSXK5OY-BekRp5Y0.js → vennDiagram-4TSXK5OY-DNdUC_Xj.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-VM6X3IG4-kdnV_Hdm.js → wardleyDiagram-VM6X3IG4-C2oY-YbF.js} +1 -1
- package/dist/client/assets/wiki-link-resolver-DFIwErjc.js +1 -0
- package/dist/client/assets/{xychartDiagram-S5SC5T6Z-DufGwNSB.js → xychartDiagram-S5SC5T6Z-CoIR8CBX.js} +1 -1
- package/dist/client/assets/{yjs-provider-reset-guard-DE0vINDP.js → yjs-provider-reset-guard-9ul1qF6k.js} +1 -1
- package/dist/client/drawio-editor.html +11 -3
- package/dist/client/excalidraw-editor.html +45 -2
- package/dist/client/export-document.html +3 -3
- package/dist/client/index.html +67 -35
- package/integrations/pi/index.ts +94 -0
- package/package.json +41 -32
- package/src/client/app/drawio-editor.html +2 -2
- package/src/client/app/excalidraw-editor.html +2 -2
- package/src/client/app/export-document.html +1 -1
- package/src/client/app/index.html +49 -33
- package/src/client/app/main-entry.js +15 -1
- package/src/client/application/app-shell/chat-feature.js +7 -22
- package/src/client/application/app-shell/git-feature.js +23 -5
- package/src/client/application/app-shell/presence-feature.js +8 -25
- package/src/client/application/app-shell/ui-feature-shell.js +36 -91
- package/src/client/application/app-shell/ui-feature-sidebar.js +43 -7
- package/src/client/application/app-shell/ui-feature-tab-activity.js +19 -6
- package/src/client/application/app-shell/ui-feature-toolbar.js +16 -129
- package/src/client/application/app-shell-elements.js +4 -0
- package/src/client/application/preview-render-compiler.js +1 -87
- package/src/client/application/preview-render-scheduler.js +8 -24
- package/src/client/application/preview-renderer.js +2 -2
- package/src/client/application/webmcp-diagram-renderer.js +47 -0
- package/src/client/application/workspace-coordinator.js +3 -1
- package/src/client/application/workspace-route-controller.js +7 -0
- package/src/client/bootstrap/collabmd-app-shell.js +78 -1
- package/src/client/domain/excalidraw-element-link.js +73 -0
- package/src/client/domain/excalidraw-scene.js +21 -0
- package/src/client/domain/hash-routes.js +8 -0
- package/src/client/domain/room.js +1 -5
- package/src/client/domain/runtime-paths.js +5 -0
- package/src/client/excalidraw-editor.js +135 -10
- package/src/client/export/export-host.js +3 -1
- package/src/client/export/export-pipeline.js +4 -17
- package/src/client/infrastructure/agent-connection-api-client.js +23 -0
- package/src/client/infrastructure/auth-client.js +3 -13
- package/src/client/infrastructure/editor-session.js +11 -0
- package/src/client/infrastructure/editor-view-adapter.js +13 -0
- package/src/client/infrastructure/excalidraw-room-client.js +80 -1
- package/src/client/infrastructure/git-api-client.js +39 -33
- package/src/client/infrastructure/lobby-presence.js +2 -5
- package/src/client/infrastructure/runtime-config.js +11 -1
- package/src/client/infrastructure/tab-activity-lock.js +2 -5
- package/src/client/infrastructure/vault-api-client.js +33 -26
- package/src/client/infrastructure/webmcp-tool-registry.js +283 -0
- package/src/client/infrastructure/workspace-sync-client.js +6 -4
- package/src/client/presentation/agent-connection-controller.js +255 -0
- package/src/client/presentation/backlinks-panel.js +3 -0
- package/src/client/presentation/bases-preview-controller.js +27 -18
- package/src/client/presentation/comment-ui/comment-ui-card.js +4 -2
- package/src/client/presentation/create-menu-presenter.js +19 -16
- package/src/client/presentation/excalidraw-embed-controller.js +164 -4
- package/src/client/presentation/file-explorer-view.js +70 -12
- package/src/client/presentation/file-history-view-controller.js +13 -11
- package/src/client/presentation/git-diff-view-controller.js +35 -43
- package/src/client/presentation/git-panel-controller.js +77 -27
- package/src/client/presentation/image-lightbox-controller.js +20 -16
- package/src/client/presentation/layout-controller.js +3 -1
- package/src/client/presentation/quick-switcher-controller.js +20 -78
- package/src/client/presentation/quick-switcher-text-search.js +10 -14
- package/src/client/styles/components/navigation.css +1 -2
- package/src/client/styles/features/agent-connection.css +202 -0
- package/src/client/styles/features/collaboration-chat.css +8 -1
- package/src/client/styles/features/collaboration-dialogs.css +16 -1
- package/src/client/styles/features/collaboration-presence.css +17 -4
- package/src/client/styles/features/diff-toolbar.css +1 -1
- package/src/client/styles/features/media-lightbox.css +12 -3
- package/src/client/styles/features/quick-switcher.css +20 -11
- package/src/client/styles/foundation/themes.css +2 -0
- package/src/client/styles/layout/editor-page.css +25 -11
- package/src/client/styles/layout/responsive.css +2 -20
- package/src/client/styles/layout/shell.css +1 -0
- package/src/client/styles/layout/sidebar.css +7 -4
- package/src/client/styles/primitives/controls.css +21 -54
- package/src/client/styles/style.css +1 -0
- package/src/domain/agent-tool-definitions.js +796 -0
- package/src/domain/collabmd-content-capabilities.js +149 -0
- package/src/domain/collaboration-protocol.js +2 -0
- package/src/domain/comment-threads.js +3 -5
- package/src/domain/diagram-source.js +50 -0
- package/src/domain/editable-content-revision.js +10 -0
- package/src/domain/editable-text.js +3 -0
- package/src/domain/exact-text-edits.js +69 -0
- package/src/domain/excalidraw-agent-scene.js +522 -0
- package/src/domain/excalidraw-agent-verification.js +460 -0
- package/src/domain/excalidraw-room-codec.js +1 -5
- package/src/domain/video-embed.js +76 -0
- package/src/server/application/agent-connection-service.js +178 -0
- package/src/server/application/agent-content-service.js +773 -0
- package/src/server/application/workspace-reconciliation.js +5 -7
- package/src/server/config/env.js +51 -1
- package/src/server/create-app-server.js +36 -0
- package/src/server/domain/bases/base-query-service.js +1 -5
- package/src/server/domain/collaboration/collaboration-room.js +121 -25
- package/src/server/domain/collaboration/protocol.js +4 -0
- package/src/server/domain/hosted-workspace.js +21 -0
- package/src/server/domain/markdown-reference-extractor.js +15 -1
- package/src/server/infrastructure/git/git-service.js +19 -1
- package/src/server/infrastructure/git/history-service.js +1 -1
- package/src/server/infrastructure/git/local-exclude.js +25 -0
- package/src/server/infrastructure/git/parsers.js +19 -17
- package/src/server/infrastructure/git/path-utils.js +0 -16
- package/src/server/infrastructure/git/status-service.js +1 -1
- package/src/server/infrastructure/git/untracked-files.js +12 -21
- package/src/server/infrastructure/http/create-agent-api-handler.js +171 -0
- package/src/server/infrastructure/http/create-git-api-command-handler.js +32 -0
- package/src/server/infrastructure/http/create-request-handler.js +28 -0
- package/src/server/infrastructure/http/create-static-handler.js +6 -0
- package/src/server/infrastructure/mcp/create-agent-mcp-handler.js +199 -0
- package/src/server/infrastructure/persistence/agent-connection-store.js +120 -0
- package/src/server/infrastructure/persistence/pull-backup-store.js +2 -27
- package/src/server/infrastructure/persistence/vault-file-store.js +9 -2
- package/src/server/shared/agent-tool-image.js +22 -0
- package/src/server/shared/agent-tool-rate-limiter.js +20 -0
- package/src/server/startup/git-remote-bootstrap.js +5 -33
- package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-BPH4FJkv.js +0 -1
- package/dist/client/assets/abnfDiagram-VCTEODGH-BNDLzJ7L.js +0 -1
- package/dist/client/assets/browser-utils--H_DkyEF.js +0 -1
- package/dist/client/assets/channel-CaoKA_We.js +0 -1
- package/dist/client/assets/chunk-DSNCTWBM-8xkug7fQ.js +0 -2
- package/dist/client/assets/chunk-DU6HZSFF-COXDzJK1.js +0 -127
- package/dist/client/assets/chunk-R7TYR2AO-CTd0Yj98.js +0 -10
- package/dist/client/assets/classDiagram-DTDB5LWJ-7fEmn0zV.js +0 -1
- package/dist/client/assets/classDiagram-v2-JRS7N3AN-7fEmn0zV.js +0 -1
- package/dist/client/assets/comment-threads-9J6Em-_y.js +0 -4
- package/dist/client/assets/comment-ui-shared-DuoyznXW.js +0 -7
- package/dist/client/assets/diagram-VSXAHHWV-CQRVEZR7.js +0 -3
- package/dist/client/assets/dist-73RPdcyU.js +0 -1
- package/dist/client/assets/dist-CH-sQu3r.js +0 -1
- package/dist/client/assets/document-formatter-Dxl_a8XO.js +0 -2
- package/dist/client/assets/drawio-editor-BVaNNtYp.js +0 -9
- package/dist/client/assets/drawioEditor-BkIBlXx0.js +0 -2
- package/dist/client/assets/ebnfDiagram-PWID7BFC-OXa8VEp1.js +0 -1
- package/dist/client/assets/editor-session-DMyVdHLj.js +0 -54
- package/dist/client/assets/excalidraw-editor-BjYaNEMY.js +0 -9
- package/dist/client/assets/excalidraw-mermaid-stub-BNckbX2n.js +0 -1
- package/dist/client/assets/excalidraw-mermaid-stub-DE5FTiZB.js +0 -1
- package/dist/client/assets/excalidrawEditor-ChqF_d82.js +0 -2
- package/dist/client/assets/export-page-Dyu0XCbu.js +0 -57
- package/dist/client/assets/exportDocument-CJBx4Xjx.css +0 -1
- package/dist/client/assets/exportDocument-Dgvfa2Sd.js +0 -2
- package/dist/client/assets/flowDiagram-A5DVABFB-CiW1eN8C.js +0 -1
- package/dist/client/assets/image-ZVKINSPA-0zXSnE7M.js +0 -1
- package/dist/client/assets/index-CSNIMyOP.css +0 -1
- package/dist/client/assets/index-DG3N2Ps-.js +0 -2
- package/dist/client/assets/main-D0wCxpVn.js +0 -903
- package/dist/client/assets/mermaid.core-BJRLUQZE.js +0 -11
- package/dist/client/assets/pegDiagram-XKGWAZYB-B31fKPR2.js +0 -1
- package/dist/client/assets/preview-render-compiler-CrJIooVD.js +0 -35
- package/dist/client/assets/preview-render-compiler-O0JxBVNF.js +0 -1
- package/dist/client/assets/preview-render-profile-B4RWYWHt.js +0 -1
- package/dist/client/assets/prod-BiYPMR1i.js +0 -177
- package/dist/client/assets/prod-VxdGZ5Ly.js +0 -1
- package/dist/client/assets/quick-switcher-controller-CaEjEtq_.js +0 -1
- package/dist/client/assets/railroadDiagram-O6MQD6OU-BPifP0MB.js +0 -1
- package/dist/client/assets/runtime-config-BLrEKVO1.js +0 -1
- package/dist/client/assets/stateDiagram-v2-4QOOHH4V-B--gjrit.js +0 -1
- package/dist/client/assets/swimlanesDiagram-VK2B7HYN-DO8XNXEg.js +0 -8
- package/dist/client/assets/vault-api-client-BkwdFjx0.js +0 -6
- package/src/client/app/drawio-editor-entry.js +0 -1
- package/src/client/app/excalidraw-editor-entry.js +0 -1
- package/src/client/excalidraw-mermaid-stub.js +0 -7
- package/src/client/main.js +0 -16
- /package/dist/client/assets/{drawio-editor-UQQ8XHou.css → drawioEditor-UQQ8XHou.css} +0 -0
- /package/dist/client/assets/{excalidraw-editor-BbSbI80a.css → excalidrawEditor-BbSbI80a.css} +0 -0
- /package/dist/client/assets/{sizeCapture-X5ZJPWSS-B0uUizjq.js → sizeCapture-INFHLROL-B0uUizjq.js} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { setDiagramActionButtonIcon } from '../domain/diagram-action-icons.js';
|
|
2
|
+
import { parseExcalidrawElementLink } from '../domain/excalidraw-element-link.js';
|
|
2
3
|
import { reconcileEmbedEntries } from './excalidraw-embed-reconciler.js';
|
|
3
|
-
import { resolveAppUrl, resolveWsServerOverride } from '../domain/runtime-paths.js';
|
|
4
|
+
import { resolveAppPath, resolveAppUrl, resolveWsServerOverride } from '../domain/runtime-paths.js';
|
|
4
5
|
import {
|
|
5
6
|
cancelIdleRender,
|
|
6
7
|
isNearViewport,
|
|
@@ -26,6 +27,7 @@ export class ExcalidrawEmbedController {
|
|
|
26
27
|
constructor({
|
|
27
28
|
getTheme,
|
|
28
29
|
getLocalUser,
|
|
30
|
+
onOpenElement = null,
|
|
29
31
|
onOpenFile = null,
|
|
30
32
|
onStopFollowing = null,
|
|
31
33
|
onToggleQuickSwitcher = null,
|
|
@@ -35,6 +37,7 @@ export class ExcalidrawEmbedController {
|
|
|
35
37
|
}) {
|
|
36
38
|
this.getTheme = getTheme;
|
|
37
39
|
this.getLocalUser = getLocalUser;
|
|
40
|
+
this.onOpenElement = onOpenElement;
|
|
38
41
|
this.onOpenFile = onOpenFile;
|
|
39
42
|
this.onStopFollowing = onStopFollowing;
|
|
40
43
|
this.onToggleQuickSwitcher = onToggleQuickSwitcher;
|
|
@@ -56,6 +59,8 @@ export class ExcalidrawEmbedController {
|
|
|
56
59
|
this.followedPeerIdsByFilePath = new Map();
|
|
57
60
|
this.pendingDisconnectRequests = new Map();
|
|
58
61
|
this.disconnectRequestCounter = 0;
|
|
62
|
+
this.pendingAgentBridgeRequests = new Map();
|
|
63
|
+
this.agentBridgeRequestCounter = 0;
|
|
59
64
|
|
|
60
65
|
this._onMessage = this._onMessage.bind(this);
|
|
61
66
|
this._onKeyDown = this._onKeyDown.bind(this);
|
|
@@ -96,6 +101,10 @@ export class ExcalidrawEmbedController {
|
|
|
96
101
|
request.resolve(false);
|
|
97
102
|
});
|
|
98
103
|
this.pendingDisconnectRequests.clear();
|
|
104
|
+
this.pendingAgentBridgeRequests.forEach((request) => {
|
|
105
|
+
request.resolve({ status: 'destroyed' });
|
|
106
|
+
});
|
|
107
|
+
this.pendingAgentBridgeRequests.clear();
|
|
99
108
|
this.followedPeerIdsByFilePath.clear();
|
|
100
109
|
this.overlayRoot?.remove();
|
|
101
110
|
this.overlayRoot = null;
|
|
@@ -251,6 +260,28 @@ export class ExcalidrawEmbedController {
|
|
|
251
260
|
return true;
|
|
252
261
|
}
|
|
253
262
|
|
|
263
|
+
openElement(filePath, elementId, elementType = 'element') {
|
|
264
|
+
if (!filePath || !elementId) {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const entry = this._findEntryByFilePath(filePath);
|
|
269
|
+
if (!entry) {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
entry.pendingElementFocus = {
|
|
274
|
+
elementId: String(elementId),
|
|
275
|
+
elementType: elementType === 'group' ? 'group' : 'element',
|
|
276
|
+
};
|
|
277
|
+
if (entry.isReady) {
|
|
278
|
+
this._postPendingElement(entry);
|
|
279
|
+
} else if (!entry.wrapper) {
|
|
280
|
+
this._enqueueHydration(entry, { prioritize: true });
|
|
281
|
+
}
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
|
|
254
285
|
prepareFileDisconnect(filePath, { timeoutMs = 10000 } = {}) {
|
|
255
286
|
const entry = this._findEntryByFilePath(filePath);
|
|
256
287
|
if (!entry?.iframe?.contentWindow) {
|
|
@@ -310,6 +341,73 @@ export class ExcalidrawEmbedController {
|
|
|
310
341
|
});
|
|
311
342
|
}
|
|
312
343
|
|
|
344
|
+
flushPendingAgentWrites(filePath, { signal = null, timeoutMs = 1500 } = {}) {
|
|
345
|
+
const entry = this._findEntryByFilePath(filePath);
|
|
346
|
+
if (
|
|
347
|
+
!entry?.isReady
|
|
348
|
+
|| !entry.iframe?.contentWindow
|
|
349
|
+
|| this._getEntryMode(entry) !== 'edit'
|
|
350
|
+
) {
|
|
351
|
+
return Promise.resolve({ status: 'not-active' });
|
|
352
|
+
}
|
|
353
|
+
return this._requestAgentBridge(
|
|
354
|
+
entry,
|
|
355
|
+
'flush-agent-writes',
|
|
356
|
+
{},
|
|
357
|
+
{ signal, timeoutMs },
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
waitForAgentPaint(filePath, revision, {
|
|
362
|
+
afterRevision = '',
|
|
363
|
+
signal = null,
|
|
364
|
+
timeoutMs = 5000,
|
|
365
|
+
} = {}) {
|
|
366
|
+
const entry = this._findEntryByFilePath(filePath);
|
|
367
|
+
if (!entry?.isReady || !entry.iframe?.contentWindow || !revision) {
|
|
368
|
+
return Promise.resolve({ status: 'not-active' });
|
|
369
|
+
}
|
|
370
|
+
return this._requestAgentBridge(
|
|
371
|
+
entry,
|
|
372
|
+
'wait-for-agent-revision',
|
|
373
|
+
{ afterRevision, revision },
|
|
374
|
+
{ signal, timeoutMs },
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
_requestAgentBridge(entry, type, payload, { signal, timeoutMs }) {
|
|
379
|
+
const requestId = `agent-bridge-${++this.agentBridgeRequestCounter}`;
|
|
380
|
+
return new Promise((resolve) => {
|
|
381
|
+
const finish = (value) => {
|
|
382
|
+
const request = this.pendingAgentBridgeRequests.get(requestId);
|
|
383
|
+
if (!request) return;
|
|
384
|
+
window.clearTimeout(request.timeoutId);
|
|
385
|
+
signal?.removeEventListener?.('abort', request.abort);
|
|
386
|
+
this.pendingAgentBridgeRequests.delete(requestId);
|
|
387
|
+
resolve(value);
|
|
388
|
+
};
|
|
389
|
+
const abort = () => finish({ status: 'cancelled' });
|
|
390
|
+
const timeoutId = window.setTimeout(() => finish({ status: 'timeout' }), timeoutMs);
|
|
391
|
+
this.pendingAgentBridgeRequests.set(requestId, {
|
|
392
|
+
abort,
|
|
393
|
+
entry,
|
|
394
|
+
resolve: finish,
|
|
395
|
+
timeoutId,
|
|
396
|
+
});
|
|
397
|
+
signal?.addEventListener?.('abort', abort, { once: true });
|
|
398
|
+
if (signal?.aborted) {
|
|
399
|
+
abort();
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
this._postMessageToEntry(entry, {
|
|
403
|
+
...payload,
|
|
404
|
+
requestId,
|
|
405
|
+
source: 'collabmd-host',
|
|
406
|
+
type,
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
|
|
313
411
|
_ensurePlaceholderObserver() {
|
|
314
412
|
if (!this.previewContainer) {
|
|
315
413
|
return;
|
|
@@ -419,6 +517,9 @@ export class ExcalidrawEmbedController {
|
|
|
419
517
|
|
|
420
518
|
if (!entry.wrapper) {
|
|
421
519
|
const mount = this._createEmbedContainer(entry);
|
|
520
|
+
if (!mount) {
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
422
523
|
entry.header = mount.header;
|
|
423
524
|
entry.wrapper = mount.wrapper;
|
|
424
525
|
entry.iframe = mount.iframe;
|
|
@@ -491,6 +592,7 @@ export class ExcalidrawEmbedController {
|
|
|
491
592
|
reusedEntry.key = nextEntry.key;
|
|
492
593
|
reusedEntry.label = nextEntry.label;
|
|
493
594
|
reusedEntry.placeholder = nextEntry.placeholder;
|
|
595
|
+
reusedEntry.pendingElementFocus = null;
|
|
494
596
|
reusedEntry.queued = false;
|
|
495
597
|
nextEntries.set(key, reusedEntry);
|
|
496
598
|
});
|
|
@@ -644,7 +746,12 @@ export class ExcalidrawEmbedController {
|
|
|
644
746
|
}
|
|
645
747
|
|
|
646
748
|
_buildIframeUrl(entry) {
|
|
647
|
-
|
|
749
|
+
let iframeUrl;
|
|
750
|
+
try {
|
|
751
|
+
iframeUrl = new URL(resolveAppUrl(EDITOR_IFRAME_PATH));
|
|
752
|
+
} catch {
|
|
753
|
+
return null;
|
|
754
|
+
}
|
|
648
755
|
const theme = this.getTheme?.() || 'dark';
|
|
649
756
|
|
|
650
757
|
iframeUrl.searchParams.set('file', entry.filePath);
|
|
@@ -687,6 +794,11 @@ export class ExcalidrawEmbedController {
|
|
|
687
794
|
}
|
|
688
795
|
|
|
689
796
|
_createEmbedContainer(entry) {
|
|
797
|
+
const iframeUrl = this._buildIframeUrl(entry);
|
|
798
|
+
if (!iframeUrl) {
|
|
799
|
+
return null;
|
|
800
|
+
}
|
|
801
|
+
|
|
690
802
|
const wrapper = document.createElement('div');
|
|
691
803
|
wrapper.className = 'excalidraw-embed diagram-preview-shell';
|
|
692
804
|
wrapper.dataset.embedKey = entry.key;
|
|
@@ -727,7 +839,7 @@ export class ExcalidrawEmbedController {
|
|
|
727
839
|
iframe.className = 'excalidraw-embed-iframe';
|
|
728
840
|
iframe.dataset.instanceId = String(++this.instanceCounter);
|
|
729
841
|
entry.instanceId = iframe.dataset.instanceId;
|
|
730
|
-
iframe.src =
|
|
842
|
+
iframe.src = iframeUrl.toString();
|
|
731
843
|
// The controller already lazy-hydrates embeds near the viewport, so the
|
|
732
844
|
// iframe should start loading immediately once it has been mounted.
|
|
733
845
|
iframe.setAttribute('loading', 'eager');
|
|
@@ -1030,6 +1142,7 @@ export class ExcalidrawEmbedController {
|
|
|
1030
1142
|
entry.bootMode = null;
|
|
1031
1143
|
entry.loadedFilePath = null;
|
|
1032
1144
|
entry.loadedMode = null;
|
|
1145
|
+
entry.pendingElementFocus = null;
|
|
1033
1146
|
entry.placeholder = null;
|
|
1034
1147
|
if (entry.wrapper.parentElement !== warmCacheRoot) {
|
|
1035
1148
|
warmCacheRoot.appendChild(entry.wrapper);
|
|
@@ -1053,7 +1166,11 @@ export class ExcalidrawEmbedController {
|
|
|
1053
1166
|
entry.bootMode = this._getEntryMode(entry);
|
|
1054
1167
|
entry.loadedFilePath = null;
|
|
1055
1168
|
entry.loadedMode = null;
|
|
1056
|
-
|
|
1169
|
+
const iframeUrl = this._buildIframeUrl(entry);
|
|
1170
|
+
if (!iframeUrl) {
|
|
1171
|
+
return;
|
|
1172
|
+
}
|
|
1173
|
+
entry.iframe.src = iframeUrl.toString();
|
|
1057
1174
|
this._armEntryBootTimeout(entry);
|
|
1058
1175
|
}
|
|
1059
1176
|
|
|
@@ -1218,6 +1335,7 @@ export class ExcalidrawEmbedController {
|
|
|
1218
1335
|
});
|
|
1219
1336
|
this._syncEntryFollowState(entry);
|
|
1220
1337
|
this._postPendingCommentThread?.(entry);
|
|
1338
|
+
this._postPendingElement?.(entry);
|
|
1221
1339
|
if (this._entryNeedsHardReload(entry)) {
|
|
1222
1340
|
void this._hydrateEntry(entry);
|
|
1223
1341
|
}
|
|
@@ -1234,6 +1352,17 @@ export class ExcalidrawEmbedController {
|
|
|
1234
1352
|
return;
|
|
1235
1353
|
}
|
|
1236
1354
|
|
|
1355
|
+
if (msg.type === 'open-element-link') {
|
|
1356
|
+
const target = parseExcalidrawElementLink(msg.href, {
|
|
1357
|
+
appPath: resolveAppPath('/'),
|
|
1358
|
+
origin: window.location.origin,
|
|
1359
|
+
});
|
|
1360
|
+
if (target) {
|
|
1361
|
+
this.onOpenElement?.(target);
|
|
1362
|
+
}
|
|
1363
|
+
return;
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1237
1366
|
if (msg.type === 'error') {
|
|
1238
1367
|
if (entry.isParked) {
|
|
1239
1368
|
return;
|
|
@@ -1252,6 +1381,23 @@ export class ExcalidrawEmbedController {
|
|
|
1252
1381
|
return;
|
|
1253
1382
|
}
|
|
1254
1383
|
|
|
1384
|
+
if (
|
|
1385
|
+
msg.type === 'agent-writes-flushed'
|
|
1386
|
+
|| msg.type === 'agent-revision-painted'
|
|
1387
|
+
|| msg.type === 'agent-revision-not-painted'
|
|
1388
|
+
) {
|
|
1389
|
+
const request = this.pendingAgentBridgeRequests.get(msg.requestId);
|
|
1390
|
+
if (request?.entry === entry) {
|
|
1391
|
+
request.resolve({
|
|
1392
|
+
...(msg.revision ? { revision: msg.revision } : {}),
|
|
1393
|
+
status: msg.status || (msg.type === 'agent-writes-flushed'
|
|
1394
|
+
? 'flushed'
|
|
1395
|
+
: (msg.type === 'agent-revision-painted' ? 'painted' : 'not-painted')),
|
|
1396
|
+
});
|
|
1397
|
+
}
|
|
1398
|
+
return;
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1255
1401
|
if (msg.type === 'disconnect-blocked') {
|
|
1256
1402
|
entry.authorityState = msg.state || 'reconnecting-readonly';
|
|
1257
1403
|
this.toastController?.show?.('Waiting for the diagram to reconnect before leaving');
|
|
@@ -1300,6 +1446,20 @@ export class ExcalidrawEmbedController {
|
|
|
1300
1446
|
entry.pendingCommentThreadId = null;
|
|
1301
1447
|
}
|
|
1302
1448
|
|
|
1449
|
+
_postPendingElement(entry) {
|
|
1450
|
+
if (!entry?.isReady || !entry.pendingElementFocus) {
|
|
1451
|
+
return;
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
this._postMessageToEntry(entry, {
|
|
1455
|
+
elementId: entry.pendingElementFocus.elementId,
|
|
1456
|
+
elementType: entry.pendingElementFocus.elementType,
|
|
1457
|
+
source: 'collabmd-host',
|
|
1458
|
+
type: 'focus-element',
|
|
1459
|
+
});
|
|
1460
|
+
entry.pendingElementFocus = null;
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1303
1463
|
_requestPreviewViewportFit(entry) {
|
|
1304
1464
|
if (this._isFilePreviewEntry(entry)) {
|
|
1305
1465
|
return;
|
|
@@ -58,7 +58,10 @@ export class FileExplorerView {
|
|
|
58
58
|
this.longPressContext = null;
|
|
59
59
|
this.suppressedActivationTarget = null;
|
|
60
60
|
this.contextMenuCloseHandler = null;
|
|
61
|
+
this.contextMenuCloseTimer = null;
|
|
62
|
+
this.contextMenuAnchor = null;
|
|
61
63
|
this.actionSheetCloseHandler = null;
|
|
64
|
+
this.blockingModalHandler = () => this.removeContextMenu();
|
|
62
65
|
this.dragSource = null;
|
|
63
66
|
this.currentSearchQuery = '';
|
|
64
67
|
this.activeDropTarget = null;
|
|
@@ -336,6 +339,8 @@ export class FileExplorerView {
|
|
|
336
339
|
button.setAttribute('aria-expanded', String(isExpanded));
|
|
337
340
|
button.dataset.path = node.path;
|
|
338
341
|
button.dataset.entryType = 'directory';
|
|
342
|
+
// Dynamic labels are escaped and icons are application-owned markup.
|
|
343
|
+
// pi-lens-ignore: no-inner-html-js
|
|
339
344
|
button.innerHTML = `
|
|
340
345
|
<svg class="file-tree-chevron${isExpanded ? ' expanded' : ''}" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"/></svg>
|
|
341
346
|
<svg class="file-tree-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
|
|
@@ -502,6 +507,8 @@ export class FileExplorerView {
|
|
|
502
507
|
${parentPath ? `<span class="file-tree-search-path">${escapeHtml(parentPath)}</span>` : ''}
|
|
503
508
|
</span>`
|
|
504
509
|
: `<span class="file-tree-name">${escapeHtml(displayName)}</span>`;
|
|
510
|
+
// Dynamic labels are escaped and icons are application-owned markup.
|
|
511
|
+
// pi-lens-ignore: no-inner-html-js
|
|
505
512
|
button.innerHTML = `
|
|
506
513
|
${getVaultFileIconSvg(filePath)}
|
|
507
514
|
${nameMarkup}
|
|
@@ -965,18 +972,23 @@ export class FileExplorerView {
|
|
|
965
972
|
return;
|
|
966
973
|
}
|
|
967
974
|
|
|
975
|
+
const contextAnchor = event.currentTarget instanceof Element ? event.currentTarget : event.target;
|
|
976
|
+
this.contextMenuAnchor = contextAnchor instanceof HTMLElement ? contextAnchor : null;
|
|
968
977
|
if (this.isMobileViewport()) {
|
|
969
978
|
this.showActionSheet(items);
|
|
970
979
|
return;
|
|
971
980
|
}
|
|
972
981
|
|
|
973
|
-
const contextAnchor = event.currentTarget instanceof Element ? event.currentTarget : event.target;
|
|
974
982
|
const menu = document.createElement('div');
|
|
975
983
|
menu.className = 'file-context-menu';
|
|
984
|
+
menu.setAttribute('role', 'menu');
|
|
985
|
+
menu.setAttribute('aria-label', 'File actions');
|
|
976
986
|
|
|
977
987
|
for (const item of items) {
|
|
978
988
|
const button = document.createElement('button');
|
|
989
|
+
button.type = 'button';
|
|
979
990
|
button.className = `file-context-item${item.danger ? ' file-context-danger' : ''}`;
|
|
991
|
+
button.setAttribute('role', 'menuitem');
|
|
980
992
|
button.textContent = item.label;
|
|
981
993
|
button.addEventListener('click', () => {
|
|
982
994
|
this.removeContextMenu();
|
|
@@ -999,17 +1011,47 @@ export class FileExplorerView {
|
|
|
999
1011
|
}
|
|
1000
1012
|
};
|
|
1001
1013
|
this.contextMenuCloseHandler = close;
|
|
1002
|
-
|
|
1014
|
+
const handleKeydown = (keyEvent) => {
|
|
1015
|
+
const buttons = Array.from(menu.querySelectorAll('[role="menuitem"]'));
|
|
1016
|
+
const index = Math.max(0, buttons.indexOf(document.activeElement));
|
|
1017
|
+
if (keyEvent.key === 'Escape') {
|
|
1018
|
+
keyEvent.preventDefault();
|
|
1019
|
+
this.removeContextMenu();
|
|
1020
|
+
return;
|
|
1021
|
+
}
|
|
1022
|
+
if (keyEvent.key === 'Tab') {
|
|
1023
|
+
this.removeContextMenu({ restoreFocus: false });
|
|
1024
|
+
return;
|
|
1025
|
+
}
|
|
1026
|
+
const nextIndex = keyEvent.key === 'Home'
|
|
1027
|
+
? 0
|
|
1028
|
+
: keyEvent.key === 'End'
|
|
1029
|
+
? buttons.length - 1
|
|
1030
|
+
: keyEvent.key === 'ArrowDown'
|
|
1031
|
+
? (index + 1) % buttons.length
|
|
1032
|
+
: keyEvent.key === 'ArrowUp'
|
|
1033
|
+
? (index - 1 + buttons.length) % buttons.length
|
|
1034
|
+
: -1;
|
|
1035
|
+
if (nextIndex >= 0) {
|
|
1036
|
+
keyEvent.preventDefault();
|
|
1037
|
+
buttons[nextIndex]?.focus();
|
|
1038
|
+
}
|
|
1039
|
+
};
|
|
1040
|
+
menu.addEventListener('keydown', handleKeydown);
|
|
1041
|
+
document.addEventListener('collabmd:close-custom-modals', this.blockingModalHandler);
|
|
1042
|
+
this.contextMenuCloseTimer = setTimeout(() => {
|
|
1043
|
+
this.contextMenuCloseTimer = null;
|
|
1044
|
+
if (menu.isConnected && this.contextMenuCloseHandler === close) {
|
|
1045
|
+
document.addEventListener('click', close);
|
|
1046
|
+
}
|
|
1047
|
+
}, 0);
|
|
1048
|
+
menu.querySelector('[role="menuitem"]')?.focus();
|
|
1003
1049
|
}
|
|
1004
1050
|
|
|
1005
1051
|
showActionSheet(items) {
|
|
1006
|
-
const
|
|
1007
|
-
backdrop.type = 'button';
|
|
1008
|
-
backdrop.className = 'file-action-sheet-backdrop';
|
|
1009
|
-
backdrop.setAttribute('aria-label', 'Close file actions');
|
|
1010
|
-
|
|
1011
|
-
const sheet = document.createElement('div');
|
|
1052
|
+
const sheet = document.createElement('dialog');
|
|
1012
1053
|
sheet.className = 'file-action-sheet';
|
|
1054
|
+
sheet.setAttribute('aria-label', 'File actions');
|
|
1013
1055
|
|
|
1014
1056
|
items.forEach((item) => {
|
|
1015
1057
|
const button = document.createElement('button');
|
|
@@ -1038,26 +1080,42 @@ export class FileExplorerView {
|
|
|
1038
1080
|
});
|
|
1039
1081
|
sheet.appendChild(cancelButton);
|
|
1040
1082
|
|
|
1041
|
-
|
|
1083
|
+
sheet.addEventListener('cancel', (event) => {
|
|
1084
|
+
event.preventDefault();
|
|
1042
1085
|
this.removeContextMenu();
|
|
1043
1086
|
});
|
|
1087
|
+
sheet.addEventListener('click', (event) => {
|
|
1088
|
+
const bounds = sheet.getBoundingClientRect();
|
|
1089
|
+
if (event.clientX < bounds.left || event.clientX > bounds.right
|
|
1090
|
+
|| event.clientY < bounds.top || event.clientY > bounds.bottom) this.removeContextMenu();
|
|
1091
|
+
});
|
|
1044
1092
|
|
|
1045
|
-
document.body.append(
|
|
1093
|
+
document.body.append(sheet);
|
|
1094
|
+
document.addEventListener('collabmd:close-custom-modals', this.blockingModalHandler);
|
|
1046
1095
|
this.actionSheetCloseHandler = () => {
|
|
1047
|
-
|
|
1096
|
+
if (sheet.open) sheet.close();
|
|
1048
1097
|
sheet.remove();
|
|
1049
1098
|
this.actionSheetCloseHandler = null;
|
|
1050
1099
|
};
|
|
1100
|
+
sheet.showModal();
|
|
1101
|
+
sheet.querySelector('button:not(:disabled)')?.focus();
|
|
1051
1102
|
}
|
|
1052
1103
|
|
|
1053
|
-
removeContextMenu() {
|
|
1104
|
+
removeContextMenu({ restoreFocus = true } = {}) {
|
|
1054
1105
|
this.cancelLongPress();
|
|
1055
1106
|
this.clearDragFeedback();
|
|
1056
1107
|
document.querySelectorAll('.file-context-menu').forEach((menu) => menu.remove());
|
|
1108
|
+
if (this.contextMenuCloseTimer !== null) {
|
|
1109
|
+
clearTimeout(this.contextMenuCloseTimer);
|
|
1110
|
+
this.contextMenuCloseTimer = null;
|
|
1111
|
+
}
|
|
1057
1112
|
if (this.contextMenuCloseHandler) {
|
|
1058
1113
|
document.removeEventListener('click', this.contextMenuCloseHandler);
|
|
1059
1114
|
this.contextMenuCloseHandler = null;
|
|
1060
1115
|
}
|
|
1116
|
+
document.removeEventListener('collabmd:close-custom-modals', this.blockingModalHandler);
|
|
1061
1117
|
this.actionSheetCloseHandler?.();
|
|
1118
|
+
if (restoreFocus) this.contextMenuAnchor?.focus?.();
|
|
1119
|
+
this.contextMenuAnchor = null;
|
|
1062
1120
|
}
|
|
1063
1121
|
}
|
|
@@ -544,12 +544,14 @@ export class FileHistoryViewController {
|
|
|
544
544
|
this.actionsDivider?.classList.add('hidden');
|
|
545
545
|
this.editorActionsGroup?.classList.remove('hidden');
|
|
546
546
|
this.modeButtons.forEach((button) => {
|
|
547
|
+
const active = button.getAttribute('data-diff-mode') === this.diffMode;
|
|
547
548
|
button.classList.toggle('hidden', !hasSelection);
|
|
548
|
-
button.classList.toggle('active',
|
|
549
|
+
button.classList.toggle('active', active);
|
|
550
|
+
button.setAttribute?.('aria-pressed', String(active));
|
|
549
551
|
});
|
|
550
552
|
this.openEditorButton?.toggleAttribute('disabled', !this.currentFilePath);
|
|
551
553
|
if (this.openEditorButton) {
|
|
552
|
-
this.openEditorButton.textContent = 'Open
|
|
554
|
+
this.openEditorButton.textContent = 'Open file';
|
|
553
555
|
}
|
|
554
556
|
this.primaryActionButton?.toggleAttribute('disabled', true);
|
|
555
557
|
this.commitButton?.toggleAttribute('disabled', true);
|
|
@@ -562,13 +564,13 @@ export class FileHistoryViewController {
|
|
|
562
564
|
this.page?.classList.remove('hidden');
|
|
563
565
|
if (this.content) {
|
|
564
566
|
this.content.classList.add('diff-content--history');
|
|
565
|
-
this.content.innerHTML = '<div class="git-panel-empty">Loading file history
|
|
567
|
+
this.content.innerHTML = '<div class="git-panel-empty" role="status" aria-live="polite">Loading file history…</div>';
|
|
566
568
|
}
|
|
567
569
|
this.historyListElement = null;
|
|
568
570
|
this.syncToolbar();
|
|
569
571
|
}
|
|
570
572
|
|
|
571
|
-
renderEmpty(message) {
|
|
573
|
+
renderEmpty(message, { alert = false } = {}) {
|
|
572
574
|
if (!this.isActive) {
|
|
573
575
|
return;
|
|
574
576
|
}
|
|
@@ -576,7 +578,7 @@ export class FileHistoryViewController {
|
|
|
576
578
|
if (this.content) {
|
|
577
579
|
this.content.classList.add('diff-content--history');
|
|
578
580
|
// pi-lens-ignore: no-inner-html-js
|
|
579
|
-
this.content.innerHTML = `<div class="git-panel-empty">${escapeHtml(message)}</div>`;
|
|
581
|
+
this.content.innerHTML = `<div class="git-panel-empty"${alert ? ' role="alert"' : ''}>${escapeHtml(message)}</div>`;
|
|
580
582
|
}
|
|
581
583
|
this.historyListElement = null;
|
|
582
584
|
this.syncToolbar();
|
|
@@ -691,7 +693,7 @@ export class FileHistoryViewController {
|
|
|
691
693
|
type="button"
|
|
692
694
|
data-file-history-open-selected-diff
|
|
693
695
|
>
|
|
694
|
-
Open
|
|
696
|
+
Open standalone diff
|
|
695
697
|
</button>
|
|
696
698
|
${entry.type === 'commit' ? `
|
|
697
699
|
<button
|
|
@@ -699,7 +701,7 @@ export class FileHistoryViewController {
|
|
|
699
701
|
type="button"
|
|
700
702
|
data-file-history-open-selected-preview
|
|
701
703
|
>
|
|
702
|
-
Preview
|
|
704
|
+
Preview file
|
|
703
705
|
</button>
|
|
704
706
|
` : ''}
|
|
705
707
|
</div>
|
|
@@ -719,7 +721,7 @@ export class FileHistoryViewController {
|
|
|
719
721
|
<div class="diff-file-header">
|
|
720
722
|
<span class="diff-file-path">${escapeHtml(entry.pathAtCommit || this.currentFilePath || '')}</span>
|
|
721
723
|
</div>
|
|
722
|
-
<div class="diff-empty-state">Loading diff
|
|
724
|
+
<div class="diff-empty-state" role="status" aria-live="polite">Loading diff…</div>
|
|
723
725
|
</section>
|
|
724
726
|
`;
|
|
725
727
|
}
|
|
@@ -728,7 +730,7 @@ export class FileHistoryViewController {
|
|
|
728
730
|
return `
|
|
729
731
|
<section class="diff-file-block file-history-diff-block">
|
|
730
732
|
${this.renderDiffFileHeader({ path: entry.pathAtCommit || this.currentFilePath || '' })}
|
|
731
|
-
<div class="diff-empty-state">${escapeHtml(selection.error)}</div>
|
|
733
|
+
<div class="diff-empty-state" role="alert">${escapeHtml(selection.error)}</div>
|
|
732
734
|
</section>
|
|
733
735
|
`;
|
|
734
736
|
}
|
|
@@ -764,7 +766,7 @@ export class FileHistoryViewController {
|
|
|
764
766
|
|
|
765
767
|
const hasRows = Boolean(this.localChanges) || (this.history.commits?.length ?? 0) > 0;
|
|
766
768
|
if (!hasRows) {
|
|
767
|
-
this.renderEmpty(this.history.error || 'No history found for this file.');
|
|
769
|
+
this.renderEmpty(this.history.error || 'No history found for this file.', { alert: Boolean(this.history.error) });
|
|
768
770
|
return;
|
|
769
771
|
}
|
|
770
772
|
|
|
@@ -794,7 +796,7 @@ export class FileHistoryViewController {
|
|
|
794
796
|
data-file-history-load-more
|
|
795
797
|
${this.history.loadingMore ? 'disabled' : ''}
|
|
796
798
|
>
|
|
797
|
-
${this.history.loadingMore ? 'Loading
|
|
799
|
+
${this.history.loadingMore ? 'Loading…' : 'Load more'}
|
|
798
800
|
</button>
|
|
799
801
|
</div>
|
|
800
802
|
` : ''}
|