A Signal's own icon, from all of Font Awesome Free, searchable (#261)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-16 18:36:08 +00:00
parent 9e5dcbb8c4
commit b18c92d1f5
15 changed files with 269 additions and 31 deletions

View File

@@ -16,6 +16,9 @@ their Signals that has not heard about the item yet.
#256). It is closed or open as an OPML's folder is, remembered in each browser. A + at the right
of the folder's row opens New signal. Inside the folder are the person's Signals, each with its
words under its name and its unread count.
- **An icon of its own** (#261), chosen in the Signal's dialog from all of Font Awesome Free 7.3.1,
the set the page's own icons come from: 2,883 icons, solid, regular and brands, searched by name
and Font Awesome's search terms ("ai" finds the robot). Without one, a Signal shows its initials.
- **The folder's page** lists the Signals, as an OPML's page lists its feeds, with a + of its own.
- **A Signal's page** is an ordinary item list: All, Unread, Downloaded and Pinned, search and sort.
Its header says what it listens for (the sentence, or the words), and that nothing is picked
@@ -190,8 +193,10 @@ up to 500 characters. Anything else is a `400` saying so.
### `PATCH /api/signals/{id}`
Any of the three: `{ "name": "F1" }`, `{ "keywords": ["f1", "grand prix"] }`,
`{ "description": null }` (null or empty clears it). Any change drops the Signal's verdicts and
wakes the judge, since each is part of the question. Answers `204`, or `404` for a Signal that is not yours.
`{ "description": null }` (null or empty clears it), `{ "icon": "solid/robot" }`. A change to the
name, words or sentence drops the Signal's verdicts and wakes the judge, since each is part of the
question; a new icon does not. The page sends only what changed. An icon is `solid/`, `regular/` or
`brands/` and a plain name, since the page puts it into an address: anything else is a `400`. Answers `204`, or `404` for a Signal that is not yours.
### `DELETE /api/signals/{id}`
@@ -261,6 +266,7 @@ erDiagram
text name
text keywords "JSON array"
text description "NULL: none"
text icon "solid/robot, NULL: initials"
bigint created
}
signal_verdicts {
@@ -272,8 +278,12 @@ erDiagram
```
- `signals` and `signal_verdicts` are created from their entities like every table
(`crates/ipx/src/entity.rs`). `users.typesafe_key` and `signals.description` were added to
existing tables, so `create_missing` adds each column when it is missing.
(`crates/ipx/src/entity.rs`). `users.typesafe_key`, `signals.description` and `signals.icon`
were added to existing tables, so `create_missing` adds each column when it is missing.
- The icons are files of ipx-web's, not the database's: `web/build.mjs` copies Font Awesome Free's
SVGs to `/icons/<style>/<name>.svg`, kept a day, and writes `/icons/index.json`, names, labels
and search terms, about 90 KB compressed, named by its hash and fetched when the picker first
opens. A Signal's tile draws its one file as a CSS mask, so it takes the theme's colour.
- A Signal's list is `entries_where` with
`EXISTS (SELECT 1 FROM signal_verdicts v WHERE v.signal_id = $n AND v.feed_id = e.feed_id AND v.guid = e.guid AND v.hit)`
on top of the subscribed-feeds scope. So filters, search, sort, block lists and read state all