Commit Graph
15 Commits
Author SHA1 Message Date
KeelrLeek f67a0a30b4 shared playlists: importing a share follows it, so the owner's next revision reads as "2 new tracks since you imported"
Importing a shared playlist was a one-time snapshot: the owner's next
revision could only arrive as a whole second copy. A copy now remembers
WHICH revision it was made from, and the app reads the pointer for it
every ten minutes — no new contract, the same pointer and revision reads
the share card already does.

The ledger gains `following`, keyed `owner:uuid` — the one key a database
cannot hand out twice. A follow records the local playlist, the synced
revision (hash + seq) and what the last check saw: the current revision,
the entries it has that the synced one never had (in the owner's order),
and how many synced entries are gone. The diff is by occurrence id, the
proposal board's rule: a reorder is not news, a removal is counted, a
duplicate stays its own row. `import` stages the fetched revision so
`follow` records exactly what the copy was made from — a pointer read of
its own could already name a newer one.

Update appends the new rows through the same resolve path an import uses
(library first, Soulseek stream otherwise) and never removes or reorders:
the copy is the follower's to edit, and a track the owner dropped is
reported, not taken away. It runs under the ledger lock end to end, so a
check landing meanwhile merges against the new synced revision or not at
all. Checks read the network WITHOUT the lock — a pointer read is a ring
search — and merge each result under it afterwards, dropped if the follow
moved on.

Deleting the local copy ends the follow, in `forget_playlist` and the
startup reconcile both: the row id goes back to SQLite, and the next
playlist created must not start taking someone else's updates. Seen live:
the re-import after a delete took row id 1 again and followed cleanly.

Surfaces: an Inbox card when a check finds news ("2 new tracks since you
imported it · 1 removed", Add 2 tracks / stop following), and a Following
row in the playlist's Share sheet (up to date / N new / withdrawn by the
owner, Check now, Stop following). The poll rides the inbox watch: its own
ten-minute interval, plus one pass when the adapter connects.

Live, two instances on this machine: import + follow 582 ms; the owner's
revision 2 (one dropped, two added) read back as exactly "2 new, 1 removed"
in 2.7 s; Add appended two stream rows in 46 ms and left the dropped track
in place; a withdraw read as withdrawn in 57 ms; delete took the follow
with it; re-follow and unfollow both left the copy alone. One pointer read
after a republish timed out at 120 s and arrived a second later — the same
first-read-after-a-change lag the board has.

Tests: the diff (order, removal, a duplicate occurrence) and the ledger
reading files written before follows existed. App 152 · 6 ignored.
2026-09-06 08:16:45 -05:00
KeelrLeek df06f849e0 spaces: a room carries what its members are playing, sealed in the window its chat already uses 2026-09-04 12:20:27 -05:00
KeelrLeek 7b7f48ebc6 community: declare what you like on soulseek, so the similar-users shelf finally has something to rank on 2026-09-03 15:05:23 -05:00
KeelrLeek b3c121fa94 community: the inbox check belongs to the app, not to the page that happened to be open 2026-09-03 12:38:57 -05:00
KeelrLeek fd216ecd3d community: a proposal on your board arrives as a toast, carried sealed through the inbox 2026-09-03 12:16:33 -05:00
KeelrLeek 0846b39d45 community: the library overlap shelf, their share folders against your albums on this device after a browse 2026-09-02 17:08:25 -05:00
KeelrLeek bf81792c49 the proposal board: a Space's pinned playlist takes signed proposals, and an accept republishes it 2026-09-02 16:33:38 -05:00
KeelrLeek 8b511b20e7 community: spaces, an owner-signed roster with epochs, a bounded window of signed lines, bodies sealed to a rotating key when private 2026-09-02 15:50:18 -05:00
KeelrLeek 4378c4c0cc community: the encrypted inbox, friend requests and shares travel sealed to a box key when the other side has published one 2026-09-02 15:26:30 -05:00
KeelrLeek 13c44f731a community: shared playlists, a signed revision and a pointer on the network, a reference over soulseek, an import through the normal door 2026-09-02 15:02:06 -05:00
KeelrLeek 984738135a community: friends, two signed answers on one request carried over soulseek, one answer is only ever pending 2026-09-02 14:40:33 -05:00
KeelrLeek 6ed6f5b8f8 community: the soulseek link proof, one message to yourself links the account and one question links anyone who answers 2026-09-02 14:27:54 -05:00
KeelrLeek 5160d97a5f community: the drawer asks a peer for its card and the server for interests, and discover gets the similar-users shelf 2026-09-02 14:03:26 -05:00
KeelrLeek 64a7561750 community absorbs the hub: search, transfers and browse ride the same pills, one entry in the sidebar 2026-09-02 13:46:57 -05:00
KeelrLeek 8c25f93afe community: one area for the people on both networks, and the hub grows search tabs, a folder column and a queue column 2026-09-02 13:43:16 -05:00