pull down to refresh

A few days ago, I created a userscript to never see 'reply from someone you muted' again.

Due to the popular demand here of three other stackers, I decided it's worth making it easier to install and writing a post about it.

I still have to figure out if there's a way to run this in the PWA, too.


mutenukemutenuke

Never see 'reply from someone you muted' on Stacker News again.

Installation via userscript extensionInstallation via userscript extension

  1. Install a userscript extension like Tampermonkey
  2. Go to the mutenuke page on GreasyFork
  3. Click "Install this script"

Installation via Brave ShieldsInstallation via Brave Shields

On Brave, you don't need a userscript extension. You can run custom scriptlets within Shields as mentioned here!

  1. Go to brave://settings/shields/filters
  2. Enable developer mode
  3. Save this as a new custom scriptlet named 'mutenuke':
window.addEventListener('DOMContentLoaded', () => {
    function mutenuke() {
        document.querySelectorAll('div[class*="comment_collapsed"]')
            .forEach(node => {
                if (node.textContent.startsWith("reply from someone you muted")) node.remove()
            }
        )
    }

    // Run on initial page load
    mutenuke();

    // Watch for dynamically loaded content
    const observer = new MutationObserver(mutenuke);
    observer.observe(document.body, { childList: true, subtree: true });
})
  1. Save this as a new custom filter:
stacker.news##+js(user-mutenuke.js)

Done!

Installation via Brave Shields will cause React hydration errors, but as far as I know, it doesn't impact the functionality of the site.

555 sats \ 9 replies \ @optimism 1h

Fixes courtesy of:

  • runAfterHydration: GPT, Claude, Gemini and GLM (all said the same, lol)
  • node.style = "visibility: hidden" instead of node.remove(): Opti, because the removal gave me errors on comment.
window.addEventListener('load', () => {
  function runAfterHydration(callback) {
    requestAnimationFrame(() => {
      requestAnimationFrame(callback);
    });
  }

  runAfterHydration(() => {
    function removeCollapsedComments() {
      document
        .querySelectorAll('div[class*="comment_collapsed"]')
        .forEach(node => {
          if (node.textContent.startsWith("reply from someone you muted")) {
            node.style = "visibility: hidden";
          }
        });
    }

    removeCollapsedComments();

    const observer = new MutationObserver(removeCollapsedComments);
    observer.observe(document.body, { childList: true, subtree: true });
  });
});
reply
101 sats \ 8 replies \ @ek OP 1h

Ohh, nice fix! Also nice edit within the 10-minute timer, haha

reply
101 sats \ 7 replies \ @optimism 1h

It was the ultimate pressure cooking exercise in javascript debugging because I wrote "verified works" and then I hit post and it died 😂

reply
101 sats \ 6 replies \ @ek OP 51m

Mhh, node.style = "visibility: hidden" leaves empty space behind.

But node.style = "display: none" should work! The node is still there for React without taking up any space in the DOM.

reply
101 sats \ 5 replies \ @optimism 50m

confirmed. This why you don't let old people code for the browser 😂

reply
101 sats \ 4 replies \ @ek OP 32m

With node.style = "display: none", you can also keep running it after the slightly faster DOMContentLoaded event and don't need requestAnimationFrame. The load event will also wait until images are loaded.

Thank you!!

reply
101 sats \ 3 replies \ @optimism 29m

Wait! Are you saying that my noob code reimplemented by you, and not the trillion dollar training of the 4 most expensive databases that have ever existed, fixed the bug?

Take that, silicon brains. lol

reply
101 sats \ 2 replies \ @ek OP 20m

You probably told it to run after hydration, and that’s what it did, haha

But when we don’t remove the node, we don’t interfere with hydration, so we don’t need to run it after hydration.

Edit: But sounded like it was still broken after the first prompt, so you prompted it again, and that contained the actual, inspiring fix via CSS haha

Op @ek why don't you attach and show attached LN wallets?
Clearly you are capable but maybe you dont believe in verifying you are on board with and maximising your use of and support of LN here on SNs?
Genuinely mystified why you would not attach or deliberately conceal your LN wallet attached status.

reply
1 sat \ 1 reply \ @ek OP 1h

I don't need to virtue-signal about lightning, my work speaks for itself

reply

You do not believe content consumers here who ultimately must fund the entire platform if it is to be viable have a right to know which content providers have made the effort to attach LN wallets and thereby maximise their use of and support for the LN?

There are a number content providers who write a lot about LN development and potential who 'virtue signalling' that they are 'living on the Bitcoin Standard' but who have never bothered to attach both sending and receiving LN wallets. I see that as hypocrisy and do not want to spend my sats on them.

Showing attached wallets verifies to content consumers that a content provider is NOT just virtue signalling but is walking the talk.

reply

I don’t remember the lifecycle of mutation observers, do you need to clean them up somehow?

reply
51 sats \ 4 replies \ @ek OP 2h

Mhh, good point, probably, but this runs in the global context, so I guess the browser will clean up for me anyway when you close the tab? haha

reply

I think that’s right in this case. Fun stuff!

reply
51 sats \ 2 replies \ @ek OP 1h

Well, it was short-lived fun, my post already disappeared from the front page, haha. Anyway!

reply

Ironically, it's been oblivionzapped by the person that needs your script most.

reply

Op @ek why don't you attach and show attached LN wallets?
Clearly you are capable but maybe you dont believe in verifying you are on board with and maximising your use of and support of LN here on SNs?
Genuinely mystified why you would not attach or deliberately conceal your LN wallet attached status.

reply