-
Notifications
You must be signed in to change notification settings - Fork 297
Display longform article preview cards for naddr/nevent references #3497
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Display longform article preview cards for naddr/nevent references #3497
Conversation
Add first_longform_naddr_mention() function to detect kind 30023 naddr references in note content blocks. Create LongformNaddrMentionView and LongformNeventMentionView components that asynchronously load referenced longform articles and display them as LongformPreview cards. Falls back to abbreviated link on load failure. Signed-off-by: alltheseas <[email protected]>
Show LongformMentionView in EventShell (threaded/wide), SelectedEventView, ChatEventView, and DMView when a note contains naddr/nevent references to kind 30023 longform articles. Suppress inline @naddr/@Nevent text when preview cards are displayed to avoid showing both the abbreviated reference and the preview card. Note: In .no_mentions contexts where preview cards aren't rendered, the references won't be visible - same limitation as regular note mentions. Signed-off-by: alltheseas <[email protected]>
Show preview card when user pastes naddr or nevent referencing a longform article (kind 30023) in the compose view. Supports both naddr1... and nevent1... formats with real-time preview updates. Handles draft persistence by re-inserting extracted references before saving, so references aren't lost when dismissing and reopening. Prevents duplicates on send by removing any references that remain in text (user may have retyped an already-extracted reference). Includes whitespace trimming to avoid orphan blank lines. Signed-off-by: alltheseas <[email protected]>
Add all_longform_mentions() to detect all naddr/nevent references with kind 30023. Display multiple longform previews in a vertical stack for viewing notes, and horizontal carousel for composing notes. Viewing: LongformMentionsStack shows read-only vertical list Composing: LongformCarouselView with delete buttons, extracts all references from text and re-adds them when posting. Changelog-Added: Display multiple longform article previews in notes Closes: damus-io#2798 Signed-off-by: alltheseas <[email protected]>
Fixes: 84a2e3d ("Support multiple longform article mentions with vertical stack") Signed-off-by: William Casarin <[email protected]>
📝 WalkthroughWalkthroughThis pull request introduces a complete longform article mention and preview feature across the damus app. It adds infrastructure for detecting, extracting, and displaying longform references (naddr/nevent) as interactive preview cards, integrating these views into chat, direct messages, event displays, and the post composition interface. The implementation includes new data types, extraction utilities, and SwiftUI components. Changes
Sequence DiagramsequenceDiagram
actor User
participant PostView
participant Extraction as Extraction Utils
participant State as App State
participant NostrNet as Nostr Network
participant UI as LongformMentionView
User->>PostView: Enter text with naddr/nevent
PostView->>Extraction: extractAllLongformReferences(text)
Extraction-->>PostView: [LongformExtractionResult]
PostView->>State: Update longformReferences state
PostView->>UI: Render LongformCarouselView
rect rgb(200, 220, 240)
Note over UI: Async Loading Phase
UI->>NostrNet: lookup(naddr) or lookup(noteId)
NostrNet-->>UI: NostrEvent (article)
end
UI-->>User: Display preview (title, image, author)
User->>PostView: Send post
PostView->>Extraction: Remove naddr/nevent from text
PostView->>State: Re-insert as nostr:… strings
PostView->>NostrNet: Publish event with references
NostrNet-->>User: Post confirmed
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
Comment |
| func extractAndRemoveLongformReferences() { | ||
| let text = post.string | ||
| let extractions = extractAllLongformReferences(from: text) | ||
|
|
||
| // Filter out references we already have | ||
| let newExtractions = extractions.filter { extraction in | ||
| !longformReferences.contains(extraction.reference) | ||
| } | ||
|
|
||
| guard !newExtractions.isEmpty else { return } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
notes are already parsed in the note blocks data structure. you can just walk over that instead of doing parsing here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI Agents
In @damus/Core/Nostr/NostrEvent.swift:
- Around line 872-898: In all_longform_mentions (function all_longform_mentions)
the closure passed to blockGroup.reduce declares an unused parameter named
`index`; replace that parameter with `_` (i.e., change `(index, refs, block)` to
`(_, refs, block)`) so SwiftLint stops flagging the unused parameter and the
closure semantics remain unchanged.
In @damus/Features/Events/Models/NoteContent.swift:
- Around line 117-138: In NoteContent.swift update the closure passed to
blocks.reduce that computes has_longform_ref to avoid unused-parameter warnings:
replace the unused closure parameters `index` and `partialResult` with
underscores (e.g., use `_` placeholders) in the reduce closure signature so it
becomes `{ _, _, item in ... }`, leaving the body and logic (mentions,
MentionRef handling, nip19 checks and loopReturn/loopContinue) unchanged.
🧹 Nitpick comments (8)
damus/Features/Chat/ChatEventView.swift (1)
165-167: Consider performance optimization and pattern consistency.The
all_longform_mentionsfunction performs block parsing viaNdbBlockGroup.borrowBlockGroupand is called directly in the view body, meaning it executes on every view render. This differs from theMentionViewpattern above (lines 160-164), which usesif letto check for mentions before rendering.Consider these improvements:
- Check for empty results: Wrap the view in a conditional to avoid unnecessary rendering when no longform mentions exist.
- Cache the result: Store the result in a
@Stateor computed property that's only calculated once, rather than on every view update.Suggested refactor to match MentionView pattern
- LongformMentionsStack(damus_state: damus_state, references: all_longform_mentions(ndb: damus_state.ndb, ev: event, keypair: damus_state.keypair)) - .background(DamusColors.adaptableWhite) - .clipShape(RoundedRectangle(cornerSize: CGSize(width: 10, height: 10))) + let longform_refs = all_longform_mentions(ndb: damus_state.ndb, ev: event, keypair: damus_state.keypair) + if !longform_refs.isEmpty { + LongformMentionsStack(damus_state: damus_state, references: longform_refs) + .background(DamusColors.adaptableWhite) + .clipShape(RoundedRectangle(cornerSize: CGSize(width: 10, height: 10))) + }Alternatively, introduce a cached computed property similar to the
Mentionpattern used elsewhere in the file.damus/Features/DMs/Views/DMView.swift (1)
28-30: Match the Mention property pattern for consistency.The
LongformMentioncomputed property callsall_longform_mentionson every access without checking if the result is empty. This differs from theMentionproperty (lines 18-26), which returnsEmptyView()when no mentions exist.Additionally, SwiftUI may call computed properties multiple times per render cycle, and
all_longform_mentionsperforms potentially expensive block parsing viaNdbBlockGroup.borrowBlockGroup.Suggested refactor to match Mention pattern
var LongformMention: some View { - LongformMentionsStack(damus_state: damus_state, references: all_longform_mentions(ndb: damus_state.ndb, ev: event, keypair: damus_state.keypair)) + Group { + let references = all_longform_mentions(ndb: damus_state.ndb, ev: event, keypair: damus_state.keypair) + if !references.isEmpty { + LongformMentionsStack(damus_state: damus_state, references: references) + } else { + EmptyView() + } + } }This ensures consistent patterns across the file and avoids rendering when no longform mentions exist.
Also applies to: 76-76
damus/Features/Events/SelectedEventView.swift (2)
94-97: Match the Mention property pattern for consistency.The
LongformMentioncomputed property should follow the same pattern as theMentionproperty (lines 85-92), which uses aGroupwith a conditional check before rendering.Suggested refactor to match Mention pattern
var LongformMention: some View { - LongformMentionsStack(damus_state: damus, references: all_longform_mentions(ndb: damus.ndb, ev: event, keypair: damus.keypair)) - .padding(.horizontal) + Group { + let references = all_longform_mentions(ndb: damus.ndb, ev: event, keypair: damus.keypair) + if !references.isEmpty { + LongformMentionsStack(damus_state: damus, references: references) + .padding(.horizontal) + } + } }This ensures the view hierarchy is only created when longform mentions actually exist.
94-97: Consider extracting the repeated longform mention pattern.The same
all_longform_mentionscall andLongformMentionsStackrendering pattern appears in ChatEventView.swift (lines 165-167), DMView.swift (lines 28-30), and here. This code duplication could be reduced by:
- Creating a reusable computed property or helper on
NostrEventthat caches the longform mentions- Extracting a shared view component that encapsulates the check and rendering logic
This would improve maintainability and ensure consistent behavior across all three views.
damus/Features/Events/EventShell.swift (1)
46-52: Add a docstring for the new helper method.Per coding guidelines, docstring coverage should be ensured for new or modified code. Consider adding a brief doc comment explaining the purpose and return value.
+ /// Returns all longform article mentions (naddr/nevent with kind 30023) in the event content. + /// Returns an empty array if the event is nested or mentions are disabled. func get_longform_mentions(ndb: Ndb) -> [LongformReference] { if self.options.contains(.nested) || self.options.contains(.no_mentions) { return [] } return all_longform_mentions(ndb: ndb, ev: event, keypair: state.keypair) }damus/Features/Events/LongformNaddrMentionView.swift (1)
52-59: Consider reusingLongformReference.bech32instead of duplicating the encoding logic.The
LongformReferenceenum already has abech32computed property that performs the same encoding. You can simplify this toreference.bech32.private var bech32: String { - switch reference { - case .naddr(let naddr): - return Bech32Object.encode(.naddr(naddr)) - case .nevent(let nevent): - return Bech32Object.encode(.nevent(nevent)) - } + reference.bech32 }damus/Features/Posting/Views/PostView.swift (2)
127-175: Consider extracting the whitespace-trimming deletion logic into a shared helper.The range expansion logic (lines 140-161) to include surrounding whitespace is duplicated in
extractAndRemoveLongformReferences(lines 322-343). Extracting this into a shared helper would reduce duplication and improve maintainability.Additionally, ensure that manually typed
nostr:naddr1...strings that haven't been extracted yet are handled correctly—currently they would be removed and re-added, which should be fine but worth verifying.
300-349: Whitespace handling logic is duplicated from send_post.This function duplicates the same range expansion logic found in
send_post(lines 140-161). Consider extracting into a shared helper like:private func expandRangeToIncludeSurroundingWhitespace( range: NSRange, in text: String ) -> NSRangeThis would consolidate the logic and reduce maintenance burden.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
damus.xcodeproj/project.pbxprojdamus/Core/Nostr/NostrEvent.swiftdamus/Features/Chat/ChatEventView.swiftdamus/Features/DMs/Views/DMView.swiftdamus/Features/Events/EventShell.swiftdamus/Features/Events/LongformNaddrMentionView.swiftdamus/Features/Events/Models/NoteContent.swiftdamus/Features/Events/SelectedEventView.swiftdamus/Features/Posting/Views/PostView.swift
👮 Files not reviewed due to content moderation or server errors (1)
- damus.xcodeproj/project.pbxproj
🧰 Additional context used
📓 Path-based instructions (1)
**/*.swift
📄 CodeRabbit inference engine (AGENTS.md)
**/*.swift: Maximize usage of nostrdb facilities (Ndb, NdbNote, iterators) whenever possible for persistence and queries in the Damus iOS app
Favor Swift-first solutions that lean on nostrdb types (Ndb, NdbNote, iterators) before introducing new storage mechanisms
Ensure docstring coverage for any code added, or modified
Ensure nevernesting: favor early returns and guard clauses over deeply nested conditionals; simplify control flow by exiting early instead of wrapping logic in multiple layers of if statements
Files:
damus/Features/Events/SelectedEventView.swiftdamus/Features/Events/EventShell.swiftdamus/Core/Nostr/NostrEvent.swiftdamus/Features/DMs/Views/DMView.swiftdamus/Features/Chat/ChatEventView.swiftdamus/Features/Posting/Views/PostView.swiftdamus/Features/Events/LongformNaddrMentionView.swiftdamus/Features/Events/Models/NoteContent.swift
🧠 Learnings (6)
📓 Common learnings
Learnt from: CR
Repo: damus-io/damus PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-06T01:28:30.381Z
Learning: Review and follow pull_request_template.md when creating PRs for iOS Damus
📚 Learning: 2026-01-06T01:28:30.381Z
Learnt from: CR
Repo: damus-io/damus PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-06T01:28:30.381Z
Learning: Applies to **/*.swift : Maximize usage of nostrdb facilities (Ndb, NdbNote, iterators) whenever possible for persistence and queries in the Damus iOS app
Applied to files:
damus/Features/Events/LongformNaddrMentionView.swiftdamus.xcodeproj/project.pbxproj
📚 Learning: 2026-01-06T01:28:30.381Z
Learnt from: CR
Repo: damus-io/damus PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-06T01:28:30.381Z
Learning: Ensure new targets or resources integrate cleanly with the damus.xcodeproj main scheme
Applied to files:
damus.xcodeproj/project.pbxproj
📚 Learning: 2026-01-06T01:28:30.381Z
Learnt from: CR
Repo: damus-io/damus PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-06T01:28:30.381Z
Learning: Applies to **/*.swift : Ensure docstring coverage for any code added, or modified
Applied to files:
damus.xcodeproj/project.pbxproj
📚 Learning: 2026-01-06T01:28:30.381Z
Learnt from: CR
Repo: damus-io/damus PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-06T01:28:30.381Z
Learning: Review and follow pull_request_template.md when creating PRs for iOS Damus
Applied to files:
damus.xcodeproj/project.pbxproj
📚 Learning: 2026-01-06T01:28:30.381Z
Learnt from: CR
Repo: damus-io/damus PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-06T01:28:30.381Z
Learning: Applies to **/*.swift : Favor Swift-first solutions that lean on nostrdb types (Ndb, NdbNote, iterators) before introducing new storage mechanisms
Applied to files:
damus.xcodeproj/project.pbxproj
🧬 Code graph analysis (8)
damus/Features/Events/SelectedEventView.swift (1)
damus/Core/Nostr/NostrEvent.swift (1)
all_longform_mentions(873-898)
damus/Features/Events/EventShell.swift (1)
damus/Core/Nostr/NostrEvent.swift (2)
first_eref_mention(828-847)all_longform_mentions(873-898)
damus/Core/Nostr/NostrEvent.swift (3)
damus/Shared/Utilities/Bech32Object.swift (1)
encode(183-199)nostrdb/NdbBlock.swift (2)
borrowBlockGroup(124-139)reduce(296-298)nostrdb/NonCopyableLinkedList.swift (1)
reduce(62-84)
damus/Features/DMs/Views/DMView.swift (1)
damus/Core/Nostr/NostrEvent.swift (1)
all_longform_mentions(873-898)
damus/Features/Chat/ChatEventView.swift (1)
damus/Core/Nostr/NostrEvent.swift (1)
all_longform_mentions(873-898)
damus/Features/Posting/Views/PostView.swift (1)
damus/Shared/Utilities/Bech32Object.swift (1)
parse(159-181)
damus/Features/Events/LongformNaddrMentionView.swift (1)
damus/Shared/Utilities/DisplayName.swift (1)
abbrev_identifier(88-90)
damus/Features/Events/Models/NoteContent.swift (2)
nostrdb/NdbBlock.swift (1)
reduce(296-298)nostrdb/NonCopyableLinkedList.swift (1)
reduce(62-84)
🪛 SwiftLint (0.57.0)
damus/Core/Nostr/NostrEvent.swift
[Warning] 875-875: Unused parameter in a closure should be replaced with _
(unused_closure_parameter)
damus/Features/Events/Models/NoteContent.swift
[Warning] 118-118: Unused parameter in a closure should be replaced with _
(unused_closure_parameter)
[Warning] 118-118: Unused parameter in a closure should be replaced with _
(unused_closure_parameter)
🔇 Additional comments (17)
damus/Features/Events/EventShell.swift (2)
86-91: LGTM!The integration of
LongformMentionsStackafterMentionViewin the Threaded layout is correct. The guard logic is handled insideget_longform_mentions, andLongformMentionsStackrenders anEmptyViewwhen the array is empty, so no additional conditional is needed here.
118-128: LGTM!The Wide layout correctly guards the
LongformMentionsStackwith!options.contains(.no_mentions)and applies horizontal padding consistently with other elements.damus/Features/Events/Models/NoteContent.swift (1)
266-282: LGTM!The suppression logic correctly skips inline rendering of longform naddr/nevent mentions when
has_longform_refis true, ensuring preview cards are displayed instead. The early continue prevents duplicate display of longform content.damus/Core/Nostr/NostrEvent.swift (2)
28-42: LGTM!The
LongformReferenceenum is well-designed with clear cases fornaddrandnevent, Equatable conformance for deduplication, and a convenientbech32computed property that delegates toBech32Object.encode.
849-870: LGTM!The
first_longform_naddr_mentionfunction correctly uses nostrdb's block iteration facilities to find the first naddr mention with kind 30023. The docstring provides clear documentation.damus/Features/Events/LongformNaddrMentionView.swift (4)
10-12: LGTM!Good docstring coverage for the main view. The async loading pattern with LoadState enum is clean.
139-148: Using\.offsetas ForEach id may cause animation issues during deletion.When items are removed, offsets shift, which can cause SwiftUI to misidentify views and produce animation glitches. Since
LongformReferenceisEquatable, consider making itHashableorIdentifiableto use a stable identity.For now, since the carousel is relatively small and this is a compose view where perfect animations are less critical, this is acceptable.
61-83: LGTM!The async loading correctly handles both naddr and nevent cases. The continuation pattern for nevent preserves the copy semantics required by the lender API. The MainActor dispatch ensures thread-safe state updates.
155-170: LGTM!The
LongformMentionsStackcorrectly renders anEmptyViewwhen there are no references and a vertical stack otherwise. Using\.offsetas id here is acceptable since this is a read-only view with no mutations.damus/Features/Posting/Views/PostView.swift (8)
90-91: LGTM!The new state variable for tracking extracted longform references is appropriately scoped as private.
185-186: LGTM!The
is_post_emptycheck now correctly considerslongformReferences, preventing the post button from being disabled when only longform references are present.
355-388: LGTM!The draft persistence logic correctly re-embeds longform references into the saved content so they aren't lost when the view is dismissed. The check for existing refs prevents duplication.
410-413: LGTM!Calling
extractAndRemoveLongformReferences()on text change enables real-time preview of pasted longform references.
544-552: LGTM!The
LongformCarouselViewis correctly integrated into the Editor view with appropriate padding and conditional rendering.
1110-1167: LGTM!The extraction utilities are well-structured with clear docstrings. The regex patterns correctly handle the optional
nostr:prefix and the bech32 character set. The kind check ensures only longform articles (kind 30023) are extracted.
1169-1231: LGTM!The individual extraction functions for naddr and nevent are well-implemented with proper null safety and early returns. The docstrings clearly document the expected behavior.
1233-1253: LGTM!The convenience wrappers
extractLongformNaddrandextractLongformNeventprovide a cleaner API for callers that only need the reference without the match range.
| /// Returns all longform article mentions (naddr or nevent with kind 30023) in the event content. | ||
| func all_longform_mentions(ndb: Ndb, ev: NostrEvent, keypair: Keypair) -> [LongformReference] { | ||
| return (try? NdbBlockGroup.borrowBlockGroup(event: ev, using: ndb, and: keypair, borrow: { blockGroup in | ||
| let mentions: [LongformReference] = (try? blockGroup.reduce(initialResult: [LongformReference](), { index, refs, block in | ||
| switch block { | ||
| case .mention(let mention): | ||
| guard let mentionRef = MentionRef(block: mention) else { return .loopContinue } | ||
| switch mentionRef.nip19 { | ||
| case .naddr(let naddr): | ||
| if naddr.kind == NostrKind.longform.rawValue { | ||
| return .loopReturn(refs + [.naddr(naddr)]) | ||
| } | ||
| case .nevent(let nevent): | ||
| if nevent.kind == NostrKind.longform.rawValue { | ||
| return .loopReturn(refs + [.nevent(nevent)]) | ||
| } | ||
| default: | ||
| break | ||
| } | ||
| default: | ||
| break | ||
| } | ||
| return .loopContinue | ||
| })) ?? [] | ||
| return mentions | ||
| })) ?? [] | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Replace unused closure parameter index with _.
SwiftLint reports that the index parameter is unused. Replace it with an underscore.
func all_longform_mentions(ndb: Ndb, ev: NostrEvent, keypair: Keypair) -> [LongformReference] {
return (try? NdbBlockGroup.borrowBlockGroup(event: ev, using: ndb, and: keypair, borrow: { blockGroup in
- let mentions: [LongformReference] = (try? blockGroup.reduce(initialResult: [LongformReference](), { index, refs, block in
+ let mentions: [LongformReference] = (try? blockGroup.reduce(initialResult: [LongformReference](), { _, refs, block in
switch block {🧰 Tools
🪛 SwiftLint (0.57.0)
[Warning] 875-875: Unused parameter in a closure should be replaced with _
(unused_closure_parameter)
🤖 Prompt for AI Agents
In @damus/Core/Nostr/NostrEvent.swift around lines 872 - 898, In
all_longform_mentions (function all_longform_mentions) the closure passed to
blockGroup.reduce declares an unused parameter named `index`; replace that
parameter with `_` (i.e., change `(index, refs, block)` to `(_, refs, block)`)
so SwiftLint stops flagging the unused parameter and the closure semantics
remain unchanged.
| // Check for any longform naddr/nevent mentions (kind 30023) - suppress inline when preview cards shown | ||
| let has_longform_ref: Bool = (try? blocks.reduce(initialResult: false) { index, partialResult, item in | ||
| switch item { | ||
| case .mention(let mention): | ||
| guard let mentionRef = MentionRef(block: mention) else { return .loopContinue } | ||
| switch mentionRef.nip19 { | ||
| case .naddr(let naddr): | ||
| if naddr.kind == NostrKind.longform.rawValue { | ||
| return .loopReturn(true) | ||
| } | ||
| case .nevent(let nevent): | ||
| if nevent.kind == NostrKind.longform.rawValue { | ||
| return .loopReturn(true) | ||
| } | ||
| default: | ||
| break | ||
| } | ||
| default: | ||
| break | ||
| } | ||
| return .loopContinue | ||
| }) ?? false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Replace unused closure parameters with _ to fix SwiftLint warnings.
The index and partialResult parameters are unused in this closure. Per SwiftLint's unused_closure_parameter rule, replace them with underscores.
- let has_longform_ref: Bool = (try? blocks.reduce(initialResult: false) { index, partialResult, item in
+ let has_longform_ref: Bool = (try? blocks.reduce(initialResult: false) { _, _, item in
switch item {
case .mention(let mention):
guard let mentionRef = MentionRef(block: mention) else { return .loopContinue }
switch mentionRef.nip19 {
case .naddr(let naddr):
if naddr.kind == NostrKind.longform.rawValue {
return .loopReturn(true)
}
case .nevent(let nevent):
if nevent.kind == NostrKind.longform.rawValue {
return .loopReturn(true)
}
default:
break
}
default:
break
}
return .loopContinue
}) ?? false📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Check for any longform naddr/nevent mentions (kind 30023) - suppress inline when preview cards shown | |
| let has_longform_ref: Bool = (try? blocks.reduce(initialResult: false) { index, partialResult, item in | |
| switch item { | |
| case .mention(let mention): | |
| guard let mentionRef = MentionRef(block: mention) else { return .loopContinue } | |
| switch mentionRef.nip19 { | |
| case .naddr(let naddr): | |
| if naddr.kind == NostrKind.longform.rawValue { | |
| return .loopReturn(true) | |
| } | |
| case .nevent(let nevent): | |
| if nevent.kind == NostrKind.longform.rawValue { | |
| return .loopReturn(true) | |
| } | |
| default: | |
| break | |
| } | |
| default: | |
| break | |
| } | |
| return .loopContinue | |
| }) ?? false | |
| // Check for any longform naddr/nevent mentions (kind 30023) - suppress inline when preview cards shown | |
| let has_longform_ref: Bool = (try? blocks.reduce(initialResult: false) { _, _, item in | |
| switch item { | |
| case .mention(let mention): | |
| guard let mentionRef = MentionRef(block: mention) else { return .loopContinue } | |
| switch mentionRef.nip19 { | |
| case .naddr(let naddr): | |
| if naddr.kind == NostrKind.longform.rawValue { | |
| return .loopReturn(true) | |
| } | |
| case .nevent(let nevent): | |
| if nevent.kind == NostrKind.longform.rawValue { | |
| return .loopReturn(true) | |
| } | |
| default: | |
| break | |
| } | |
| default: | |
| break | |
| } | |
| return .loopContinue | |
| }) ?? false |
🧰 Tools
🪛 SwiftLint (0.57.0)
[Warning] 118-118: Unused parameter in a closure should be replaced with _
(unused_closure_parameter)
[Warning] 118-118: Unused parameter in a closure should be replaced with _
(unused_closure_parameter)
🤖 Prompt for AI Agents
In @damus/Features/Events/Models/NoteContent.swift around lines 117 - 138, In
NoteContent.swift update the closure passed to blocks.reduce that computes
has_longform_ref to avoid unused-parameter warnings: replace the unused closure
parameters `index` and `partialResult` with underscores (e.g., use `_`
placeholders) in the reduce closure signature so it becomes `{ _, _, item in ...
}`, leaving the body and logic (mentions, MentionRef handling, nip19 checks and
loopReturn/loopContinue) unchanged.
Summary
Display preview cards for longform article (kind 30023) references in notes instead of abbreviated inline text (
@naddr1...).Checklist
Standard PR Checklist
Closes:orFixes:tags in the commit messages wherever applicable, or made sure those are not needed. See Submitting patchesTest report
Device: iPhone 15 Pro (Simulator)
iOS: 18.2
Damus: feature/longform-naddr-preview branch (84a2e3d)
Setup: Test account with access to notes containing longform article references
Steps:
Results:
Other notes
Closes #2798
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.