From 90a74e77211a318932d2a45762ff510734b9ca48 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 28 Jan 2026 18:02:37 +0000 Subject: [PATCH] fix(perf): parallelize user data loading during NIP-07 login 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 <53631862+PR0M3TH3AN@users.noreply.github.com> --- js/app.js | 76 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 27 deletions(-) diff --git a/js/app.js b/js/app.js index 296a6c11..6858bec8 100644 --- a/js/app.js +++ b/js/app.js @@ -4178,7 +4178,12 @@ class Application { const hashtagPreferencesPromise = Promise.resolve( this.loadHashtagPreferencesForPubkey(loginContext.pubkey), - ); + ).catch((error) => { + devLogger.warn( + "[Application] Background hashtag preferences load failed:", + error + ); + }); if (this.zapController) { try { @@ -4266,7 +4271,7 @@ class Application { } await nwcPromise; - await hashtagPreferencesPromise; + // We do not await hashtagPreferencesPromise here; it loads in the background. try { await accessControl.ensureReady(); @@ -4279,37 +4284,54 @@ class Application { if (activePubkey) { const aggregatedBlacklist = accessControl.getBlacklist(); - try { - await userBlocks.seedWithNpubs( - activePubkey, - Array.isArray(aggregatedBlacklist) ? aggregatedBlacklist : [], - ); - } catch (error) { - if ( - error?.code === "extension-permission-denied" || - error?.code === "nip04-missing" || - error?.name === "RelayPublishError" - ) { - userLogger.error( - "[Application] Failed to seed shared block list after login:", - error, - ); - } else { - devLogger.error( - "[Application] Unexpected error while seeding shared block list:", - error, - ); - } - } + // Background the seeding process because it involves publishing events, + // which can block the login flow significantly. + userBlocks + .seedWithNpubs( + activePubkey, + Array.isArray(aggregatedBlacklist) ? aggregatedBlacklist : [] + ) + .catch((error) => { + if ( + error?.code === "extension-permission-denied" || + error?.code === "nip04-missing" || + error?.name === "RelayPublishError" + ) { + userLogger.error( + "[Application] Failed to seed shared block list after login:", + error + ); + } else { + devLogger.error( + "[Application] Unexpected error while seeding shared block list:", + error + ); + } + }); + + // Attempt to load blocks with a short timeout so we don't block the UI forever. + // If it times out, the UI will refresh reactively when the data arrives. + const blockLoadPromise = userBlocks.ensureLoaded(activePubkey); + const blockLoadTimeout = new Promise((resolve) => + setTimeout(resolve, 2000) + ); try { - await subscriptions.ensureLoaded(activePubkey); + await Promise.race([blockLoadPromise, blockLoadTimeout]); } catch (error) { devLogger.warn( - "[Application] Failed to load subscriptions during login:", - error, + "[Application] Block list load timed out or failed:", + error ); } + + // Load subscriptions in the background to avoid blocking the main feed. + subscriptions.ensureLoaded(activePubkey).catch((error) => { + devLogger.warn( + "[Application] Failed to load subscriptions during login:", + error + ); + }); } try {