From 13cad18857674135401da757560c6946d597641c Mon Sep 17 00:00:00 2001 From: rays Date: Fri, 16 Oct 2026 16:58:27 +0000 Subject: [PATCH] Signals' words: what matters out of the noise of your feeds (#254) The dialog asks what to listen for, the page says what it picked out of the noise of your feeds, and a new Signal says nothing has come through yet instead of showing an empty list. Co-Authored-By: Claude Opus 5.5 --- crates/ipx/CHANGELOG.md | 2 +- web/CHANGELOG.md | 2 +- web/src/dialogs.ts | 6 +++--- web/src/items.ts | 2 ++ web/src/signals.ts | 16 ++++++++-------- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/crates/ipx/CHANGELOG.md b/crates/ipx/CHANGELOG.md index a0085dd..6d856fa 100644 --- a/crates/ipx/CHANGELOG.md +++ b/crates/ipx/CHANGELOG.md @@ -14,7 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Signals: a feed you make from your own subscriptions, with keywords, holding the items TypeSafe's Jev says are about them, from the last 30 days and every new one, judged on your own TypeSafe key (`/api/signals`, and `typesafe_key` on `/api/me`) (#254). +- Signals: a feed of your own, picked out of the noise of everything you subscribe to, holding the items TypeSafe's Jev says are about the words you give it, from the last 30 days and every new one, judged on your own TypeSafe key (`/api/signals`, and `typesafe_key` on `/api/me`) (#254). ### Changed diff --git a/web/CHANGELOG.md b/web/CHANGELOG.md index a99c243..ff5003f 100644 --- a/web/CHANGELOG.md +++ b/web/CHANGELOG.md @@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Signals, under the places in the sidebar: New signal makes one from a name and keywords, and its page lists the items from your feeds that are about them, read and unread as in their own feeds. Settings takes your TypeSafe key, which Signals need (#254). +- Signals, under the places in the sidebar, pick what matters out of the noise of every feed you subscribe to: New signal takes a name and what to listen for, and its page lists the items from your feeds that are about it, read and unread as in their own feeds. Settings takes your TypeSafe key, which Signals need (#254). - A list opens at once when you have seen it before or the page fetched it ahead: All Subscriptions and the feeds with something unread are fetched when the page loads, and a feed or filter as the pointer or a finger reaches it, then refreshed behind once shown. A list that has to be waited for shows a spinner instead of nothing (#247). Currently Listening and the Directory's front page are fetched ahead the same way and open at once (#248). ### Changed diff --git a/web/src/dialogs.ts b/web/src/dialogs.ts index 410bfff..28b598f 100644 --- a/web/src/dialogs.ts +++ b/web/src/dialogs.ts @@ -444,9 +444,9 @@ async function prefsModal(){
- Signals are picked by TypeSafe's Jev on your own key, from - typesafe.ai. It is kept on this - server and never shown again. + Signals pick what matters out of everything you subscribe to, using TypeSafe's + Jev on your own key, from typesafe.ai. + The key is kept on this server and never shown again.
diff --git a/web/src/items.ts b/web/src/items.ts index 6a70573..909d2cb 100644 --- a/web/src/items.ts +++ b/web/src/items.ts @@ -133,6 +133,8 @@ function renderEntries(){ if(!S.entries.length){ // Said only for a search, where the words typed are why; an empty feed or tab speaks for itself. if(S.q) box.innerHTML='

Nothing matches that search.

'; + // A new Signal is empty while Jev reads, which would otherwise look broken. + else if(sg&&S.filter==='all') box.innerHTML='

Nothing has come through yet. Jev reads new items as your feeds are checked.

'; return; } for(const e of S.entries) box.appendChild(epEl(e)); diff --git a/web/src/signals.ts b/web/src/signals.ts index cd4eeed..cbec04d 100644 --- a/web/src/signals.ts +++ b/web/src/signals.ts @@ -38,8 +38,8 @@ function signalHead(sg: Signal){
${ICON.signal}

${esc(sg.name)}

-
Items from your feeds about ${esc(sg.keywords.join(', '))} · ${sg.unread} unread
- ${nokey?'
Nothing is picked until you add your TypeSafe key in Settings.
':''} +
Picked out of the noise of your ${plural(S.feeds.length,'feed')}: anything about ${esc(sg.keywords.join(', '))} · ${sg.unread} unread
+ ${nokey?'
No TypeSafe key yet, so nothing is being picked out. Add one in Settings.
':''}
@@ -65,12 +65,12 @@ function signalModal(sg?: Signal){ openModal(`

${sg?'Edit signal':'New signal'}

-
+
${chipsHTML(sg?.keywords||[],'sgkwin')}
- TypeSafe's Jev reads each item in the feeds you subscribe to, the last 30 days - of them and every new one, and puts the ones about any of these here as well as in their own - feed. Each item is one call on your TypeSafe key.${sg?' Changing these reads them all again.':''}
- ${nokey?'

Add your TypeSafe key in Settings first: nothing is picked without one.

':''} + TypeSafe's Jev reads every item in the feeds you subscribe to, the last 30 + days of them and each new one, and pulls out the ones about any of these. The rest stays + noise, in its own feed. Each item is one call on your TypeSafe key.${sg?' Changing these reads everything again.':''}
+ ${nokey?'

Add your TypeSafe key in Settings first: without one, nothing is picked out.

':''}
`); wireChips($('#sgkw')); @@ -83,7 +83,7 @@ function signalModal(sg?: Signal){ try{ const r=sg ? await api(`/api/signals/${sg.id}`,{method:'PATCH',body}) : await api('/api/signals',{method:'POST',body}); - closeModal(); toast(sg?'Saved':'Made. Items show up here as Jev reads them'); + closeModal(); toast(sg?'Saved. Jev reads everything again':'Listening. What Jev picks out shows up here'); await loadFeeds(true); selectFeed(':signal:'+(sg?sg.id:r.id)); }catch(e){ toast(why(e),true); } };