feat: new posts banner, mark-as-read on scroll, unread filter

- Poll every 30s for new items, show sticky "N new posts — Load" banner
- IntersectionObserver marks cards as read at 50% visibility, batches to
  server every 5s
- Read cards fade to 70% opacity, full opacity on hover
- "Unread" toggle in tab bar filters to unread-only items
- New API: GET /api/timeline/count-new, POST /api/timeline/mark-read

Confab-Link: http://localhost:8080/sessions/e9d666ac-3c90-4298-9e92-9ac9d142bc06
This commit is contained in:
Ricardo
2026-03-02 10:54:11 +01:00
parent 68aadb6ff2
commit 508ac75363
8 changed files with 381 additions and 17 deletions

View File

@@ -61,7 +61,7 @@ import {
} from "./lib/controllers/featured-tags.js";
import { resolveController } from "./lib/controllers/resolve.js";
import { tagTimelineController } from "./lib/controllers/tag-timeline.js";
import { apiTimelineController } from "./lib/controllers/api-timeline.js";
import { apiTimelineController, countNewController, markReadController } from "./lib/controllers/api-timeline.js";
import {
exploreController,
exploreApiController,
@@ -239,6 +239,8 @@ export default class ActivityPubEndpoint {
router.get("/admin/reader", readerController(mp));
router.get("/admin/reader/tag", tagTimelineController(mp));
router.get("/admin/reader/api/timeline", apiTimelineController(mp));
router.get("/admin/reader/api/timeline/count-new", countNewController());
router.post("/admin/reader/api/timeline/mark-read", markReadController());
router.get("/admin/reader/explore", exploreController(mp));
router.get("/admin/reader/api/explore", exploreApiController(mp));
router.get("/admin/reader/api/explore/hashtag", hashtagExploreApiController(mp));