A share button in the feed's header, beside an item's "Open the original", and on each file.
It uses the Web Share API where the browser has it, which is the share sheet on a phone, and
copies the link where it does not. A file is shared by the publisher's address, not /media/,
which only someone signed in here can open.
Paid feeds carry the subscriber's access in their address, Patreon's in a token, so sharing one
gives the subscription away. An address that looks like that asks first.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The scan's events reach everyone, so every browser showed "<feed>: N new" and
"Scanning…" toasts, and refreshed, for everyone's feeds. Now a feed's row, and
its folder's, carries a spinner between feed_start and its done, skip or error;
the list refreshes only for the reader's own feeds; the scan toasts are gone, and
"Downloaded" is said only for a file on screen.
"Check every feed" from the web UI sent a scan of every feed on the server.
Command::Fetch takes an optional `feeds` list -- those feeds and the feeds
inside any OPML among them -- and the web fills it with the asker's
subscriptions. The schedule and the CLI send none, meaning every feed.
Closes#37.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
subscriptions.pinned, per person, set by PATCH /api/feeds/{id} {pinned} and
returned as FeedRow.pinned. Kept out of Sub, which the scanner merges into its
policy; set_subscription names its columns, so saving a feed's settings leaves
the pin alone (tested).
Pinned feeds come first in the list, a pin before the name and a rule under the
block: a pinned folder with its feeds under it, a feed from inside one lifted out
of it. The pin button is on both the feed and the folder page.
Closes#33.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- web/src/*.ts: the script that was inline in index.html and login.html, split along its
existing sections. Still one scope, concatenated in order, not modules.
- web/build.mjs strips the types, puts the script in the page and minifies it with swc;
build.rs runs it into OUT_DIR and web.rs include_str!s the result. 137 KB -> 106 KB.
- npx tsc -p . type-checks web/src, loosely; the handful of annotations it needed
change no behaviour.
- The Docker build installs node and swc (npm ci --omit=dev).
- Two list requests racing no longer let the older one win, and switching tabs clears
the selection it closes, which made a browser test flaky.
Closes#23, #24.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>