Skip to content

Commit

Permalink
Fix note rendering for those that contain previewable items or leadin…
Browse files Browse the repository at this point in the history
…g and trailing whitespaces

Changelog-Fixed: Fixed note rendering for those that contain previewable items or leading and trailing whitespaces
Closes: #2187
Signed-off-by: Terry Yiu <[email protected]>
  • Loading branch information
tyiu committed Mar 1, 2025
1 parent 2b3d869 commit 9241039
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 67 deletions.
14 changes: 12 additions & 2 deletions damus-c/damus.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,12 @@ int damus_parse_content(struct note_blocks *blocks, const char *content) {
blocks->words = 0;
blocks->num_blocks = 0;
make_cursor((u8*)content, (u8*)content + strlen(content), &cur);


// **Skip leading whitespace**
while (cur.p < cur.end && is_whitespace(*cur.p)) {
cur.p++;
}

start = cur.p;
while (cur.p < cur.end && blocks->num_blocks < MAX_BLOCKS) {
cp = peek_char(&cur, -1);
Expand Down Expand Up @@ -362,7 +367,12 @@ int damus_parse_content(struct note_blocks *blocks, const char *content) {

cur.p++;
}


// **Trim trailing whitespace**
while (cur.p > start && is_whitespace(*(cur.p - 1))) {
cur.p--;
}

if (cur.p - start > 0) {
if (!add_text_block(blocks, start, cur.p))
return 0;
Expand Down
2 changes: 1 addition & 1 deletion damus/Components/TranslateView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func translate_note(profiles: Profiles, keypair: Keypair, event: NostrEvent, set

// Render translated note
let translated_blocks = parse_note_content(content: .content(translated_note, event.tags))
let artifacts = render_blocks(blocks: translated_blocks, profiles: profiles)
let artifacts = render_blocks(blocks: translated_blocks, profiles: profiles, hide_last_only_previewable_ref: true)

// and cache it
return .translated(Translated(artifacts: artifacts, language: note_lang))
Expand Down
102 changes: 44 additions & 58 deletions damus/Models/NoteContent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,83 +73,74 @@ func render_note_content(ev: NostrEvent, profiles: Profiles, keypair: Keypair) -
return .longform(LongformContent(ev.content))
}

return .separated(render_blocks(blocks: blocks, profiles: profiles))
return .separated(render_blocks(blocks: blocks, profiles: profiles, hide_last_only_previewable_ref: true))
}

func render_blocks(blocks bs: Blocks, profiles: Profiles) -> NoteArtifactsSeparated {
func render_blocks(blocks bs: Blocks, profiles: Profiles, hide_last_only_previewable_ref: Bool = false) -> NoteArtifactsSeparated {
var invoices: [Invoice] = []
var urls: [UrlType] = []
let blocks = bs.blocks

let one_note_ref = blocks
.filter({
if case .mention(let mention) = $0,
case .note = mention.ref {
return true
}
else {
return false
}
})
.count == 1


// Use lazy with prefix to avoid iterating over all blocks if at least two previewable blocks have been found.
let one_preview_ref = hide_last_only_previewable_ref && blocks.lazy.filter({ $0.is_previewable }).prefix(2).count == 1

var ind: Int = -1
let txt: CompatibleText = blocks.reduce(CompatibleText()) { str, block in
ind = ind + 1

let lastBlock = ind == blocks.count - 1

// Add the rendered previewable blocks to their type-specific lists.
switch block {
case .invoice(let invoice):
invoices.append(invoice)
case .url(let url):
let url_type = classify_url(url)
urls.append(url_type)
default:
break
}

// No need to show the string if the block is previewable, there is only one previewable block and it is the
// last block. This is to save unnecessary use of screen space.
if one_preview_ref && lastBlock && block.is_previewable {
return str
}

switch block {
case .mention(let m):
if case .note = m.ref, one_note_ref {
return str
}
return str + mention_str(m, profiles: profiles)
case .text(let txt):
return str + CompatibleText(stringLiteral: reduce_text_block(blocks: blocks, ind: ind, txt: txt, one_note_ref: one_note_ref))

return str + CompatibleText(stringLiteral: reduce_text_block(blocks: blocks, ind: ind, txt: txt, one_preview_ref: one_preview_ref))
case .relay(let relay):
return str + CompatibleText(stringLiteral: relay)

case .hashtag(let htag):
return str + hashtag_str(htag)
case .invoice(let invoice):
invoices.append(invoice)
return str
return str + invoice_str(invoice)
case .url(let url):
let url_type = classify_url(url)
switch url_type {
case .media:
urls.append(url_type)
return str
case .link(let url):
urls.append(url_type)
return str + url_str(url)
}
return str + url_str(url)
}
}

return NoteArtifactsSeparated(content: txt, words: bs.words, urls: urls, invoices: invoices)
}

func reduce_text_block(blocks: [Block], ind: Int, txt: String, one_note_ref: Bool) -> String {
var trimmed = txt

if let prev = blocks[safe: ind-1],
case .url(let u) = prev,
classify_url(u).is_media != nil {
trimmed = " " + trim_prefix(trimmed)
}

func reduce_text_block(blocks: [Block], ind: Int, txt: String, one_preview_ref: Bool) -> String {
if let next = blocks[safe: ind+1] {
if case .url(let u) = next, classify_url(u).is_media != nil {
trimmed = trim_suffix(trimmed)
} else if case .mention(let m) = next,
case .note = m.ref,
one_note_ref {
trimmed = trim_suffix(trimmed)
if one_preview_ref && ind+1 == blocks.count-1 && next.is_previewable {
return trim_suffix(txt)
}
}

return trimmed

return txt
}

func invoice_str(_ invoice: Invoice) -> CompatibleText {
// Add foreground color to Lightning invoice but no need to link to anything as the attached preview is sufficient.
var attributedString = AttributedString(stringLiteral: abbrev_identifier(invoice.string))
attributedString.foregroundColor = DamusColors.purple

return CompatibleText(attributed: attributedString)
}

func url_str(_ url: URL) -> CompatibleText {
Expand Down Expand Up @@ -194,11 +185,11 @@ func mention_str(_ m: Mention<MentionRef>, profiles: Profiles) -> CompatibleText
let display_str: String = {
switch m.ref {
case .pubkey(let pk): return getDisplayName(pk: pk, profiles: profiles)
case .note: return abbrev_pubkey(bech32String)
case .nevent: return abbrev_pubkey(bech32String)
case .note: return abbrev_identifier(bech32String)
case .nevent: return abbrev_identifier(bech32String)
case .nprofile(let nprofile): return getDisplayName(pk: nprofile.author, profiles: profiles)
case .nrelay(let url): return url
case .naddr: return abbrev_pubkey(bech32String)
case .naddr: return abbrev_identifier(bech32String)
}
}()

Expand All @@ -216,11 +207,6 @@ func trim_suffix(_ str: String) -> String {
return str.replacingOccurrences(of: "\\s+$", with: "", options: .regularExpression)
}

// trim prefix whitespace and newlines
func trim_prefix(_ str: String) -> String {
return str.replacingOccurrences(of: "^\\s+", with: "", options: .regularExpression)
}

struct LongformContent {
let markdown: MarkdownContent
let words: Int
Expand Down
18 changes: 17 additions & 1 deletion damus/Types/Block.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,23 @@ enum Block: Equatable {
return false
}
}


var is_previewable: Bool {
switch self {
case .mention(let m):
switch m.ref {
case .note, .nevent: return true
default: return false
}
case .invoice:
return true
case .url:
return true
default:
return false
}
}

case text(String)
case mention(Mention<MentionRef>)
case hashtag(String)
Expand Down
4 changes: 2 additions & 2 deletions damus/Util/DisplayName.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ func parse_display_name(profile: Profile?, pubkey: Pubkey) -> DisplayName {
}

func abbrev_bech32_pubkey(pubkey: Pubkey) -> String {
return abbrev_pubkey(String(pubkey.npub.dropFirst(4)))
return abbrev_identifier(String(pubkey.npub.dropFirst(4)))
}

func abbrev_pubkey(_ pubkey: String, amount: Int = 8) -> String {
func abbrev_identifier(_ pubkey: String, amount: Int = 8) -> String {
return pubkey.prefix(amount) + ":" + pubkey.suffix(amount)
}
2 changes: 1 addition & 1 deletion damus/Views/PubkeyView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ struct PubkeyView: View {
let bech32 = pubkey.npub

HStack {
Text(verbatim: "\(abbrev_pubkey(bech32, amount: sidemenu ? 12 : 16))")
Text(verbatim: "\(abbrev_identifier(bech32, amount: sidemenu ? 12 : 16))")
.font(sidemenu ? .system(size: 10) : .footnote)
.foregroundColor(keyColor())
.padding(5)
Expand Down
3 changes: 1 addition & 2 deletions damusTests/damusTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,9 @@ class damusTests: XCTestCase {
XCTAssertEqual(bytes.count, 32)
}

func testTrimmingFunctions() {
func testTrimSuffix() {
let txt = " bobs "

XCTAssertEqual(trim_prefix(txt), "bobs ")
XCTAssertEqual(trim_suffix(txt), " bobs")
}

Expand Down

0 comments on commit 9241039

Please sign in to comment.