13 Commits

Author SHA1 Message Date
Laan Tungir
1a17bef1ac Implement Phase 1 remaining tasks: notifications append-only, listener leak fix, memory caps
Task 1.2: Append-only rendering for notifications page
- Extracted buildNotificationRow(item) helper from renderNotifications()
- Added prependNotificationRow(item) with sorted insertion by created_at
- addNotificationFromEvent uses prepend when DOM has children

Task 1.3: Fix notification document.click listener leak
- Removed per-row document.addEventListener('click') that leaked on every render
- Added single delegated click listener in main() using .notif-menu-panel class
- Menu panels still close when clicking outside .notif-right

Task 1.4: Cap posts[] and postIds with rolling eviction
- Added MAX_STORED_POSTS=500 constant to feed.html and post.html
- Added prunePostsArray() that sorts, slices, rebuilds postIds/renderedPostIds
- Called in upsertFeedPost/upsertPost with +50 batch threshold
- post.html skips pruning in event mode

Task 1.5: Cap notificationsById/unreadNotificationsById with periodic pruning
- Added MAX_STORED_NOTIFICATIONS=500, MAX_POST_IMAGE_CACHE=200
- Added pruneNotificationMaps() that prunes both Maps and LRU-caps postImageCache
- Called in addNotificationFromEvent, hydrateNotificationsFromCache/Relays

Updated plan checklist marking all Phase 1 tasks complete.
2026-07-01 09:33:29 -04:00
Laan Tungir
ee0077063d Implement append-only rendering for feed and post pages (task 1.1)
Split renderFeed() into full rebuild + prependPostCard() on both feed.html
and post.html. New live events now prepend a single card at the top of the
feed without rebuilding existing cards, eliminating O(n) DOM rebuilds on
every incoming event. DOM is trimmed to displayCount on overflow with
renderedPostIds kept in sync. Full rebuild path preserved for See More,
mute removal, bootstrap completion, and event mode.

Also added implementation checklist to plans/long-running-memory-bloat-fix.md.
2026-07-01 07:59:39 -04:00
Laan Tungir
0f31e1c301 Batched broadcast publishing: split 600+ relays into batches of 25, publish sequentially to avoid browser WebSocket connection limits. 10s per-relay timeout per batch. 2026-06-30 10:21:55 -04:00
Laan Tungir
10ddda633c Add broadcast relays feature: kind 10088 list with always-on union, persistent skip-marks, live progress in post.html footer, sidenav management UI on relays.html 2026-06-30 07:47:22 -04:00
Laan Tungir
ae67e65969 Mark Phases 1-4 as complete in feed-outbox-assessment.md, update summary table with status column 2026-06-26 09:44:56 -04:00
Laan Tungir
c758333269 Implement feed outbox model pre-warming (Phases 1-3) and relays.html connection history toggle with performance fixes (Phase 4)
Phase 1 (ndk-worker.js): Add warmOutbox, setRelayEventLogging, and getDiscoveredRelays RPC handlers. Gate broadcastRelayEvent and logRelayEvent IndexedDB writes behind relayEventLoggingEnabled flag (default off). trackRelayRead/trackRelayWrite left ungated to preserve footer activity carrots.

Phase 2 (init-ndk.mjs): Add warmOutbox, setRelayEventLogging, and getDiscoveredRelays page API exports with proper request/response wiring and timeouts.

Phase 3 (feed.html): Pre-warm outbox tracker via warmOutbox() before bootstrapFeedPosts and fetchFeedWindow calls so NDK routes author-based subscriptions to follows' write relays before short-lived fetchEvents EOSE.

Phase 4 (relays.html): Add 'Show connection history' sidenav toggle (sidenavRowToggle pattern from feed.html), gate ndkRelayEvent listener and DB loading behind connectionHistoryEnabled flag, switch live event stream to incremental DOM appending, sync state on init/beforeunload.
2026-06-26 09:38:31 -04:00
Laan Tungir
a42edcf6d6 Feed upgrade Phases 3-5: zap capability indicators, rail selector, balance checks
Phase 3 — Zap Capability Indicators:
- Added resolveZapCapabilities() to zaps.mjs with 5-min TTL cache
- Checks lud16 (from profile cache) for Lightning capability
- Checks kind 10019 (via walletFetchMintList) for nutzap capability
- Computes shared mints between sender and recipient
- Added capability badges (🥜/) to zap button in post-interactions.mjs
- Badges use var(--accent-color) for available, var(--muted-color) for unavailable
- Added proactive kind 10019 batch fetch for followed users in ndk-worker.js
- New IDB store ndk-nutzap-mintlists for persistent caching (6h TTL)
- Non-blocking: badges appear after async resolution

