From dfad5449fd57821395612fe7a8d702fdfd2e5424 Mon Sep 17 00:00:00 2001 From: Kynan Ware <47394200+BagToad@users.noreply.github.com> Date: Sat, 18 May 2024 10:33:17 -0600 Subject: [PATCH] Add visual scroll-to comment indicator (#73) * Add visual indicator for scrolled-to comment Related to #63 Implements visual feedback for scrolled-to comments in Zendesk Link Collector extension. - Adds a new function `highlightComment` to apply a temporary highlight to a comment after scrolling to it. - Modifies the `scrollToComment` function to call `highlightComment`, providing a visual indication of the scrolled-to comment. - Ensures the highlight fades away after a few seconds, improving user experience by clearly indicating the comment of interest. * feat: Add visual indicator for scrolled-to comment & refactor scroll-to comment function to prevent duplicate messages * refactor: Improve highlightComment function and add counter for DOM traversal --- src/content-scripts/contentscript.js | 78 ++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 21 deletions(-) diff --git a/src/content-scripts/contentscript.js b/src/content-scripts/contentscript.js index 9030064..44836fe 100644 --- a/src/content-scripts/contentscript.js +++ b/src/content-scripts/contentscript.js @@ -4,39 +4,42 @@ console.log("Zendesk Link Collector - loaded content script"); browser.runtime.onMessage.addListener(function (request, sender, sendResponse) { // Scroll to the comment. if (request.type == "scroll") { - const element = document.querySelector( - `[data-comment-id="${request.commentID}"]` - ) - ? // Older Zendesk versions. - document.querySelector(`[data-comment-id="${request.commentID}"]`) - : // Newer Zendesk versions. - document.querySelector(`[id="comment-${request.auditID}"]`); - if (element) { - element.scrollIntoView({ behavior: "smooth", block: "center" }); - return; - } - - // Last resort, sometimes zendesk does not add the data-comment-id or id attributes to the comments. - // Get the comment from the audits endpoint, find the comment with the same HTML in the DOM and scroll to it. - const url = new URL(document.URL); - const urlArr = url.href.split("/"); - const ticketID = urlArr[urlArr.length - 1]; + // This is async because it contains a fetch which we must wait for before sending a response. + (async () => { + const element = document.querySelector( + `[data-comment-id="${request.commentID}"]` + ) + ? // Older Zendesk versions. + document.querySelector(`[data-comment-id="${request.commentID}"]`) + : // Newer Zendesk versions. + document.querySelector(`[id="comment-${request.auditID}"]`); + if (element) { + element.scrollIntoView({ behavior: "smooth", block: "center" }); + highlightComment(element); + return; + } + // Last resort, sometimes zendesk does not add the data-comment-id or id attributes to the comments. + // Get the comment from the audits endpoint, find the comment with the same HTML in the DOM and scroll to it. + const url = new URL(document.URL); + const urlArr = url.href.split("/"); + const ticketID = urlArr[urlArr.length - 1]; - fetch( - `${url.protocol}//${url.hostname}/api/v2/tickets/${ticketID}/audits/${request.auditID}` - ).then(async function (response) { + const response = await fetch( + `${url.protocol}//${url.hostname}/api/v2/tickets/${ticketID}/audits/${request.auditID}` + ); const data = await response.json(); document.querySelectorAll(".zd-comment").forEach((comment) => { data.audit.events.forEach((event) => { if (event.type == "Comment") { if (comment.outerHTML == event.html_body) { comment.scrollIntoView({ behavior: "smooth", block: "center" }); + highlightComment(comment); return; } } }); }); - }); + })(); } // Code from https://stackoverflow.com/questions/55214828/how-to-make-a-cross-origin-request-in-a-content-script-currently-blocked-by-cor/55215898#55215898 @@ -130,3 +133,36 @@ browser.runtime.onMessage.addListener(function (request, sender, sendResponse) { return true; }); + +function highlightComment(element) { + let highlightElement = element; + let counter = 0; + const maxCounter = 20; + // Traverse up the DOM tree until an 'article' element is found or counter reaches 10 + while ( + highlightElement && + highlightElement.nodeName.toLowerCase() !== "article" && + counter < maxCounter + ) { + highlightElement = highlightElement.parentElement; + counter++; + } + + // If an 'article' element is found or the nth parent is reached, highlight whatever the element is. + if (highlightElement) { + const originalColor = highlightElement.style.backgroundColor; + + highlightElement.style.transition = "background-color 0.5s ease"; + highlightElement.style.backgroundColor = "#ffff99"; + setTimeout(() => { + // Set the background color back to its original color to start the fade-out transition + highlightElement.style.backgroundColor = originalColor; + }, 2000); + + // After the transition is complete, remove the style attribute + setTimeout(() => { + highlightElement.removeAttribute("style"); + }, 2500); // Ensure the style attribute is removed after the transition is complete. + // This is very important to ensure the HTML of this element stays the same as what is returned by the audits endpoint. + } +}