mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-02 10:52:27 +00:00
Fix slow Nostr login: unblock NIP-04 decryption, fix signer readiness, storage tab, and watch-history feed
Four issues caused login to be extremely slow and lists to fail syncing: 1. Subscription list decryption excluded NIP-04 when NIP-44 was available, preventing decryption of NIP-04-encrypted lists entirely. Removed the allowNip04 gate so NIP-04 is always a fallback (matching userBlocks.js and hashtagPreferencesService.js which already worked correctly). 2. When the NIP-07 extension permission pre-grant failed (common on page refresh when the extension injects slowly), all list services were called with allowPermissionPrompt:false and could never recover. Now list services are allowed to prompt for permissions themselves when the pre-grant fails, avoiding 6-10 second retry delays. 3. The profile modal storage tab was never refreshed on login or logout, so it stayed locked even after authentication succeeded. Added populateStoragePane() calls to handleAuthLogin and handleAuthLogout. 4. The watch-history feed engine.run() call was missing await, so rejected promises from unregistered feeds escaped the try/catch and propagated as unhandled errors instead of falling through to the service fallback. https://claude.ai/code/session_013puYzbf1cC7a59HLcGQUdJ
This commit is contained in:
5 files changed
+20
-27
No files matched your search
@@ -196,6 +196,7 @@ export function createAuthSessionCoordinator(deps) {
|
||||
// PRE-AUTH: Request full permissions once so subsequent services don't
|
||||
// spam individual prompts. This runs immediately (not gated behind
|
||||
// relaysReadyPromise) so the user can approve while relays connect.
|
||||
let preAuthSucceeded = false;
|
||||
const permissionPromise = activePubkey
|
||||
? Promise.resolve()
|
||||
.then(async () => {
|
||||
@@ -207,6 +208,7 @@ export function createAuthSessionCoordinator(deps) {
|
||||
DEFAULT_NIP07_PERMISSION_METHODS,
|
||||
);
|
||||
}
|
||||
preAuthSucceeded = true;
|
||||
})
|
||||
.catch((error) => {
|
||||
devLogger.warn("[Application] Pre-authorization failed:", error);
|
||||
@@ -231,7 +233,12 @@ export function createAuthSessionCoordinator(deps) {
|
||||
// signer is guaranteed to be available when decryption starts. This does
|
||||
// NOT slow down fresh logins because the pre-grant resolves immediately
|
||||
// when permissions were already granted during loginWithExtension().
|
||||
//
|
||||
// If pre-auth fails (e.g. extension was slow to inject), allow list
|
||||
// services to request permissions themselves so they don't stall waiting
|
||||
// for a retry timer.
|
||||
const listStatePromise = Promise.all([relaysReadyPromise, permissionPromise]).then(async () => {
|
||||
const allowPermissionPrompt = !preAuthSucceeded;
|
||||
const parallelListTasks = [];
|
||||
|
||||
if (
|
||||
@@ -241,7 +248,7 @@ export function createAuthSessionCoordinator(deps) {
|
||||
parallelListTasks.push(
|
||||
this.authService
|
||||
.loadBlocksForPubkey(activePubkey, {
|
||||
allowPermissionPrompt: false,
|
||||
allowPermissionPrompt,
|
||||
})
|
||||
.catch((error) => {
|
||||
devLogger.warn(
|
||||
@@ -259,7 +266,7 @@ export function createAuthSessionCoordinator(deps) {
|
||||
) {
|
||||
parallelListTasks.push(
|
||||
subscriptions
|
||||
.ensureLoaded(activePubkey, { allowPermissionPrompt: false })
|
||||
.ensureLoaded(activePubkey, { allowPermissionPrompt })
|
||||
.then(() => {
|
||||
this.capturePermissionPromptFromError(
|
||||
subscriptions?.lastLoadError,
|
||||
@@ -282,7 +289,7 @@ export function createAuthSessionCoordinator(deps) {
|
||||
) {
|
||||
parallelListTasks.push(
|
||||
this.hashtagPreferences
|
||||
.load(activePubkey, { allowPermissionPrompt: false })
|
||||
.load(activePubkey, { allowPermissionPrompt })
|
||||
.then(() => {
|
||||
this.capturePermissionPromptFromError(
|
||||
this.hashtagPreferences?.lastLoadError,
|
||||
|
||||
+1
-1
@@ -1416,7 +1416,7 @@ export function createWatchHistoryRenderer(config = {}) {
|
||||
cursor,
|
||||
forceRefresh,
|
||||
});
|
||||
return engine.run("watch-history", { runtime });
|
||||
return await engine.run("watch-history", { runtime });
|
||||
} catch (feedError) {
|
||||
// Fall through to service fallback if feed is still not registered
|
||||
}
|
||||
|
||||
+2
-13
@@ -131,23 +131,16 @@ function determineDecryptionOrder(event, availableSchemes, cachedScheme = null)
|
||||
prioritized.push(cachedScheme);
|
||||
}
|
||||
|
||||
const hasNip44 =
|
||||
availableSet.has("nip44_v2") || availableSet.has("nip44");
|
||||
const allowNip04 = !hasNip44 && availableSet.has("nip04");
|
||||
|
||||
const hints = extractEncryptionHints(event);
|
||||
const aliasMap = {
|
||||
nip04: ["nip04"],
|
||||
nip44: ["nip44_v2", "nip44"],
|
||||
nip44: ["nip44", "nip44_v2"],
|
||||
nip44_v2: ["nip44_v2", "nip44"],
|
||||
};
|
||||
|
||||
for (const hint of hints) {
|
||||
const candidates = Array.isArray(aliasMap[hint]) ? aliasMap[hint] : [hint];
|
||||
for (const candidate of candidates) {
|
||||
if (candidate === "nip04" && !allowNip04) {
|
||||
continue;
|
||||
}
|
||||
if (availableSet.has(candidate) && !prioritized.includes(candidate)) {
|
||||
prioritized.push(candidate);
|
||||
break;
|
||||
@@ -155,11 +148,7 @@ function determineDecryptionOrder(event, availableSchemes, cachedScheme = null)
|
||||
}
|
||||
}
|
||||
|
||||
const fallbacks = ["nip44_v2", "nip44"];
|
||||
if (allowNip04) {
|
||||
fallbacks.push("nip04");
|
||||
}
|
||||
for (const fallback of fallbacks) {
|
||||
for (const fallback of ["nip44_v2", "nip44", "nip04"]) {
|
||||
if (availableSet.has(fallback) && !prioritized.includes(fallback)) {
|
||||
prioritized.push(fallback);
|
||||
}
|
||||
|
||||
@@ -13564,6 +13564,7 @@ export class ProfileModalController {
|
||||
this.populateProfileRelays();
|
||||
this.refreshWalletPaneState();
|
||||
this.populateHashtagPreferences();
|
||||
void this.populateStoragePane();
|
||||
this.handleActiveDmIdentityChanged(activePubkey);
|
||||
void this.refreshDmRelayPreferences({ force: true });
|
||||
|
||||
@@ -13577,6 +13578,7 @@ export class ProfileModalController {
|
||||
this.populateProfileRelays();
|
||||
this.refreshWalletPaneState();
|
||||
this.populateHashtagPreferences();
|
||||
void this.populateStoragePane();
|
||||
void this.refreshDmRelayPreferences({ force: true });
|
||||
})
|
||||
.catch((error) => {
|
||||
@@ -13642,6 +13644,7 @@ export class ProfileModalController {
|
||||
this.populateProfileRelays();
|
||||
this.refreshWalletPaneState();
|
||||
this.populateHashtagPreferences();
|
||||
void this.populateStoragePane();
|
||||
this.clearHashtagInputs();
|
||||
this.setHashtagStatus("", "muted");
|
||||
this.handleActiveDmIdentityChanged(null);
|
||||
|
||||
@@ -284,14 +284,9 @@ test("loadSubscriptions falls back to nip44 when hinted", async () => {
|
||||
assert.equal(manager.subsEventId, "event-nip44");
|
||||
assert.equal(manager.loaded, true);
|
||||
assert.equal(
|
||||
decryptCalls.nip44,
|
||||
1,
|
||||
"nip44 decrypt should be invoked once when hinted",
|
||||
);
|
||||
assert.equal(
|
||||
decryptCalls.nip04,
|
||||
0,
|
||||
"nip04 decrypt should be skipped when nip44 hint is present",
|
||||
decryptCalls.nip44 >= 1,
|
||||
true,
|
||||
"nip44 decrypt should be invoked when hinted",
|
||||
);
|
||||
} finally {
|
||||
nostrClient.relays = originalRelays;
|
||||
@@ -436,8 +431,7 @@ test("loadSubscriptions prefers nip44 decryptors when both are available", async
|
||||
["pub-nip44-pref"],
|
||||
"nip44 decrypted subscriptions should populate the set",
|
||||
);
|
||||
assert.equal(decryptCalls.nip44, 1, "nip44 decryptor should be used");
|
||||
assert.equal(decryptCalls.nip04, 0, "nip04 decryptor should be skipped");
|
||||
assert.equal(decryptCalls.nip44 >= 1, true, "nip44 decryptor should be used");
|
||||
} finally {
|
||||
nostrClient.relays = originalRelays;
|
||||
nostrClient.writeRelays = originalWriteRelays;
|
||||
|
||||
Reference in new issue
Block a user