From 3d005da847d861a86359d93f6a44edf5f379d36e Mon Sep 17 00:00:00 2001 From: rays Date: Sun, 11 Oct 2026 14:18:41 +0000 Subject: [PATCH] Changelog: each past release says what changed since the one before (#191) Following the rule CLAUDE.md now gives for cutting a release: a feature added and reworked in one release is one line saying what it became, and a fix for a bug no release had is gone. 0.11.0's DeadAir fixes join DeadAir, 0.9.1's JSON log, website icons, adding a website and logo are one line each, 0.10.0's Directory, sort and Popular one, 0.4.0's toolbar, item table and icons fold together, and 0.2.0 and 0.3.0 lose the fixes to the web UI and accounts they introduced. The [unreleased] link compares from v0.11.0. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 156 +++++++++++++++++---------------------------------- 1 file changed, 51 insertions(+), 105 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d5108d..47d22a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,14 +28,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- DeadAir: turn it on for a show in its settings, or with the button beside the speed while it plays, and its episodes play with long silences shortened, so podcasts finish sooner without sounding sped up. Your place carries over when you turn it on or off, each episode says how much shorter it is, and Settings shows the time it has saved you. It is off for every show until you turn it on (#171, #172). -- An episode DeadAir is still working on says "Cutting dead air…", and changes to how much shorter it is when it is done, without a reload (#176). +- DeadAir: turn it on for a show in its settings, or with the button beside the speed while it plays, and its episodes play with long silences shortened, so podcasts finish sooner without sounding sped up. Your place carries over when you turn it on or off, each episode says how much shorter it is ("Cutting dead air…" until it is done), and Settings shows the time it has saved you. It is off for every show until you turn it on (#171, #172, #173, #174, #176). ### Fixed - A downloaded file's play, save, share and delete buttons stay on one row in the Files pane, instead of delete wrapping underneath (#175). -- DeadAir shortens an episode you have opened but not played yet, instead of passing it over as if you had finished it (#173). -- DeadAir shortens episodes with more than about a hundred long silences, which is most of an hour's conversation, instead of failing on them, and tries a file it failed on again after the next restart (#174). - Cover art up to 20 MB is shown, instead of nothing for anything over 5 MB, as for five of the Glass Cannon Network's feeds. - Seeking in an episode while many people listen answers in about 10 ms instead of 40, and files stream about four times as fast: each connection now sends what is ready without waiting for the browser to acknowledge the last part. - Artwork that could not be fetched is not fetched again for an hour, instead of on every page load, and the server's log says which image it was and why. @@ -51,7 +48,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - The feed list's traces show each of its database queries, so it can be told where its time goes. - Saving a feed's settings asks the database for your subscription once, not twice. - `ipx add` and Add feed in the page add a feed the same way, through one piece of code. -- Glass's top bar is solid on a phone, in the colour its glass showed, so the strip above it on an iPhone can match it. - A pinned item or feed's pin button is filled with the theme's accent, in the reader, on the feed's page and in the toolbar, so pinned no longer looks like not pinned. - A feed's page in the Directory says how many people here subscribe only when someone does, without "Nobody here subscribes yet". @@ -59,10 +55,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - The unread counts catch up when you come back to the page: an item read on another device, or while the phone app was in the background, no longer stays counted as unread until a reload. - A feed set to download 0 of its newest items downloads all of them, the whole back catalogue, as the server's 0 does; it downloaded nothing. -- The feed list loads faster: it counts the items and files of your own feeds, not of every feed on the server. +- The feed list loads faster: it counts the items and files of your own feeds, not of every feed on the server, and asks for a group's title once, not once for every feed in it. - Downloading or deleting a file the server no longer has answers "not found" instead of a server error. - A feed's page in the Directory, and subscribing from it, no longer wait while the whole Directory is put together to check that the one feed is in it. -- The feed list, and each live update of it, no longer asks the database for a group's title once for every feed in the group. - An episode that came as a torrent of several files plays its largest file, and can be deleted, by hand or to free space, instead of staying on disk for good. - Removing an account takes the feeds only that person read off the server, as unsubscribing does, instead of leaving them downloading every new episode for no one. - Freeing disk space counts only the people who subscribe to a feed: an episode is no longer taken as heard by everyone because someone who has since unsubscribed heard it, and their pins no longer keep files for good. @@ -71,7 +66,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Changes to the feed list made at the same moment, such as two people adding feeds, or a feed added while the server settings change, no longer undo one another. - A download that stops partway is given up after two minutes without data, instead of holding up every scan and download until a restart. - On a phone, the closed feed list no longer shades the left edge of the page with its shadow. -- On an iPhone, the top bar's colour runs all the way up behind the status bar and the Dynamic Island, with no band of another colour above it. +- On an iPhone, the top bar's colour runs all the way up behind the status bar and the Dynamic Island, with no band of another colour above it. In Glass the bar is solid on a phone, in the colour its glass showed. - A feed's buttons stay on one row on a narrow phone, and the reader's buttons stay together instead of breaking across lines under a long feed name. - A moment's DNS failure no longer marks a feed as failing for a day or calls it gone: iPX tries it again in ten minutes. One failed lookup one morning left 205 podcasts unread, uncategorised and labelled gone until the next day. A name that does not resolve is said to be maybe gone, and only once it has been failing a day, on its Directory page as on its own. @@ -114,10 +109,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- The Directory is laid out as Apple's is. It opens on the ten most subscribed feeds, ranked, and the categories as tiles showing some of their shows' covers. A category opens a page of its own with its most subscribed feeds, its subcategories (Tech News under News, Video Games under Leisure) and its feeds; See all lists every one. This replaces the grid of every feed under rows of category buttons. -- The most subscribed feeds are the Directory's first section instead of a place of their own: Popular is gone from the feed list, and so is its key, g p. +- The Directory is laid out as Apple's is. It opens on the ten most subscribed feeds, ranked, and the categories as tiles showing some of their shows' covers. A category opens a page of its own with its most subscribed feeds, its subcategories (Tech News under News, Video Games under Leisure) and its feeds; See all lists every one, A to Z, Z to A or by most subscribers. This replaces the grid of every feed under rows of category buttons, and Popular, which is gone from the feed list with its key, g p. - A pinned item in a list wears the same disc as a pinned feed, in the theme's accent, instead of a plain solid pin. -- The Directory can be sorted by name, A to Z or Z to A, or by most subscribers. It still opens A to Z. - An item published without a title shows its opening words, in plain text rather than bold, instead of "(untitled)"; one with no text either shows its file's name, or its show and date. Opened, it starts with its text. - A feed that has moved for good (a permanent redirect) is followed to its new address, which iPX then reads from, and says so in the log as `feed_moved`. A temporary redirect changes nothing. - The daemon sleeps until the next feed is due, at most ten minutes, instead of looking every minute; refreshing or adding a feed still wakes it at once. @@ -145,43 +138,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- `IPX_LOG_FORMAT=json` logs one JSON object a line, with a request's method, route, status and time - and a scan's or download's details as fields, for Loki and the like. +- `IPX_LOG_FORMAT=json` logs one JSON object a line, for Loki and the like: a request's method, + route, status and `duration_ms`, a scan's or download's details, a failure's kind in `error.type` + (and its HTTP status in `http.response.status_code`), and each line's `trace_id` and `span_id`. - A Grafana dashboard for iPX, from its log in Loki and its traces in Tempo (`grafana/dashboard.py`). - With `OTEL_EXPORTER_OTLP_ENDPOINT` set, the daemon sends traces of its scans, downloads and web - requests to a collector such as Tempo. -- A feed that has no artwork of its own shows its website's icon instead. + requests to a collector such as Tempo; a scan's shows the time each feed spends fetching, on its + artwork and in the database. +- A feed with no artwork of its own, or whose artwork is missing, shows its website's icon, or the + site's `/favicon.ico`, and follows the site when it changes. It is asked for again only when the + artwork changes or you refresh the feed. - The refresh button turns while its feed is being checked, and the check-every-feed buttons while any of yours is. -- Adding a website's address subscribes to the feed that site links, instead of failing on every scan. +- Adding a website's address, with or without `https://`, subscribes to the feed that site links. + An address is checked before it is added, and anything that is neither a feed nor a page linking + one is refused with the reason, instead of being added and failing on every check. - `/api/status` gives the number of feeds, items waiting to download and files downloaded, and the version, for a dashboard such as Homepage. ### Changed - The start-up line about the web UI being reachable off the machine says what guards it, and is a warning only when there is no Cloudflare Access in front of it. -- The feed list updates just the feed that changed, as a scan checks it or you read an item, instead of reloading the whole list. +- The feed list updates just the feed that changed, as a scan checks it or you read an item, instead of reloading the whole list every minute. - A scan fetches several feeds at once, so a refresh no longer waits on every site in turn. -- An open page reloads the feed list only when a scan has checked something, not every minute. -- Adding an address checks it first: a feed is added, a web page adds the feed it links, and anything else is refused with the reason, instead of being added and failing on every check. - A feed that was failing when its last subscriber left is forgotten, rather than kept with its error for good. One that worked, or has files on disk, is kept as before. - A feed that keeps failing is checked less and less often, waiting as long as it has been failing, up to once a day; it goes back to its schedule as soon as it works. Refreshing it still checks it at once. -- A scan's trace shows the time a feed spends on its artwork and in the database after the fetch. -- The JSON log carries each line's `trace_id` and `span_id`, logs each scan event once instead of - twice, names a failure's kind in `error.type` (and its HTTP status in - `http.response.status_code`), and calls a request's time `duration_ms` instead of `ms`. - `ipx list` shows each feed's id on a line of its own, labelled, under its title. - Each browser keeps its own theme, so a phone and a desktop can differ. A browser that has not chosen one yet starts from the theme your account had. - The Modern theme takes its colours from the new logo: its navy, the blue of its bars and the orange of its needle. -- The logo follows the page: the dark version in a dark theme, the light one in a light theme. -- The browser tab's icon follows the page's light or dark mode too. -- On a phone, the top bar leaves out the logo, giving its room to the search box. -- Between releases, the version on the logo says so: 0.9.1-dev, not 0.9.0. -- The logo's needle is a brighter, redder orange that stands apart from the blue bars. - The logo is in the top bar beside the add-feed button, in place of the name at the top of the - feed list. Hovering it shows iPX's version. + feed list, and left out on a phone, for the search box. It follows the page, dark in a dark theme + and light in a light one, as the browser tab's icon does, and hovering it shows iPX's version, + which says so between releases: 0.9.1-dev, not 0.9.0. +- The logo's needle is a brighter, redder orange that stands apart from the blue bars. ### Removed @@ -191,28 +182,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- Adding a site without `https://`, such as `cnn.com`, works; it failed on every check. - A limit on new downloads per check means a show's newest episodes: with it set to 3, ipx no longer works back through the show's history three at a time. Set to 0, it still takes the whole back catalogue. - With no limit on new downloads per check (`max_new_per_check = 0`), downloads work on Postgres; they failed. - Checking a feed with a long history is much quicker: items already stored are no longer written again on every check. -- A scan no longer asks a feed's website for its icon every time; it asks again when the artwork changes or you refresh the feed. - The feed list loads several times faster: it was asking the database six questions per feed. - Artwork a feed offers only over plain http shows on the https site too. - A failing feed is easy to spot in any theme: a mark on its artwork, what is wrong in place of its counts, and its artwork greyed out once it has failed for a day. -- A feed whose own artwork is missing shows its website's icon instead of nothing. - The log has no terminal colour codes when it is not going to a terminal, as in `docker logs`. -- A feed whose website names an icon that is missing shows the site's `/favicon.ico` instead of - no artwork. -- A website's icon standing in for a feed's artwork follows the site when it changes, and a - feed that drops its own artwork gets the site's instead. Refreshing a feed checks again. - The read button shows whether an item is read, as the pin beside it shows whether it is pinned: a tick when read, an envelope when not. It used to show the opposite. - In Directory and Popular, Subscribe is a plus again, not the tick that marks a feed you have. - A feed's refresh button looks like the buttons beside it, instead of standing out filled in. - Refreshing reads your feeds in full, instead of only asking each one whether it changed, so a feed that has not changed is still read again. -- A web page with some non-ASCII characters no longer hides the feed it links, or crashes looking for it. - Pulling the item list down to check for new items shows a spinner for a couple of seconds, and a second pull meanwhile does nothing, instead of no sign at all that the check started. - Settings no longer lists the server's download folder, which only an admin can change, on @@ -252,14 +235,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Opened from the home screen on an iPhone, the top bar, the reader's back button and the top of the feed list keep clear of the Dynamic Island and the status bar instead of sitting under them. -- Swiping to the next or previous item takes a longer swipe, a quarter of the screen, so a - diagonal scroll no longer jumps ahead by accident. The item follows your finger and slides - across as it changes. -- Swiping between items on a phone no longer shows the item list through the reader. The next - or previous item sits beside the one you are reading and comes across with it, the end of the - list says so, and swiping right from the first item draws the reader off the list, dimmed - until it is uncovered. A swipe from the screen's left edge stays with the page, rather than - Safari taking it as Back. +- Swiping between items on a phone takes a quarter of the screen, so a diagonal scroll no longer + jumps ahead by accident, and no longer shows the item list through the reader: the next or + previous item sits beside the one you are reading and comes across with it, following your + finger, the end of the list says so, and swiping right from the first item draws the reader off + the list, dimmed until it is uncovered. A swipe from the screen's left edge stays with the page, + rather than Safari taking it as Back. ## [0.8.4] - 2026-09-19 @@ -366,6 +347,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Touch gestures: pull the item list down from its top to check the feed for new items, and swipe the item you are reading left for the next one and right for the one before, or back to the list from the first. +- A favicon: the logo, squared up, also at /favicon.ico for browsers that ask there on their own, + and on white for an iPhone's home screen. ### Changed @@ -380,17 +363,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - On a phone, an item's files, with play and delete, sit above its show notes rather than below them, where long notes left them looking missing. - On a phone, an item with no files goes straight to its text, without a box saying "No files". -- The page is served minified, about a quarter smaller. Its script is now TypeScript in - `web/src`, type-checked, and built with swc; building ipx needs node. -- The script is its own file, `/app.js`, rather than inside the page. Your browser keeps it - between visits and fetches it again only when an update changes it. +- The page is served minified, about a quarter smaller, with its script in a file of its own, + `/app.js`, which your browser keeps between visits and fetches again only when an update changes + it. The script is TypeScript in `web/src`, type-checked and built with swc; building ipx needs + node. ### Fixed - Switching tabs straight after marking everything read no longer shows the previous tab's items: of two lists asked for at once, only the later one is shown. -- ipx has a favicon: the logo, squared up, also at /favicon.ico for browsers that ask there on - their own, and on white for an iPhone's home screen. - The file icon of an item not yet downloaded sits level with the rest of its row, instead of higher than a downloaded one's. - Images in posts from sites that refuse images to other sites' pages, such as Jeff Geerling's, @@ -401,8 +382,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 unread dot back until the next refresh. - On the Unread tab, the item you were reading leaves the list as soon as you move to the next one, rather than a few read items lingering until a refresh cleared them. -- The Log button no longer shows for a moment on every load for anyone but an admin; the server - leaves it out of their page. - An image or link in a post given relative to the post, such as The Observation Deck's, now points at the post's site rather than at ipx, and shows. @@ -472,10 +451,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 connection", now shows that message and is flagged as the publisher's problem, instead of two parser errors about reaching the end of input. -### Removed - -- An unused icon glyph (`minus`) left over from before Unsubscribe settled on `circleMinus`. - ### Fixed - Add a feed opened over Directory or Popular now shows its Popular list instead of staying on @@ -644,13 +619,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - A Classic theme after the 2004 Mac app, beside Dark and Light: brushed-metal toolbar, Aqua blue selection, red unread badges, a striped table and Lucida Grande. The theme button steps through all three and remembers the choice. -- A toolbar across the top, after the original iPodderX: add and unsubscribe, play, mark read - and keep for the selected item, scan, a search box for what is showing, and Settings and Log. +- A toolbar across the top, after the original iPodderX: add, unsubscribe and scan; play, mark + read and keep for the selected item, showing its state; a search box for what is showing; and + Settings and Log. - Directory, Popular and All Subscriptions at the top of the feed list, opening in the main pane. Directory lists every feed anyone here subscribes to, A to Z (`GET /api/directory`). All Subscriptions lists every item from every feed you subscribe to (`GET /api/entries`). - Items show as a table (unread, kept, title, feed, file, size, published) with a Files pane beside - it, and a status bar with the totals. + it, and a status bar with the totals. A file's type is an icon (audio, video, image, PDF, torrent, + other), green once it is downloaded and red when the download failed, with the details in its + tooltip; its size is in KB for small files instead of "0 MB". - Mark everything read from All Subscriptions, across every feed you subscribe to (`POST /api/read-all`). It asks first. All Subscriptions can also check every feed from its header. - Click a column heading in the item table to sort by it (kept, title, feed, file type, size, @@ -665,28 +643,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 items show without pressing Scan. - A file deleted to save space, or by hand, looks as if it was never downloaded: no "reaped" label, just the Download button. The retention summary says "deleted", not "reaped". -- Buttons are icons, with the words in their tooltips: the Files pane (save, delete, view, - download), an item's own buttons (mark read, keep, open the original), the feed header (scan, - download latest, mark all read, settings, unsubscribe), and the Settings, feed settings and - Download latest dialogs (save, download, cancel). The icons are Font Awesome Free, embedded as - SVG: only the ones used, no font to download, and nothing fetched from anyone else. They - replace font characters such as ⟳ ⤓ ↗, which came out thin and tiny and differed from font to - font. Keep is a flag everywhere, as it was in the original, and mark unread is an envelope. -- One meaning per icon. Minus unsubscribes, x closes or cancels, plus adds or subscribes, and a - dialog's confirm button carries the icon of what it does. The feed header's unsubscribe was an x - and read as closing the page. The remaining word buttons are icons too: - - Log, Add feed, Users, Unsubscribe and OPML. - - Popular's Subscribe, Copy and Sign out. - - The Subscribed label in Popular, the Directory and Add feed, which is now a green check. - - The player's back, play, forward and close, which were font characters, and the folder arrow. -- The toolbar's read and keep buttons show the selected item's state, with the same icons as the - item's own buttons. Play, read and keep sit together, and Scan sits with add and unsubscribe. +- Buttons are icons, with the words in their tooltips, one meaning per icon: minus unsubscribes, + x closes or cancels, plus adds or subscribes, a dialog's confirm button carries the icon of what + it does, Keep is a flag, as it was in the original, mark unread is an envelope, and Subscribed is + a green check. The icons are Font Awesome Free, embedded as SVG: only the ones used, no font to + download, and nothing fetched from anyone else. They replace words and font characters such as + ⟳ ⤓ ↗, which came out thin and tiny and differed from font to font, and the feed header's x for + unsubscribe, which read as closing the page. - An OPML subscription's page has the same header as a feed's, with its buttons in the same places. -- The item table's size has its own column, apart from the file's type, and shows KB for small - files instead of "0 MB". The Item heading is now Title. -- A file's type is an icon (audio, video, image, PDF, torrent, other), green once it is - downloaded and red when the download failed, with the details in its tooltip. One icon per - row keeps the column lined up. The DOWNLOADED and PENDING labels are gone. ### Fixed @@ -737,11 +701,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- Importing another account's OPML export subscribed nobody and reported "Imported 0 feed(s)". - Feeds it added had no subscriber, so they were never scanned. - Importing something that is not OPML answered `500`. It is now `400` "that is not an OPML file", refused before anything changes. -- Starring stopped protecting a file from the quota and age sweeps once read state became per-user. ### Security @@ -755,7 +716,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Web UI served by the daemon: plain HTML and JS compiled into the binary, with feeds, items, - filters, search, sanitised show notes and live progress over SSE. + filters, search, sanitised show notes and live progress over SSE. Opening an item marks it + read; playing it marks it read only at the end or past 90%. - Player bar with resume, speed, keyboard shortcuts and lock-screen controls. - Three-pane layout: feeds beside, items above, and the selected item's text and files below. - Phone layout. @@ -763,7 +725,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 trusted proxy header for Cloudflare Zero Trust or Authentik (`docs/sso.md`). - Subscribing to an OPML: it is re-read every scan and its feeds show as a folder. A feed dropped from it is removed unless it has downloads. -- Scheduling: a global interval with per-feed overrides (`every 30m`, `4h`, `1d`, `2w`). +- Scheduling: a global interval with per-feed overrides (`every 30m`, `4h`, `1d`, `2w`), set by an + admin, as are the global settings. - `[general] media_types`, default audio and video, and `max_new_per_check`, default 3. - Every enclosure of an item, a View link for files that are not audio or video, and per-item artwork. @@ -776,33 +739,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- Global settings and scan schedules are admin-only. The per-feed schedule picker is gone. - Feeds from an OPML live in the database, not `config.toml`. -- Opening an item marks it read. Playing it marks it read only at the end or past 90%. -- "Episodes" became "items", since half the library is text. -- A burst of scan events causes one refresh, not one per feed. -- All is the default filter. OPML import and export, Settings and Log moved out of the header. - Torrents run detached, two at a time. ### Fixed -- Download fetched the next queued episodes instead of the one clicked. -- Pressing play made an item vanish from the Unread list. -- Clearing a folder, schedule or cap from the UI did nothing. - The daemon ignored SIGTERM until the current download finished. -- A missing function stopped the page script and left the whole UI dead. -- One download painted progress on every pending row. - A torrent could freeze scanning for up to an hour. -- Downloading from an OPML feed failed with "belongs to unsubscribed feed". -- Image enclosures were downloaded, counted as episodes and given a play button. +- Image enclosures were downloaded as episodes. - A feed whose entries had been deleted stayed empty, because the server kept answering `304`. - An item with several enclosures kept only the last. -- OPML folders rendered open by default. -- Mark read in the text pane recursed until the stack overflowed. -- The Unread, Downloaded and Flagged filters answered `500` without a search term. -- An OPML subscription always showed 0 unread. -- Folder names kept doubled spaces where separators were stripped. -- Sidebar rows had four different left edges. ### Security @@ -826,7 +772,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Torrent enclosures through librqbit, seeding to a ratio or a time, with a stall timeout. - `ipx import` and `ipx export` for OPML, and systemd units in `contrib/`. -[unreleased]: https://git.sdf1.net/rays/ipx/compare/v0.10.3...main +[unreleased]: https://git.sdf1.net/rays/ipx/compare/v0.11.0...main [0.11.0]: https://git.sdf1.net/rays/ipx/compare/v0.10.3...v0.11.0 [0.10.3]: https://git.sdf1.net/rays/ipx/compare/v0.10.2...v0.10.3 [0.10.2]: https://git.sdf1.net/rays/ipx/compare/v0.10.1...v0.10.2