Commit Graph

154 Commits

Author SHA1 Message Date
Jure 9051c14205 polish: capitalise sidebar labels, rounded avatars, stronger article titles
- sidebar nav labels Title Case; follows -> People, dm -> Messages
- NoteCard + ArticleCard avatars rounded-sm -> rounded-md
- ArticleCard title 14px/medium -> 15px/semibold; larger tag pills
2026-05-18 18:17:13 +02:00
Jure 7678ad2f1f Feed virtualization Stage 2: infinite scroll
Adds older-notes pagination to the Global feed. fetchGlobalFeed gains an
optional until param (fetch events before a timestamp, no since bound).
The feed store's new loadOlderNotes action fetches 50 older notes when
triggered, dedups, merges, re-sorts. MAX_FEED_SIZE raised 200 to 1000 —
virtualization bounds the DOM-node/bitmap count, so this just caps the JS
notes array as hygiene.

Feed.tsx auto-triggers loadOlderNotes when the user scrolls within ~8 rows
of the bottom; a 'Loading older notes' row shows during the fetch. Global
tab only (Following uses a separate path, Trending is a ranked snapshot).

Pending: sandboxed memory verification.
2026-05-17 20:26:15 +02:00
Jure 73c1bd1ac9 Virtualize feed list with @tanstack/react-virtual
Stage 1 of the feed virtualization work. The feed now renders only the
visible window of note cards (~25-35 in the DOM) instead of all up to 200,
via @tanstack/react-virtual (pinned 3.13.24). This structurally caps the
WebKit decoded-bitmap accumulation that caused the v0.12.6-era OOM.

