collabmd 0.1.44 → 0.1.46
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 +39 -19
- package/bin/collabmd.js +27 -1
- package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-CYM5nxUi.js +1 -0
- package/dist/client/assets/browser-utils--H_DkyEF.js +1 -0
- package/dist/client/assets/chunk-ERSWUTIN-hHdvnhaY.js +41 -0
- package/dist/client/assets/{chunk-CZQZEIFA-DT3N9fo7.js → chunk-YGJVY4SA-CjSe7Bx7.js} +2 -2
- package/dist/client/assets/comment-thread-store-CdcwrObc.js +1 -0
- package/dist/client/assets/comment-threads-9J6Em-_y.js +4 -0
- package/dist/client/assets/comment-ui-shared-BC4pt4w8.js +7 -0
- package/dist/client/assets/dist-B5HTH2BO.js +1 -0
- package/dist/client/assets/{dist-DhLvC8DS.js → dist-B5Jf1SLZ.js} +2 -2
- package/dist/client/assets/{dist-CnL7Y2sM.js → dist-BDt3rz7l.js} +1 -1
- package/dist/client/assets/dist-BEwK4csK.js +1 -0
- package/dist/client/assets/dist-BKW4PALF.js +1 -0
- package/dist/client/assets/dist-BWcHHOx-.js +1 -0
- package/dist/client/assets/{dist-CYZmbokb.js → dist-BalScOwZ.js} +9 -9
- package/dist/client/assets/dist-Bf8f4HmM.js +6 -0
- package/dist/client/assets/dist-BjHJDtyU.js +1 -0
- package/dist/client/assets/dist-Bm6pf9Bl.js +1 -0
- package/dist/client/assets/dist-BoVBdSjk.js +1 -0
- package/dist/client/assets/dist-CC5IrQMG.js +1 -0
- package/dist/client/assets/{dist-C11hHqv_.js → dist-CCP_AKPG.js} +12 -12
- package/dist/client/assets/dist-CZgOmxK6.js +1 -0
- package/dist/client/assets/{dist-D2AQ-76g.js → dist-Cqhv5LAk.js} +1 -1
- package/dist/client/assets/{dist-MvcV4190.js → dist-D-Z6FLem.js} +1 -1
- package/dist/client/assets/dist-DLMiIsNC.js +11 -0
- package/dist/client/assets/{dist-3bgCp7iY.js → dist-DZKu9Cs8.js} +1 -1
- package/dist/client/assets/dist-DaYdhcVs.js +1 -0
- package/dist/client/assets/dist-FWJsgGYI.js +1 -0
- package/dist/client/assets/dist-Kh2COra_.js +1 -0
- package/dist/client/assets/{dist-JYEDRrPT.js → dist-PDZ3bSqm.js} +1 -1
- package/dist/client/assets/{dist-Drp8uu5J.js → dist-TjMh8n1u.js} +1 -1
- package/dist/client/assets/{dist-DGb27Dl6.js → dist-dtAdgL39.js} +1 -1
- package/dist/client/assets/dist-jv4WdPnK.js +9 -0
- package/dist/client/assets/{dist-DK5Gs2wa.js → dist-rGBmqxC7.js} +1 -1
- package/dist/client/assets/{dist-DCzuX1AF.js → dist-shrl6K_0.js} +1 -1
- package/dist/client/assets/dist-tOaegDYS2.js +1 -0
- package/dist/client/assets/dist-ule2n6ak.js +1 -0
- package/dist/client/assets/dist-xElaxbia.js +1 -0
- package/dist/client/assets/drawio-editor-FzY1cVw8.js +9 -0
- package/dist/client/assets/drawioEditor-BjiKJqlc.js +2 -0
- package/dist/client/assets/editor-session-Cm9ekeNo.js +54 -0
- package/dist/client/assets/embedded-editor-base-CwTkk911.css +1 -0
- package/dist/client/assets/{en-GADW4C6J-DQ6zyCEM.js → en-7NFCYGKX-BrgYZAEe.js} +1 -1
- package/dist/client/assets/{preview-render-profile-BZzGSg6K.js → es-DXGV3RHd.js} +13 -13
- package/dist/client/assets/excalidraw-editor-B46zsTFI.js +9 -0
- package/dist/client/assets/excalidraw-editor-Bt7gMSoh.css +1 -0
- package/dist/client/assets/excalidraw-scene-BOben2gr.js +1 -0
- package/dist/client/assets/excalidrawEditor-CT2pHq7e.js +2 -0
- package/dist/client/assets/export-page-A7NHawJY.js +39 -0
- package/dist/client/assets/exportDocument-B2L8fe34.css +1 -0
- package/dist/client/assets/exportDocument-BaqcOAAW.js +2 -0
- package/dist/client/assets/file-icon-svg-CQAjlWjK.js +1 -0
- package/dist/client/assets/file-kind-BbqgGzpc.js +1 -0
- package/dist/client/assets/image-QXRYHUNP-SWEV8H0J.js +1 -0
- package/dist/client/assets/index-ClbjMBVt.js +2 -0
- package/dist/client/assets/index-Pum8ET-5.css +1 -0
- package/dist/client/assets/main-B3uPyqic.js +893 -0
- package/dist/client/assets/modulepreload-polyfill-P2Xu9kJm.js +1 -0
- package/dist/client/assets/pdf-BL9Pr2D5.js +54 -0
- package/dist/client/assets/pdf.worker-CLesOks4.mjs +64857 -0
- package/dist/client/assets/pdf_viewer-FVkkThnz.js +551 -0
- package/dist/client/assets/preview-diagram-utils-txBCoW8d.js +1 -0
- package/dist/client/assets/{preview-render-compiler-BSaQO_p3.js → preview-render-compiler-BD-XhkS2.js} +2 -2
- package/dist/client/assets/preview-render-compiler-BKedaMxx.js +1 -0
- package/dist/client/assets/preview-render-profile-CE-5rVTC.js +1 -0
- package/dist/client/assets/{preview-render-worker-B42LWvrD.js → preview-render-worker-CiPqc9n6.js} +20 -20
- package/dist/client/assets/prod-Dy20X7eT.js +1 -0
- package/dist/client/assets/prod-hnwh7wRM.js +177 -0
- package/dist/client/assets/quick-switcher-controller-fqOYR7qR.js +12 -0
- package/dist/client/assets/runtime-config-BLrEKVO1.js +1 -0
- package/dist/client/assets/vault-api-client-_LpV1aIn.js +6 -0
- package/dist/client/assets/{yjs-provider-reset-guard-Cox4nxwu.js → yjs-provider-reset-guard-DE0vINDP.js} +1 -1
- package/dist/client/drawio-editor.html +3 -2
- package/dist/client/excalidraw-editor.html +3 -2
- package/dist/client/export-document.html +4 -3
- package/dist/client/index.html +109 -27
- package/docker-compose.yml +42 -0
- package/package.json +26 -15
- package/scripts/local-structurizr-compose.mjs +101 -0
- package/src/client/app/drawio-editor-entry.js +0 -3
- package/src/client/app/drawio-editor.html +1 -0
- package/src/client/app/excalidraw-editor-entry.js +0 -3
- package/src/client/app/excalidraw-editor.html +1 -0
- package/src/client/app/export-document-entry.js +0 -3
- package/src/client/app/export-document.html +1 -0
- package/src/client/app/index.html +106 -24
- package/src/client/app/main-entry.js +0 -5
- package/src/client/application/app-shell/chat-feature.js +180 -124
- package/src/client/application/app-shell/comments-feature.js +20 -11
- package/src/client/application/app-shell/git-feature.js +16 -9
- package/src/client/application/app-shell/presence-feature.js +18 -11
- package/src/client/application/app-shell/ui-feature-shell.js +78 -17
- package/src/client/application/app-shell/ui-feature-sidebar.js +74 -1
- package/src/client/application/app-shell/ui-feature-tab-activity.js +2 -2
- package/src/client/application/app-shell/ui-feature-toolbar.js +2 -52
- package/src/client/application/app-shell/workspace-feature.js +27 -84
- package/src/client/application/app-shell-elements.js +9 -1
- package/src/client/application/diagram-chrome.js +161 -166
- package/src/client/application/diagram-preview-export.js +7 -34
- package/src/client/application/diagram-preview-hydrator.js +1 -19
- package/src/client/application/markdown-frontmatter.js +0 -2
- package/src/client/application/mermaid-preview-hydrator.js +1 -14
- package/src/client/application/pdf-preview-controller.js +992 -0
- package/src/client/application/plantuml-preview-hydrator.js +0 -10
- package/src/client/application/preview-diagram-utils.js +31 -2
- package/src/client/application/preview-render-compiler.js +2 -1
- package/src/client/application/preview-renderer.js +2 -2
- package/src/client/application/quick-switcher-loader.js +3 -1
- package/src/client/application/structurizr-preview-controller.js +395 -0
- package/src/client/application/workspace-coordinator.js +25 -3
- package/src/client/application/workspace-preview-controller.js +91 -5
- package/src/client/bootstrap/collabmd-app-shell.js +155 -43
- package/src/client/browser-utils.js +44 -0
- package/src/client/domain/excalidraw-collaboration.js +0 -2
- package/src/client/domain/room.js +38 -0
- package/src/client/domain/runtime-paths.js +26 -5
- package/src/client/domain/structurizr-language.js +99 -0
- package/src/client/domain/vault-paths.js +48 -0
- package/src/client/excalidraw-editor.js +833 -51
- package/src/client/export/export-pipeline.js +6 -34
- package/src/client/infrastructure/auth-client.js +4 -10
- package/src/client/infrastructure/browser-notification-port.js +33 -20
- package/src/client/infrastructure/browser-preferences-port.js +46 -9
- package/src/client/infrastructure/comment-thread-store.js +34 -13
- package/src/client/infrastructure/editor-session.js +10 -0
- package/src/client/infrastructure/editor-view-adapter.js +133 -5
- package/src/client/infrastructure/excalidraw-room-client.js +103 -14
- package/src/client/infrastructure/git-api-client.js +5 -0
- package/src/client/infrastructure/lobby-presence.js +1 -0
- package/src/client/infrastructure/vault-api-client.js +51 -0
- package/src/client/infrastructure/workspace-sync-client.js +13 -1
- package/src/client/presentation/comment-overview-controller.js +18 -53
- package/src/client/presentation/comment-ui/comment-ui-card.js +1 -12
- package/src/client/presentation/comment-ui/comment-ui-layout.js +242 -219
- package/src/client/presentation/comment-ui/comment-ui-render.js +32 -45
- package/src/client/presentation/comment-ui/comment-ui-shared.js +68 -13
- package/src/client/presentation/comment-ui-controller.js +5 -1
- package/src/client/presentation/drawio-embed-controller.js +9 -102
- package/src/client/presentation/drawio-viewer.js +118 -0
- package/src/client/presentation/excalidraw-embed-controller.js +74 -8
- package/src/client/presentation/file-action-controller.js +134 -0
- package/src/client/presentation/file-explorer-controller.js +33 -3
- package/src/client/presentation/file-explorer-view.js +59 -34
- package/src/client/presentation/file-icon-svg.js +40 -0
- package/src/client/presentation/file-tree-state.js +12 -4
- package/src/client/presentation/git-diff-view-controller.js +731 -3
- package/src/client/presentation/outline-controller.js +86 -0
- package/src/client/presentation/quick-switcher-controller.js +257 -74
- package/src/client/presentation/quick-switcher-text-search.js +3 -3
- package/src/client/presentation/toast-controller.js +3 -0
- package/src/client/styles/components/feedback.css +6 -0
- package/src/client/styles/components/navigation.css +11 -1
- package/src/client/styles/features/collaboration-chat.css +49 -53
- package/src/client/styles/features/collaboration-presence.css +9 -7
- package/src/client/styles/features/comment-card.css +25 -11
- package/src/client/styles/features/comment-overlays.css +0 -4
- package/src/client/styles/features/comment-overview.css +44 -21
- package/src/client/styles/features/comments-drawer.css +2 -100
- package/src/client/styles/features/diagram-preview.css +81 -18
- package/src/client/styles/features/diff-special.css +309 -0
- package/src/client/styles/features/embedded-preview.css +8 -33
- package/src/client/styles/features/quick-switcher.css +8 -0
- package/src/client/styles/foundation/themes.css +6 -0
- package/src/client/styles/foundation/tokens.css +1 -0
- package/src/client/styles/layout/editor-page.css +40 -0
- package/src/client/styles/layout/responsive.css +31 -1
- package/src/client/styles/layout/shell.css +383 -7
- package/src/client/styles/layout/sidebar.css +47 -15
- package/src/client/styles/layout/view-modes.css +1 -0
- package/src/client/styles/overrides/codemirror.css +217 -15
- package/src/client/styles/style.css +1 -0
- package/src/client/styles/surfaces/excalidraw-editor.css +294 -0
- package/src/domain/comment-threads.js +63 -5
- package/src/domain/excalidraw-room-codec.js +6 -4
- package/src/domain/file-kind.js +35 -3
- package/src/server/application/workspace-reconciliation.js +1 -1
- package/src/server/config/env.js +79 -0
- package/src/server/create-app-server.js +14 -3
- package/src/server/domain/bases/base-definition.js +1 -1
- package/src/server/domain/bases/base-expression-runtime.js +1 -4
- package/src/server/domain/bases/base-index-snapshot-store.js +1 -4
- package/src/server/domain/bases/base-query-service.js +1 -77
- package/src/server/domain/bases/base-transform.js +1 -4
- package/src/server/domain/collaboration/collaboration-room.js +55 -21
- package/src/server/domain/comment-overview.js +25 -8
- package/src/server/domain/docx-exporter.js +24 -33
- package/src/server/domain/ripgrep-search-service.js +7 -1
- package/src/server/domain/workspace-state.js +32 -11
- package/src/server/infrastructure/git/diff-service.js +29 -13
- package/src/server/infrastructure/git/git-service.js +61 -10
- package/src/server/infrastructure/git/history-service.js +96 -29
- package/src/server/infrastructure/git/image-mime.js +14 -0
- package/src/server/infrastructure/git/path-utils.js +1 -1
- package/src/server/infrastructure/git/responses.js +0 -95
- package/src/server/infrastructure/git/untracked-files.js +28 -1
- package/src/server/infrastructure/github/github-app-client.js +22 -15
- package/src/server/infrastructure/http/create-git-api-query-handler.js +31 -1
- package/src/server/infrastructure/http/create-request-handler.js +18 -31
- package/src/server/infrastructure/http/create-static-handler.js +5 -2
- package/src/server/infrastructure/http/create-structurizr-api-handler.js +145 -0
- package/src/server/infrastructure/http/create-vault-api-command-handler.js +70 -8
- package/src/server/infrastructure/http/create-vault-api-query-handler.js +51 -3
- package/src/server/infrastructure/http/http-errors.js +7 -1
- package/src/server/infrastructure/http/http-request-helpers.js +22 -0
- package/src/server/infrastructure/persistence/path-utils.js +1 -1
- package/src/server/infrastructure/persistence/vault-file-store.js +3 -0
- package/src/server/infrastructure/structurizr/structurizr-embed.css +43 -0
- package/src/server/infrastructure/structurizr/structurizr-workspace-service.js +374 -0
- package/src/server/infrastructure/websocket/attach-collaboration-gateway.js +4 -22
- package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-CbSISC1w.js +0 -1
- package/dist/client/assets/bases-preview-controller-2pLHk0uk.js +0 -143
- package/dist/client/assets/browser-utils-CKtI_rZl.js +0 -1
- package/dist/client/assets/button-BCEiw4Rw.js +0 -1
- package/dist/client/assets/chunk-AXR3VHVW-0GTk_evH.js +0 -41
- package/dist/client/assets/comment-threads-D-iKphIp.js +0 -4
- package/dist/client/assets/diagram-action-icons-aa_KOv9h.js +0 -36
- package/dist/client/assets/dist-BH87JoHx.js +0 -11
- package/dist/client/assets/dist-BIkPRZO7.js +0 -6
- package/dist/client/assets/dist-BqCsFpx4.js +0 -1
- package/dist/client/assets/dist-C2JHCt8U.js +0 -1
- package/dist/client/assets/dist-CZjTtmTu.js +0 -1
- package/dist/client/assets/dist-Cig4Ov_X.js +0 -1
- package/dist/client/assets/dist-CqQEC8gR.js +0 -1
- package/dist/client/assets/dist-D4Rzqod1.js +0 -1
- package/dist/client/assets/dist-D5sn-mwk.js +0 -9
- package/dist/client/assets/dist-D7G-n87v.js +0 -1
- package/dist/client/assets/dist-DRqOrNgN.js +0 -1
- package/dist/client/assets/dist-DetkMS_4.js +0 -1
- package/dist/client/assets/dist-Dp6FVkQ1.js +0 -1
- package/dist/client/assets/dist-DtbjNB28.js +0 -1
- package/dist/client/assets/dist-DyrYcvpo2.js +0 -1
- package/dist/client/assets/dist-GrygD2zE.js +0 -1
- package/dist/client/assets/dist-HmEpWUow.js +0 -1
- package/dist/client/assets/dist-RTa81Km7.js +0 -1
- package/dist/client/assets/drawio-editor-DDvFoarP.js +0 -9
- package/dist/client/assets/drawio-embed-controller-BD1GTRwn.js +0 -1
- package/dist/client/assets/drawioEditor-Bu5grlH5.js +0 -2
- package/dist/client/assets/editor-session-DGlpiAsK.js +0 -16
- package/dist/client/assets/embedded-editor-base-C9roKYpW.css +0 -1
- package/dist/client/assets/excalidraw-editor-BHu6k8d4.js +0 -9
- package/dist/client/assets/excalidraw-editor-Cr_184EF.css +0 -1
- package/dist/client/assets/excalidraw-embed-controller-y2fenN_g.js +0 -1
- package/dist/client/assets/excalidraw-embed-reconciler-DGiagExg.js +0 -1
- package/dist/client/assets/excalidraw-scene-BvsQ6mLP.js +0 -176
- package/dist/client/assets/excalidrawEditor-4vFE--Uw.js +0 -2
- package/dist/client/assets/export-page-Cby8JzPO.js +0 -39
- package/dist/client/assets/exportDocument-C9v-bc7I.css +0 -1
- package/dist/client/assets/exportDocument-CRHCfsdo.js +0 -2
- package/dist/client/assets/file-history-view-controller-BDjEV9xJ.js +0 -112
- package/dist/client/assets/file-kind-BKPOIRPE.js +0 -1
- package/dist/client/assets/git-diff-view-controller-DgdM1aqb.js +0 -150
- package/dist/client/assets/git-panel-controller-BDTR2HVp.js +0 -207
- package/dist/client/assets/image-XGD7JQR6-XDUWHRpO.js +0 -1
- package/dist/client/assets/index-7xOyXDhP.css +0 -1
- package/dist/client/assets/index-Bz1KuQ6y.js +0 -2
- package/dist/client/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/dist/client/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/dist/client/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/dist/client/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/dist/client/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/dist/client/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/dist/client/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
- package/dist/client/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
- package/dist/client/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/dist/client/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
- package/dist/client/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
- package/dist/client/assets/main-Ci07m9oP.js +0 -152
- package/dist/client/assets/preview-diagram-utils-n_bbJA9V.js +0 -1
- package/dist/client/assets/preview-render-compiler-csGM5ZFz.js +0 -1
- package/dist/client/assets/quick-switcher-controller-CoiYvllm.js +0 -12
- package/dist/client/assets/room-CDrmIdDt.js +0 -1
- package/dist/client/assets/runtime-config-CDgeuPWN.js +0 -1
- package/dist/client/assets/runtime-config-loader-BHGniHP5.js +0 -1
- package/dist/client/assets/runtime-paths-DvpihCEq.js +0 -1
- package/dist/client/assets/segmented-control-DJrHSz8M.js +0 -1
- package/dist/client/assets/vault-api-client-sLB2bo56.js +0 -1
- package/dist/client/assets/vault-paths-CVkuh0j-.js +0 -5
- package/src/client/bootstrap/lazy-controller-feature.js +0 -433
- package/src/client/infrastructure/backlinks-api-client.js +0 -16
- package/src/client/infrastructure/plantuml-api-client.js +0 -19
- package/src/client/infrastructure/runtime-config-loader.js +0 -56
- package/src/server/domain/collaboration/room-persistence-controller.js +0 -80
- package/src/server/infrastructure/git/command-runner.js +0 -49
- package/src/server/infrastructure/git/errors.js +0 -8
- package/src/server/infrastructure/http/create-esm-proxy-handler.js +0 -130
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
createCommentOverviewThread,
|
|
3
|
+
formatAnchorLabel,
|
|
4
|
+
getLatestGroupMessage,
|
|
5
|
+
} from './comment-ui-shared.js';
|
|
2
6
|
|
|
3
7
|
/**
|
|
4
8
|
* @typedef {object} CommentUiRenderContext
|
|
@@ -61,18 +65,38 @@ function renderDrawer() {
|
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
this.commentsDrawer.classList.toggle('hidden', !this.supported || !this.drawerOpen);
|
|
68
|
+
if (!this.supported || !this.drawerOpen) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
64
72
|
this.commentsDrawerList.replaceChildren();
|
|
65
73
|
const groups = this.getThreadGroups();
|
|
66
74
|
this.commentsDrawerEmpty?.classList.toggle('hidden', groups.length > 0);
|
|
67
|
-
if (
|
|
75
|
+
if (groups.length === 0) {
|
|
68
76
|
return;
|
|
69
77
|
}
|
|
70
78
|
|
|
71
79
|
const fragment = document.createDocumentFragment();
|
|
72
80
|
groups.forEach((group) => {
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
81
|
+
const latestMessage = getLatestGroupMessage(group);
|
|
82
|
+
const messageCount = group.threads.reduce(
|
|
83
|
+
(count, thread) => count + (Array.isArray(thread.messages) ? thread.messages.length : 0),
|
|
84
|
+
0,
|
|
85
|
+
);
|
|
86
|
+
const button = createCommentOverviewThread({
|
|
87
|
+
authorName: latestMessage?.userName || group.threads[0]?.createdByName || 'Anonymous',
|
|
88
|
+
buttonClassName: 'comment-overview-thread comments-drawer-item',
|
|
89
|
+
footerClassName: 'comment-overview-thread-footer comments-drawer-item-footer',
|
|
90
|
+
headerClassName: 'comment-overview-thread-header comments-drawer-item-header',
|
|
91
|
+
lineClassName: 'comment-overview-thread-line comments-drawer-item-title',
|
|
92
|
+
lineLabel: formatAnchorLabel(group.anchor),
|
|
93
|
+
messageCount,
|
|
94
|
+
previewBody: latestMessage?.body || '',
|
|
95
|
+
previewClassName: 'comment-markdown comment-overview-thread-preview comments-drawer-item-preview',
|
|
96
|
+
quote: group.anchor?.quote || group.anchor?.excerpt || 'Source anchored comment',
|
|
97
|
+
quoteClassName: 'comment-overview-thread-quote comments-drawer-item-quote',
|
|
98
|
+
timestamp: latestMessage ? this.formatTimestamp(latestMessage.createdAt) : '',
|
|
99
|
+
});
|
|
76
100
|
button.classList.toggle('is-active', this.activeCard?.groupKey === group.key);
|
|
77
101
|
button.addEventListener('pointerdown', (event) => {
|
|
78
102
|
event.preventDefault();
|
|
@@ -81,48 +105,11 @@ function renderDrawer() {
|
|
|
81
105
|
this.onNavigateToLine?.(group.anchor?.startLine ?? 1);
|
|
82
106
|
this.openThreadGroup(group, {
|
|
83
107
|
anchor: group.anchor,
|
|
84
|
-
origin: '
|
|
85
|
-
sourceRect:
|
|
108
|
+
origin: 'editor',
|
|
109
|
+
sourceRect: this.session?.getCommentAnchorClientRect?.(group.anchor)
|
|
110
|
+
?? button.getBoundingClientRect(),
|
|
86
111
|
});
|
|
87
112
|
});
|
|
88
|
-
|
|
89
|
-
const header = document.createElement('div');
|
|
90
|
-
header.className = 'ui-record-header comments-drawer-item-header';
|
|
91
|
-
|
|
92
|
-
const title = document.createElement('span');
|
|
93
|
-
title.className = 'comments-drawer-item-title';
|
|
94
|
-
title.textContent = formatAnchorLabel(group.anchor);
|
|
95
|
-
|
|
96
|
-
const count = document.createElement('span');
|
|
97
|
-
count.className = 'ui-pill-badge ui-pill-badge--count ui-pill-badge--accent comments-drawer-item-count';
|
|
98
|
-
count.textContent = String(group.threads.length);
|
|
99
|
-
|
|
100
|
-
header.append(title, count);
|
|
101
|
-
|
|
102
|
-
const quote = document.createElement('p');
|
|
103
|
-
quote.className = 'comments-drawer-item-quote';
|
|
104
|
-
quote.textContent = group.anchor.quote || group.anchor.excerpt || 'Source anchored comment';
|
|
105
|
-
|
|
106
|
-
const latestMessage = getLatestGroupMessage(group);
|
|
107
|
-
const preview = createRenderedCommentBody(
|
|
108
|
-
latestMessage?.body || '',
|
|
109
|
-
'comment-markdown comments-drawer-item-preview',
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
const footer = document.createElement('div');
|
|
113
|
-
footer.className = 'ui-record-meta comments-drawer-item-footer';
|
|
114
|
-
const countLabel = document.createElement('span');
|
|
115
|
-
countLabel.textContent = `${group.threads.length} thread${group.threads.length === 1 ? '' : 's'}`;
|
|
116
|
-
|
|
117
|
-
const updatedLabel = document.createElement('span');
|
|
118
|
-
updatedLabel.className = 'comments-drawer-item-updated';
|
|
119
|
-
updatedLabel.textContent = latestMessage
|
|
120
|
-
? `${latestMessage.userName} • ${this.formatTimestamp(latestMessage.createdAt)}`
|
|
121
|
-
: '';
|
|
122
|
-
|
|
123
|
-
footer.append(countLabel, updatedLabel);
|
|
124
|
-
|
|
125
|
-
button.append(header, quote, preview, footer);
|
|
126
113
|
fragment.appendChild(button);
|
|
127
114
|
});
|
|
128
115
|
|
|
@@ -13,10 +13,6 @@ export const COMMENT_CARD_WIDTH = 520;
|
|
|
13
13
|
export const COMMENT_SELECTION_REVEAL_DELAY_MS = 150;
|
|
14
14
|
export const COMMENT_SELECTION_CHIP_GAP = 12;
|
|
15
15
|
export const COMMENT_CONTROL_SLOT_HEIGHT = 36;
|
|
16
|
-
export const COMMENT_PREVIEW_BADGE_MIN_WIDTH = 28;
|
|
17
|
-
export const COMMENT_PREVIEW_RAIL_SLOT_HEIGHT = 30;
|
|
18
|
-
export const COMMENT_PREVIEW_RAIL_MIN_WIDTH = 400;
|
|
19
|
-
export const COMMENT_PREVIEW_RAIL_BREAKPOINT = 769;
|
|
20
16
|
export const COMMENT_REACTION_PRESET_EMOJIS = Object.freeze(['👍', '❤️', '🎉', '👀', '🚀']);
|
|
21
17
|
export const COMMENT_REACTION_MORE_EMOJIS = Object.freeze(['😂', '🔥', '✅', '🙏', '💡', '🤔', '👏', '😄', '🎯', '🙌']);
|
|
22
18
|
|
|
@@ -55,19 +51,19 @@ export function areAnchorsEqual(left, right) {
|
|
|
55
51
|
}
|
|
56
52
|
|
|
57
53
|
export function formatAnchorLabel(anchor) {
|
|
58
|
-
if (
|
|
59
|
-
return '
|
|
54
|
+
if (getAnchorKind(anchor) === 'diagram-element') {
|
|
55
|
+
return 'Diagram element';
|
|
60
56
|
}
|
|
61
57
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
58
|
+
const startLine = Number(anchor?.startLine || 0);
|
|
59
|
+
const endLine = Number(anchor?.endLine || startLine);
|
|
60
|
+
if (!Number.isFinite(startLine) || startLine <= 0) {
|
|
61
|
+
return 'No source anchor';
|
|
66
62
|
}
|
|
67
63
|
|
|
68
|
-
return
|
|
69
|
-
? `Line ${
|
|
70
|
-
: `Lines ${
|
|
64
|
+
return startLine === endLine
|
|
65
|
+
? `Line ${startLine}`
|
|
66
|
+
: `Lines ${startLine}-${endLine}`;
|
|
71
67
|
}
|
|
72
68
|
|
|
73
69
|
export function getAnchorGroupKey(anchor = {}) {
|
|
@@ -120,6 +116,65 @@ export function createRenderedCommentBody(body, className = 'comment-markdown')
|
|
|
120
116
|
return container;
|
|
121
117
|
}
|
|
122
118
|
|
|
119
|
+
export function createCommentOverviewThread({
|
|
120
|
+
authorName = 'Anonymous',
|
|
121
|
+
buttonClassName = 'comment-overview-thread',
|
|
122
|
+
footerClassName = 'comment-overview-thread-footer',
|
|
123
|
+
headerClassName = 'comment-overview-thread-header',
|
|
124
|
+
lineClassName = 'comment-overview-thread-line',
|
|
125
|
+
lineLabel = '',
|
|
126
|
+
messageCount = 0,
|
|
127
|
+
previewBody = '',
|
|
128
|
+
previewClassName = 'comment-markdown comment-overview-thread-preview',
|
|
129
|
+
quote = 'Source anchored comment',
|
|
130
|
+
quoteClassName = 'comment-overview-thread-quote',
|
|
131
|
+
timestamp = '',
|
|
132
|
+
} = {}) {
|
|
133
|
+
const button = document.createElement('button');
|
|
134
|
+
button.type = 'button';
|
|
135
|
+
button.className = buttonClassName;
|
|
136
|
+
|
|
137
|
+
const header = document.createElement('div');
|
|
138
|
+
header.className = headerClassName;
|
|
139
|
+
|
|
140
|
+
const line = document.createElement('span');
|
|
141
|
+
line.className = lineClassName;
|
|
142
|
+
line.textContent = lineLabel;
|
|
143
|
+
|
|
144
|
+
const meta = document.createElement('span');
|
|
145
|
+
meta.className = 'comment-overview-thread-meta';
|
|
146
|
+
meta.textContent = timestamp;
|
|
147
|
+
header.append(line, meta);
|
|
148
|
+
|
|
149
|
+
const body = document.createElement('div');
|
|
150
|
+
body.className = 'comment-overview-thread-body';
|
|
151
|
+
const preview = createRenderedCommentBody(previewBody, previewClassName);
|
|
152
|
+
|
|
153
|
+
const quoteSection = document.createElement('div');
|
|
154
|
+
quoteSection.className = 'comment-overview-thread-section comment-overview-thread-reference';
|
|
155
|
+
const quoteLabel = document.createElement('span');
|
|
156
|
+
quoteLabel.className = 'comment-overview-thread-section-label';
|
|
157
|
+
quoteLabel.textContent = 'Reference';
|
|
158
|
+
const quoteNode = document.createElement('span');
|
|
159
|
+
quoteNode.className = quoteClassName;
|
|
160
|
+
quoteNode.textContent = quote;
|
|
161
|
+
quoteSection.append(quoteLabel, quoteNode);
|
|
162
|
+
body.append(preview, quoteSection);
|
|
163
|
+
|
|
164
|
+
const footer = document.createElement('div');
|
|
165
|
+
footer.className = footerClassName;
|
|
166
|
+
const author = document.createElement('span');
|
|
167
|
+
author.className = 'comment-overview-thread-author';
|
|
168
|
+
author.textContent = authorName;
|
|
169
|
+
const messages = document.createElement('span');
|
|
170
|
+
messages.className = 'comment-overview-thread-message-count';
|
|
171
|
+
messages.textContent = `${messageCount} message${messageCount === 1 ? '' : 's'}`;
|
|
172
|
+
footer.append(author, messages);
|
|
173
|
+
|
|
174
|
+
button.append(header, body, footer);
|
|
175
|
+
return button;
|
|
176
|
+
}
|
|
177
|
+
|
|
123
178
|
export function hasLocalReaction(reaction, localUserId) {
|
|
124
179
|
return Boolean(localUserId && reaction?.users?.some((user) => user?.userId === localUserId));
|
|
125
180
|
}
|
|
@@ -89,9 +89,13 @@ export class CommentUiController {
|
|
|
89
89
|
if (this.activeCard?.mode === 'create' && this.activeCard.origin === 'preview') {
|
|
90
90
|
return;
|
|
91
91
|
}
|
|
92
|
-
|
|
92
|
+
const previewSelection = this.supported && this.fileKind === 'markdown'
|
|
93
93
|
? createPreviewSelection(window.getSelection(), this.previewElement, this.session?.getText?.() ?? '')
|
|
94
94
|
: null;
|
|
95
|
+
if (!previewSelection && !this.previewSelection) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
this.previewSelection = previewSelection;
|
|
95
99
|
this.scheduleLayoutRefresh();
|
|
96
100
|
};
|
|
97
101
|
this.handleCommentSelectionButtonPointerDown = (event) => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createDrawioLeaseRoomName } from '../../domain/drawio-room.js';
|
|
2
2
|
import { setDiagramActionButtonIcon } from '../domain/diagram-action-icons.js';
|
|
3
3
|
import { resolveAppUrl } from '../domain/runtime-paths.js';
|
|
4
|
+
import { renderDrawioViewer } from './drawio-viewer.js';
|
|
4
5
|
import {
|
|
5
6
|
cancelIdleRender,
|
|
6
7
|
isNearViewport,
|
|
@@ -8,62 +9,6 @@ import {
|
|
|
8
9
|
} from '../browser-utils.js';
|
|
9
10
|
|
|
10
11
|
const HYDRATE_VIEWPORT_MARGIN_PX = 360;
|
|
11
|
-
const DRAWIO_VIEWER_SCRIPT_URL = 'https://viewer.diagrams.net/js/viewer-static.min.js';
|
|
12
|
-
|
|
13
|
-
let drawioViewerLoadPromise = null;
|
|
14
|
-
|
|
15
|
-
function ensureDrawioViewerLoaded() {
|
|
16
|
-
if (window.GraphViewer?.processElements) {
|
|
17
|
-
return Promise.resolve(window.GraphViewer);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
if (drawioViewerLoadPromise) {
|
|
21
|
-
return drawioViewerLoadPromise;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
drawioViewerLoadPromise = new Promise((resolve, reject) => {
|
|
25
|
-
const existingScript = document.querySelector('script[data-collabmd-drawio-viewer]');
|
|
26
|
-
const script = existingScript instanceof HTMLScriptElement
|
|
27
|
-
? existingScript
|
|
28
|
-
: document.createElement('script');
|
|
29
|
-
|
|
30
|
-
const cleanup = () => {
|
|
31
|
-
script.removeEventListener('error', handleError);
|
|
32
|
-
script.removeEventListener('load', handleLoad);
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const handleError = () => {
|
|
36
|
-
cleanup();
|
|
37
|
-
drawioViewerLoadPromise = null;
|
|
38
|
-
reject(new Error('Failed to load draw.io viewer'));
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const handleLoad = () => {
|
|
42
|
-
cleanup();
|
|
43
|
-
if (!window.GraphViewer?.processElements) {
|
|
44
|
-
drawioViewerLoadPromise = null;
|
|
45
|
-
reject(new Error('draw.io viewer did not initialize'));
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
resolve(window.GraphViewer);
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
script.addEventListener('error', handleError, { once: true });
|
|
53
|
-
script.addEventListener('load', handleLoad, { once: true });
|
|
54
|
-
|
|
55
|
-
if (!existingScript) {
|
|
56
|
-
script.src = DRAWIO_VIEWER_SCRIPT_URL;
|
|
57
|
-
script.async = true;
|
|
58
|
-
script.dataset.collabmdDrawioViewer = 'true';
|
|
59
|
-
document.head.append(script);
|
|
60
|
-
} else if (window.GraphViewer?.processElements) {
|
|
61
|
-
handleLoad();
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
return drawioViewerLoadPromise;
|
|
66
|
-
}
|
|
67
12
|
|
|
68
13
|
export class DrawioEmbedController {
|
|
69
14
|
constructor({
|
|
@@ -350,59 +295,21 @@ export class DrawioEmbedController {
|
|
|
350
295
|
}
|
|
351
296
|
|
|
352
297
|
async renderViewerEntry(entry) {
|
|
353
|
-
const
|
|
354
|
-
this.vaultApiClient.readFile(entry.filePath),
|
|
355
|
-
ensureDrawioViewerLoaded(),
|
|
356
|
-
]);
|
|
298
|
+
const { content } = await this.vaultApiClient.readFile(entry.filePath);
|
|
357
299
|
|
|
358
300
|
if (!entry.wrapper?.isConnected || !entry.viewerElement?.isConnected) {
|
|
359
301
|
return;
|
|
360
302
|
}
|
|
361
303
|
|
|
362
304
|
const theme = this.getTheme?.() === 'light' ? 'light' : 'dark';
|
|
363
|
-
const graphElement = document.createElement('div');
|
|
364
|
-
graphElement.className = 'mxgraph drawio-viewer-frame';
|
|
365
|
-
graphElement.dataset.action = 'open-file';
|
|
366
|
-
graphElement.dataset.filePath = entry.filePath;
|
|
367
|
-
graphElement.setAttribute('role', 'button');
|
|
368
|
-
graphElement.setAttribute('tabindex', '0');
|
|
369
|
-
graphElement.setAttribute('aria-label', `Open ${entry.label.replace(/\.drawio$/i, '')}`);
|
|
370
|
-
graphElement.addEventListener('click', (event) => {
|
|
371
|
-
event.preventDefault();
|
|
372
|
-
this.onOpenFile?.(entry.filePath);
|
|
373
|
-
});
|
|
374
|
-
graphElement.addEventListener('keydown', (event) => {
|
|
375
|
-
if (event.key !== 'Enter' && event.key !== ' ') {
|
|
376
|
-
return;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
event.preventDefault();
|
|
380
|
-
this.onOpenFile?.(entry.filePath);
|
|
381
|
-
});
|
|
382
|
-
graphElement.dataset.mxgraph = JSON.stringify({
|
|
383
|
-
'check-visible-state': false,
|
|
384
|
-
center: true,
|
|
385
|
-
border: 0,
|
|
386
|
-
'dark-mode': theme,
|
|
387
|
-
editable: false,
|
|
388
|
-
fit: 1,
|
|
389
|
-
lightbox: false,
|
|
390
|
-
nav: false,
|
|
391
|
-
resize: false,
|
|
392
|
-
tooltips: false,
|
|
393
|
-
xml: String(content ?? ''),
|
|
394
|
-
});
|
|
395
|
-
|
|
396
305
|
const viewerHost = entry.wrapper.querySelector('.drawio-viewer-shell') ?? entry.viewerElement;
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
viewer.processElements();
|
|
306
|
+
entry.viewerElement = await renderDrawioViewer(viewerHost, {
|
|
307
|
+
ariaLabel: `Open ${entry.label.replace(/\.drawio$/i, '')}`,
|
|
308
|
+
className: 'mxgraph drawio-viewer-frame',
|
|
309
|
+
onActivate: () => this.onOpenFile?.(entry.filePath),
|
|
310
|
+
source: String(content ?? ''),
|
|
311
|
+
theme,
|
|
312
|
+
});
|
|
406
313
|
}
|
|
407
314
|
|
|
408
315
|
buildIframeUrl(entry) {
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
const DRAWIO_VIEWER_SCRIPT_URL = 'https://viewer.diagrams.net/js/viewer-static.min.js';
|
|
2
|
+
|
|
3
|
+
let drawioViewerLoadPromise = null;
|
|
4
|
+
|
|
5
|
+
export function ensureDrawioViewerLoaded() {
|
|
6
|
+
if (window.GraphViewer?.processElements) {
|
|
7
|
+
return Promise.resolve(window.GraphViewer);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (drawioViewerLoadPromise) {
|
|
11
|
+
return drawioViewerLoadPromise;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
drawioViewerLoadPromise = new Promise((resolve, reject) => {
|
|
15
|
+
const existingScript = document.querySelector('script[data-collabmd-drawio-viewer]');
|
|
16
|
+
const script = existingScript instanceof HTMLScriptElement
|
|
17
|
+
? existingScript
|
|
18
|
+
: document.createElement('script');
|
|
19
|
+
|
|
20
|
+
const cleanup = () => {
|
|
21
|
+
script.removeEventListener('error', handleError);
|
|
22
|
+
script.removeEventListener('load', handleLoad);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const handleError = () => {
|
|
26
|
+
cleanup();
|
|
27
|
+
drawioViewerLoadPromise = null;
|
|
28
|
+
reject(new Error('Failed to load draw.io viewer'));
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const handleLoad = () => {
|
|
32
|
+
cleanup();
|
|
33
|
+
if (!window.GraphViewer?.processElements) {
|
|
34
|
+
drawioViewerLoadPromise = null;
|
|
35
|
+
reject(new Error('draw.io viewer did not initialize'));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
resolve(window.GraphViewer);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
script.addEventListener('error', handleError, { once: true });
|
|
43
|
+
script.addEventListener('load', handleLoad, { once: true });
|
|
44
|
+
|
|
45
|
+
if (!existingScript) {
|
|
46
|
+
script.src = DRAWIO_VIEWER_SCRIPT_URL;
|
|
47
|
+
script.async = true;
|
|
48
|
+
script.dataset.collabmdDrawioViewer = 'true';
|
|
49
|
+
document.head.append(script);
|
|
50
|
+
} else if (window.GraphViewer?.processElements) {
|
|
51
|
+
handleLoad();
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
return drawioViewerLoadPromise;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function createDrawioViewerElement({
|
|
59
|
+
ariaLabel = '',
|
|
60
|
+
className = 'drawio-viewer-frame',
|
|
61
|
+
onActivate = null,
|
|
62
|
+
source = '',
|
|
63
|
+
theme = 'dark',
|
|
64
|
+
} = {}) {
|
|
65
|
+
const graphElement = document.createElement('div');
|
|
66
|
+
graphElement.className = className;
|
|
67
|
+
if (ariaLabel) {
|
|
68
|
+
graphElement.setAttribute('aria-label', ariaLabel);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (typeof onActivate === 'function') {
|
|
72
|
+
graphElement.dataset.action = 'open-file';
|
|
73
|
+
graphElement.setAttribute('role', 'button');
|
|
74
|
+
graphElement.setAttribute('tabindex', '0');
|
|
75
|
+
graphElement.addEventListener('click', (event) => {
|
|
76
|
+
event.preventDefault();
|
|
77
|
+
onActivate();
|
|
78
|
+
});
|
|
79
|
+
graphElement.addEventListener('keydown', (event) => {
|
|
80
|
+
if (event.key !== 'Enter' && event.key !== ' ') {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
event.preventDefault();
|
|
85
|
+
onActivate();
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
graphElement.dataset.mxgraph = JSON.stringify({
|
|
90
|
+
'check-visible-state': false,
|
|
91
|
+
center: true,
|
|
92
|
+
border: 0,
|
|
93
|
+
'dark-mode': theme === 'light' ? 'light' : 'dark',
|
|
94
|
+
editable: false,
|
|
95
|
+
fit: 1,
|
|
96
|
+
lightbox: false,
|
|
97
|
+
nav: false,
|
|
98
|
+
resize: false,
|
|
99
|
+
tooltips: false,
|
|
100
|
+
xml: String(source ?? ''),
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
return graphElement;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export async function renderDrawioViewer(host, options = {}) {
|
|
107
|
+
const viewer = await ensureDrawioViewerLoaded();
|
|
108
|
+
const graphElement = createDrawioViewerElement(options);
|
|
109
|
+
host.replaceChildren(graphElement);
|
|
110
|
+
|
|
111
|
+
if (typeof viewer.createViewerForElement === 'function') {
|
|
112
|
+
viewer.createViewerForElement(graphElement);
|
|
113
|
+
} else {
|
|
114
|
+
viewer.processElements();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return graphElement;
|
|
118
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { setDiagramActionButtonIcon } from '../domain/diagram-action-icons.js';
|
|
2
2
|
import { reconcileEmbedEntries } from './excalidraw-embed-reconciler.js';
|
|
3
|
-
import { resolveAppUrl } from '../domain/runtime-paths.js';
|
|
3
|
+
import { resolveAppUrl, resolveWsServerOverride } from '../domain/runtime-paths.js';
|
|
4
4
|
import {
|
|
5
5
|
cancelIdleRender,
|
|
6
6
|
isNearViewport,
|
|
@@ -15,6 +15,13 @@ const MAX_IFRAME_BOOT_ATTEMPTS = 3;
|
|
|
15
15
|
const MIN_HEIGHT = 200;
|
|
16
16
|
const EDITOR_IFRAME_PATH = '/excalidraw-editor.html';
|
|
17
17
|
|
|
18
|
+
function findEmbedPlaceholder(previewElement, key) {
|
|
19
|
+
const placeholders = previewElement?.querySelectorAll?.(
|
|
20
|
+
'.excalidraw-embed-placeholder[data-embed-key]',
|
|
21
|
+
);
|
|
22
|
+
return Array.from(placeholders || []).find((placeholder) => placeholder.dataset?.embedKey === key) || null;
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
export class ExcalidrawEmbedController {
|
|
19
26
|
constructor({
|
|
20
27
|
getTheme,
|
|
@@ -70,12 +77,16 @@ export class ExcalidrawEmbedController {
|
|
|
70
77
|
|
|
71
78
|
this.embedEntries.forEach((entry) => {
|
|
72
79
|
this._clearEntryBootTimeout(entry);
|
|
80
|
+
entry.resizerCleanup?.();
|
|
81
|
+
entry.resizerCleanup = null;
|
|
73
82
|
entry.wrapper?.remove();
|
|
74
83
|
entry.placeholder = null;
|
|
75
84
|
});
|
|
76
85
|
this.embedEntries.clear();
|
|
77
86
|
if (this.warmEntry) {
|
|
78
87
|
this._clearEntryBootTimeout(this.warmEntry);
|
|
88
|
+
this.warmEntry.resizerCleanup?.();
|
|
89
|
+
this.warmEntry.resizerCleanup = null;
|
|
79
90
|
this.warmEntry.wrapper?.remove();
|
|
80
91
|
this.warmEntry = null;
|
|
81
92
|
}
|
|
@@ -219,6 +230,25 @@ export class ExcalidrawEmbedController {
|
|
|
219
230
|
});
|
|
220
231
|
}
|
|
221
232
|
|
|
233
|
+
openCommentThread(filePath, threadId) {
|
|
234
|
+
if (!filePath || !threadId) {
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const entry = this._findEntryByFilePath(filePath);
|
|
239
|
+
if (!entry) {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
entry.pendingCommentThreadId = threadId;
|
|
244
|
+
if (entry.isReady) {
|
|
245
|
+
this._postPendingCommentThread(entry);
|
|
246
|
+
} else if (!entry.wrapper) {
|
|
247
|
+
this._enqueueHydration(entry, { prioritize: true });
|
|
248
|
+
}
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
|
|
222
252
|
prepareFileDisconnect(filePath, { timeoutMs = 10000 } = {}) {
|
|
223
253
|
const entry = this._findEntryByFilePath(filePath);
|
|
224
254
|
if (!entry?.iframe?.contentWindow) {
|
|
@@ -394,6 +424,7 @@ export class ExcalidrawEmbedController {
|
|
|
394
424
|
entry.maxButton = mount.maxButton;
|
|
395
425
|
entry.openButton = mount.openButton;
|
|
396
426
|
entry.instanceId = mount.instanceId;
|
|
427
|
+
entry.resizerCleanup = mount.resizerCleanup;
|
|
397
428
|
entry.isReady = false;
|
|
398
429
|
entry.bootFilePath = entry.filePath;
|
|
399
430
|
entry.bootMode = this._getEntryMode(entry);
|
|
@@ -414,7 +445,7 @@ export class ExcalidrawEmbedController {
|
|
|
414
445
|
_attachWrapper(entry) {
|
|
415
446
|
const placeholder = entry.placeholder?.isConnected
|
|
416
447
|
? entry.placeholder
|
|
417
|
-
: this.previewElement
|
|
448
|
+
: findEmbedPlaceholder(this.previewElement, entry.key);
|
|
418
449
|
|
|
419
450
|
if (!placeholder) {
|
|
420
451
|
return;
|
|
@@ -476,6 +507,8 @@ export class ExcalidrawEmbedController {
|
|
|
476
507
|
}
|
|
477
508
|
|
|
478
509
|
this._clearEntryBootTimeout(entry);
|
|
510
|
+
entry.resizerCleanup?.();
|
|
511
|
+
entry.resizerCleanup = null;
|
|
479
512
|
if (this.warmEntry === entry) {
|
|
480
513
|
this.warmEntry = null;
|
|
481
514
|
}
|
|
@@ -634,7 +667,7 @@ export class ExcalidrawEmbedController {
|
|
|
634
667
|
}
|
|
635
668
|
|
|
636
669
|
const hostSearchParams = new URLSearchParams(window.location.search);
|
|
637
|
-
const serverOverride =
|
|
670
|
+
const serverOverride = resolveWsServerOverride();
|
|
638
671
|
if (serverOverride) {
|
|
639
672
|
iframeUrl.searchParams.set('server', serverOverride);
|
|
640
673
|
}
|
|
@@ -702,7 +735,7 @@ export class ExcalidrawEmbedController {
|
|
|
702
735
|
const resizer = document.createElement('div');
|
|
703
736
|
resizer.className = 'excalidraw-embed-resizer';
|
|
704
737
|
resizer.title = 'Drag to resize';
|
|
705
|
-
this._setupResizer(resizer, iframe, () => {
|
|
738
|
+
const resizerCleanup = this._setupResizer(resizer, iframe, () => {
|
|
706
739
|
this._syncEntryLayout(entry);
|
|
707
740
|
this._requestPreviewViewportFit(entry);
|
|
708
741
|
});
|
|
@@ -769,6 +802,7 @@ export class ExcalidrawEmbedController {
|
|
|
769
802
|
labelElement: label,
|
|
770
803
|
maxButton: maxBtn,
|
|
771
804
|
openButton: openBtn,
|
|
805
|
+
resizerCleanup,
|
|
772
806
|
wrapper,
|
|
773
807
|
};
|
|
774
808
|
}
|
|
@@ -793,6 +827,7 @@ export class ExcalidrawEmbedController {
|
|
|
793
827
|
_setupResizer(resizer, iframe, onResizeEnd = null) {
|
|
794
828
|
let startY = 0;
|
|
795
829
|
let startHeight = 0;
|
|
830
|
+
let isDragging = false;
|
|
796
831
|
|
|
797
832
|
const onPointerMove = (event) => {
|
|
798
833
|
const delta = event.clientY - startY;
|
|
@@ -801,20 +836,37 @@ export class ExcalidrawEmbedController {
|
|
|
801
836
|
iframe.style.pointerEvents = 'none';
|
|
802
837
|
};
|
|
803
838
|
|
|
804
|
-
const
|
|
839
|
+
const stopDragging = () => {
|
|
840
|
+
if (!isDragging) {
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
isDragging = false;
|
|
805
845
|
iframe.style.pointerEvents = '';
|
|
806
846
|
document.removeEventListener('pointermove', onPointerMove);
|
|
807
847
|
document.removeEventListener('pointerup', onPointerUp);
|
|
848
|
+
};
|
|
849
|
+
|
|
850
|
+
const onPointerUp = () => {
|
|
851
|
+
stopDragging();
|
|
808
852
|
onResizeEnd?.();
|
|
809
853
|
};
|
|
810
854
|
|
|
811
|
-
|
|
855
|
+
const onPointerDown = (event) => {
|
|
812
856
|
event.preventDefault();
|
|
857
|
+
isDragging = true;
|
|
813
858
|
startY = event.clientY;
|
|
814
859
|
startHeight = iframe.offsetHeight;
|
|
815
860
|
document.addEventListener('pointermove', onPointerMove);
|
|
816
861
|
document.addEventListener('pointerup', onPointerUp);
|
|
817
|
-
}
|
|
862
|
+
};
|
|
863
|
+
|
|
864
|
+
resizer.addEventListener('pointerdown', onPointerDown);
|
|
865
|
+
|
|
866
|
+
return () => {
|
|
867
|
+
resizer.removeEventListener?.('pointerdown', onPointerDown);
|
|
868
|
+
stopDragging();
|
|
869
|
+
};
|
|
818
870
|
}
|
|
819
871
|
|
|
820
872
|
_ensureOverlayRoot() {
|
|
@@ -1064,7 +1116,7 @@ export class ExcalidrawEmbedController {
|
|
|
1064
1116
|
|
|
1065
1117
|
const placeholder = entry.placeholder?.isConnected
|
|
1066
1118
|
? entry.placeholder
|
|
1067
|
-
: this.previewElement
|
|
1119
|
+
: findEmbedPlaceholder(this.previewElement, entry.key);
|
|
1068
1120
|
|
|
1069
1121
|
if (!placeholder) {
|
|
1070
1122
|
return;
|
|
@@ -1163,6 +1215,7 @@ export class ExcalidrawEmbedController {
|
|
|
1163
1215
|
theme: this.getTheme?.() || 'dark',
|
|
1164
1216
|
});
|
|
1165
1217
|
this._syncEntryFollowState(entry);
|
|
1218
|
+
this._postPendingCommentThread?.(entry);
|
|
1166
1219
|
if (this._entryNeedsHardReload(entry)) {
|
|
1167
1220
|
void this._hydrateEntry(entry);
|
|
1168
1221
|
}
|
|
@@ -1227,6 +1280,19 @@ export class ExcalidrawEmbedController {
|
|
|
1227
1280
|
entry?.iframe?.contentWindow?.postMessage(payload, window.location.origin);
|
|
1228
1281
|
}
|
|
1229
1282
|
|
|
1283
|
+
_postPendingCommentThread(entry) {
|
|
1284
|
+
if (!entry?.isReady || !entry.pendingCommentThreadId) {
|
|
1285
|
+
return;
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
this._postMessageToEntry(entry, {
|
|
1289
|
+
source: 'collabmd-host',
|
|
1290
|
+
threadId: entry.pendingCommentThreadId,
|
|
1291
|
+
type: 'open-comment-thread',
|
|
1292
|
+
});
|
|
1293
|
+
entry.pendingCommentThreadId = null;
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1230
1296
|
_requestPreviewViewportFit(entry) {
|
|
1231
1297
|
if (this._isFilePreviewEntry(entry)) {
|
|
1232
1298
|
return;
|