revamp the way page:treehouse/new works

- treehouse/new is now a regular page, not a special template
- most of the code related to the `new` badge in page:index has been removed
- you're meant to discern between pages you've read vs ones you haven't by looking at the colors of the links (blue vs purple)
This commit is contained in:
liquidex 2024-11-12 19:49:57 +01:00
parent 8d1deee626
commit e201ea7058
6 changed files with 128 additions and 362 deletions

View file

@ -1,133 +1,159 @@
%% template = "_new.hbs"
title = "a curated feed of updates to the house"
%% title = "a curated feed of updates to the house"
styles = ["new.css"]
feed = "news"
% id = "01J4J5N6WZQ03VTB3TZ51J7QZK"
- [featured]{.badge .blue} I was bored over a weekend, so I decided to write the tiniest programming language I could imagine.
it came out looking pretty Lispy, and I'm glad about that!
I learned a ton about Lisps in the process of researching it.
even though it didn't end up having macros...
% id = "01JCGWPM6T73PAC5Q8YHPBEAA1"
+ hello!
if you've been wondering what I've been up to, you've come to the right place.
### haku - writing a little programming language for fun
% id = "01JCGWPM6T3W07KAGG3J29JMVF"
- posts are sorted from newest to oldest.
[read][page:programming/blog/haku]
% id = "01JCGWPM6TGQ17JPSJW8G58SB0"
- you can keep track of which posts you've read by looking at the color of the links.
% id = "01JCGWPM6TMAJT0B50GQSA4BDW"
- there is currently no RSS or Atom feed for this page, sorry!
% id = "01JBAGZAZ30K443QYPK0XBNZWM"
- ### the curious case of Amon Tobin's Creatures
- ### [the curious case of Amon Tobin's Creatures][page:music/creatures]
a weird anomaly I noticed while listening to some breaks
[read][page:music/creatures]
% id = "01JBAGZAZ3NKBED4M9FANR5RPZ"
- a weird anomaly I noticed while listening to some breaks
% id = "01J8ZP2EG9TM8320R9E3K1GQEC"
- I was listening to Oneohtrix Point Never's _Magic Oneohtrix Point Never_, and had some retrospective thoughts about the distorted vocals in...
- ### [I Don't Love Me Anymore][page:music/reviews/opn/i-dont-love-me-anymore]
### I Don't Love Me Anymore
% id = "01J8ZP2EG96VQ2ZK0XYK0FK1NR"
- I was listening to Oneohtrix Point Never's _Magic Oneohtrix Point Never_, and had some retrospective thoughts about the vocals in this song.
it's also a nice opportunity to say that I've refreshed the music section a bit!
[read][page:music/reviews/opn/i-dont-love-me-anymore]
% id = "01J8ZP2EG92T1SM7F6MTCXZHNJ"
- it's also a nice opportunity to say that I've refreshed the music section a bit!
% id = "01J7C1KBZ58BR21AVFA1PMWV68"
- ### [not quite buildless][page:programming/blog/buildsome]
% id = "01J7C1KBZ5XKZRN4V5BWFQTV6Y"
- I like lean websites. did you know that?
I also really like lean websites that are simple in construction and deployment. did you know the treehouse is a website like that?
% id = "01J7C1KBZ50EMBK9VPH9CE3F7H"
- I also really like lean websites that are simple in construction and deployment. did you know the treehouse is a website like that?
so I've decided to write up a few anecdotes and other cool stories about the treehouse's inner workings.
% id = "01J7C1KBZ5QCVM6DDT9G5KQGP2"
- so I've decided to write up a few anecdotes and other cool stories about the treehouse's inner workings.
also, it's (way past) its one year anniversary! hooray!
### not quite buildless
[read][page:programming/blog/buildsome]
% id = "01J7C1KBZ5S0XTQXKY41VZNWJZ"
- also, it's (way past) its one year anniversary! hooray!
% id = "01J73BSWA15KHTQ21T0S14NZW0"
- ### [the ListenBrainz data set][page:music/brainz]
% id = "01J73BSWA1EX7ZP28KCCG088DD"
- I decided to write up some ideas on what sort of cool data analysis I could do on my [ListenBrainz data set][def:social/listenbrainz].
I haven't done any of it yet, but I thought it'd be cool to share my ideas anyways!
### the ListenBrainz data set
% id = "01J73BSWA1ANRQ31DNYHTNPSP5"
- I haven't done any of it yet, but I thought it'd be cool to share my ideas anyways!
[read][page:music/brainz]
% id = "01J4J5N6WZQ03VTB3TZ51J7QZK"
- ### [haku - writing a little programming language for fun][page:programming/blog/haku]
% id = "01J4J5N6WZQ1316WKDXB1M5W6E"
- I was bored over a weekend, so I decided to write the tiniest programming language I could imagine.
% id = "01J4J5N6WZ2RW32HJX1VBJM58X"
- it came out looking pretty Lispy, and I'm glad about that!
% id = "01J4J5N6WZV6E1AHF65PQ5J6GF"
- I learned a ton about Lisps in the process of researching it.
even though it didn't end up having macros...
% id = "01J293BFEBT15W0Z3XF1HEFGZT"
- ### [JavaScript is not as bad as people make it out to be][page:programming/languages/javascript]
% id = "01J293BFEB4G7214N20SZA8V7W"
- sometimes people call me crazy for saying that bashing JavaScript is senseless and that it's not as bad of a language as people make it out to be.
so I decided to collect my thoughts into a nice little page I can link easily.
### JavaScript is not as bad as people make it out to be
[why dude why][page:programming/languages/javascript]
% id = "01J293BFEBYSW4K7YHVN42J3WP"
- so I decided to collect my thoughts into a nice little page I can link easily.
% id = "01J0VNHPTRNC1HFXAQ790Y1EZB"
- ### [freeing C memory automatically using `std::unique_ptr` and `std::shared_ptr`][page:programming/languages/cxx/shared-unique-ptr-deleter]
% id = "01J0VNHPTRP51XYDA4N2RPG58F"
- a friend of mine asked if it makes sense to define your own wrapper class for `SDL_Window` the way [Lazy Foo](https://lazyfoo.net/tutorials/SDL/10_color_keying/index.php) does it.
I told him there's no reason to do that in modern C++, because `std::unique_ptr` can do everything for you anyways.
### freeing C memory automatically using `std::unique_ptr` and `std::shared_ptr`
% id = "01J0VNHPTRW3XR4YG0GWGFF4N4"
- I told him there's no reason to do that in modern C++, because `std::unique_ptr` can do everything for you anyways.
~on another note, I did read a blog post about this once somewhere, but couldn't be bothered to find it. so there you go! I made a post about this too.~
[read][page:programming/languages/cxx/shared-unique-ptr-deleter]
% id = "01J0VNHPTRMXFTH3F601R7V1S9"
- on another note, I did read a blog post about this once somewhere, but couldn't be bothered to find it. so there you go! I made a post about this too.
% id = "01J0KRPMV7SS48B64BFCJZK7VQ"
- ### [about me (version 2)][page:about]
% id = "01J0KRPMV73K71D3QXFQ3GNY2N"
- it's updatin' time! I took some time to clean up old pages and update my _about me_.\
over time I've been learning how to write content on the treehouse effectively, and the new about me reflects that.
### about me (version 2)
[read][page:about] [version 1][page:about/v1]
% id = "01J0KRPMV7KD7X3HHXGKBS0VAX"
- [version 1][page:about/v1]
% id = "01HY5R1ZW2PYZSSP2J2KAA23DA"
- ### [what's up with `*x` not always meaning the same thing in different contexts?][page:programming/blog/lvalues]
% id = "01HY5R1ZW24YJ2NF2RYWRZG4ZT"
- I recently got a question from my someone telling me they doesn't understand why `*x` does not read from the pointer `x` when on the left-hand side of an assignment.
and that made me think,
### what's up with `*x` not always meaning the same thing in different contexts?
[read][page:programming/blog/lvalues]
and that made me think, _why_ is that the case?
% id = "01HV1DGFHZ65GJVQRSREKR67J9"
- ### [systems are just a bunch of code][page:programming/blog/systems]
% id = "01HV1DGFHZFFZSQNCVWBTJ1VHM"
- I've been thinking recently how cool it is to be able to single-step into Unreal Engine's source code and edit it while you're working with it, and how uncool it is that I can't do the same thing easily in the Rust world.
after all, aren't we just dealing with a bunch of code running on the computer? why not let me poke at it?
% id = "01HV1DGFHZGFYWT5MMM57SEWNN"
- after all, aren't we just dealing with a bunch of code running on the computer? why not let me poke at it?
### systems are just a bunch of code
[can _you_ can read other people's code?][page:programming/blog/systems] [bonus: dismantling Unreal Engine's GENERATED_BODY][page:programming/technologies/unreal-engine/generated-body]
% id = "01HV1DGFHZ2SDPDV3VYRR7VBRR"
- bonus: [dismantling Unreal Engine's `GENERATED_BODY`][page:programming/technologies/unreal-engine/generated-body]
% id = "01HTWNETT2S5NSBF3QR4HYA7HN"
- ### [OR-types][page:programming/blog/or-types]
% id = "01HTWNETT2N8NPENETWYFBTXEM"
- last night I couldn't sleep because of type theory. in the process of trying to write down my thoughts, I ended up discovering a class of types which, to my knowledge, no language implements.
### OR-types
[what the hell do you mean, aren't sum types exactly that??][page:programming/blog/or-types]
% id = "01HRG3VN091V715A8T54QK5PVX"
- I really like Lua, did you know that? but I get kind of tired of explaining why a thousand times to people who don't know the language, so…
- ### [programming languages: Lua][page:programming/languages/lua]
### programming languages: Lua
[read why I like it so much][page:programming/languages/lua]
% id = "01HRG3VN095BNHERHWVX1TKS9K"
- I really like Lua, did you know that? but I get kind of tired of explaining why a thousand times to people who don't know the language, so here's a page with my thoughts!
% id = "01HR9ZTS8RS4VJNJYSNRQYSKHZ"
- sidebars! also known as, _"enjoying the main content? how about I distract you from it so that you can't focus!"_\
seriously though. I don't like them.
- ### [design: sidebars][page:design/sidebars]
### design: sidebars
% id = "01HR9ZTS8RY3N4EJM5W7WBTF0G"
- sidebars! also known as, _"enjoying the main content? how about I distract you from it so that you can't focus!"_
[read why I don't like them so much][page:design/sidebars]
% id = "01HR9ZTS8RQ1EN0THYEVNQRY2A"
- seriously though. I don't like them.
% id = "01HQ8KV8T8GRCVFDJ3EP6QE163"
- ### [liquidex's treehouse: design][page:design]
% id = "01HQ8KV8T8EEX6XBG2K1X3FGKW"
- I started a branch on user interface and user experience design, because I was working with mintty at work and had some thoughts about it.
"why does mintty always feel so _out of place_ compared to `cmd.exe`?"
### liquidex's treehouse: design
[read: _on digital textures_][page:design/digital-textures] [go to branch][page:design]
% id = "01HQ8KV8T865WKME5R9TD0DSTN"
- I also wrote a post summarising my thoughts: [_on digital textures_][page:design/digital-textures]
% id = "01HQ6G30PTVT5H0Z04VVRHEZQF"
- ### [tairu - an interactive exploration of 2D autotiling techniques][page:programming/blog/tairu]
% id = "01HQ6G30PTG8QA5MAPEJPWSM14"
- ever wondered how Terraria renders its worlds? or how editors like Tiled manage to make painting tiles so easy?
### tairu - an interactive exploration of 2D autotiling techniques
[read][page:programming/blog/tairu]
% id = "01HQ6G30PT1D729Z29NYVDCFDB"
- this post explores basically just that.

View file

@ -1,134 +1,33 @@
/* Give the intro and outro some breathing room. */
section {
padding: 1em 2em;
}
/* Style all links in the last paragraph as big buttons. */
.tree th-bc>p:last-child {
--transition-duration: 0.2s;
margin-top: var(--8px);
margin-bottom: var(--4px);
&>a {
display: inline-block;
padding: 0.5em 1.5em;
color: var(--text-color);
background-color: transparent;
border: var(--1px) solid var(--border-1);
border-radius: 2em;
text-decoration: none;
transition:
color var(--transition-duration),
background-color var(--transition-duration),
border-color var(--transition-duration);
&:hover,
&:focus {
color: white;
background-color: #058ef0;
border-color: white;
}
}
}
.tree li>div:first-child,
.tree li>details>summary:first-child {
--margin: 2.5em;
border: none;
margin-left: var(--tree-indent-width);
width: calc(100% - var(--tree-indent-width));
margin-top: var(--margin);
margin-bottom: var(--margin);
}
.tree th-bp {
display: none;
}
.tree th-bb {
.tree .branch-container {
&:has(th-bc > h3) > th-bb {
opacity: 100%;
& .branch-date {
display: block !important;
}
}
}
@media (max-width: 600px) {
@media (max-width: 720px) {
.tree .branch-container {
flex-direction: column-reverse;
}
}
&:has(th-bc > h3) {
flex-direction: column;
padding-left: 1rem;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
section.settings {
& h3 {
display: inline;
}
& details>summary {
--recursive-wght: 700;
list-style: none;
cursor: pointer;
opacity: 50%;
transition: opacity var(--transition-duration);
&::-webkit-details-marker {
& > th-bp {
display: none;
}
&::before {
--recursive-casl: 0.0;
--recursive-mono: 1.0;
--recursive-slnt: 0.0;
content: '+';
margin-right: 0.3em;
opacity: 50%;
& > th-bc > h3 {
margin-top: 0;
margin-bottom: 0;
}
&:hover {
opacity: 100%;
}
}
& details[open]>summary {
opacity: 100%;
&::before {
content: '-';
}
}
& p {
margin-bottom: var(--8px);
}
& button {
border: var(--1px) solid var(--border-1);
border-radius: 999px;
padding: var(--4px) var(--12px);
background: none;
color: var(--text-color);
font-size: 1rem;
cursor: pointer;
transition:
color var(--transition-duration),
background-color var(--transition-duration),
border-color var(--transition-duration);
&:hover {
color: white;
background-color: #058ef0;
border-color: white;
& > th-bb {
margin: 0;
}
}
}
}

View file

@ -1,71 +0,0 @@
// news.js because new.js makes the TypeScript language server flip out.
// Likely because `new` is a keyword, but also, what the fuck.
import { addSpell, spell } from "treehouse/spells.js";
import { getSettingValue } from "treehouse/settings.js";
import { Branch } from "treehouse/tree.js";
const seenStatesKey = "treehouse.news.seenBranches";
const seenStates = new Set(JSON.parse(localStorage.getItem(seenStatesKey)) || []);
let seenCount = seenStates.size;
let unseenCount = TREEHOUSE_NEWS_COUNT - seenCount;
function saveSeenStates() {
localStorage.setItem(seenStatesKey, JSON.stringify(Array.from(seenStates)));
}
function markAsRead(branch) {
let branchData = spell(branch, Branch);
if (!seenStates.has(branchData.namedID) && seenCount > 0) {
let badge = document.createElement("span");
badge.classList.add("badge", "red", "before-content");
badge.textContent = "new";
branchData.branchContent.firstChild.insertBefore(badge, branchData.branchContent.firstChild.firstChild);
}
seenStates.add(branchData.namedID);
}
export function initNewsPage() {
for (let [_, branch] of Branch.branchesByNamedID) {
markAsRead(branch);
}
saveSeenStates();
// If any branches are added past the initial load, add them to the seen set too.
Branch.onAdded.push(branch => {
markAsRead(branch);
saveSeenStates();
})
}
export function markAllAsUnread() {
localStorage.removeItem(seenStatesKey);
}
addSpell("new", class New {
constructor(element) {
// Do not show the badge to people who have never seen any news.
// It's just annoying in that case.
// In case you do not wish to see the badge anymore, go to the news page and uncheck the
// checkbox at the bottom.
let userSawNews = seenCount > 0;
let userWantsToSeeNews = getSettingValue("showNewPostIndicator");
if (userSawNews && userWantsToSeeNews && unseenCount > 0) {
this.newText = document.createElement("span");
this.newText.classList.add("new-text");
this.newText.textContent = element.textContent;
element.textContent = "";
element.appendChild(this.newText);
this.badge = document.createElement("span");
this.badge.classList.add("badge", "red");
this.badge.textContent = unseenCount.toString();
element.appendChild(this.badge);
element.classList.add("has-news");
}
}
});

View file

@ -1,72 +0,0 @@
<!DOCTYPE html>
<html lang="en-US" prefix="og: https://ogp.me/ns#">
<head>
{{> components/_head.hbs }}
</head>
<body>
{{#> components/_nav.hbs }}
{{!-- For /index, include a "new" link that goes to the curated news feed page. --}}
{{#if (eq page.tree_path "index")}}
<a href="{{ config.site }}/treehouse/new" data-cast="new">new</a>
{{/if}}
{{/ components/_nav.hbs }}
{{> components/_noscript.hbs }}
<section>
<p>welcome!</p>
<p>since you clicked here, you must be curious as to what's been going on since your last visit to the house. so
here's a recap just for you - enjoy!</p>
</section>
{{> components/_tree.hbs }}
<section>
<p>note that this page does not include any updates that were made to the website itself - for that, you can
visit <a href="{{ config.site }}/treehouse/changelog">the changelog</a>.
</p>
</section>
<section class="settings" data-cast="js">
<details>
<summary>
settings
</summary>
<section>
<p>if you find the newsfeed annoying, you can customize some aspects of it.</p>
<p>
<input type="checkbox" data-cast="setting-checkbox" id="showNewPostIndicator">
<label for="showNewPostIndicator">show the <span class="badge red">1</span> badge on the homepage
for
new posts you haven't read yet</label>
</p>
<p>
<button id="mark-all-as-unread"
title="Mostly useful for debugging purposes, but it's there if you really wanna do it.">
mark all as unread</button>
</p>
</section>
</details>
</section>
{{!-- For all pages except the one linked from the footer, include the footer icon. --}}
{{#if (ne page.tree_path "treehouse")}}
{{> components/_footer.hbs }}
{{/if}}
<script type="module" defer>
import { initNewsPage, markAllAsUnread } from "{{ config.site }}/static/js/news.js";
initNewsPage();
document.getElementById("mark-all-as-unread").addEventListener("click", () => {
markAllAsUnread();
alert("congration! you done it");
});
</script>
</body>
</html>

View file

@ -18,7 +18,6 @@ clever to do while browser vendors figure that out, we'll just have to do a cach
<script>
const TREEHOUSE_SITE = `{{ config.site }}`;
const TREEHOUSE_NEWS_COUNT = {{ len feeds.news.branches }};
{{!-- Yeah, this should probably be solved in a better way somehow.
For now this is used to allow literate-programming.js to refer to syntax files with the ?cache attribute,
@ -35,7 +34,6 @@ clever to do while browser vendors figure that out, we'll just have to do a cach
import "treehouse/settings.js";
import "treehouse/tree.js";
import "treehouse/emoji.js";
import "treehouse/news.js";
</script>
<meta property="og:site_name" content="{{ config.user.title }}">

View file

@ -3,17 +3,3 @@
{{{ include_static 'svg/object/logo.svg' }}}
</a>
</nav>
{{!--
I don't have any idea where to put this right now.
There's no obvious place, and even when it is there, I hate the hideous red badge on new entries.
No time to figure it out. Will do later.
{{#if (eq page.tree_path 'index')}}
<nav id="nav-links">
<a href="{{ config.site }}/treehouse/new" data-cast="new">new</a>
</nav>
{{/if}}
--}}