Phase 4 — Zap Rail Selector:
- Updated promptZapDetails with rail toggle (🥜 Nutzap /  Lightning)
- Shows Cashu balance and insufficient balance warning
- Shows shared mint info when nutzap selected
- Default rail: nutzap for <1000 sats, Lightning for >=1000 sats
- Updated handleZapClick to resolve capabilities and respect user's rail choice
- Added zap rail toggle CSS to client.css (all CSS variables)
- Wired walletGetBalance through post-interactions2.mjs and post-feed.html

Phase 5 — Balance Check and Error Handling:
- Pre-flight balance check before sending (hard stop if insufficient)
- Barely-sufficient balance confirmation dialog
- Friendly error messages for melt/swap/timeout/insufficient failures
- Post-zap balance refresh via ndkWalletBalance event

Review fix: threaded walletGetMints through post-interactions2.mjs and post-feed.html
so resolveZapCapabilities can compute shared mints correctly
2026-06-25 20:48:38 -04:00
Laan Tungir
c5f682c5fe Feed upgrade Phase 2.5: Threaded replies with vertical lines in post-feed.html
- Added computeReplyLevels() to compute reply depth from NIP-10 e tags
- Added buildDepthFirstOrder() for depth-first thread sorting (root first, children grouped by parent chronologically)
- Render vertical indent lines using CSS variables (var(--muted-color) for non-selected, var(--accent-color) for focused post)
- Added collapse/expand functionality with hidden reply count
- Added focused post highlight via ?focus=<eventId> URL param
- Real-time subscriptions preserved — new replies appear in correct threaded position
- All colors use CSS variables — no hardcoded colors
2026-06-25 19:53:36 -04:00
Laan Tungir
073fb9e9af Feed upgrade Phase 1 & 2: simplified feed2.html + post-feed.html thread page
Phase 1 (feed2.html):
- Removed inline comment rendering and Comments toggle button
- Comment button now opens post-feed.html?event=<eventId> in new tab
- Removed inline reply composer (kept quote composer)
- Fixed missing queryCache dependency in initPostCards
- Fixed hardcoded color:red -> var(--primary-color)

Phase 2 (post-feed.html):
- New post thread page showing post + all replies + inline composer
- Parses ?event=<hex|nevent|note> URL parameter
- Fetches replies via { kinds: [1], '#e': [postId] }
- Real-time subscriptions for new replies
- Comment button on replies opens sub-threads in new tabs
- Error states for missing/invalid/not-found posts
- All CSS uses variables, no hardcoded colors
2026-06-25 19:45:36 -04:00
Laan Tungir
7b77da7349 Fix NIP-60 kind 17375 content format: use tag-array instead of proprietary object
- Changed walletPayloadObj from {mints, nutzap} object to [['mint',url],['privkey',hex]] tag-array
- Removed non-standard pubkey tag from 17375 public tags (belongs on kind 10019)
- Added parseWalletContent() helper that reads both new tag-array and legacy object formats
- Added migrateLegacyWalletEventIfNeeded() for one-time auto-migration of old wallets
- Bumped WORKER_REVISION to nip60-tagarray-fix-1 to force SharedWorker restart
- Added wallet-page.md plan for unified wallet.html (Bitcoin, Cashu, NWC, CLINK)
2026-06-25 12:24:48 -04:00
Laan Tungir
eed00f67cf Migrate music playlists to Gruuv a-tag hydration and add optional lazy FRIENDS loading 2026-06-09 15:15:08 -04:00
Laan Tungir
0c9e8bebcb Implement document page chat binding, JSON editor flow, and resizable columns 2026-04-28 10:00:02 -04:00
Laan Tungir
a8bbbbafb9 rename to client 2026-04-17 16:52:51 -04:00