Recognise a favorite by its URL, and take the listing's copy of it

The same video reaches this client under two identities: saved from a
card it carries the server's id, imported from a Hot Tub backup it
carries only its URL. indexOfEntry already matched on either, but the
grid card and the player asked only whether the key was known -- so an
imported favorite left its own listing card, and the player, showing an
empty heart. All three surfaces now ask one question.

Once matched, the listing's copy is the better one: it has the id the
cards key on, and a thumbnail URL that hasn't been sitting in
localStorage since whenever the backup was taken. So a page of listing
videos rewrites the favorites it matches, keeping only the date each was
first saved -- the one fact the listing doesn't know, and the one the
sort depends on. Nothing is written when nothing differs.

Both identity sets now come from one cache dropped on write, since this
is read once per card built and per layout probe, and each read was
re-parsing the whole favorites list out of localStorage.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QBDkEXP4htyXTCZUwMLphd
This commit is contained in:
Simon
2026-09-08 17:04:34 +00:00
parent 74b719b2ea
commit 1dbac33359
4 changed files with 106 additions and 11 deletions

View File

@@ -469,7 +469,7 @@ App.feed = App.feed || {};
const favBtn = slide.querySelector('.feed-fav-btn');
if (favBtn && App.favorites) {
App.favorites.setButtonState(favBtn, App.favorites.indexOfEntry(App.favorites.getAll(), v) >= 0);
App.favorites.setButtonState(favBtn, App.favorites.has(v));
favBtn.addEventListener('click', (event) => {
event.stopPropagation();
App.favorites.toggle(v);