Created
February 21, 2026 01:53
-
-
Save hotsphink/259f12c8e02b08730fbd07c857b57020 to your computer and use it in GitHub Desktop.
mkgist-created gist
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name phabricator unsubmitted indicator | |
| // @namespace Violentmonkey Scripts | |
| // @match https://phabricator.services.mozilla.com/D* | |
| // @run-at document-end | |
| // @version 1.0 | |
| // @author Steve Fink <sfink@mozilla.com> | |
| // @description Make it obvious when there are unsubmitted comments. | |
| // @grant none | |
| // ==/UserScript== | |
| var pending = false; | |
| var line; | |
| // There seems to be some timing issue with this one. It seems simple enough: | |
| // rely on whether this is visible or not. But I seem to be seeing it visible | |
| // after it should be gone (yet the next time I check, it's gone.) | |
| var main_preview = document.querySelector(".phui-comment-preview-view"); | |
| // For now, rely on comment contents. | |
| var main_comments = document.querySelector("textarea[name='comment']"); | |
| var favicon; | |
| var orig_favicon; | |
| var tinted_favicon = | |
| "data:image/png;base64,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"; | |
| function updateIndicator() { | |
| pending = 0; | |
| console.log("Checking..."); | |
| const hasInlineComments = [ | |
| ...document.querySelectorAll(".inline-state-is-draft"), | |
| ].filter((elt) => elt.offsetParent).length; | |
| const hasInlineCommentEditor = !!document.querySelector( | |
| ".differential-inline-comment-edit", | |
| ); | |
| //const hasMainComment = !!main_preview.offsetParent; | |
| const hasMainComment = main_comments.value != ""; | |
| const hasUnsubmitted = | |
| hasInlineComments || hasInlineCommentEditor || hasMainComment; | |
| const title = document.title; | |
| let newTitle = title.replace("** ", "").replace(" **", ""); | |
| if (hasUnsubmitted) { | |
| newTitle = "** " + newTitle + " **"; | |
| line.hidden = false; | |
| favicon.href = tinted_favicon; | |
| } else { | |
| line.hidden = true; | |
| favicon.href = orig_favicon; | |
| } | |
| if (newTitle !== title) { | |
| document.title = newTitle; | |
| } | |
| console.log("Checked", { | |
| hasInlineComments, | |
| hasInlineCommentEditor, | |
| hasMainComment, | |
| }); | |
| } | |
| // This can be called frequently, and will internally debounce the update using rAF. | |
| function bouncy_update() { | |
| if (pending) return; | |
| pending = true; | |
| requestAnimationFrame(() => { | |
| pending = false; | |
| updateIndicator(); | |
| }); | |
| } | |
| const watcher = new MutationObserver((mutations, observer) => { | |
| bouncy_update(); | |
| }); | |
| function init() { | |
| line = document.createElement("div"); | |
| Object.assign(line.style, { | |
| position: "fixed", | |
| top: 0, | |
| left: 0, | |
| width: "100%", | |
| height: "10px", | |
| background: | |
| "linear-gradient(to bottom, rgba(255,0,0,1) 0%, rgba(255,0,0,0.4) 40%, rgba(255,0,0,0) 100%)", | |
| zIndex: 99999, | |
| pointerEvents: "none", | |
| }); | |
| document.body.appendChild(line); | |
| // TODO: Be more specific | |
| watcher.observe(document.body, { | |
| subtree: true, | |
| childList: true, | |
| }); | |
| document | |
| .querySelector("textarea[name='comment']") | |
| .addEventListener("input", bouncy_update); | |
| favicon = document.querySelector("link#favicon"); | |
| orig_favicon = favicon.href; | |
| } | |
| init(); | |
| console.log("phabricator unsubmitted indicator user script init complete."); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment