From 7eafe973d92c4f3889bb902cdc31ff59f0967244 Mon Sep 17 00:00:00 2001 From: alltheseas <64376233+alltheseas@users.noreply.github.com> Date: Mon, 17 Nov 2025 22:39:03 -0600 Subject: [PATCH] Ensure mention profiles render with display names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daniel D’Aquino Closes: https://github.com/damus-io/damus/issues/3331 Changelog-Fixed: Fix mention pills falling back to @npub text when profile metadata is missing Signed-off-by: alltheseas <64376233+alltheseas@users.noreply.github.com> --- .../NostrNetworkManager/ProfilesManager.swift | 4 ++ damus/Features/Events/NoteContentView.swift | 52 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/damus/Core/Networking/NostrNetworkManager/ProfilesManager.swift b/damus/Core/Networking/NostrNetworkManager/ProfilesManager.swift index 1b33988d..ff3ac3f1 100644 --- a/damus/Core/Networking/NostrNetworkManager/ProfilesManager.swift +++ b/damus/Core/Networking/NostrNetworkManager/ProfilesManager.swift @@ -101,6 +101,10 @@ extension NostrNetworkManager { relevantStream.continuation.yield(profile) } } + + // Notify the rest of the app so views that rely on rendered text (like mention strings) + // can reload and pick up the freshly fetched profile metadata. + notify(.profile_updated(.remote(pubkey: metadataEvent.pubkey))) } diff --git a/damus/Features/Events/NoteContentView.swift b/damus/Features/Events/NoteContentView.swift index 827718f7..73a7f23a 100644 --- a/damus/Features/Events/NoteContentView.swift +++ b/damus/Features/Events/NoteContentView.swift @@ -45,6 +45,7 @@ struct NoteContentView: View { let event: NostrEvent @State var blur_images: Bool @State var load_media: Bool = false + @State private var requestedMentionProfiles: Set = [] let size: EventViewKind let preview_height: CGFloat? let options: EventViewOptions @@ -273,10 +274,61 @@ struct NoteContentView: View { .padding(.horizontal) } + func ensureMentionProfilesAreFetchingIfNeeded() { + guard let blockGroup = try? NdbBlockGroup.from(event: event, using: damus_state.ndb, and: damus_state.keypair) else { + return + } + + var mentionPubkeys: Set = [] + let _: ()? = try? blockGroup.forEachBlock({ _, block in + switch block { + case .mention(let mentionBlock): + if let mention = MentionRef(block: mentionBlock), + let pubkey = mention.pubkey { + mentionPubkeys.insert(pubkey) + } + default: + break + } + return .loopContinue + }) + + guard !mentionPubkeys.isEmpty else { return } + + var toFetch: [Pubkey] = [] + for pubkey in mentionPubkeys { + if requestedMentionProfiles.contains(pubkey) { + continue + } + requestedMentionProfiles.insert(pubkey) + + if let txn = damus_state.ndb.lookup_profile(pubkey), + damus_state.profiles.has_fresh_profile(id: pubkey, txn: txn) { + continue + } + + toFetch.append(pubkey) + } + + guard !toFetch.isEmpty else { return } + + // Kick off metadata fetches for any missing mention profiles so their names can render once loaded. + for pubkey in toFetch { + Task { + for await _ in await damus_state.nostrNetwork.profilesManager.streamProfile(pubkey: pubkey) { + // NO-OP, we will receive the update via `notify` + break + } + } + } + } + func load(force_artifacts: Bool = false) { if case .loading = damus_state.events.get_cache_data(event.id).artifacts_model.state { return } + + ensureMentionProfilesAreFetchingIfNeeded() // always reload artifacts on load let plan = get_preload_plan(evcache: damus_state.events, ev: event, our_keypair: damus_state.keypair, settings: damus_state.settings)