diff --git a/js/app.js b/js/app.js index 6858bec8..150e18c2 100644 --- a/js/app.js +++ b/js/app.js @@ -3272,17 +3272,25 @@ class Application { ); } - try { - await this.nostrService.loadDirectMessages({ - actorPubkey: activePubkey, - limit: 50, - initialLoad: true, - }); - } catch (error) { - devLogger.warn( - "[Application] Failed to sync direct messages during login:", - error, - ); + const activePubkey = + this.normalizeHexPubkey(getActiveProfilePubkey()) || this.pubkey; + if ( + activePubkey && + this.nostrService && + typeof this.nostrService.loadDirectMessages === "function" + ) { + this.nostrService + .loadDirectMessages({ + actorPubkey: activePubkey, + limit: 50, + initialLoad: true, + }) + .catch((error) => { + devLogger.warn( + "[Application] Failed to sync direct messages during login:", + error, + ); + }); } } @@ -4263,13 +4271,6 @@ class Application { devLogger.error("Post-login hydration failed:", error); }); - let postLoginResult = null; - try { - postLoginResult = await postLoginPromise; - } catch (error) { - devLogger.error("Post-login processing failed:", error); - } - await nwcPromise; // We do not await hashtagPreferencesPromise here; it loads in the background. @@ -4282,6 +4283,26 @@ class Application { ); } + const scheduleLoginRefresh = (reason) => { + try { + this.lastIdentityRefreshPromise = this.refreshAllVideoGrids({ + reason, + forceMainReload: true, + }); + return this.lastIdentityRefreshPromise; + } catch (error) { + devLogger.error("Failed to refresh video grids after login:", error); + this.lastIdentityRefreshPromise = null; + return null; + } + }; + + try { + this.reinitializeVideoListView({ reason: "login" }); + } catch (error) { + devLogger.warn("Failed to reinitialize video list view after login:", error); + } + if (activePubkey) { const aggregatedBlacklist = accessControl.getBlacklist(); @@ -4314,16 +4335,40 @@ class Application { // 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) + setTimeout(() => resolve({ timedOut: true }), 2000) ); - try { - await Promise.race([blockLoadPromise, blockLoadTimeout]); - } catch (error) { - devLogger.warn( - "[Application] Block list load timed out or failed:", - error - ); - } + + Promise.race([ + blockLoadPromise + .then(() => ({ timedOut: false })) + .catch((error) => ({ error })), + blockLoadTimeout, + ]) + .then((result) => { + if (result?.error) { + devLogger.warn( + "[Application] Block list load timed out or failed:", + result.error + ); + } else if (result?.timedOut) { + devLogger.warn( + "[Application] Block list load timed out:", + result + ); + } + const refreshPromise = scheduleLoginRefresh("auth-login"); + if (refreshPromise && typeof refreshPromise.finally === "function") { + refreshPromise.finally(() => { + this.lastIdentityRefreshPromise = null; + }); + } else { + this.lastIdentityRefreshPromise = null; + } + }) + .catch((error) => { + devLogger.error("Failed to refresh video grids after login:", error); + this.lastIdentityRefreshPromise = null; + }); // Load subscriptions in the background to avoid blocking the main feed. subscriptions.ensureLoaded(activePubkey).catch((error) => { @@ -4332,24 +4377,33 @@ class Application { error ); }); - } - try { - this.reinitializeVideoListView({ reason: "login", postLoginResult }); - } catch (error) { - devLogger.warn("Failed to reinitialize video list view after login:", error); - } - - try { - this.lastIdentityRefreshPromise = this.refreshAllVideoGrids({ - reason: "auth-login", - forceMainReload: true, - }); - await this.lastIdentityRefreshPromise; - } catch (error) { - devLogger.error("Failed to refresh video grids after login:", error); - } finally { - this.lastIdentityRefreshPromise = null; + if ( + this.nostrService && + typeof this.nostrService.loadDirectMessages === "function" + ) { + this.nostrService + .loadDirectMessages({ + actorPubkey: activePubkey, + limit: 50, + initialLoad: true, + }) + .catch((error) => { + devLogger.warn( + "[Application] Failed to sync direct messages during login:", + error + ); + }); + } + } else { + const refreshPromise = scheduleLoginRefresh("auth-login"); + if (refreshPromise && typeof refreshPromise.finally === "function") { + refreshPromise.finally(() => { + this.lastIdentityRefreshPromise = null; + }); + } else { + this.lastIdentityRefreshPromise = null; + } } this.forceRefreshAllProfiles(); diff --git a/js/ui/profileModalController.js b/js/ui/profileModalController.js index 505da8f5..1990ffe2 100644 --- a/js/ui/profileModalController.js +++ b/js/ui/profileModalController.js @@ -8111,7 +8111,13 @@ export class ProfileModalController { this.blockList.innerHTML = ""; + const blocksLoaded = this.services.userBlocks?.loaded === true; if (!deduped.length) { + if (this.blockListLoadingState === "loading" && !blocksLoaded) { + this.blockListEmpty.classList.add("hidden"); + this.blockList.classList.add("hidden"); + return; + } this.blockListEmpty.classList.remove("hidden"); this.blockList.classList.add("hidden"); if (this.blockListLoadingState === "loading") { @@ -8319,7 +8325,13 @@ export class ProfileModalController { this.subscriptionList.innerHTML = ""; + const subscriptionsLoaded = service.loaded === true; if (!deduped.length) { + if (this.subscriptionsLoadingState === "loading" && !subscriptionsLoaded) { + this.subscriptionListEmpty.classList.add("hidden"); + this.subscriptionList.classList.add("hidden"); + return; + } this.subscriptionListEmpty.classList.remove("hidden"); this.subscriptionList.classList.add("hidden"); if (this.subscriptionsLoadingState === "loading") { @@ -12939,6 +12951,8 @@ export class ProfileModalController { // Trigger aggressive parallel fetches if (activePubkey) { + this.setBlockListLoadingState("loading"); + this.setSubscriptionsLoadingState("loading"); if (this.services.userBlocks) { this.services.userBlocks.loadBlocks(activePubkey).catch(noop); } @@ -13004,6 +13018,8 @@ export class ProfileModalController { this.profileSwitcherSelectionPubkey = null; this.renderSavedProfiles(); + this.setBlockListLoadingState("idle"); + this.setSubscriptionsLoadingState("idle"); try { await this.refreshAdminPaneState();