diff --git a/js/nostr/client.js b/js/nostr/client.js index 3d2bb550..8df98750 100644 --- a/js/nostr/client.js +++ b/js/nostr/client.js @@ -161,6 +161,7 @@ import { summarizeRpcResultForLog, summarizeRelayPublishResultsForLog, } from "./nip46Client.js"; +import { profileCache } from "../state/profileCache.js"; let activeSigner = null; const activeSignerRegistry = new Map(); @@ -278,6 +279,7 @@ function setActiveSigner(signer) { : ""; if (pubkey) { activeSignerRegistry.set(pubkey, signer); + profileCache.clearSignerRuntime(pubkey); } } @@ -3432,15 +3434,18 @@ export class NostrClient { } getSyncLastSeen(kind, pubkey, dTag, relayUrl) { - return this.syncMetadataStore.getLastSeen(kind, pubkey, dTag, relayUrl); + const effectivePubkey = pubkey || this.pubkey; + return this.syncMetadataStore.getLastSeen(kind, effectivePubkey, dTag, relayUrl); } updateSyncLastSeen(kind, pubkey, dTag, relayUrl, createdAt) { - this.syncMetadataStore.updateLastSeen(kind, pubkey, dTag, relayUrl, createdAt); + const effectivePubkey = pubkey || this.pubkey; + this.syncMetadataStore.updateLastSeen(kind, effectivePubkey, dTag, relayUrl, createdAt); } getPerRelaySyncLastSeen(kind, pubkey, dTag) { - return this.syncMetadataStore.getPerRelayLastSeen(kind, pubkey, dTag); + const effectivePubkey = pubkey || this.pubkey; + return this.syncMetadataStore.getPerRelayLastSeen(kind, effectivePubkey, dTag); } async fetchListIncrementally({ kind, pubkey, dTag, relayUrls, fetchFn } = {}) { diff --git a/js/nostr/watchHistory.js b/js/nostr/watchHistory.js index 0a5ce49f..c4c35968 100644 --- a/js/nostr/watchHistory.js +++ b/js/nostr/watchHistory.js @@ -955,6 +955,21 @@ class WatchHistoryManager { this.cacheTtlMs = 0; this.fingerprints = new Map(); this.lastCreatedAt = 0; + + profileCache.subscribe((event, detail) => { + if (event === "profileChanged") { + this.clear(); + } else if (event === "runtimeCleared") { + const activePubkey = typeof this.deps.getActivePubkey === "function" + ? this.deps.getActivePubkey() + : ""; + const normalized = normalizeActorKey(detail.pubkey); + const active = normalizeActorKey(activePubkey); + if (normalized && active && normalized === active) { + this.cache.delete(normalized); + } + } + }); } getCacheTtlMs() { diff --git a/js/services/hashtagPreferencesService.js b/js/services/hashtagPreferencesService.js index f4b46bc6..4b0dc22f 100644 --- a/js/services/hashtagPreferencesService.js +++ b/js/services/hashtagPreferencesService.js @@ -249,6 +249,11 @@ class HashtagPreferencesService { profileCache.subscribe((event, detail) => { if (event === "profileChanged") { this.reset(); + } else if (event === "runtimeCleared" && detail.pubkey === this.activePubkey) { + this.reset(); + if (this.activePubkey) { + this.load(this.activePubkey); + } } }); } diff --git a/js/state/profileCache.js b/js/state/profileCache.js index bc07fd38..a54bd62f 100644 --- a/js/state/profileCache.js +++ b/js/state/profileCache.js @@ -168,6 +168,7 @@ class ProfileCache { // But if services manage runtime state, `profileCache` acts as the persistence layer. this.emit("update", { pubkey, section, data }); + this.emit("partition-updated", { pubkey, key: section }); } // Runtime memory cache methods (for decrypted data, if services want to use it) @@ -197,6 +198,15 @@ class ProfileCache { } } + clearSignerRuntime(pubkey) { + const normalized = this.normalizeHexPubkey(pubkey); + if (!normalized) { + return; + } + this.clearMemoryCache(normalized); + this.emit("runtimeCleared", { pubkey: normalized }); + } + subscribe(callback) { this.listeners.add(callback); return () => this.listeners.delete(callback); diff --git a/js/subscriptions.js b/js/subscriptions.js index 59f923ef..9f22cbe8 100644 --- a/js/subscriptions.js +++ b/js/subscriptions.js @@ -246,6 +246,11 @@ class SubscriptionsManager { this.reset(); // Optionally reload immediately if we have a pubkey? // Usually UI triggers reload via showSubscriptionVideos + } else if (event === "runtimeCleared" && detail.pubkey === this.currentUserPubkey) { + this.reset(); + if (this.currentUserPubkey) { + this.loadSubscriptions(this.currentUserPubkey); + } } }); } diff --git a/js/userBlocks.js b/js/userBlocks.js index d67f249b..1b156db4 100644 --- a/js/userBlocks.js +++ b/js/userBlocks.js @@ -633,6 +633,11 @@ class UserBlockListManager { profileCache.subscribe((event, detail) => { if (event === "profileChanged") { this.reset(); + } else if (event === "runtimeCleared" && detail.pubkey === this.activePubkey) { + this.reset(); + if (this.activePubkey) { + this.loadBlocks(this.activePubkey); + } } }); } @@ -678,6 +683,8 @@ class UserBlockListManager { async loadBlocks(userPubkey, options = {}) { const normalized = normalizeHex(userPubkey); + this.activePubkey = normalized; + if (!normalized) { this.reset(); this.loaded = true;