11 ms·
Show HN: Display a bell emoji on HN comments you haven't read yet
- garyfirestorm 5y agothis is really nice! i think i will learn jscript - i have no clue what i am getting into but thanks for inspiring ps im a mechanical engineer
- eCa 5y agoNitpicking: Note that JScript[1] is not Javascript. The common abbreviation for Javascript is js. [1] https://en.wikipedia.org/wiki/JScript https://en.wikipedia.org/wiki/JScript
- hunter2_ 5y agoBased on the most recent stable release being 2011, I agree. But I found it funny that the article also says "A lot of people think that JScript and JavaScript are different but similar languages. That's not the case. They are just different names for the same language"!
- sillysaurusx 5y agoI was going to leave a comment complimenting you on your awesome HN username, but I try not to go off on too many tangents. However, I notice you have exactly 1337 karma right now. So the combination of hunter2 + 1337 is too irresistible not to mention. :) https://i.imgur.com/PM1T8DM.jpg https://i.imgur.com/PM1T8DM.jpg (It's strange that http://bash.org/?244321 http://bash.org/?244321 "only" has ~40k upvotes. I remember upvoting it when I was in high school, and it still seems to be working today, so you'd think a famous bash.org quote would accumulate more than a mildly popular Reddit post worth of upvotes...) Anyway, have a great week!
- linkdd 5y agoOk let's get off-topic because it's not everyday someone posts about bash.org. My favorite: http://bash.org/?835030 http://bash.org/?835030
- sillysaurusx 5y agoHahaa, I love that one. I remember reading http://bash.org/?5273 http://bash.org/?5273 as a teenager and thinking "What! How could anyone possibly lose a whole computer?" But then I lost a fully-working-responds-to-ping raspberry pi a few years ago too. :) Cheers!
- hunter2_ 5y agoHeh, thanks and you too!
- zamadatix 5y agoEven from the day it was made it was never the same language it was however a superset of JavaScript (at the time) having several proprietary extensions to the language.
- ModernMech 5y agoBetter than just upvoting everything, which is how I track this now.
- Y_Y 5y agoYou've made me realise I do something similar. It's probably a good idea that you're forbidden from downvoting direct replies though, because that's often a temptation.
- BelenusMordred 5y agoNice, I'd really like one to collapse all second-level comments. There's enough 1000+ comment links now that the top comment takes up the entire page and everyone wandering in tends to just respond to that or the children rather than numerous others making valid points.
- leephillips 5y agoThe extension “Refined Hacker News” for Chrome lets you click to collapse a comment thread.
- rashkov 5y agoThis is now a feature of hacker news itself, as of a year or two ago (?). No extension required. I think the parent comment wants a feature to collapse all comment threads at the same time, so only the top level comments are visible.
- appleflaxen 5y agoCan you elaborate? The feature seems nice, but I access HN on multiple browsers for which a plugin isn't workable. Looking at settings and links on the page I don't see any functionality like you describe.
- jraph 5y agoClick on [–] at the end of a comment header with JavaScript enabled.
- leephillips 5y agoAh, that’s right. (It’s the [-] link in the comment header.) RFN does have a link at the top of the story page called "toggle all commments," but I guess it’s broken, as it only seems to toggle the first comment. The extension does have a convenient feature, a [collapse root] link on each comment in a thread, so you can collapse the thread from within it, without having to find its origin.
- leppr 5y agoNice short implementation. Here's a similar userscript I use: https://greasyfork.org/en/scripts/18066-hn-comment-trees/ https://greasyfork.org/en/scripts/18066-hn-comment-trees/
- rashkov 5y agoThis is so useful! I've previously resorted to searching the page for the word "minutes" to see the recent comments, but that's been unsatisfying. I only wish that we didn't have to use third party extensions for loading scripts like this. I can never quite bring myself to trust them with full access to all of my pages. This really should be a part of the browser functionality already.
- linkdd 5y agoThe extension I listed stores your scripts in localStorage. But I agree, it should be a browser feature.
- punnerud 5y agoWhat if we could add our own JavaScript within our user settings on HN?
- linkdd 5y agoThat would be a new feature. The philosophy of HN is to evolve slowly and carefully. This surely would break someone's workflow ;) https://xkcd.com/1172/ https://xkcd.com/1172/
- punnerud 5y agoNot break anything, just option “hidden” under settings. Just as they open the possibility to add HEX value to change the color on HN when you reach enough points on HN
- linkdd 5y agoHN would need to store the scripts and load them. This would mean slower loading time, and increased maintenance on databases. Also open the door to bugs like "why is this loading the scripts of another user?" which can be security threats. It's "just" a simple feature, but it still have costs. I'd rather have the browser allowing me to load scripts without relying on an extension.
- krapp 5y agoOn the other hand, it is kind of weird that a site called "Hacker News" is less hackable than MySpace back in the day. At the very least they could redesign the layout to make it easier for external scripts to deal with. Given how many people here long for the quirky old days of the web, I say whomever starts a thread should also get to create a custom CSS theme for it.
- tfsh 5y agoThis is a sweet and simple implementation, however I don't think the title "[...] you haven't read yet" is correct. The code caches every comment ID which exists in the page, even ones outside of the viewport. A more accurate title would be "Display a bell emoji on new HN comments". - Using the JavaScript Intersection Observer may be an interesting addition, as this would explicitly differentiate comments on the thread which you may not have scrolled down to.
- deleted 5y ago[deleted]
- legrande 5y ago> This is a sweet and simple implementation I love one-thing-well items of code instead of large (and thus non-secure) abstractions built upon other abstractions. Big fan of the K.I.S.S principle https://en.wikipedia.org/wiki/KISS_principle https://en.wikipedia.org/wiki/KISS_principle
- obventio56 5y agoI will point out that that reason this can be so concise is because of a set of large foundational abstractions.
- legrande 5y agoGood point. I never thought of it that way. The modern PC is a marvel. On one hand it's a complex mess, on the other we can write poetry like that JS snippet, and it all works seamlessly (unless you're doing something weird).
- sillysaurusx 5y agoI changed the script so that the bells stay till you mouseover each HN comment: https://news.ycombinator.com/item?id=28540049 https://news.ycombinator.com/item?id=28540049
- myfonj 5y agoI've made userscript that locally stores hashes of titles and comments that stays in viewport for some time period and adds some marker to those displayed for the first time (i.e. guaranteed to be "unread" for the browser profile, provided there was no edit). https://greasyfork.org/en/scripts/423969-hn-style-unread-content/code https://greasyfork.org/en/scripts/423969-hn-style-unread-con... It uses IntersectionObserver for "exposition watch" and "crypto.subtle.digest" for SHA-1 hashes - I was pleasantly surprised those native APIs are enough to get this magic working. It's very POC-ey (absolutely no checks for storage capacity etc) but works quite well for me. E: Actual markers are just light green right borders on "unread" items that slightly fades out after "exposition timeout". I'm using dark userstyle for HN (https://uso.kkx.one/style/71155 https://uso.kkx.one/style/71155 ); in default theme they are probably too light to be visible.
- kuschku 5y agoFor reddit, this is massively easier to implement, as each comment contains in markup an accurate timestamp. That way the script only has to store the timestamps on which you visit a comment section, not the comment ids. Additionally, that way you can select "highlight all comments since visit [...]" with a dropdown from which you can choose out of all recent visits you did. Sadly, Hacker News does not provide any such metadata in the markup. (Just like the comment formatting is shit, and the markup structure is as well. HN should just copy the nesting markup and formatting 1:1 from reddit, and it'd be massively improved already).
- linkdd 5y agoBut it would break the workflow of so many people relying on that shitty structure! https://xkcd.com/1172/ https://xkcd.com/1172/ I like the fact that HN is so "stable".
- jraph 5y agoHN is so "table", I'd say.
- kogir 5y agoComment item ids are sequential (unless that’s changed since I last looked). You can perform relative ordering operations using them just like you could dates.
- sorenjan 5y agoNext to your comment there's a timestamp for when it was posted, with the title "2021-09-15T14:18:16". This is available for all comments as far as I can see. In what way is this inaccurate?
- MrGilbert 5y agoI think I like the outlined approach (minus the rant) that GP described - it sounds kind of simple, yet elegant.
- franhield 5y agoIsn't the GitHub title quite different from the title? Great code, though; Javascript can do wonders in the browser.
- riofoxx 5y agoT.o a.s.s.i.s.t y.o.u i.n t.r.a.d.e.s f.o.r b.e.t.t.e.r i.m.p.r.o.v.e.m.e.n.t on c.r.y.p.t.o.c.u.r.r.e.n.c.y W.h.a.t.s.A.p.p (+13052395906)
- sorenjan 5y agoWouldn't it make more sense to add an "unread" class to the comment and style it with css instead of appending new elements? I also think it would make sense to store the page load time, and compare to a comment's post time to determine if it's new instead of storing all comment ids.
- linkdd 5y agoI already have a custom CSS (using Stylus) for Dark Mode. The CSS is trickier due to the HTML structure.
- sorenjan 5y agoI was thinking of something like this: let style = document.createElement('style'); style.innerHTML = ".unread::after {content: ':bell:'}"; document.getElementsByTagName('head')[0].appendChild(style); document.querySelectorAll('.athing.comtr').forEach(comm => { if (comment is unread) { comm.querySelector('.comhead').classList.add("unread"); } }) That shouldn't collide with other custom CSS, and it avoids adding extra elements in the loop. Edit: I used the actual bell emoji in the code, but HN removed that, so I just replaced it with :bell:.
- kklisura 5y agoWhile we are here, let me plug my chrome extension that tracks comments which have been read https://github.com/kklisura/hn-comment-tracker https://github.com/kklisura/hn-comment-tracker The read comments have striped background and orange bar on the right, so identifying unread is easy.
- chhickman 5y agoI use a FireFox plugin that applies CSS for colorizing visited links on HN: a:link{ color: orange !important; } /* visited link */ a:visited { color: green !important; } https://mybrowseraddon.com/custom-style-script.html https://mybrowseraddon.com/custom-style-script.html
- mercora 5y agothey are already distinguishable by color without any change. this is about comments although it marks only comments as new it hasn't seen before regardless if you read them or not.
- lambdaba 5y agoThis gave me the idea that I would like that standard everywhere. This convention is just so helpful. Maybe replacing with an outline on more heavily styled links, so as not to break layouts too much.
- lolinder 5y agoIs it not the standard everywhere? All my links, on every page, are lighter when visited. I suppose some sites might override this, but I've rarely seen it.
- Nition 5y agoIt is standard everywhere unless a site explicitly overrides it. For example, do a Google search and click one of the links. Now do the same search again. The link you followed last time is now purple instead of blue. On Hacker News the links go a lighter grey.
- lambdaba 5y agoYes I know, but a lot of websites override it, I'd just like a unified style everywhere. To be honest I'd like consistent styling in a lot more places and I know of some add-ons that get pretty close but not quite.
- Santosh83 5y agoHN does not aim to be infinite scroll social media which addicts you and makes you keep checking and re-checking for more obsessively. It is purposefully barebones so that you're not tempted to read every single comment and waste time.
- junon 5y ago> makes you keep checking and re-checking for more obsessively. Yet I do this more on HN than any other site since I don't know if someone's responded to me. Noprocrast was... helpful, I guess, but I found myself racing to make poor quality responses sometimes, or HN was constantly locked out whenever I wanted to take a short break, instead of being able to take the time to respond with a thoughtful answer.
- andrewzah 5y agoYou can get notified of replies via email: https://www.hnreplies.com/ https://www.hnreplies.com/
- kjaftaedi 5y agoResponses aren't necessarily "to you" If you are going to post a comment that does nothing more than respond to the previous person, you are doing a disservice by forcing thousands of people to read text that is likely irrelevant or unhelpful to them. The fact that this site is designed to prevent this behavior is one of its stronger points IMHO
- junon 5y agoYou've completely missed the point of why I want response notifications.
- kjaftaedi 5y agoI get where you're coming from, but unless you're the only expert in your field, I think it's better to have group discussions. Response notifications will primarily be used by people to dominate the chat, and your use case doesn't negate that.
- silisili 5y agoSo, I get and appreciate the lack of notifications and distractions on HN. That said, I'd really like a way to find, distraction free(so in some submenu), reply comments. The current way seems narcissistic, as I have to go through my whole history to see why may have replied. And even then I have to do math to figure out if I'd seen it or not.
- c17r 5y agoI use https://www.hnreplies.com/ https://www.hnreplies.com/ for that
- silisili 5y agoThanks! I was hoping for something on the site, as I don't really want to be 'notified'. That said, I just plugged in an email I don't check often so that should accomplish it about the same. Never knew this existed - thanks again.
- jove2001 5y agoHacker News: The only place on the net where you actually should read the comments.
- carreau 5y agoAnother chrome extension that does similar things https://chrome.google.com/webstore/detail/hckr-news/mnlaodleonmmfkdhfofamacceeikgecp https://chrome.google.com/webstore/detail/hckr-news/mnlaodle...
- rasz 5y ago+ my userscript https://github.com/raszpl/hackahackernews https://github.com/raszpl/hackahackernews
- pcr910303 5y agoI'm not sure if this is something I am fine to say, but I've never signed an NDA or something so I'll just say: (Moderators, feel free to hide this comment if you would rather not like an influx of alpha testers.) If you sign up to the alpha-testing HN[0], you get access to the thread feature, which is... (quoted from my forwarded mail) > New feature: when you visit a thread, the software now highlights > comments that are new since you last viewed the page. These are > displayed with an orange (or whatever your topcolor is) bar to the > left of the new comment. Refreshing the page will reset these. Very useful, I can't imagine having HN without these indicators any more. [0]: https://news.ycombinator.com/item?id=22788678 https://news.ycombinator.com/item?id=22788678
- brundolf 5y agoFor those who don't want to switch to alpha, I made a bookmarklet that lets you enter an amount of time and highlights comments made within that amount of time (i.e. "15 minutes" ago, etc) https://news.ycombinator.com/item?id=25424560 https://news.ycombinator.com/item?id=25424560
- jeffdn 5y agoHow do you sign up for it?
- carl_dr 5y agoTaken from the parent comment : https://news.ycombinator.com/item?id=22788678 https://news.ycombinator.com/item?id=22788678
- krapp 5y agoI used to be on the beta testing list, but I think I was removed. It would be nice if awareness of this was more visible, maybe as a link on the footer, with a list of in progress or planned features.
- kuschku 5y agoI wrote a userscript that implements exactly that, but with the added benefit of storing every time you visited that page, so you can select between all your visits to that page and see which comments have been added after each visit. https://gist.github.com/justjanne/e61fcc9edb7d3dc60bc1a788d0329a0e https://gist.github.com/justjanne/e61fcc9edb7d3dc60bc1a788d0...
- sillysaurusx 5y agoI updated the script so that bells stay until you click on each HN comment you read: https://gist.github.com/shawwn/d0c370212793eeefdf6ef50468afe2da https://gist.github.com/shawwn/d0c370212793eeefdf6ef50468afe... Surprisingly it doesn't annoy me, because I'm often clicking on the comments I read anyway. (Old habit.) EDIT: I changed it to onmousemove. Feels pretty nice!
- linkdd 5y agoAwesome, thank you!
- sillysaurusx 5y ago(Fixed a typo; if you were getting an error, try now. Sorry about that!)
- lambdaba 5y agoIs there a "diff" type addon for all web pages? That would be so helpful. To be clear, I'd like a diff against stuff that I actually could've read (that's been in the viewport) not simply loaded.
- bestinterest 5y agoNice I added on the below as the Windows emoji is a bit big for my liking and keeps the emoji color neutral. span.style.cssText = ` font-size: 5px; color: transparent; text-shadow: 0 0 0 gray; margin-bottom: 2px; vertical-align: middle; display: inline-block; `
- mxstbr 5y agoAdditionally, I'm a big fan of the Hacker News Notifications extension[0] to keep track of responses to my conversations. It adds a small bell icon with a dropdown to the navbar that shows new replies to your posts and comments. 10/10, would recommend. [0]: https://chrome.google.com/webstore/detail/hacker-news-notifications/bbkfblhdgiddlkfkipjdhhfoephonoba?hl=en https://chrome.google.com/webstore/detail/hacker-news-notifi...
- chirau 5y agoDumb question... so how do I actually use this?
- linkdd 5y agoThere is no such thing as a dumb question. There is a Chrome extension "Custom Javascript for Website" (link in the first line of the snippet) that lets you add JS scripts to any website. Install the extension, then while on hackernews, open the extension and copy-paste the snippet into it.
- chirau 5y agoThank you for the assistance. So do I have to repeat the copy-paste each time I open HN? Also, it didn't work for me the first time, or now.
- deleted 5y ago[deleted]
- spowerei 5y agothis add a slider selector for the time range to consider and give higher values of alpha channel to more recent posts. const div = document.createElement("div"); div.innerHTML = `<div style="position:fixed;top:20px;right:20px;width:40px;background:#ff05;"> <input type="range" orient="vertical" id="interval" min="0" max="95" value="30" style="width:100%"> <label for="interval" style="display:block"></label> </div>`; const input = div.firstElementChild.firstElementChild; const label = input.nextElementSibling; document.body.appendChild(div); const formatTime = (mins) => { if (mins > 60) { return `${Math.floor(mins / 60)}h ${mins % 60}m`; } return `${mins}m`; }; const extrapolate = (val) => { val = val * 2; for (let t = 30; t <= 150; t += 30) { val += Math.max(0, val - t); } return val; }; input.oninput = () => colorStuff(extrapolate(input.value)); const colorStuff = (interval_minutes) => { label.innerText = `${formatTime(interval_minutes)}`; const comments = Array.from(document.getElementsByClassName("athing comtr")); dates = Array.from(document.getElementsByClassName('age')); dates.sort((c1, c2) => Date.parse((c2).title) - Date.parse((c1).title)); const now = new Date(); const timestamp = now.getTime() + now.getTimezoneOffset() * 60E3; comments.forEach((c) => { const commentDateString = c.getElementsByClassName("age")[0].title; const diff=(timestamp-Date.parse(c.getElementsByClassName('age')[0].title))/60E3; const diff2=(Date.parse(dates[0].title)-Date.parse(c.getElementsByClassName('age')[0].title))/60E3; if (diff < interval_minutes) { const alpha = (1 - diff2 / interval_minutes)**6; c.style.backgroundColor = `rgba(100, 255, 100, ${alpha})`; } else { c.style.backgroundColor = "rgba(255, 255, 255,0)"; } }); }; colorStuff(extrapolate(input.value));
- jimmySixDOF 5y agoThis discussion calls to mind the quote, miss-attributed to Albert Einstein, "We cannot solve our problems with the same thinking we used when we created them."
- rasz 5y agoLinked snipped will overflow localstorage in ~year of daily use and might take hundreds of miliseconds to parse multi megabyte json on every page load. I do this in my version to prune: function checkquota(){ // localStorage limit is ~5MB, should probably do something about exceeding quota ;) // lets trigger around 3MB // deleting half of the oldest empty(seen, never interacted with) entries first // popping a warning when we finally reach over 2MB non empty // // total entries: localStorage.length // storage bytes left: 1024 * 1024 * 5 - escape(encodeURIComponent(JSON.stringify(localStorage))).length // non empty entries: Object.entries(localStorage).filter(value => value[1] != "1") // non empty entries size: escape(encodeURIComponent(JSON.stringify(Object.entries(localStorage).filter(value => value[1] != "1")))).length // empty entries sorted, oldest first Object.entries(localStorage).filter(value => value[1] == "1").sort(function (a, b) {return parseInt(a[0]) - parseInt(b[0]);}); //size check is expensive, can be as long as 500ms for full localstorage, limit size checks to ~once per 24h if (GM_getValue("lastquotacheck") > Date.now()) return; GM_setValue("lastquotacheck", Date.now()+86400000); let size = encodeURIComponent(JSON.stringify(localStorage)).length; console.log("Current size: "+size+" bytes"); if (size > 1024 * 1024 * 3) { alert("Current hackahackernews consumed localStorage size: "+size+" bytes, cleaning older entries to make more room."); let sortedStorage = Object.entries(localStorage).filter(value => value[1] == "1").sort(function (a, b) {return parseInt(a[0]) - parseInt(b[0]);}); let cutout = parseInt(sortedStorage.length/2); for (let [index, value] of sortedStorage.entries()) { if (index < cutout) { localStorage.removeItem(value[0]); } } size = encodeURIComponent(JSON.stringify(localStorage)).length; console.log("Size after culling empty entries: "+size+" bytes"); let nonempty = Object.entries(localStorage).filter(value => value[1] != "1"); if (encodeURIComponent(JSON.stringify(nonempty)).length > 1024 * 1024 * 2) { console.log("Non empty entries size is over 2MB! currently at: "+encodeURIComponent(JSON.stringify(nonempty)).length+" bytes."); if (confirm("Saved visited links are consuming "+encodeURIComponent(JSON.stringify(nonempty)).length+" bytes, delete half of the oldest entries?")) { let sortedNonempty = nonempty.sort(function (a, b) {return parseInt(a[0]) - parseInt(b[0]);}); let cutout = parseInt(sortedNonempty.length/2); for (let [index, value] of sortedNonempty.entries()) { if (index < cutout) { localStorage.removeItem(value[0]); } } } } size = encodeURIComponent(JSON.stringify(localStorage)).length; console.log("Final size after culling: "+size+" bytes"); } }