Notes, replies, quotes, polls and articles can carry ["client", "Sunstone"]
so other clients show what you posted with. NIP-89 says this is opt-out, so
it is a persisted setting (default on) exposed as a "Sunstone" toggle in both
the note composer and the article editor — toggling either sets your default.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the square banner with a rounded, translucent "Catching up…" pill
(bottom-centre, clear of the new-notes pill) with a spinner, matching the
new-pill styling. Drive it by actual network activity: each merge bumps a
timestamp and a 1s ticker hides the pill ~4s after merges go quiet (60s hard
cap), so it runs as long as the sync actually does.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cached notes paint instantly but the relay catch-up keeps running underneath,
so a half-full feed at launch read as broken. Add an adw::Banner under the feed
header that says it's updating in the background, auto-dismissed after the
initial sync window. Init-only — no new messages or handler changes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The count cap (200) was below the feed working set, so cards re-decoded on
every rebuild and saturated the shared decode gate — starving avatars (which
decode through the same gate) so disk-cached profile pictures never painted,
and everything got slow. Switch to a byte budget with headroom (feed 384 MiB,
video/streams 192, light pages 96) so normal browsing never evicts and only a
long session trims the oldest entries. Memory stays bounded without the thrash.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The zap picker was a bare adw::Dialog with no header — the only way out was
Escape, which isn't discoverable. Wrap its content in a ToolbarView +
HeaderBar so it gets the standard close (✕) and title, matching the composer.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The volume slider inits to full, but its value-changed handler is wired after
that initial set, so playbin never heard about it — the bar showed full while
playback sat at playbin's own default, and you had to wiggle the bar to sync.
Set playbin volume to 1.0 at construction and re-assert the slider value on
each play() (playbin3 can drop volume across a Null→Playing cycle).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Every page held an uncapped HashMap<String, gdk::Texture> that only ever grew
— gdk textures keep their decoded RGBA resident, so every image/avatar/cover
scrolled past stayed in memory for the session (the multi-GB RSS climb). Add a
bounded TextureCache (insertion-order eviction past 200 textures; the core
disk/byte cache still holds the source for cheap re-decode) and use it on all
seven pages.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Asset source paths are resolved relative to the crate dir, not the workspace
root, so the desktop/icon/README paths were unresolvable. Point them at the
crate (../../ for workspace-root files). Maintainer email → enki@sovbit.host.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Plain description, no pitch framing.
- Remove highlights (NIP-84) from features — not built; moved to Roadmap.
- DMs / proxy stated plainly, no caveat essays.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The profile only fetched the author's own kind-1/long-form notes, so their
reposts never appeared. Also pull their kind 6/16 reposts, resolve each
boosted note (embedded in the repost content, or fetched by e-tag), and merge
them into the timeline ordered by repost time. Cards carry a reposted_by
marker and render a "🔁 Reposted" header.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The reply count only credited a reply to its immediate parent, so a note
showed 2 when a back-and-forth under those comments really meant 7+. Per
NIP-10 a nested reply still e-tags the thread root, so count a reply toward
every batched note it references (deduped per event) — the count now reflects
the whole conversation, not just top-level replies.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
list_transactions isn't reliably available over the connected wallet, so the
TX list was dead weight. Keep the balance + node alias (the useful, reliable
"wallet info"); wallet_overview now only calls get_info + get_balance.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
NIP-47 caps list_transactions pages small; a 50-item request blows past the
64KB payload many relays reject at, which surfaced as an empty TX list. Drop
to 20, and log the failure at warn so an empty list is diagnosable (method
unsupported vs relay timeout).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New Core::wallet_overview queries the connected NWC wallet for node alias,
balance, and recent transactions (get_info / get_balance / list_transactions,
all concurrent and individually best-effort). The Wallet settings tab gains a
"Balance & activity" section: balance headline, a refresh button, and a
transaction list (direction-tinted amounts, descriptions, relative times). It
loads on open when a wallet is configured and after saving a new NWC URI.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
dm_cache is per-session, so the first time Messages opened after each launch
re-decrypted the whole mailbox one gift wrap at a time on a single thread —
the real cause of slow DM loads. Decrypt the wraps concurrently across the
runtime's worker threads instead (unwrap_dm stays cache-backed, so warm
wraps still return instantly).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Posting no longer claims success when zero relays accepted the event:
note/reply/quote/poll now error ("saved locally — try Broadcast") so the
composer surfaces it instead of a false "posted".
- The post button shows a spinner while publishing.
- Like / react / repost / delete were silent on failure; they now toast the
error, and repost/delete confirm success ("Reposted ✓", "Note deleted").
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The reply button now carries a live count next to it, alongside the like,
repost, react and zap tallies. engagement_for counts direct replies (kind-1
events whose reply target is the note) so the number rides the same fetch +
optimistic-update path as the rest.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Restructure as a friendly landing page: a plain one-liner, a "what you
can do" section in human language, then install — with the dense NIP
list, build-from-source, env vars, and project layout moved to a
"technically inclined" section at the end.
Accuracy fixes:
- Flatpak install is now download-the-prebuilt-bundle from Releases
plus the one-time Flathub remote, not the flatpak-builder dev flow.
- Arch install points at the AUR (paru/yay) instead of `makepkg -si`,
which fails because no v0.1.0 tag exists.
- Drop the `cargo deb` quick-install (no packaging metadata yet); note
a .deb is in progress and point to Flatpak/source.
- URLs point at git.utn.lol/enki/sunstone.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- packaging/arch/build-local.sh: build a native .pkg.tar.zst from the
current git HEAD without needing a published forge release (tarballs
the checkout and runs makepkg --nodeps with the existing PKGBUILD).
- .gitignore: ignore dist/ (local package output).
- sunstone-gtk: drop invalid `margin: 0 auto` on .kind-badge children;
GTK CSS rejects `auto` for margin, which logged a parse warning. The
value was already being ignored, so rendering is unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A GTK4 + libadwaita nostr client in Rust on rust-nostr: social feed with the
outbox/gossip model, long-form articles, live streams and video, NIP-17 DMs,
NIP-29 groups, calendar, polls, and NIP-57 zaps over NWC.
Published under the MIT license.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 22:06:30 -07:00
3 changed files with 25 additions and 48 deletions
# Local PKGBUILD: pin pkgver + swap the forge source for the local tarball.
sed -e "s|^pkgver=.*|pkgver=$ver|"\
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.