]> BookStack Code Mirror - bookstack/commitdiff
Comments: Addressed a range of edge cases and ux issues for references
authorDan Brown <redacted>
Thu, 1 May 2025 15:33:42 +0000 (16:33 +0100)
committerDan Brown <redacted>
Thu, 1 May 2025 15:33:42 +0000 (16:33 +0100)
Handles only display and handling references when they're in the active
tab, while handling proper removal when made not visible.

resources/js/components/page-comment-reference.ts
resources/js/components/page-comment.ts
resources/js/services/components.ts

index 72e3dbe480d815ea801758b22edbfc33070afb1e..edf24354b3ba663f3a73f3c1557bd01beb9c0893 100644 (file)
@@ -3,7 +3,7 @@ import {findTargetNodeAndOffset, hashElement} from "../services/dom";
 import {el} from "../wysiwyg/utils/dom";
 import commentIcon from "@icons/comment.svg";
 import closeIcon from "@icons/close.svg";
-import {scrollAndHighlightElement} from "../services/util";
+import {debounce, scrollAndHighlightElement} from "../services/util";
 
 /**
  * Track the close function for the current open marker so it can be closed
@@ -29,7 +29,7 @@ export class PageCommentReference extends Component {
 
         // Show within page display area if seen
         const pageContentArea = document.querySelector('.page-content');
-        if (pageContentArea instanceof HTMLElement) {
+        if (pageContentArea instanceof HTMLElement && this.link.checkVisibility()) {
             this.updateMarker(pageContentArea);
         }
 
@@ -43,6 +43,21 @@ export class PageCommentReference extends Component {
                  this.hideMarker();
              }
         });
+
+        // Handle comments tab changes to hide/show markers & indicators
+        window.addEventListener('tabs-change', event => {
+            const sectionId = (event as {detail: {showing: string}}).detail.showing;
+            if (!sectionId.startsWith('comment-tab-panel') || !(pageContentArea instanceof HTMLElement)) {
+                return;
+            }
+
+            const panel = document.getElementById(sectionId);
+            if (panel?.contains(this.link)) {
+                this.updateMarker(pageContentArea);
+            } else {
+                this.hideMarker();
+            }
+        });
     }
 
     protected showForEditor() {
@@ -111,9 +126,10 @@ export class PageCommentReference extends Component {
             scrollAndHighlightElement(refEl);
         });
 
-        window.addEventListener('resize', () => {
+        const debouncedReposition = debounce(() => {
             this.positionMarker(refEl, refRange);
-        });
+        }, 50, false).bind(this);
+        window.addEventListener('resize', debouncedReposition);
     }
 
     protected positionMarker(targetEl: HTMLElement, range: string) {
@@ -145,12 +161,13 @@ export class PageCommentReference extends Component {
         this.markerWrap.style.height = `${targetBounds.height}px`;
     }
 
-    protected hideMarker() {
+    public hideMarker() {
         // Hide marker and close existing marker windows
         if (openMarkerClose) {
             openMarkerClose();
         }
         this.markerWrap?.remove();
+        this.markerWrap = null;
     }
 
     protected showCommentAtMarker(marker: HTMLElement): void {
index 12485b807287d20c5a38b6cd0625f893749b9107..18b9ab73bf0c82c48cb8380eb42f02e38327a892 100644 (file)
@@ -1,6 +1,7 @@
 import {Component} from './component';
 import {getLoading, htmlToDom} from '../services/dom.ts';
 import {buildForInput} from '../wysiwyg-tinymce/config';
+import {PageCommentReference} from "./page-comment-reference";
 
 export class PageComment extends Component {
 
@@ -142,7 +143,13 @@ export class PageComment extends Component {
         const response = await window.$http.put(`/comment/${this.commentId}/${action}`);
         window.$events.success(this.archiveText);
         this.$emit(action, {new_thread_dom: htmlToDom(response.data as string)});
-        this.container.closest('.comment-branch')?.remove();
+
+        const branch = this.container.closest('.comment-branch') as HTMLElement;
+        const references = window.$components.allWithinElement<PageCommentReference>(branch, 'page-comment-reference');
+        for (const reference of references) {
+            reference.hideMarker();
+        }
+        branch.remove();
     }
 
     protected showLoading(): HTMLElement {
index c19939e92a9b874aa61da08943012c6cbd9aa505..0e13cd0a09fca78429a117a50b2aa875f18012e3 100644 (file)
@@ -139,8 +139,8 @@ export class ComponentStore {
     /**
      * Get all the components of the given name.
      */
-    public get(name: string): Component[] {
-        return this.components[name] || [];
+    public get<T extends Component>(name: string): T[] {
+        return (this.components[name] || []) as T[];
     }
 
     /**
@@ -150,4 +150,9 @@ export class ComponentStore {
         const elComponents = this.elementComponentMap.get(element) || {};
         return elComponents[name] || null;
     }
+
+    public allWithinElement<T extends Component>(element: HTMLElement, name: string): T[] {
+        const components = this.get<T>(name);
+        return components.filter(c => element.contains(c.$el));
+    }
 }