mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-02 19:02:28 +00:00
Fix profile modal opening latency by deferring expensive UI updates
The profile modal was slow to open (~100ms+ delay) when a user has many trusted contacts, blocked users, or moderation reports, because `refreshModerationSettingsUi` and `populateBlockedList` were called synchronously before making the modal visible. This change refactors `ProfileModalController.show()` to: 1. Render the header synchronously (fast). 2. Call `open()` immediately to make the modal visible. 3. Defer expensive data population (`refreshModerationSettingsUi`, `populateBlockedList`, `refreshWalletPaneState`) to the next animation frame using `requestAnimationFrame`. This significantly improves the perceived responsiveness of the profile button. Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
1 parent
8b9ef3858d
commit
bc51f21c0d
3 files changed
+263
-337
No files matched your search
@@ -12450,91 +12450,99 @@ export class ProfileModalController {
|
||||
this.previouslyFocusedElement = activeElement;
|
||||
}
|
||||
|
||||
// Render the header (saved profiles) synchronously so the modal doesn't look empty.
|
||||
// This is generally fast as it only touches the top section.
|
||||
this.renderSavedProfiles();
|
||||
this.refreshWalletPaneState();
|
||||
this.refreshModerationSettingsUi();
|
||||
this.syncLinkPreviewSettingsUi();
|
||||
|
||||
// Show the modal immediately to prevent UI lag.
|
||||
this.open(pane);
|
||||
|
||||
const hasBlockHydrator =
|
||||
this.services.userBlocks &&
|
||||
typeof this.services.userBlocks.ensureLoaded === "function";
|
||||
|
||||
if (hasBlockHydrator) {
|
||||
this.setBlockListLoadingState("loading");
|
||||
} else {
|
||||
this.populateBlockedList();
|
||||
}
|
||||
|
||||
this.open(pane);
|
||||
// Defer expensive operations to the next animation frame to allow the modal to paint.
|
||||
requestAnimationFrame(() => {
|
||||
this.refreshWalletPaneState();
|
||||
this.refreshModerationSettingsUi();
|
||||
this.syncLinkPreviewSettingsUi();
|
||||
|
||||
const backgroundTasks = [];
|
||||
if (!hasBlockHydrator) {
|
||||
this.populateBlockedList();
|
||||
}
|
||||
|
||||
backgroundTasks.push(
|
||||
Promise.resolve()
|
||||
.then(() => this.refreshAdminPaneState())
|
||||
.catch((error) => {
|
||||
userLogger.error(
|
||||
"Failed to refresh admin pane while opening profile modal:",
|
||||
error,
|
||||
);
|
||||
}),
|
||||
);
|
||||
const backgroundTasks = [];
|
||||
|
||||
backgroundTasks.push(
|
||||
Promise.resolve().then(() => {
|
||||
try {
|
||||
this.populateProfileRelays();
|
||||
} catch (error) {
|
||||
userLogger.warn(
|
||||
"Failed to populate relay list while opening profile modal:",
|
||||
error,
|
||||
);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
if (hasBlockHydrator) {
|
||||
const activeHex = this.normalizeHexPubkey(this.getActivePubkey());
|
||||
backgroundTasks.push(
|
||||
Promise.resolve()
|
||||
.then(() => this.services.userBlocks.ensureLoaded(activeHex))
|
||||
.then(() => {
|
||||
try {
|
||||
this.populateBlockedList();
|
||||
} catch (error) {
|
||||
.then(() => this.refreshAdminPaneState())
|
||||
.catch((error) => {
|
||||
userLogger.error(
|
||||
"Failed to refresh admin pane while opening profile modal:",
|
||||
error,
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
backgroundTasks.push(
|
||||
Promise.resolve().then(() => {
|
||||
try {
|
||||
this.populateProfileRelays();
|
||||
} catch (error) {
|
||||
userLogger.warn(
|
||||
"Failed to populate relay list while opening profile modal:",
|
||||
error,
|
||||
);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
if (hasBlockHydrator) {
|
||||
const activeHex = this.normalizeHexPubkey(this.getActivePubkey());
|
||||
backgroundTasks.push(
|
||||
Promise.resolve()
|
||||
.then(() => this.services.userBlocks.ensureLoaded(activeHex))
|
||||
.then(() => {
|
||||
try {
|
||||
this.populateBlockedList();
|
||||
} catch (error) {
|
||||
userLogger.warn(
|
||||
"Failed to render blocked creators after hydration:",
|
||||
error,
|
||||
);
|
||||
this.setBlockListLoadingState("error", {
|
||||
message: "Blocked creators may be out of date. Try again later.",
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
userLogger.warn(
|
||||
"Failed to render blocked creators after hydration:",
|
||||
"Failed to refresh user block list while opening profile modal:",
|
||||
error,
|
||||
);
|
||||
this.setBlockListLoadingState("error", {
|
||||
message:
|
||||
"Blocked creators may be out of date. Try again later.",
|
||||
message: "Blocked creators may be out of date. Try again later.",
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
userLogger.warn(
|
||||
"Failed to refresh user block list while opening profile modal:",
|
||||
error,
|
||||
);
|
||||
this.setBlockListLoadingState("error", {
|
||||
message:
|
||||
"Blocked creators may be out of date. Try again later.",
|
||||
});
|
||||
try {
|
||||
this.populateBlockedList();
|
||||
} catch (populateError) {
|
||||
userLogger.warn(
|
||||
"Failed to render blocked creators after hydration failure:",
|
||||
populateError,
|
||||
);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
try {
|
||||
this.populateBlockedList();
|
||||
} catch (populateError) {
|
||||
userLogger.warn(
|
||||
"Failed to render blocked creators after hydration failure:",
|
||||
populateError,
|
||||
);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (backgroundTasks.length) {
|
||||
void Promise.allSettled(backgroundTasks);
|
||||
}
|
||||
if (backgroundTasks.length) {
|
||||
void Promise.allSettled(backgroundTasks);
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user