- Remove undefined hashtagPreferencesPromise reference in handleAuthLogin
that caused the feed sync Promise.allSettled to silently fail, preventing
proper list/profile synchronization before grid refresh
- Add missing getModerationSettings and getActiveProfilePubkey dependency
injection to authSessionCoordinator, fixing crashes during logout
moderation reset and profile switch pubkey resolution
- Parallelize NIP-07 permission request with relay readiness instead of
gating list loading behind it; parallelize subscriptions and hashtag
preference loading (independent of each other, only blocks must sequence)
- Add native run() alias to feedEngine so callers don't rely solely on
the applicationBootstrap compatibility shim
- Remove redundant refreshVisibleModerationUi call from renderVideoList
that re-decorated every video immediately after decoration
- Avoid re-normalizing moderation settings on every getActiveModerationThresholds
call when settings are already an object
https://claude.ai/code/session_01FCosieUXjEn95KtUeyGemY
Move cohesive method groups out of the monolithic Application class
(js/app.js, ~10K lines) into five coordinator modules under js/app/:
- feedCoordinator: feed registration, runtime building, refresh,
video loading, URL-health helpers, and feed telemetry
- playbackCoordinator: URL-first + magnet fallback pipeline, probing,
torrent status intervals, and video timestamp resolution
- authSessionCoordinator: signer lifecycle, profile switching,
relay/block/wallet management, and cleanup
- modalCoordinator: modal open/close, view-count subscriptions,
watch-history metadata, and playback logging
- moderationCoordinator: moderation settings, video decoration,
override/block/hide action routing
Each coordinator factory receives injected dependencies instead of
importing globals. Application retains thin delegator methods so all
public call-sites remain unchanged. Coordinator initialisation is
idempotent (via _initCoordinators) and supports both constructor-based
and Object.create()-based instantiation used by test harnesses.
All existing unit tests, lint checks, and syntax validation pass.
https://claude.ai/code/session_01C3PKJTCdavsGbk5jjC85EB
The user's block/mute list (NIP-51) was not being checked when
processing direct messages, allowing blocked users' messages to appear
in conversations, trigger notifications, and increment unseen counts.
This adds block filtering at four layers:
- nostrService.applyDirectMessage: drops incoming DMs from blocked users
before they enter the in-memory message cache
- nostrService.persistDirectMessageRecord: prevents blocked DM senders
from being persisted to IndexedDB or triggering notifications
- profileModalController.buildDmConversationData: filters blocked users
from the conversation list UI (catches pre-block persisted messages)
- applicationBootstrap: excludes blocked-user conversations from the
unread DM badge count
The block checker is injected via setDmBlockChecker() to keep
nostrService decoupled from userBlocks, wired up in app.js init().
https://claude.ai/code/session_01EAVLtAM14GN99Eik8otLg2
The login-to-feed pipeline had several issues causing lists (blocks,
subscriptions, hashtag preferences) to load too slowly or not reflect
in the feed:
1. All list loading was chained after profileStatePromise, adding
2.5-6s of unnecessary delay. Lists only need relay URLs, not profile
data. Now they chain off relaysReadyPromise instead, loading in
parallel with profile fetching.
2. The video grid refreshed immediately without waiting for any lists,
so the feed briefly displayed unfiltered content. Now the grid refresh
waits (up to 8s) for critical feed-filtering lists to settle.
3. Hashtag preferences weren't cached into the snapshot before the feed
rendered, so interests/disinterests were empty on first paint.
4. Subscription ensureLoaded had a 6s timeout that was too aggressive
for relay fetch (12s) + decryption (3-12s), causing silent failures.
Increased to 30s.
5. Subscription relay fetches for user and session actor ran sequentially.
Now they run in parallel via Promise.all.
https://claude.ai/code/session_01UKmTWb83AnQPRVQo3bKZqm
* Update `refreshAllVideoGrids` in `js/app.js` to detect the currently active feed (For You, Kids, Explore, or Recent) and invoke the corresponding loader, preventing staleness when interacting with the UI.
* Refactor `HashtagPreferencesService` mutation methods (`addInterest`, etc.) to be `async` and await the `publish()` call, ensuring state is persisted before returning.
* Remove redundant `persistPreferencesFromMenu` call in `TagPreferenceMenuController`, relying on the service's internal persistence logic.
* Update unit tests for `HashtagPreferencesService` and `TagPreferenceMenuController` to align with the async behavior.
Co-authored-by: PR0M3TH3AN <[email protected]>
Preload watch history in `refreshForYouFeed` to ensure `watchHistoryService` has the latest data.
Update `buildForYouFeedRuntime` to include a `watchHistory` suppression hook that checks against preloaded watch history items.
Register `createWatchHistorySuppressionStage` in the "for-you" feed pipeline to filter out watched videos.
Co-authored-by: PR0M3TH3AN <[email protected]>
- Moved `showError`, `showStatus`, `showSuccess`, and `updateNotificationPortalVisibility` logic to `js/ui/notificationController.js`.
- Instantiated `NotificationController` in `js/ui/applicationBootstrap.js`.
- Refactored `js/app.js` to delegate notification calls to the controller.
- Added unit tests for `NotificationController`.
- Followed AGENTS.md refactoring checklist.
Co-authored-by: PR0M3TH3AN <[email protected]>
Moves `handleAddProfile` logic from the main application class into `ProfileModalController` to improve separation of concerns as per `AGENTS.md`.
- Extracts `handleAddProfile` to `js/ui/profileModalController.js`.
- Updates `ProfileModalController` to handle add account flow internally.
- Removes legacy callback wiring from `js/app.js` and `js/ui/applicationBootstrap.js`.
- Adds unit tests for the extracted logic in `tests/ui/profileModalController-addProfile.test.mjs`.
Co-authored-by: PR0M3TH3AN <[email protected]>
- Reduced decryption timeout for user lists from 90s to 15s to fail faster.
- Optimized NIP-07 decryption calls to avoid retries and long timeouts during critical loading paths.
- Fixed a bug where `loginWithExtension` triggered `getPublicKey` twice, doubling the user interaction time.
- Added a 10s grace period for relay health warnings to prevent false positives on startup.
- Verified `deferBlocks` logic in `authService` prevents blocking the login UI on slow list decryption.
Co-authored-by: PR0M3TH3AN <[email protected]>
Prior to this change, user-specific lists (block lists, subscriptions, hashtag preferences, DMs, NWC settings) were fetched concurrently with the profile/relay initialization in `handleAuthLogin`. This caused a race condition where the application would attempt to fetch sensitive user data using default relays instead of the user's preferred relays, often resulting in empty or stale data.
This patch refactors `handleAuthLogin` in `js/app.js` to chain the loading of these lists to the completion of `profileStatePromise` (which ensures relays are loaded via `postLoginPromise`). This guarantees that the correct relays are used for fetching user-specific data.
Also defines `dmStatePromise`, `nwcPromise` and `hashtagPreferencesPromise` which were previously referenced but seemingly undefined in the scope, ensuring proper promise tracking.
Co-authored-by: PR0M3TH3AN <[email protected]>
Prioritizes fetching the user's relay list (NIP-65) immediately after login, ensuring that subsequent data fetches (profile, contact list, DMs, feed) utilize the user's preferred relays instead of default ones. This prevents "slow" or incomplete data loading issues caused by relying on defaults.
- Refactored `authService.applyPostLoginState` to sequence relay loading before profile/block loading.
- Refactored `app.handleAuthLogin` to await relay loading before initiating dependent fetches (Hashtags, Moderation, DMs, NWC, Lists, Feed).
- Updated unit tests in `tests/auth-service.test.mjs` to verify sequential execution and correct return values.
Co-authored-by: PR0M3TH3AN <[email protected]>
- Added `scripts/agent/smoke-test.mjs` which performs an end-to-e2e smoke test using a local relay, Node.js client, and headless Playwright browser.
- Fixed a bug in `js/app.js` where `activeProfilePubkey` and `savedProfiles` getters were missing, preventing auto-login and session restoration.
- The smoke test verifies:
- Login flow (using ephemeral keys and localStorage injection).
- Relay connection (using a local test relay).
- Publish and Receive flow (Video Post).
- DM Encryption/Decryption flow (Node.js client).
Co-authored-by: PR0M3TH3AN <[email protected]>
Optimizes `handleAuthLogin` in `js/app.js` to run user data fetching (blocks, subscriptions, hashtag preferences) in the background instead of blocking the main UI render. This significantly improves perceived login speed, especially for users with large lists or slow NIP-07 extensions.
- Moves `userBlocks.seedWithNpubs` (which involves publishing) to background.
- Moves `subscriptions.ensureLoaded` and `hashtagPreferences.load` (which involve decryption) to background.
- Adds a race condition for `userBlocks.ensureLoaded` (read-only) with a short timeout to attempt early hydration without blocking indefinitely.
- Ensures the UI updates reactively when background data arrives via existing event listeners.
Co-authored-by: PR0M3TH3AN <[email protected]>
* Boost DM decryption priority to HIGH in `nostrClient` to match other critical user data.
* Enforce blocking in `handleAuthLogin` to await initial DM sync before refreshing the main video feed.
* This ensures users see their personal data (blocks, messages) correctly loaded before the public feed appears, improving the perception of consistency.
Co-authored-by: PR0M3TH3AN <[email protected]>
Prioritize fetching of block lists, subscriptions, and other user data before loading the main video feed during login.
- In `handleAuthLogin`, stop the existing video feed subscription immediately to free up bandwidth.
- Explicitly await `subscriptions.ensureLoaded(activePubkey)` alongside `userBlocks.seedWithNpubs` before triggering `refreshAllVideoGrids`.
This ensures user context is fully loaded before the heavy feed sync starts, addressing slow sync issues especially with NIP-07.
Co-authored-by: PR0M3TH3AN <[email protected]>
This change ensures that cloud storage credentials are not leaked between Nostr profiles when switching accounts in the UI.
Changes:
- Imported `storageService` in `js/app.js` to enable the `bitvid:auth-changed` event listener to correctly lock the previous profile's storage session.
- Updated `ProfileModalController.populateStoragePane` to explicitly clear the storage form before loading new data.
- Enhanced `ProfileModalController.handleClearStorage` to fully reset the form state, including the provider selection and visibility toggles.
Verified with a reproduction script (`reproduce_storage_isolation.mjs`) that `StorageService` correctly isolates data by pubkey at the backend level. The UI fixes address the frontend persistence issue.