Files
damus/damus/ContentParsing.swift
Daniel D’Aquino d71d448ac8 Add support for rendering highlights with comments
This commit implements rendering comments from the `["comment",
<COMMENT_TEXT>]` tag in a highlight note.

Comment contents get rendered like a kind 1 note's "content" field

This commit also adds the `r` "reference" tag as a standard tag reference type

Changelog-Added: Add support for rendering highlights with comments
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
2024-09-01 07:23:16 -07:00

116 lines
3.0 KiB
Swift

//
// ContentParsing.swift
// damus
//
// Created by William Casarin on 2023-07-22.
//
import Foundation
enum NoteContent {
case note(NostrEvent)
case content(String, TagsSequence?)
init(note: NostrEvent, keypair: Keypair) {
if note.known_kind == .dm || note.known_kind == .highlight {
self = .content(note.get_content(keypair), note.tags)
} else {
self = .note(note)
}
}
}
func parsed_blocks_finish(bs: inout note_blocks, tags: TagsSequence?) -> Blocks {
var out: [Block] = []
var i = 0
while (i < bs.num_blocks) {
let block = bs.blocks[i]
if let converted = Block(block, tags: tags) {
out.append(converted)
}
i += 1
}
let words = Int(bs.words)
blocks_free(&bs)
return Blocks(words: words, blocks: out)
}
func parse_note_content(content: NoteContent) -> Blocks {
var bs = note_blocks()
bs.num_blocks = 0;
blocks_init(&bs)
switch content {
case .content(let s, let tags):
return s.withCString { cptr in
damus_parse_content(&bs, cptr)
return parsed_blocks_finish(bs: &bs, tags: tags)
}
case .note(let note):
damus_parse_content(&bs, note.content_raw)
return parsed_blocks_finish(bs: &bs, tags: note.tags)
}
}
func interpret_event_refs(tags: TagsSequence) -> ThreadReply? {
// migration is long over, lets just do this to fix tests
return interpret_event_refs_ndb(tags: tags)
}
func interpret_event_refs_ndb(tags: TagsSequence) -> ThreadReply? {
if tags.count == 0 {
return nil
}
return interp_event_refs_without_mentions_ndb(References<NoteRef>(tags: tags))
}
func interp_event_refs_without_mentions_ndb(_ ev_tags: References<NoteRef>) -> ThreadReply? {
var first: Bool = true
var root_id: NoteRef? = nil
var reply_id: NoteRef? = nil
var mention: NoteRef? = nil
var any_marker: Bool = false
for ref in ev_tags {
if let marker = ref.marker {
any_marker = true
switch marker {
case .root: root_id = ref
case .reply: reply_id = ref
case .mention: mention = ref
}
// deprecated form, only activate if we don't have any markers set
} else if !any_marker {
if first {
root_id = ref
first = false
} else {
reply_id = ref
}
}
}
// If either reply or root_id is blank while the other is not, then this is
// considered reply-to-root. We should always have a root and reply tag, if they
// are equal this is reply-to-root
if reply_id == nil && root_id != nil {
reply_id = root_id
} else if root_id == nil && reply_id != nil {
root_id = reply_id
}
guard let reply_id, let root_id else {
return nil
}
return ThreadReply(root: root_id, reply: reply_id, mention: mention.map { m in .noteref(m) })
}