Since users can delete the corrupted decks_cache.json file, the
migration logic is no longer necessary. The URL encoding/decoding
ensures all new cache files will be saved correctly going forward.
When decks_cache.json was saved with the old format, relay URLs like
"wss://wot.nostr.net" were split by the ":" delimiter into separate
tokens: ["wss", "//wot.nostr.net"]. This commit adds migration logic
to detect and reconstruct these corrupted URLs during parsing.
Detection heuristic:
- If the relay_url token is just "wss" or "ws" (without "://")
- AND the next token (hashtags_str) starts with "//"
- Then reconstruct the full URL as "wss://..." or "ws://..."
- And pull the next token as the actual hashtags
This allows existing users with corrupted decks_cache.json files to
automatically have their relay URLs fixed on next app restart, without
needing to manually delete the cache file.
The relay URL "wss://wot.nostr.net" was being incorrectly parsed as
Relay("wss", Some(["//wot.nostr.net"])) when the app restarted and
loaded from the decks cache.
Root cause:
The TokenWriter uses ":" as the default delimiter. When relay URLs
containing ":" (like "wss://wot.nostr.net") were serialized, the
colons were not escaped, causing the URL to be split into multiple
tokens during parsing:
- Token 1: "relay" (type)
- Token 2: "wss" (mistakenly read as relay_url)
- Token 3: "//wot.nostr.net" (mistakenly read as hashtags)
Solution:
- URL-encode relay URLs when serializing (using urlencoding crate)
- URL-decode relay URLs when parsing
- Added backward compatibility: if decoding fails (old format),
fall back to using the token as-is
This ensures relay URLs with colons are correctly preserved across
app restarts.
This fix addresses the "got unknown eose subid" warnings that were appearing
in the logs when EOSE (End Of Stored Events) messages arrived from relays.
The issue was that when `TimelineSub::try_add_remote()` and
`TimelineSub::try_add_remote_with_relay()` created new subscription IDs,
they were not being tracked in the `Subscriptions.subs` HashMap. When EOSE
messages arrived for these subscription IDs, the `handle_eose()` function
couldn't find them in the HashMap, causing the "unknown eose subid" warnings.
Changes:
- Modified `try_add_remote()` and `try_add_remote_with_relay()` to accept
`&mut Subscriptions` and `&TimelineKind` parameters
- Added subscription tracking by inserting subscription IDs with
`SubKind::Timeline(timeline_kind)` into the Subscriptions HashMap
- Updated all call sites throughout the codebase to pass the required
parameters, including:
- TimelineCache::open()
- DecksCache::add_deck_default()
- DecksCache::new_with_demo_config()
- is_timeline_ready()
- execute_note_action()
- execute_and_process_note_action()
- add_demo_columns()
- demo_decks()
This ensures all subscription IDs are properly tracked, eliminating the
unknown EOSE warnings and allowing proper handling of EOSE messages.
This commit adds the ability to create columns that display content from
a specific relay, with optional hashtag filtering.
Features:
- New TimelineKind::Relay variant storing relay URL and optional hashtags
- Relay-specific subscription support in RelayPool (subscribe_to method)
- UI for configuring relay URL and hashtag filters
- Filter generation for relay-specific queries
- Column header with relay icon
- Serialization/deserialization support for deck persistence
Implementation details:
- Extended RelayPool with subscribe_to() for relay-specific subscriptions
- Added TimelineSub::try_add_remote_with_relay() to handle targeted subscriptions
- Timeline cache automatically routes relay columns to specific relays
- UI validates relay URLs before creating columns
- Hashtag filtering is optional and space-separated
Usage:
Users can now add a "Relay" column from the column picker, enter a relay
URL (e.g., wss://relay.example.com), and optionally filter by hashtags.
William Casarin (13):
net: switch ping/pong messages to trace
update nostrdb
clippy fixes
add is_root_note helper
ui: note metadata stats
ui: rename actionbar function
ui: move debug slider to ui crate
ui: add rolling number function
ui/note: use rolling numbers for note stats
windows: fix time overflow crash
nostrdb: update for windows fix
clndash: clippy fix
Changelog-Added: Add realtime note stats
from remote-tracking branches:
* kernel/fix-soft-keyboard
* kernel/composite-profiles-perf
* kernel/fix-nav-flicker
kernelkind (8):
Revert "fix: nav drawer shadow extends all the way vertically"
chore(profiling): markup composite render path
chore(tracy): repaint every frame
feat(composite-cluster): do culling for pfps
feat(mime-cache): upgrade UrlMimes
feat(reactions): use ProfileKey when possible for performance
fix(nav-drawer): shadow extends all the way vertically
fix(thread): remove flicker on opening thread
1. more performant. No more deserialization every frame
2. employs TTL (so cache doesn't grow unbounded)
3. exponential backoff to retry on error
Signed-off-by: kernelkind <kernelkind@gmail.com>
since we stop rendering when there is no user input, tracy sees
big hangs, and it's annoying to parse through which frames are
actual performance issues and which are due to no user input.
So just repaint every frame while using tracy.
Signed-off-by: kernelkind <kernelkind@gmail.com>
df5cf8a1fc caused a regression
making the soft keyboard auto close. This patch extends the shadow
all the way vertically without triggering the regression
Signed-off-by: kernelkind <kernelkind@gmail.com>
kernelkind (9):
update egui-nav
fix: nav drawer shadow extends all the way vertically
drawer: only use drag on mobile
new `egui`
update egui_nav
refactor: move `galley_centered_pos` to notedeck_ui
refactor: rename assets
assets: add accounts image
chrome: ui polish
the previous unseen notification indicator only ran once a few
seconds, but when it did it often took > 5ms because of ndb::query,
which is unacceptable.
This commit removes the ndb::query entirely and relies on the
ndb::poll_for_notes which is already being used every time there is
a new event from a relay
Signed-off-by: kernelkind <kernelkind@gmail.com>
will be used in the UI for whether to show the filled/unfilled
react icon in the actionbar. Temporary until ndb metadata lands
Signed-off-by: kernelkind <kernelkind@gmail.com>