Error and 'new notes' banners moved above the scroll container so the
virtualizer's coordinate space always starts at scrollTop 0. Upward-scroll
flicker fixed with a scroll-direction-aware measureElement that reuses the
cached row height on backward scroll (TanStack/virtual#659).

Feed still capped at MAX_FEED_SIZE; infinite scroll is Stage 2.
2026-05-16 19:02:18 +02:00
Jure db81de9007 Bump to v0.12.16 — security hardening: http(s) scheme guard on link sinks, loop-stable HTML tag strip 2026-05-16 13:59:10 +02:00
Jure 7e998be45b Bump to v0.12.11 — read-only mode write-action guards
The app now behaves coherently for users without a signer (fully logged
out, or signed in with an npub). No broken Publish buttons, no dead-end
"Not logged in" toasts.

- Add useCanSign() hook in src/stores/user.ts as the single source of
  truth for write-capability. Captures both "no pubkey" and
  "npub-only login" states.
- ReadOnlyBanner now fires for both states (was only "no pubkey" before).
- Hide account-bound sidebar entries (Bookmarks, Messages, Notifications,
  Zaps, V4V) in read-only mode. Read-only-OK views (Feed, Articles, Media,
  Podcasts, Search, Follows, Relays, Settings, Support) stay visible.
- Guard every write surface, two patterns:
  - Hide inline UI: ComposeBox, InlineReplyBox, NoteActions row, NoteCard
    context menu, ArticleFeed "Write article", FollowsView per-row
    follow/unfollow, ThreadView root reply, PollWidget vote controls,
    RelaysView "Publish list", PodcastPlayerBar ShareButton.
  - "Sign in to X" CTA: ArticleEditor publish, QuoteModal post, ZapModal,
    EditProfileForm save. CTAs open LoginModal.
- ProfileView edit/follow/mute/zap/DM buttons each gated by canSign.
- ArticleView like/repost/comment/bookmark/zap each gated by canSign.
- Belt-and-suspenders runtime guards in user store follow/unfollow.

Bookmark / mute stores already swallow publish errors via .catch(() => {}),
so they don't need explicit runtime guards.
2026-05-11 22:08:06 +02:00
Jure 7a07d732e6 Remove broken "new account" badge
The badge marked notes from pubkeys whose kind-0 profile event was
newer than 60 days, on the theory that that approximated account age.
It doesn't: kind-0 created_at is "profile last updated," so any user
who refreshed their bio recently got flagged as new regardless of how
long they've been on Nostr. The proxy was misleading, so drop it
entirely until there's a real signal to use.

- NoteCard.tsx: remove isNewAccount badge.
- social.ts: remove batchFetchProfileAges, getProfileAge, and the
  module-level profileAgeCache Map.
- nostr/index.ts: drop the barrel re-exports.
2026-04-23 19:20:37 +02:00
Jure 6a23f0223c Apply WoT filter to reactions, zaps, and all feed tabs
WoT was previously global-feed only. Now it filters notes on every feed
tab (global, following, trending) and also gates reaction pills and zap
totals — so a reaction from someone outside your social graph no longer
shows up in the counts.

- engagement.ts: wotSet param threaded through groupReactions,
  fetchReactions, fetchZapCount, fetchBatchEngagement. Zaps are filtered
  by the pubkey inside the zap request (the actual zapper), not the
  outer event.pubkey (the LNURL wallet). Extracted getZapperPubkey and
  getZapAmountSats.
- useReactions / useZapCount: cache key embeds WoT state so filtered
  and unfiltered counts don't collide. Hooks subscribe to the WoT store
  so toggling re-renders.
- feed store: reads WoT state and passes wotSet to fetchBatchEngagement,
  seeds cache with the correct key.
- Feed.tsx: drop the tab === "global" guard.
- SettingsView.tsx: update copy to reflect the wider scope.
2026-04-23 19:20:29 +02:00
Jure bc4c72d6a0 Fix Linux OOM: disable Blossom SHA-256 URL auto-detection
Commit 214c42b (v0.12.6) added auto-detection of content-addressed
Blossom URLs (64-hex SHA-256 paths) as <img> elements. Blossom is
widespread in modern Nostr feeds — every feed page started rendering
3-5x more <img> elements. Combined with WebKitGTK's weak decoded-
bitmap eviction, feed scrolling grew the WebKit web process to
8-12 GB and triggered WebKit's self-kill threshold with:

  Unable to shrink memory footprint of process (9022 MB) below
  the kill threshold (8192 MB). Killed

Disable BLOSSOM_URL_REGEX in parseContent(). Real Blossom images
shared via standard upload flows (with proper extensions) still
render. Proper reintroduction (HEAD request + Content-Type
validation, or known-server whitelist) planned for v0.12.9.

Also restore feed depth caps to pre-crisis values now that memory
is under control:
  - MAX_FEED_SIZE 30 → 200 (v0.12.6 baseline)
  - fetchFollowFeed limit 30 → 100
  - fetchGlobalFeed fetch 80 → 100
  - Following tab slice 30 → 100

The earlier 30-caps were themselves OOM firefighting that shipped
in v0.12.7 and were no longer needed.

Memory verified 2026-04-16: oscillates 1.1-1.6 GB across all tabs
(Global / Following / Trending / Media / profile / thread) under
heavy use with embedded relay enabled. No crashes. Elastic cache
behaviour rather than monotonic leak — memory spikes briefly on
content loads and reclaims within seconds.

See private_docs/WEBKIT_OOM_INVESTIGATION.md for the full
investigation (4 days of chasing symptoms before finding the
one-line regex as the real cause).
2026-04-16 21:31:04 +02:00
Jure 5fe3554579 Fix feed OOM: cap follow feed at 30, WebKit software rendering, dedup notification fetches
- followNotes capped at 30 (was 80) — following feed was rendering 2.7x more
  notes than global, causing 4GB+ spike on media-heavy follow content
- fetchFollowFeed limit 80→30 to match
- WEBKIT_FORCE_SOFTWARE_RENDERING=1 replaces WEBKIT_DISABLE_COMPOSITING_MODE=1
  (compositing mode killed Wayland path → blank window on Hyprland)
- HardwareAccelerationPolicy::Never → OnDemand (Never also caused blank screen)
- set_enable_page_cache(false) — SPA never navigates, bfcache is pure waste
- Removed duplicate fetchNotifications calls on login (was firing 3x in 8s)
- First notification poll delayed 8s→90s to avoid competing with feed load
- Result: login 3600MB→453MB, following feed crash→737MB, plateau at ~950MB
2026-04-16 11:43:48 +02:00
Jure 0894389fe0 Fix feed OOM: lazy image loading, inView gating, WebKit memory tuning
- NoteContent: remove ImageGrid from inline mode — images now only load
  when note is inView (via mediaOnly), stopping runaway scrolling leak
- NoteCard: content-visibility:auto to skip layout/paint for off-screen
  cards; inView-gated media, NoteActions, NIP-05 verification
- useInView: new IntersectionObserver hook with 300px rootMargin
- useProfile: MAX_PROFILE_CONCURRENT=8 throttle with fetch queue
- useReplyCount/useZapCount/useReactions: enabled param, throttled queues
- feed.ts: MAX_FEED_SIZE 200→30, live sub disabled (pendingNotes pattern),
  250ms batch debounce on live events
- core.ts: MAX_CONCURRENT_FETCHES=25 global NDK cap, fetchWithTimeout
  uses subscribe+stop instead of fetchEvents (no zombie subscriptions)
- lib.rs: HardwareAccelerationPolicy::Never + CacheModel::DocumentViewer
- main.rs: WEBKIT_DISABLE_COMPOSITING_MODE=1 for Linux
- relay/db.rs: TTL eviction + 5000 event cap
- feedDiagnostics.ts: file-flushing diag log survives crashes
2026-04-15 20:36:14 +02:00
Jure 018ee0e0f3 Fix thread OOM: hard-truncate events client-side, remove batchFetchProfileAges from thread 2026-04-13 22:16:02 +02:00
Jure 5d59797d5d Add thread load timing diagnostics (Ctrl+Shift+D to view) 2026-04-13 21:34:40 +02:00
Jure 95785dcb07 Fix profile fetch architecture: batch kind-0 queries, restore NDK pooling 2026-04-13 21:06:08 +02:00
Jure d8217bda49 Add new account age badge on notes (< 60 days) 2026-04-13 20:51:24 +02:00
Jure 4ce272ce5a Add opt-in WoT feed filter (hop-1 + hop-2 social graph) 2026-04-13 18:11:45 +02:00
Jure f3b92004f0 Bump to v0.12.7 — fix NIP-96 upload endpoints, block SVG uploads 2026-04-13 14:43:03 +02:00
Jure a393469c17 Add interest selection step to new-user onboarding
New users now choose topics after backing up their key. Selected interests
are saved to localStorage (wrystr_interests) and surfaced as clickable
hashtag pills in the Following feed empty state, giving new users a path
into content without auto-following strangers.

Flow: welcome → create → backup → interests → app
Login path is unchanged.
2026-04-11 22:29:25 +02:00
Jure 4759c2df64 Parse URLs, mentions and hashtags in profile bio
Profile about/bio text now renders clickable links, nostr mentions,
and hashtags instead of plain text.
2026-04-10 20:40:35 +02:00
Jure f4878f9d4f Polish DM view: clickable links, inline images, nostr entity rendering
- DM messages now parse and render URLs as clickable accent links
- Image URLs show inline in the bubble (max-h-48)
- nostr:naddr and mentions rendered as styled clickable links
- nostr:nevent quotes show a subtle indicator
- Media URLs (video/audio/youtube etc.) rendered as clickable links
- parseContent regex now case-insensitive for nostr: prefix; entity
  lowercased before nip19.decode for robustness
- renderTextSegments: add case for quote type (↩ note indicator)
2026-04-10 17:49:11 +02:00
Jure 7375ddc7e3 Fix multi-image upload in article editor; add thumbnail lightbox
- All selected images now upload and insert correctly (was: only last
  image kept due to stale content closure in loop)
- Images inserted as a block with proper newline padding
- Thumbnail strip thumbnails are now clickable — opens a lightbox;
  click overlay to dismiss
2026-04-10 11:33:13 +02:00
Jure 9fb0a7ef2e Polish pass 13 — final sentence case sweep
- NoteActions: Share, Follow/Unfollow
- SearchView: Search button, Notes/Articles/People result tabs
- RelaysView: Check all, Add (suggested relays)
- SettingsView: Add (mute keywords), Export data/Exporting…/Exported ✓
- InlineReplyBox: Reply/Replied ✓/Posting…
2026-04-09 19:51:16 +02:00
Jure 721a552f91 Polish pass 12 — sentence case on ArticleView, ComposeBox, DMView, SettingsView
- ArticleView: Back, Save/Saved, Repost/Reposted, Comment, Copy link,
  Like/Liked, Post — all button labels capitalised (header + footer)
- ComposeBox: Post, Post poll, Posting…
- DMView: Send, Start
- SettingsView: mute keyword placeholder + Remove button
2026-04-09 19:49:24 +02:00
Jure 63a0f05e92 Polish pass 11 — color tokens, text size consistency, overlay fix
- V4VHistory: text-amber-400 → text-zap on sats total
- V4VSettings: size status dot to text-[8px] for visual consistency
- Feed: last-updated timestamp text-[10px] → text-[11px] (matches siblings)
- NoteContent: +N overlay bg-black/50 → bg-bg/60, text-white → text-text,
  text-lg → text-[14px] (consistent with rest of file)
- RelaysView: last-checked timestamp text-[9px] → text-[10px]
2026-04-09 19:47:19 +02:00
Jure 9b3783b640 Polish pass 10 — hover titles, focus rings, disabled states
- NoteCard: title tooltip on truncated name and NIP-05
- NoteActions: emoji pill buttons dim (opacity-50) while disabled
- DMView: title tooltip on truncated conv name; focus ring on send button
- RelaysView: title tooltip on truncated relay URL
- OnboardingFlow: title tooltips on npub/nsec (nsec only when revealed)
- ArticleEditor: visible focus indicator on title and body textareas
2026-04-09 19:27:22 +02:00
Jure d6287fc240 Polish pass 8 — console → debug, sentence case, attachment button
- core.ts, feed.ts, user.ts: replace all console.log/warn/error with
  debug.log/warn/error (silent in production builds)
- ArticleFeed: "write article" → "Write article"
- ComposeBox: attachment remove x → ×, add aria-label
2026-04-09 19:20:47 +02:00
Jure f2546b5af7 Polish pass 7 — sentence case across profile, thread, follows, podcasts
- ProfileView: Cancel/Back, Edit profile, Zap, Follow/Unfollow, Mute/Unmute,
  Message, Notes/Articles/Media tab labels
- ThreadView: Back, Retry, Reply/Posting…/Replied ✓; console.error → debug.error
- ThreadNode: Reply/Posting…/Replied ✓
- FollowsView: Follow/Unfollow, Followers/Following tabs, Follows header
- EpisodeList: Back, Loading episodes…, amber → zap theme token on V4V badge
- AccountSwitcher: Login, Add account, Sign out, Remove
- PodcastCard: + Subscribe / Subscribed
2026-04-09 18:42:03 +02:00
Jure e30e42971e Polish pass 6 + fix V4V auto-streaming not stopping on manual toggle
Polish:
- ArticleEditor: sentence case on all buttons (← Drafts, Write, Preview,
  Zen, Meta, Publish, ← Back, New draft)
- EditProfileForm: Save profile / Saving… / Saved ✓
- ImageField: Upload / Uploading…
- RelaysView: Add, Publish list, Remove dead, Discover relays (sentence case)
- InlineReplyBox: attachment remove x → ×, aria-labels on remove/attach/emoji

Bug fix:
- V4VIndicator: add userDisabledRef so manually turning off streaming
  prevents auto-start from re-engaging on subsequent play/pause/seek
  events for the same episode; resets automatically on new episode
- V4VIndicator: remaining amber-* colors → zap theme token
2026-04-09 18:36:28 +02:00
Jure bac52b15ac Polish pass 5 — sentence case, theme tokens, remaining a11y
- Sentence case on all button labels (Mark read, Go to settings, Try again,
  Mark all read, Disconnect, Connect wallet, Logging in, Posting, Quote & post,
  Loading, Refresh); V4V tabs capitalized
- V4VDashboard: amber-500 hard-coded colors → zap theme token
- BookmarkView: tab container rounded-sm overflow-hidden
- ToastContainer, DebugPanel, PodcastPlayerBar: aria-labels on dismiss/close buttons
- PodcastPlayerBar: ASCII x → × Unicode, ... → … Unicode
- AboutView: document bg-white on QR code as intentional
2026-04-09 18:29:43 +02:00
Jure 3eb6968de0 Polish pass 4 — remove remaining hard-coded colors and inline styles
- Fix bg-white toggle thumbs in V4VSettings and V4VIndicator
- Replace hard-coded amber nudge colors with theme 'warning' token
- Remove redundant gridTemplateRows and move aspectRatio to Tailwind
- Replace MarkdownToolbar inline font styles with conditional classes
2026-04-09 15:47:12 +02:00
Jure 30147afc87 Polish pass 3 — theme tokens, debug logging, remaining ellipses
- Move DMView console.log/error behind debug.log/error (silent in prod)
- Replace hard-coded text-[#ffffff] with text-white in NoteContent overlay
- Theme-ify Vimeo and Tidal media cards (bg-accent/15 instead of
  bg-black/40 and bg-white/10) so they adapt to light themes
- Convert Vimeo play icon SVG to currentColor for theme-aware tinting
- Add aria-label to update banner dismiss button
- Replace remaining '...' with unicode ellipsis in loading states
2026-04-09 15:39:53 +02:00
Jure 508829c38b Polish pass 2 — avatar hover, reply buttons, ellipses, a11y
- Unify NoteCard avatar hover between image and fallback variants
- Add aria-labels to compose toolbar buttons (emoji, attach, poll)
- Fix ThreadView inline reply button sizing to match compose post button
- Replace remaining '...' with unicode ellipsis across podcasts, v4v,
  thread, and ancestor chain components
2026-04-09 15:36:55 +02:00
Jure d134702da7 Polish pass — consistency, a11y, theme correctness
- Fix bg-white toggle thumbs in Settings (broke on dark themes)
- Eliminate 2px layout shift when switching Media feed tabs
- Unify "Follow"/"Mute" capitalization in NoteCard context menu
- Replace ASCII "..." with unicode ellipsis across compose/search/article
- Add rounded-sm to dropdowns, emoji picker, post/reply buttons
- Add aria-labels to sidebar toggle and onboarding copy buttons
- Add role=tablist/tab/aria-selected to login mode tabs
- Replace inline width/height styles with Tailwind w-16 h-16 in ProfileView
- Replace inline transform style with rotate-90 class in SettingsView
- Unify sidebar active state opacity (bg-accent/8 → bg-accent/10)
- Pad sidebar badges with py-0.5 for consistent pill height
- Match thread reply button sizing to compose post button
- Use var(--font-reading) on non-zen article title for consistency
- Format 'saved Xs ago' as minutes/hours after 60s
- Unify expand chevron to ▶ + rotate-90 pattern
- PollWidget: transition-all → transition-colors (no layout animation)
- Remove cryptic 'Ctrl+Enter' hint from compose and thread reply
2026-04-09 13:32:59 +02:00
Jure acd5a5979b Bump to v0.12.4 — polls, custom relay, UI polish
NIP-1068 polls: create and vote on polls inline in the feed.
Switch default relay to custom Go relay (relay2.veganostr.com).
Note action icons with tooltips, sidebar icon cleanup,
search dedup fix, thread indentation fix.
2026-04-06 18:15:48 +02:00
Jure 86b7705c07 Fix thread indentation compounding on narrow screens
Replace absolute marginLeft with relative Tailwind ml-4, cap indent
depth at 3. Deep replies get border-line only, no further indent.
2026-04-06 15:21:37 +02:00
Jure 111473ddb4 Fix DMs not loading — use subscribe instead of fetchEvents for gift wraps
NDK's fetchEvents silently returns 0 results for kind 1059 (gift wrap)
events despite relays having them. Replaced with manual subscribe +
eose listener which correctly receives the events.
2026-04-06 11:49:34 +02:00
Jure fa1eb0d89b Make logged-out state visually obvious with top banner 2026-04-04 21:07:09 +02:00
Jure 9679c6f02c Fix empty Media feed: use 24h window instead of 2h 2026-04-04 20:53:02 +02:00
Jure 4a7f616c4b Stop V4V streaming when audio playback fails
When audio hits the 15s loading timeout or fires an error event,
stop any active V4V streaming to prevent phantom sat payments
on episodes that aren't actually playing.
2026-04-04 19:04:23 +02:00
Jure ebf964980b Add V4V sidebar section with dashboard, settings, and history
- New V4V store with budget tracking, cap enforcement, and history
- Dashboard: live streaming status, per-episode + weekly budget bars, stats
- Settings: auto-enable toggle (guarded by caps), per-episode cap, weekly
  budget, default rate, info icons
- History: expandable list of past V4V episodes with recipient breakdowns
- Budget enforcement: streaming stops with toast when cap is hit
- Auto-streaming: starts automatically for V4V episodes when enabled
- Cap reached state: dashboard shows red card, ticker shows "(capped)"
- V4VIndicator: slimmed popup, AUTO badge, "open v4v" nav link
- Fix duplicate history entries on cap stop
2026-04-04 19:03:00 +02:00
Jure 1d5d43ae78 V4V: keysend payments, recipient breakdown, and episode nudge
- Add payKeysendViaNWC for node pubkey recipients with TLV records
- Route V4V payments to keysend or LNURL-pay based on recipient type
- Show recipient split breakdown in V4V panel (name + percentage)
- Add V4V nudge: brief tooltip when V4V episode starts (once per session)
- Highlight V4V button in amber when episode has recipients but streaming off
- Enhanced V4V badge in episode list with lightning icon and pill style
2026-04-04 17:58:14 +02:00
Jure 5444214041 Fix podcast player stability, V4V payments, and Lightning address
- Add audio.load() reset to prevent cascading failures between episodes
- Add onPlaying event handler for reliable post-buffer playback in WebKitGTK
- Add 15s loading timeout with user-friendly error for broken audio URLs
- Fix V4V LNURL-pay: use Tauri HTTP plugin instead of CORS-blocked browser fetch
- Fix Podcast Index API: use Tauri HTTP plugin for V4V enrichment
- Fall back to Podcast Index enclosure URL when Fountain.fm CDN is broken
- Update Lightning address to jure@getalby.com (Alby cloud migration)
- Add broad HTTPS scope for LNURL-pay across Lightning providers
2026-04-03 22:27:34 +02:00
Jure ba3ef9e2c8 Polish: reduced motion, toast animation, token consistency
- Add prefers-reduced-motion media query for accessibility
- Add slide-in animation for toast notifications
- Standardize transition durations across note cards
- Replace remaining hard-coded text-white with theme tokens
2026-04-02 18:30:10 +02:00
Jure ae5b9a444c Optimize rendering: memo, granular selectors, code splitting
- React.memo on NoteCard and ArticleCard to skip re-renders
- Granular Zustand selectors in Feed.tsx and NoteCard.tsx
- Lazy-load 19 views with React.lazy + Suspense boundary
2026-04-02 18:03:19 +02:00
Jure 1006b1a1f0 Normalize theme tokens: accent-text, zap-text, remove hard-coded colors
- Add accent-text and zap-text tokens to all 7 themes for proper contrast
  on accent/zap-colored buttons (fixes white-on-light-accent in Catppuccin,
  Nord Frost, Hackerman, Sepia, Gruvbox)
- Replace text-white → text-accent-text on all accent buttons (20+ instances)
- Replace text-white → text-zap-text on zap buttons
- Replace hover:text-white → hover:text-accent-text on follow/action buttons
- Replace bg-blue-500 → bg-accent in FountainCard (theme-aware)
- Remaining text-white is correct: overlays on bg-black, danger badges
2026-04-02 17:33:59 +02:00
Jure 1fd613425d Harden accessibility: ARIA roles, semantic buttons, alt text, form labels
- Replace clickable divs with semantic <button> elements (NoteCard, SearchView)
- Add role="dialog", aria-modal, aria-labelledby on all modals (Login, Quote, Zap, Lightbox)
- Add role="presentation" on overlay backdrops (NoteCard menu, emoji pickers)
- Add aria-label to all icon-only buttons (close, nav arrows, context menu)
- Add aria-expanded to context menu toggle
- Add meaningful alt text to all 35+ images (avatars, covers, thumbnails, media)
- Add aria-label to form inputs (search, onboarding login)
2026-04-02 17:01:02 +02:00
Jure 51a010bfc5 Mark new followers with badge, sort to top of follows list
Track new follower pubkeys in notification store. When user opens
the follows view, new followers are highlighted with an accent "new"
badge and sorted to the top. Badge clears on view open (one-time).
2026-04-01 19:23:23 +02:00
Jure 6ae795e48d Replace themes (Sepia, Nord Frost), batch bookmark fetch, debounce bookmark publish
- Replace Solarized (low contrast) with Sepia (warm coffee tones)
- Replace Tokyo Night with Nord Frost (cool blue-grey, brighter)
- Bookmark fetch uses single batch filter instead of one-by-one (much faster)
- Debounce bookmark publish to prevent race conditions with replaceable events
2026-04-01 16:01:38 +02:00
Jure 355f412455 Increase Large/XL font sizes, enlarge account switcher, fix relay drop and bookmark persistence
- Large font 16→17px, Extra Large 18→20px
- Account avatar w-8→w-10, name and arrow text larger
- resetNDK preserves outbox-discovered relay URLs instead of dropping to fallback 3
- BookmarkView merges relay results with cache instead of replacing, so cached notes survive timeouts
2026-04-01 13:49:37 +02:00
Jure a65b2d2f95 Resolve naddr references to clickable named links
Parse naddr bech32 references as a dedicated segment type with kind,
pubkey, and identifier. NaddrName component fetches the referenced event
and displays its title/name/d-tag. Clicking navigates to article view
(kind 30023) or author profile (other kinds). Supports emoji sets,
app listings, and other addressable content.
2026-04-01 13:33:31 +02:00
Jure e3f5020eeb Add embedded Nostr relay with catch-up sync on startup
Embedded relay (strfry-lite in Rust) stores events locally in SQLite.
On startup, syncs user notes, follow feed (24h), mentions (7d), and
profile/contacts from remote relays into the local relay. Uses since
timestamp for incremental syncs. Toggle in Settings with event count
and DB size display. Add webkit2gtk GPU acceleration workaround and
connectToRelays safety timeout for NDK hang.
2026-04-01 12:10:11 +02:00