From 9ad5f76aaa2f09f002a3378e5c9c6e6a6b64fa70 Mon Sep 17 00:00:00 2001 From: Adam Wright Date: Mon, 9 Dec 2024 16:41:54 -0600 Subject: [PATCH] handle nested issues ui --- src/ChromeExtension/manifest.json | 4 +- ...content-script-copy-saved-reply-element.js | 105 ++++++++++++++++++ .../pages/content-script/content-script.js | 95 +++++++++++++++- .../pages/service-worker/service-worker.js | 8 +- 4 files changed, 203 insertions(+), 9 deletions(-) create mode 100644 src/ChromeExtension/pages/content-script/content-script-copy-saved-reply-element.js diff --git a/src/ChromeExtension/manifest.json b/src/ChromeExtension/manifest.json index b65bdd3..30e0861 100644 --- a/src/ChromeExtension/manifest.json +++ b/src/ChromeExtension/manifest.json @@ -17,6 +17,7 @@ "js": [ "js/time.js", "js/null.js", + "pages/content-script/content-script-copy-saved-reply-element.js", "pages/content-script/content-script-urls.js", "pages/content-script/content-script-storage.js", "pages/content-script/content-script-elements.js", @@ -31,8 +32,7 @@ "64": "icons/icon64.png", "128": "icons/icon128.png" }, - "key":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArGi8r21wWmiQLmrqIEf+MHVXwGCE0hF/3MdAbRlDAYka4rDFIZAp+fPu5R79jgm5/WQsMfBtluGl3hELB4xWVoXQEOUEp1jEHIEsDWyh61zlDT92+KS5z+73R1sdJA0V5uEvcBuTl6B/zSqCfLNrycu+9VDZkFYSZzsMfX+ClJYbqJ89ZRS48Jh8cqlGWZ49Ukjjt+VdZAl8PqQMg2IC2KSSQxKssWaGMKX0AVVfymKxT+eC4TFs9HyP82FRBNsq/c46yKP2q+vfx/9iNQra/CpZ46k4nq4SDZ1pJJ5LZIAn1+Et4qMklU0/Yqe8VPGqRCqivfxEJPmkcntFwfC3qQIDAQAB", - "options_ui":{ + "options_ui":{ "page":"pages/options/options.html", "open_in_tab":true }, diff --git a/src/ChromeExtension/pages/content-script/content-script-copy-saved-reply-element.js b/src/ChromeExtension/pages/content-script/content-script-copy-saved-reply-element.js new file mode 100644 index 0000000..758d756 --- /dev/null +++ b/src/ChromeExtension/pages/content-script/content-script-copy-saved-reply-element.js @@ -0,0 +1,105 @@ +const getsSavedRepliesForNestedIssuesContainer = () => + document.querySelector(`#__primerPortalRoot__ div[role="listbox"] > div`); + +const getLastExistingSavedReplyElement = (savedRepliesContainer) => { + + let savedReplyElements = + savedRepliesContainer.querySelectorAll(`div[tabindex="-1"][role="option"]`); + + let lastSavedReplyElement = savedReplyElements[savedReplyElements.length- 1] + + return lastSavedReplyElement; +} + +const calculateSavedReplyId = (lastId, savedReplyIndex) => { + + let numberIndex = lastId.search(`[0-9]`); + + if(numberIndex !== -1){ + + let lastIdNumber = Number(lastId.substring(numberIndex)); + + let newNumericalId = lastIdNumber + savedReplyIndex + 1; + + let idPrefix = lastId.substring(0, numberIndex); + + let newId = idPrefix + new String(newNumericalId); + + return newId; + } + else{ + + return lastId; + } +} + +const setSavedReplyId = (element,calculatedId) => { + + element.id = calculatedId; +} + +const setSavedReplyTitle = (titleSpan, title) => { + + titleSpan.innerText = title; +} + +const setSavedReplyBody = (bodySpan, body) => { + + bodySpan.innerText = body; +} + +const createNewSavedReplyElementFromExistingElment = (templateElement, savedReply, index) => { + + let newSavedReplyElement = templateElement.cloneNode(true); + + let savedReplySpans = newSavedReplyElement.querySelectorAll(`span`); + + let titleSpan = savedReplySpans[0]; + + let bodySpan = savedReplySpans[1]; + + setSavedReplyTitle(titleSpan, savedReply.name); + + setSavedReplyBody(bodySpan, savedReply.body); + + let id = calculateSavedReplyId(templateElement.id, index); + + setSavedReplyId(newSavedReplyElement, id); + + return newSavedReplyElement; +} + +const createSavedRepliesUIForNestedIssues = (savedReplies) => { + + let savedRepliesDivs = []; + + let savedRepliesContainer = getsSavedRepliesForNestedIssuesContainer(); + + let lastSavedReplyElement = getLastExistingSavedReplyElement(savedRepliesContainer); + + for (const [index, reply] of savedReplies.entries()){ + + let newElement = + createNewSavedReplyElementFromExistingElment(lastSavedReplyElement, reply, index); + + savedRepliesDivs.push(newElement); + } + + return savedRepliesDivs; +} + +const addNewSavedReplyElementToContainer = (savedRepliesContainer,savedReplyElement ) => { + + savedRepliesContainer.appendChild(savedReplyElement); +} + +const addNewSavedRepliesToNestedIssuesContainer = (savedRepliesDivs, savedRepliesContainer) =>{ + + for (const savedReplyDiv of savedRepliesDivs){ + savedRepliesContainer.appendChild(savedReplyDiv); + } +} + +const removeNewSavedRepliesToNestedIssuesContainer = () =>{ + +} \ No newline at end of file diff --git a/src/ChromeExtension/pages/content-script/content-script.js b/src/ChromeExtension/pages/content-script/content-script.js index 70b27ee..f2fab81 100644 --- a/src/ChromeExtension/pages/content-script/content-script.js +++ b/src/ChromeExtension/pages/content-script/content-script.js @@ -7,7 +7,9 @@ const main = async () => { } let observer; + let betaObserver; let repliesUl; + let repliesForNestedIssuesDivs; let replies; const prepareRepliesUl = async () => { @@ -115,15 +117,96 @@ const main = async () => { } } }); - + + let savedReplyContainer = document.querySelector(`#saved_replies_menu_new_comment_field-dialog`); - observer.observe(savedReplyContainer, { - attributes: true, - childList: false, - subtree: false - }); + if(savedReplyContainer){ + + observer.observe(savedReplyContainer, { + attributes: true, + childList: false, + subtree: false + }); + } + + const prepareSavedRepliesForNestedIssues = async () => { + + replies = await getMatchingSavedReplyConfigsFromLocalStorage(); + + const repliesExist = arrayIsNotEmpty(replies); + + if (repliesExist) { + repliesForNestedIssuesDivs = createSavedRepliesUIForNestedIssues(replies); + } + } + + + const tryUpdateSavedRepliesForNestedIssues = () => { + + let saveRepliesContainer = getsSavedRepliesForNestedIssuesContainer(); + + const repliesExist = arrayIsNotEmpty(repliesForNestedIssuesDivs); + + if (repliesExist && saveRepliesContainer) { + + addNewSavedRepliesToNestedIssuesContainer( + repliesForNestedIssuesDivs, + saveRepliesContainer); + + return true; + + } else if (saveRepliesContainer) { + + + return true; + } + } + + const onSavedRepliesDialogIsVisible = async () => { + + await prepareSavedRepliesForNestedIssues(); + + if(tryUpdateSavedRepliesForNestedIssues()){ + + return; + } + } + + + let addSavedReplyButton = document.querySelector(`button[aria-label="Add saved reply (Ctrl + .)"]`); + + betaObserver = new MutationObserver( + async (mutationList, obs) => { + + console.log(`beta mutation happened`); + for (const mutation of mutationList) { + + if (mutation.type === "attributes" && mutation.attributeName == "aria-expanded"){ + + let savedRepliesDialogIsVisible = addSavedReplyButton.getAttribute("aria-expanded") === "true"; + + if(savedRepliesDialogIsVisible) + { + console.log("beta open") + await onSavedRepliesDialogIsVisible() + }else{ + console.log("beta closed") + } + } + } + } + ); + + if(addSavedReplyButton){ + + betaObserver.observe(addSavedReplyButton, { + attributes: true, + childList: false, + subtree: false + }); + } } document.addEventListener("soft-nav:end", main); diff --git a/src/ChromeExtension/pages/service-worker/service-worker.js b/src/ChromeExtension/pages/service-worker/service-worker.js index 26389fd..c0afe58 100644 --- a/src/ChromeExtension/pages/service-worker/service-worker.js +++ b/src/ChromeExtension/pages/service-worker/service-worker.js @@ -103,6 +103,12 @@ chrome.webNavigation.onHistoryStateUpdated.addListener( chrome.scripting.executeScript({ target: {tabId: tab.id}, - func: () => {} + func: () => { + console.log("fired"); + chrome.runtime.lastError } }); + + //chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { + //}); + }, {url: [{hostSuffix: 'github.com'}]}); \ No newline at end of file