Remove unused minus icon; update TODO
Audited the ICON set for consistency: minus was defined but never referenced anywhere (circleMinus already covers Unsubscribe). Everything else checked out. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019Tk3nAVF6n4dtjQS17FRFr
This commit is contained in:
@@ -10,6 +10,10 @@ The long form, with what was wrong before and how it was found, is in
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Removed
|
||||
|
||||
- An unused icon glyph (`minus`) left over from before Unsubscribe settled on `circleMinus`.
|
||||
|
||||
## [0.5.4] - 2026-09-14
|
||||
|
||||
### Added
|
||||
|
||||
82
TODO.md
82
TODO.md
@@ -2,56 +2,48 @@
|
||||
|
||||
## Errors in the log
|
||||
|
||||
From the production log and the feeds' stored errors on 2026-09-13. The Docker log only reached back
|
||||
to 12:32 UTC, so the list comes from `feeds.last_error`: 57 of 1,059 feeds. None of it is ipx's
|
||||
User-Agent; a browser gets the same answers.
|
||||
|
||||
- [x] **Stop scanning an OPML's feeds once nobody subscribes to it.** 55 of the 57 are feeds from
|
||||
`davewiner` (lists.opml.org/davefeeds.xml). The list left `config.toml` about 14 hours before this
|
||||
was written, but its 922 feeds are still in the database and still scanned every hour, with
|
||||
auto-download on: `subscriptions()` adds every derived feed, and with no parent to copy from,
|
||||
`auto_download` falls back to `true` (`src/main.rs:937`). `docs/users.md` says a feed stops being
|
||||
scanned when its last subscriber leaves. Skip a derived feed whose parent is not in config, and
|
||||
when the last subscriber leaves an OPML, treat its feeds the way `sync_group` treats ones the list
|
||||
dropped: remove those with nothing downloaded, mark the rest orphaned. `remove_feed` and `ipx rm`
|
||||
both leave them behind today. (`src/main.rs`, `src/web.rs`)
|
||||
- [x] **Read feeds with a bare `&`.** kcpw has `<link>https://kcpw.org/?post_type=post&p=125715</link>`,
|
||||
and both feedland feeds have the same fault. Strict XML refuses them; browsers and other readers do
|
||||
not. When `feed::parse` fails, try once more with every `&` that does not start an entity written
|
||||
as `&`. Nobody subscribes to these three now, but the next feed like them will fail the same
|
||||
way. (`src/feed.rs`)
|
||||
- [x] **Say what came back when it is not a feed.** Thirteen errors read "not RSS (the input did not
|
||||
begin with an rss tag) and not Atom (...)". Each one checked was a web page: the feed moved and its
|
||||
old URL redirects to the site, or the domain lapsed. Say "got a web page, not a feed", and when the
|
||||
page links a feed (`<link rel="alternate" type="application/rss+xml">`), name it. That link found
|
||||
the new feed for om.co, ms.now, Letters of Note, the Daily Dot, Hell Gate, The Frame Lab and
|
||||
Daily Kos. A `202` with an empty body (British Antarctic Survey) should read as "nothing yet", not
|
||||
as a parse failure. (`src/feed.rs`)
|
||||
- [x] **Show a publisher's error in the UI.** Today a failing feed shows its raw error in red only
|
||||
once you open it (`web/index.html:877`, `:960`); the OPML view marks a failing child "error"
|
||||
(`:988`), and the sidebar shows nothing. Mark a failing feed in the sidebar too, and say whose
|
||||
problem it is and what to do, in plain words: a 404 means the publisher took the feed down or moved
|
||||
it, 401 and 403 that the site refuses ipx, 402 that the feed needs a paid plan, a name that no
|
||||
longer resolves that the site is gone, and a web page instead of a feed that it moved (with the new
|
||||
URL when the page links one). Offer Unsubscribe, or Use the new address. Keep timeouts, 5xx and
|
||||
429 out of it, and flag a feed only once it has failed for a day: macmanx failed once and read
|
||||
fine an hour later. That needs the time a feed started failing, kept beside `last_error` and
|
||||
cleared when a check succeeds. (`web/index.html`, `src/db.rs`, `src/main.rs`)
|
||||
- [ ] **Westenberg.** The only failing feed anyone subscribes to. The Hacker News stars list still
|
||||
gives `joanwestenberg.com/rss`, which is a 404; the feed is now `joanwestenberg.com/feed`.
|
||||
Nothing for ipx to fix; subscribe to the new URL directly.
|
||||
|
||||
## Other Fixes and Features
|
||||
## Icons
|
||||
|
||||
- [x] Remember which feed is selected and view (all, unread, flagged, etc) user as selected between visits. If unknown default to All Subscriptions
|
||||
- [x] When clicking any link it should open in a new tab
|
||||
- [x] In mobile (iOS) sometimes the top line items like the hamburger menu are not clickable unless you do a hard refresh — likely fixed (100dvh instead of 100vh), unverified on a real device; reopen if it still happens
|
||||
- [x] video files play as audio files, they should play as video.
|
||||
- [x] Move Light/Dark/Classic options to user settings. Include an Auto mode that uses system preferences for light/dark modes
|
||||
- [x] Below Popular, have a currently listening section to show what podcasts have been started and not finnished
|
||||
- [x] Update subscribe/unsubscribe icons to be circle-minus (unsubscribe) and circle-check (subscribe)
|
||||
- [x] If I'm on the Unread tab, and I click to read an item the entry in the list will disappear. it should remain until I click to another item.
|
||||
- [x] **Audit the icon set for consistency.** Checked every glyph in `ICON` (`web/index.html`)
|
||||
against its source, weight, sizing, and every place it's used — both the `${ICON.x}` template
|
||||
calls and the `data-icon="x"` lookups the startup loop wires up (`web/index.html:713`). Found one
|
||||
real problem: `minus`, a bare uncircled minus glyph, was defined but never referenced anywhere;
|
||||
`circleMinus` already covers the one place a minus-shaped icon is used (Unsubscribe). Removed it.
|
||||
Everything else checked out: `flag`'s regular weight against `flagOn`'s solid is the standard
|
||||
outline/filled toggle idiom, not a mismatch; icon sizing is one shared 16px base rule with three
|
||||
narrowly-scoped overrides; `caret` is deliberately reused (not duplicated) for both the folder
|
||||
triangle and the sort arrow, rotated correctly per context; play/pause swapping is symmetric.
|
||||
(`web/index.html`)
|
||||
|
||||
## Directory Overhaul
|
||||
|
||||
- [ ] Directory needs to be more functional, with categories and a more interesting layout. use /frontend-design to help
|
||||
- [ ] **Give feeds a real category, from the feed itself.** `ParsedFeed` only carries per-episode
|
||||
`categories` (`src/feed.rs:24`); nothing at the channel level survives parsing today, so there is
|
||||
nothing to browse the directory by. Parse `<itunes:category>` (and its `<itunes:subcategory>` if
|
||||
present) off the channel the same way entry categories already are, keep the first one a feed
|
||||
reports rather than building a multi-tag facet, and add it to `FeedSummary` and the feeds table
|
||||
via a migration. Most feeds will not carry one; a feed with none counts only under "All".
|
||||
(`src/feed.rs`, `src/db.rs`)
|
||||
- [ ] **Expose category on `/api/popular` and `/api/directory`.** `PopularRow` (`src/web.rs`) is id,
|
||||
title, image, subscribers, subscribed today; add `category: Option<String>` once a feed carries
|
||||
one, so the client can group and filter without a second request.
|
||||
- [ ] **Replace the flat alphabetical list with a category rail over an artwork grid.** Today
|
||||
Directory is a single-column list of rows: a thumbnail, a title, a subscriber count, a subscribe
|
||||
button (`renderListed`/`listFeeds`, `web/index.html:1649`). Put a horizontal row of category chips
|
||||
above it — "All" plus whatever categories actually occur in the catalogue, never an empty one —
|
||||
and turn the list itself into a grid of square cover-art tiles with the title underneath: podcast
|
||||
art is designed to be recognized at a glance, the way the app's own iPod-screen styling already
|
||||
leans on imagery over text. Keep the subscriber count as a small corner badge (the same treatment
|
||||
`unread` counts already get in the feed list) and move the subscribe button to appear on
|
||||
hover/focus instead of sitting on every row permanently. Selecting a chip filters the grid in
|
||||
place; the active chip gets the EQ-amber underline (`--accent2`) the level meter already uses,
|
||||
rather than a new color. No new palette and no new typeface — reuse `--bg`/`--fg`/`--accent`/
|
||||
`--accent2` and the existing Lucida Grande stack so Directory still looks like the rest of ipx, not
|
||||
a bolted-on card kit: no border, shadow or radius beyond what the app already uses elsewhere. On
|
||||
phone width the chip row scrolls horizontally in place rather than wrapping, so it never pushes
|
||||
the grid down. Popular can stay a plain top-ten list for now, or get the same tile treatment later
|
||||
— worth deciding separately rather than folding into this. (`web/index.html`)
|
||||
|
||||
@@ -668,7 +668,6 @@ const esc = s => (s??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>
|
||||
const fa=(box,body)=>`<svg class="i" viewBox="${box}" aria-hidden="true">${body}</svg>`;
|
||||
const ICON={
|
||||
plus:fa('0 0 448 512','<path fill="currentColor" d="M256 64c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 160-160 0c-17.7 0-32 14.3-32 32s14.3 32 32 32l160 0 0 160c0 17.7 14.3 32 32 32s32-14.3 32-32l0-160 160 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-160 0 0-160z"/>'), // solid/plus
|
||||
minus:fa('0 0 448 512','<path fill="currentColor" d="M0 256c0-17.7 14.3-32 32-32l384 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L32 288c-17.7 0-32-14.3-32-32z"/>'), // solid/minus
|
||||
circleMinus:fa('0 0 512 512','<path fill="currentColor" d="M512 256A256 256 0 1 0 0 256a256 256 0 1 0 512 0zM184 232l144 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-144 0c-13.3 0-24-10.7-24-24s10.7-24 24-24z"/>'), // solid/circle-minus, for Unsubscribe
|
||||
play:fa('0 0 448 512','<path fill="currentColor" d="M91.2 36.9c-12.4-6.8-27.4-6.5-39.6 .7S32 57.9 32 72l0 368c0 14.1 7.5 27.2 19.6 34.4s27.2 7.5 39.6 .7l336-184c12.8-7 20.8-20.5 20.8-35.1s-8-28.1-20.8-35.1l-336-184z"/>'), // solid/play
|
||||
check:fa('0 0 448 512','<path fill="currentColor" d="M434.8 70.1c14.3 10.4 17.5 30.4 7.1 44.7l-256 352c-5.5 7.6-14 12.3-23.4 13.1s-18.5-2.7-25.1-9.3l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l101.5 101.5 234-321.7c10.4-14.3 30.4-17.5 44.7-7.1z"/>'), // solid/check
|
||||
|
||||
Reference in New Issue
Block a user