From 963565b3168ce91df7f9c3013a452a80778470db Mon Sep 17 00:00:00 2001 From: thepra Date: Mon, 5 Oct 2026 04:15:54 +0200 Subject: [PATCH] The feed hears new posts as they come decePub opens PrivaPub's streaming API (one WebSocket for the persona, its token given as the socket's protocol, never in a URL) and subscribes to the stream of the feed in view: home, a list, local, federated, a hashtag or notifications. New posts wait behind the "new" button as polled ones did; a deletion or an edit applies at once. Polling stays for the feeds PrivaPub does not stream and for any feed while the socket is down, which opens again after a pause growing to a minute. The e2e test sees a post made elsewhere in seconds and its deletion take the card away. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw --- CLAUDE.md | 6 +- Pages/Index.razor | 55 +++++++- Program.cs | 1 + Resources/AllStrings.it.resx | 6 + Resources/AllStrings.resx | 6 + Services/StreamingService.cs | 191 ++++++++++++++++++++++++++++ tests/e2e/Actions/StreamingTests.cs | 52 ++++++++ 7 files changed, 312 insertions(+), 5 deletions(-) create mode 100644 Services/StreamingService.cs create mode 100644 tests/e2e/Actions/StreamingTests.cs diff --git a/CLAUDE.md b/CLAUDE.md index 5550b41..0c58b47 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -242,8 +242,10 @@ supplies: are read on the first hover and kept for the session. PrivaPub's own host is the signed-in persona's account host, since the API may be reached under another name. - **The feed page** (`Pages/Index.razor`): `FeedTabs`, `Content` (the card, which does its own actions), `Composer`, - `GlobePanel`. Older pages load as the end comes near (`wwwroot/js/feed.js`); newer ones are polled every 45 s while - the page is visible (PrivaPub has no streaming) and wait behind a "new" button. + `GlobePanel`. Older pages load as the end comes near (`wwwroot/js/feed.js`). Newer ones come through PrivaPub's + streaming API (`Services/StreamingService.cs`: one WebSocket, the persona's token as its protocol, never in a URL) + for home, lists, local, federated, hashtags and notifications, and wait behind a "new" button; a deletion or an edit + it tells applies at once. Other feeds, and any feed while the stream is down, are polled every 45 s while visible. - **The globe** (`wwwroot/js/globe.js`, an ES module imported by `GlobePanel`) runs on globe.gl, vendored in `wwwroot/vendor/globe/` with its textures and `countries.json` (`SOURCES.md` has versions, licences and hashes; the service worker never precaches it). It looks at the spherical mean of the located posts in view, pulses and draws an diff --git a/Pages/Index.razor b/Pages/Index.razor index 11fef0a..6849eef 100644 --- a/Pages/Index.razor +++ b/Pages/Index.razor @@ -7,8 +7,10 @@ @* The feed page, the middle and right of three columns (NavMenu is the left): the feed with a tab per kind of feed, and the globe, which follows the posts in view (GlobePanel). Below lg the globe is a banner above the feed, closed by - default on phones. Pages of older posts load as the end comes near (wwwroot/js/feed.js); newer ones are polled every - 45 seconds while the page is visible and shown on request, because PrivaPub has no streaming. *@ + default on phones. Pages of older posts load as the end comes near (wwwroot/js/feed.js). Newer ones come through + PrivaPub's streaming API (StreamingService) for the feeds it streams, and are polled every 45 seconds while the page + is visible otherwise, or while the stream is down; either way they wait behind the "new" button. A deletion or an edit + the stream tells is applied at once. *@