Switch over to use use blocks from nostrdb
This is still kind of broken until queries are switched over to nostrdb. Will do this next Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
committed by
Daniel D’Aquino
parent
208b3331ca
commit
28a06af534
@@ -126,10 +126,12 @@ struct DMChatView: View, KeyboardReadable {
|
||||
|
||||
func send_message() {
|
||||
let tags = [["p", pubkey.hex()]]
|
||||
let post_blocks = parse_post_blocks(content: dms.draft)
|
||||
let content = post_blocks
|
||||
.map(\.asString)
|
||||
.joined(separator: "")
|
||||
let post_blocks = parse_post_blocks(content: dms.draft)?.blocks
|
||||
guard let content = post_blocks?.map({ pb in pb.asString }).joined(separator: "") else {
|
||||
// TODO: handle these errors somehow?
|
||||
print("error creating dm")
|
||||
return
|
||||
}
|
||||
|
||||
guard let dm = NIP04.create_dm(content, to_pk: pubkey, tags: tags, keypair: damus_state.keypair) else {
|
||||
print("error creating dm")
|
||||
|
||||
@@ -17,7 +17,7 @@ struct DMView: View {
|
||||
|
||||
var Mention: some View {
|
||||
Group {
|
||||
if let mention = first_eref_mention(ev: event, keypair: damus_state.keypair) {
|
||||
if let mention = first_eref_mention(ndb: damus_state.ndb, ev: event, keypair: damus_state.keypair) {
|
||||
BuilderEventView(damus: damus_state, event_id: mention.ref)
|
||||
} else {
|
||||
EmptyView()
|
||||
|
||||
@@ -35,12 +35,12 @@ struct EventShell<Content: View>: View {
|
||||
!options.contains(.no_action_bar)
|
||||
}
|
||||
|
||||
func get_mention() -> Mention<NoteId>? {
|
||||
func get_mention(ndb: Ndb) -> Mention<NoteId>? {
|
||||
if self.options.contains(.nested) || self.options.contains(.no_mentions) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return first_eref_mention(ev: event, keypair: state.keypair)
|
||||
return first_eref_mention(ndb: ndb, ev: event, keypair: state.keypair)
|
||||
}
|
||||
|
||||
var ActionBar: some View {
|
||||
@@ -73,7 +73,7 @@ struct EventShell<Content: View>: View {
|
||||
|
||||
content
|
||||
|
||||
if let mention = get_mention() {
|
||||
if let mention = get_mention(ndb: state.ndb) {
|
||||
MentionView(damus_state: state, mention: mention)
|
||||
}
|
||||
|
||||
@@ -103,7 +103,9 @@ struct EventShell<Content: View>: View {
|
||||
|
||||
content
|
||||
|
||||
if !options.contains(.no_mentions), let mention = get_mention() {
|
||||
if !options.contains(.no_mentions),
|
||||
let mention = get_mention(ndb: state.ndb)
|
||||
{
|
||||
MentionView(damus_state: state, mention: mention)
|
||||
.padding(.horizontal)
|
||||
}
|
||||
|
||||
@@ -66,14 +66,16 @@ func note_artifact_is_separated(kind: NostrKind?) -> Bool {
|
||||
return kind != .longform
|
||||
}
|
||||
|
||||
func render_note_content(ev: NostrEvent, profiles: Profiles, keypair: Keypair) -> NoteArtifacts {
|
||||
let blocks = ev.blocks(keypair)
|
||||
func render_note_content(ndb: Ndb, ev: NostrEvent, profiles: Profiles, keypair: Keypair) -> NoteArtifacts {
|
||||
guard let blocks = ev.blocks(ndb: ndb) else {
|
||||
return .separated(.just_content(ev.get_content(keypair)))
|
||||
}
|
||||
|
||||
if ev.known_kind == .longform {
|
||||
return .longform(LongformContent(ev.content))
|
||||
}
|
||||
|
||||
return .separated(render_blocks(blocks: blocks, profiles: profiles, can_hide_last_previewable_refs: true))
|
||||
return .separated(render_blocks(blocks: blocks.unsafeUnownedValue, profiles: profiles, note: ev, can_hide_last_previewable_refs: true))
|
||||
}
|
||||
|
||||
// FIXME(tyiu): There are a lot of hacks to get this function to render the blocks correctly.
|
||||
@@ -81,39 +83,54 @@ func render_note_content(ev: NostrEvent, profiles: Profiles, keypair: Keypair) -
|
||||
// Block previews should actually be rendered in the position of the note content where it was found.
|
||||
// Currently, we put some previews at the bottom of the note, which is incorrect as they take things out of
|
||||
// the author's intended context.
|
||||
func render_blocks(blocks bs: Blocks, profiles: Profiles, can_hide_last_previewable_refs: Bool = false) -> NoteArtifactsSeparated {
|
||||
func render_blocks(blocks: NdbBlocks, profiles: Profiles, note: NdbNote, can_hide_last_previewable_refs: Bool = false) -> NoteArtifactsSeparated {
|
||||
var invoices: [Invoice] = []
|
||||
var urls: [UrlType] = []
|
||||
let blocks = bs.blocks
|
||||
|
||||
|
||||
var end_mention_count = 0
|
||||
var end_url_count = 0
|
||||
|
||||
let ndb_blocks = blocks.iter(note: note).collect()
|
||||
let one_note_ref = ndb_blocks
|
||||
.filter({
|
||||
if case .mention(let mention) = $0,
|
||||
let typ = mention.bech32_type,
|
||||
typ.is_notelike {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
.count == 1
|
||||
|
||||
// Search backwards until we find the beginning index of the chain of previewables that reach the end of the content.
|
||||
var hide_text_index = blocks.endIndex
|
||||
var hide_text_index = ndb_blocks.endIndex
|
||||
if can_hide_last_previewable_refs {
|
||||
outerLoop: for (i, block) in blocks.enumerated().reversed() {
|
||||
outerLoop: for (i, block) in ndb_blocks.enumerated().reversed() {
|
||||
if block.is_previewable {
|
||||
switch block {
|
||||
case .mention:
|
||||
end_mention_count += 1
|
||||
|
||||
|
||||
// If there is more than one previewable mention,
|
||||
// do not hide anything because we allow rich rendering of only one mention currently.
|
||||
// This should be fixed in the future to show events inline instead.
|
||||
if end_mention_count > 1 {
|
||||
hide_text_index = blocks.endIndex
|
||||
hide_text_index = ndb_blocks.endIndex
|
||||
break outerLoop
|
||||
}
|
||||
case .url(let url):
|
||||
case .url(let url_block):
|
||||
guard let url_string = NdbBlock.convertToStringCopy(from: url_block),
|
||||
let url = URL(string: url_string) else {
|
||||
continue // We can't classify this, ignore and move on
|
||||
}
|
||||
let url_type = classify_url(url)
|
||||
if case .link = url_type {
|
||||
end_url_count += 1
|
||||
|
||||
|
||||
// If there is more than one link, do not hide anything because we allow rich rendering of only
|
||||
// one link.
|
||||
if end_url_count > 1 {
|
||||
hide_text_index = blocks.endIndex
|
||||
hide_text_index = ndb_blocks.endIndex
|
||||
break outerLoop
|
||||
}
|
||||
}
|
||||
@@ -121,7 +138,9 @@ func render_blocks(blocks bs: Blocks, profiles: Profiles, can_hide_last_previewa
|
||||
break
|
||||
}
|
||||
hide_text_index = i
|
||||
} else if case .text(let txt) = block, txt.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
} else if case .text(let txt_block) = block,
|
||||
let txt = NdbBlock.convertToStringCopy(from: txt_block),
|
||||
txt.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
// We should hide whitespace at the end sequence.
|
||||
hide_text_index = i
|
||||
} else if case .hashtag = block {
|
||||
@@ -135,16 +154,21 @@ func render_blocks(blocks bs: Blocks, profiles: Profiles, can_hide_last_previewa
|
||||
}
|
||||
|
||||
var ind: Int = -1
|
||||
let txt: CompatibleText = blocks.reduce(CompatibleText()) { str, block in
|
||||
let txt: CompatibleText = ndb_blocks.reduce(into: CompatibleText()) { str, block in
|
||||
ind = ind + 1
|
||||
|
||||
// Add the rendered previewable blocks to their type-specific lists.
|
||||
switch block {
|
||||
case .invoice(let invoice):
|
||||
invoices.append(invoice)
|
||||
case .url(let url):
|
||||
case .url(let url_block):
|
||||
guard let url_string = NdbBlock.convertToStringCopy(from: url_block),
|
||||
let url = URL(string: url_string) else {
|
||||
break // We can't classify this, ignore and move on
|
||||
}
|
||||
let url_type = classify_url(url)
|
||||
urls.append(url_type)
|
||||
case .invoice(let invoice_block):
|
||||
guard let invoice = invoice_block.as_invoice() else { break }
|
||||
invoices.append(invoice)
|
||||
default:
|
||||
break
|
||||
}
|
||||
@@ -153,7 +177,7 @@ func render_blocks(blocks bs: Blocks, profiles: Profiles, can_hide_last_previewa
|
||||
// If there are previewable blocks that occur before the consecutive sequence of them at the end of the content,
|
||||
// we should not hide the text representation of any previewable block to avoid altering the format of the note.
|
||||
if ind < hide_text_index && block.is_previewable {
|
||||
hide_text_index = blocks.endIndex
|
||||
hide_text_index = ndb_blocks.endIndex
|
||||
}
|
||||
|
||||
// No need to show the text representation of the block if the only previewables are the sequence of them
|
||||
@@ -162,41 +186,56 @@ func render_blocks(blocks bs: Blocks, profiles: Profiles, can_hide_last_previewa
|
||||
// The only exception is that if there are hashtags embedded in the end sequence, which is not uncommon,
|
||||
// then we still want to show those hashtags but hide everything else that is previewable in the end sequence.
|
||||
if ind >= hide_text_index {
|
||||
if case .text(let txt) = block, txt.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
if case .hashtag = blocks[safe: ind+1] {
|
||||
return str + CompatibleText(stringLiteral: reduce_text_block(ind: ind, hide_text_index: -1, txt: txt))
|
||||
if case .text(let txt_block) = block,
|
||||
let txt = NdbBlock.convertToStringCopy(from: txt_block),
|
||||
txt.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
if case .hashtag = ndb_blocks[safe: ind+1] {
|
||||
str = str + CompatibleText(stringLiteral: reduce_text_block(ind: ind, hide_text_index: hide_text_index, txt: txt))
|
||||
}
|
||||
} else if case .hashtag(let htag) = block {
|
||||
return str + hashtag_str(htag)
|
||||
str = str + hashtag_str(htag.as_str())
|
||||
}
|
||||
return str
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
switch block {
|
||||
case .mention(let m):
|
||||
return str + mention_str(m, profiles: profiles)
|
||||
if let typ = m.bech32_type, typ.is_notelike, one_note_ref {
|
||||
return
|
||||
}
|
||||
guard let mention = MentionRef(block: m) else { return }
|
||||
str = str + mention_str(.any(mention), profiles: profiles)
|
||||
case .text(let txt):
|
||||
if case .hashtag = blocks[safe: ind+1] {
|
||||
// SPECIAL CASE:
|
||||
// Do not trim whitespaces from suffix if the following block is a hashtag.
|
||||
// This is because of the code further up (see "SPECIAL CASE").
|
||||
return str + CompatibleText(stringLiteral: reduce_text_block(ind: ind, hide_text_index: -1, txt: txt))
|
||||
str = str + CompatibleText(stringLiteral: reduce_text_block(ind: ind, hide_text_index: -1, txt: txt.as_str()))
|
||||
} else {
|
||||
return str + CompatibleText(stringLiteral: reduce_text_block(ind: ind, hide_text_index: hide_text_index, txt: txt))
|
||||
str = str + CompatibleText(stringLiteral: reduce_text_block(ind: ind, hide_text_index: hide_text_index, txt: txt.as_str()))
|
||||
}
|
||||
case .relay(let relay):
|
||||
return str + CompatibleText(stringLiteral: relay)
|
||||
case .hashtag(let htag):
|
||||
return str + hashtag_str(htag)
|
||||
str = str + hashtag_str(htag.as_str())
|
||||
case .invoice(let invoice):
|
||||
return str + invoice_str(invoice)
|
||||
guard let inv = invoice.as_invoice() else { return }
|
||||
invoices.append(inv)
|
||||
case .url(let url):
|
||||
return str + url_str(url)
|
||||
guard let url = URL(string: url.as_str()) else { return }
|
||||
let url_type = classify_url(url)
|
||||
switch url_type {
|
||||
case .media:
|
||||
urls.append(url_type)
|
||||
case .link(let url):
|
||||
urls.append(url_type)
|
||||
str = str + url_str(url)
|
||||
}
|
||||
case .mention_index:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return NoteArtifactsSeparated(content: txt, words: bs.words, urls: urls, invoices: invoices)
|
||||
return NoteArtifactsSeparated(content: txt, words: blocks.words, urls: urls, invoices: invoices)
|
||||
}
|
||||
|
||||
func reduce_text_block(ind: Int, hide_text_index: Int, txt: String) -> String {
|
||||
@@ -262,13 +301,17 @@ func mention_str(_ m: Mention<MentionRef>, profiles: Profiles) -> CompatibleText
|
||||
let bech32String = Bech32Object.encode(m.ref.toBech32Object())
|
||||
|
||||
let display_str: String = {
|
||||
switch m.ref {
|
||||
case .pubkey(let pk): return getDisplayName(pk: pk, profiles: profiles)
|
||||
switch m.ref.nip19 {
|
||||
case .npub(let pk): return getDisplayName(pk: pk, profiles: profiles)
|
||||
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_identifier(bech32String)
|
||||
case .nsec(let prv):
|
||||
guard let npub = privkey_to_pubkey(privkey: prv)?.npub else { return "nsec..." }
|
||||
return abbrev_identifier(npub)
|
||||
case .nscript(_): return bech32String
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
@@ -23,6 +23,21 @@ struct Blur: UIViewRepresentable {
|
||||
}
|
||||
}
|
||||
|
||||
extension bech32_nprofile {
|
||||
func matches_pubkey(pk: Pubkey) -> Bool {
|
||||
pk.id.withUnsafeBytes { bytes in
|
||||
memcmp(self.pubkey, bytes, 32) == 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension bech32_npub {
|
||||
func matches_pubkey(pk: Pubkey) -> Bool {
|
||||
pk.id.withUnsafeBytes { bytes in
|
||||
memcmp(self.pubkey, bytes, 32) == 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct NoteContentView: View {
|
||||
|
||||
@@ -280,7 +295,7 @@ struct NoteContentView: View {
|
||||
}
|
||||
await preload_event(plan: plan, state: damus_state)
|
||||
} else if force_artifacts {
|
||||
let arts = render_note_content(ev: event, profiles: damus_state.profiles, keypair: damus_state.keypair)
|
||||
let arts = render_note_content(ndb: damus_state.ndb, ev: event, profiles: damus_state.profiles, keypair: damus_state.keypair)
|
||||
self.artifacts_model.state = .loaded(arts)
|
||||
}
|
||||
}
|
||||
@@ -335,19 +350,36 @@ struct NoteContentView: View {
|
||||
var body: some View {
|
||||
ArtifactContent
|
||||
.onReceive(handle_notify(.profile_updated)) { profile in
|
||||
let blocks = event.blocks(damus_state.keypair)
|
||||
for block in blocks.blocks {
|
||||
guard let blocks_txn = event.blocks(ndb: damus_state.ndb) else {
|
||||
return
|
||||
}
|
||||
let blocks = blocks_txn.unsafeUnownedValue
|
||||
for block in blocks.iter(note: event) {
|
||||
switch block {
|
||||
case .mention(let m):
|
||||
if case .pubkey(let pk) = m.ref, pk == profile.pubkey {
|
||||
load(force_artifacts: true)
|
||||
return
|
||||
guard let typ = m.bech32_type else {
|
||||
continue
|
||||
}
|
||||
switch typ {
|
||||
case .nprofile:
|
||||
if m.bech32.nprofile.matches_pubkey(pk: profile.pubkey) {
|
||||
load(force_artifacts: true)
|
||||
}
|
||||
case .npub:
|
||||
if m.bech32.npub.matches_pubkey(pk: profile.pubkey) {
|
||||
load(force_artifacts: true)
|
||||
}
|
||||
case .nevent: continue
|
||||
case .nrelay: continue
|
||||
case .nsec: continue
|
||||
case .note: continue
|
||||
case .naddr: continue
|
||||
}
|
||||
case .relay: return
|
||||
case .text: return
|
||||
case .hashtag: return
|
||||
case .url: return
|
||||
case .invoice: return
|
||||
case .mention_index(_): return
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -503,13 +535,19 @@ struct NoteContentView_Previews: PreviewProvider {
|
||||
}
|
||||
}
|
||||
|
||||
func separate_images(ev: NostrEvent, keypair: Keypair) -> [MediaUrl]? {
|
||||
let urlBlocks: [URL] = ev.blocks(keypair).blocks.reduce(into: []) { urls, block in
|
||||
guard case .url(let url) = block else {
|
||||
func separate_images(ndb: Ndb, ev: NostrEvent, keypair: Keypair) -> [MediaUrl]? {
|
||||
guard let blocks_txn = ev.blocks(ndb: ndb) else {
|
||||
return nil
|
||||
}
|
||||
let blocks = blocks_txn.unsafeUnownedValue
|
||||
let urlBlocks: [URL] = blocks.iter(note: ev).reduce(into: []) { urls, block in
|
||||
guard case .url(let url) = block,
|
||||
let parsed_url = URL(string: url.as_str()) else {
|
||||
return
|
||||
}
|
||||
if classify_url(url).is_img != nil {
|
||||
urls.append(url)
|
||||
|
||||
if classify_url(parsed_url).is_img != nil {
|
||||
urls.append(parsed_url)
|
||||
}
|
||||
}
|
||||
let mediaUrls = urlBlocks.map { MediaUrl.image($0) }
|
||||
|
||||
@@ -82,7 +82,7 @@ struct SelectedEventView: View {
|
||||
|
||||
var Mention: some View {
|
||||
Group {
|
||||
if let mention = first_eref_mention(ev: event, keypair: damus.keypair) {
|
||||
if let mention = first_eref_mention(ndb: damus.ndb, ev: event, keypair: damus.keypair) {
|
||||
MentionView(damus_state: damus, mention: mention)
|
||||
.padding(.horizontal)
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ let test_longform_event = LongformEvent.parse(from: NostrEvent(
|
||||
struct LongformView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let st = test_damus_state
|
||||
let artifacts = render_note_content(ev: test_longform_event.event, profiles: st.profiles, keypair: Keypair(pubkey: .empty, privkey: nil))
|
||||
let artifacts = render_note_content(ndb: st.ndb, ev: test_longform_event.event, profiles: st.profiles, keypair: Keypair(pubkey: .empty, privkey: nil))
|
||||
|
||||
let model = NoteArtifactsModel(state: .loaded(artifacts))
|
||||
ScrollView {
|
||||
|
||||
@@ -18,7 +18,7 @@ func process_local_notification(state: HeadlessDamusState, event ev: NostrEvent)
|
||||
return
|
||||
}
|
||||
|
||||
guard let local_notification = generate_local_notification_object(from: ev, state: state) else {
|
||||
guard let local_notification = generate_local_notification_object(ndb: state.ndb, from: ev, state: state) else {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -65,19 +65,21 @@ func should_display_notification(state: HeadlessDamusState, event ev: NostrEvent
|
||||
return true
|
||||
}
|
||||
|
||||
func generate_local_notification_object(from ev: NostrEvent, state: HeadlessDamusState) -> LocalNotification? {
|
||||
func generate_local_notification_object(ndb: Ndb, from ev: NostrEvent, state: HeadlessDamusState) -> LocalNotification? {
|
||||
guard let type = ev.known_kind else {
|
||||
return nil
|
||||
}
|
||||
|
||||
if type == .text, state.settings.mention_notification {
|
||||
let blocks = ev.blocks(state.keypair).blocks
|
||||
|
||||
for case .mention(let mention) in blocks {
|
||||
guard case .pubkey(let pk) = mention.ref, pk == state.keypair.pubkey else {
|
||||
if type == .text,
|
||||
state.settings.mention_notification,
|
||||
let blocks = ev.blocks(ndb: ndb)?.unsafeUnownedValue
|
||||
{
|
||||
for case .mention(let mention) in blocks.iter(note: ev) {
|
||||
guard case .npub = mention.bech32_type,
|
||||
(memcmp(state.keypair.pubkey.id.bytes, mention.bech32.npub.pubkey, 32) == 0) else {
|
||||
continue
|
||||
}
|
||||
let content_preview = render_notification_content_preview(ev: ev, profiles: state.profiles, keypair: state.keypair)
|
||||
let content_preview = render_notification_content_preview(ndb: ndb, ev: ev, profiles: state.profiles, keypair: state.keypair)
|
||||
return LocalNotification(type: .mention, event: ev, target: .note(ev), content: content_preview)
|
||||
}
|
||||
|
||||
@@ -101,13 +103,13 @@ func generate_local_notification_object(from ev: NostrEvent, state: HeadlessDamu
|
||||
state.settings.repost_notification,
|
||||
let inner_ev = ev.get_inner_event()
|
||||
{
|
||||
let content_preview = render_notification_content_preview(ev: inner_ev, profiles: state.profiles, keypair: state.keypair)
|
||||
let content_preview = render_notification_content_preview(ndb: ndb, ev: inner_ev, profiles: state.profiles, keypair: state.keypair)
|
||||
return LocalNotification(type: .repost, event: ev, target: .note(inner_ev), content: content_preview)
|
||||
} else if type == .like, state.settings.like_notification, let evid = ev.referenced_ids.last {
|
||||
if let txn = state.ndb.lookup_note(evid, txn_name: "local_notification_like"),
|
||||
let liked_event = txn.unsafeUnownedValue
|
||||
{
|
||||
let content_preview = render_notification_content_preview(ev: liked_event, profiles: state.profiles, keypair: state.keypair)
|
||||
let content_preview = render_notification_content_preview(ndb: ndb, ev: liked_event, profiles: state.profiles, keypair: state.keypair)
|
||||
return LocalNotification(type: .like, event: ev, target: .note(liked_event), content: content_preview)
|
||||
} else {
|
||||
return LocalNotification(type: .like, event: ev, target: .note_id(evid), content: "")
|
||||
@@ -144,10 +146,10 @@ func create_local_notification(profiles: Profiles, notify: LocalNotification) {
|
||||
}
|
||||
}
|
||||
|
||||
func render_notification_content_preview(ev: NostrEvent, profiles: Profiles, keypair: Keypair) -> String {
|
||||
func render_notification_content_preview(ndb: Ndb, ev: NostrEvent, profiles: Profiles, keypair: Keypair) -> String {
|
||||
|
||||
let prefix_len = 300
|
||||
let artifacts = render_note_content(ev: ev, profiles: profiles, keypair: keypair)
|
||||
let artifacts = render_note_content(ndb: ndb, ev: ev, profiles: profiles, keypair: keypair)
|
||||
|
||||
// special case for longform events
|
||||
if ev.known_kind == .longform {
|
||||
|
||||
@@ -97,7 +97,43 @@ extension NostrPost {
|
||||
}
|
||||
}
|
||||
|
||||
func parse_post_blocks(content: String) -> [Block] {
|
||||
return parse_note_content(content: .content(content, nil)).blocks
|
||||
/// Return a list of tags
|
||||
func parse_post_blocks(content: String) -> Blocks? {
|
||||
let buf_size = 16000
|
||||
var buffer = Data(capacity: buf_size)
|
||||
var blocks_ptr = ndb_blocks_ptr()
|
||||
var ok = false
|
||||
|
||||
return content.withCString { c_content -> Blocks? in
|
||||
buffer.withUnsafeMutableBytes { buf in
|
||||
let res = ndb_parse_content(buf, Int32(buf_size), c_content, Int32(content.utf8.count), &blocks_ptr.ptr)
|
||||
ok = res != 0
|
||||
}
|
||||
|
||||
guard ok else { return nil }
|
||||
|
||||
let words = ndb_blocks_word_count(blocks_ptr.ptr)
|
||||
let bs = collect_blocks(ptr: blocks_ptr, content: c_content)
|
||||
return Blocks(words: Int(words), blocks: bs)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fileprivate func collect_blocks(ptr: ndb_blocks_ptr, content: UnsafePointer<CChar>) -> [Block] {
|
||||
var i = ndb_block_iterator()
|
||||
var blocks: [Block] = []
|
||||
var block_ptr = ndb_block_ptr()
|
||||
|
||||
ndb_blocks_iterate_start(content, ptr.ptr, &i);
|
||||
block_ptr.ptr = ndb_blocks_iterate_next(&i)
|
||||
while (block_ptr.ptr != nil) {
|
||||
// tags are only used for indexed mentions which aren't used in
|
||||
// posts anymore, so to simplify the API let's set this to nil
|
||||
if let block = Block(block: block_ptr, tags: nil) {
|
||||
blocks.append(block);
|
||||
}
|
||||
block_ptr.ptr = ndb_blocks_iterate_next(&i)
|
||||
}
|
||||
|
||||
return blocks
|
||||
}
|
||||
|
||||
@@ -47,8 +47,9 @@ struct AboutView: View {
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
let blocks = parse_note_content(content: .content(about, nil))
|
||||
about_string = render_blocks(blocks: blocks, profiles: state.profiles).content.attributed
|
||||
// TODO: Fix about content
|
||||
//let blocks = ndb_parse_content(content: .content(about, nil))
|
||||
//about_string = render_blocks(blocks: blocks, profiles: state.profiles).content.attributed
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -781,7 +781,7 @@ class HomeModel: ContactsDelegate {
|
||||
notification_status.new_events = notifs
|
||||
|
||||
guard should_display_notification(state: damus_state, event: ev, mode: .local),
|
||||
let notification_object = generate_local_notification_object(from: ev, state: damus_state)
|
||||
let notification_object = generate_local_notification_object(ndb: self.damus_state.ndb, from: ev, state: damus_state)
|
||||
else {
|
||||
return
|
||||
}
|
||||
@@ -1155,7 +1155,7 @@ func create_in_app_profile_zap_notification(profiles: Profiles, zap: Zap, locale
|
||||
content.title = NotificationFormatter.zap_notification_title(zap)
|
||||
content.body = NotificationFormatter.zap_notification_body(profiles: profiles, zap: zap, locale: locale)
|
||||
content.sound = UNNotificationSound.default
|
||||
content.userInfo = LossyLocalNotification(type: .profile_zap, mention: .pubkey(profile_id)).to_user_info()
|
||||
content.userInfo = LossyLocalNotification(type: .profile_zap, mention: .init(nip19: .npub(profile_id))).to_user_info()
|
||||
|
||||
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
|
||||
|
||||
|
||||
@@ -159,11 +159,14 @@ 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, can_hide_last_previewable_refs: true)
|
||||
// TODO: fix translated blocks
|
||||
//let translated_blocks = parse_note_content(content: .content(translated_note, event.tags))
|
||||
//let artifacts = render_blocks(blocks: translated_blocks, profiles: profiles, can_hide_last_previewable_refs: true)
|
||||
|
||||
return .not_needed
|
||||
|
||||
// and cache it
|
||||
return .translated(Translated(artifacts: artifacts, language: note_lang))
|
||||
//return .translated(Translated(artifacts: artifacts, language: note_lang))
|
||||
}
|
||||
|
||||
func current_language() -> String {
|
||||
|
||||
@@ -408,7 +408,7 @@ func invoice_to_zap_invoice(_ invoice: Invoice) -> ZapInvoice? {
|
||||
return nil
|
||||
}
|
||||
|
||||
return ZapInvoice(description: invoice.description, amount: amt, string: invoice.string, expiry: invoice.expiry, payment_hash: invoice.payment_hash, created_at: invoice.created_at)
|
||||
return ZapInvoice(description: invoice.description, amount: amt, string: invoice.string, expiry: invoice.expiry, created_at: invoice.created_at)
|
||||
}
|
||||
|
||||
func determine_zap_target(_ ev: NostrEvent) -> ZapTarget? {
|
||||
@@ -422,35 +422,44 @@ func determine_zap_target(_ ev: NostrEvent) -> ZapTarget? {
|
||||
|
||||
return .profile(ptag)
|
||||
}
|
||||
|
||||
|
||||
extension UnsafePointer<CChar> {
|
||||
func as_str() -> String {
|
||||
String(cString: self)
|
||||
}
|
||||
}
|
||||
|
||||
func decode_bolt11(_ s: String) -> Invoice? {
|
||||
var bs = note_blocks()
|
||||
bs.num_blocks = 0
|
||||
blocks_init(&bs)
|
||||
|
||||
let bytes = s.utf8CString
|
||||
var bolt11_ptr: UnsafeMutablePointer<bolt11>?
|
||||
|
||||
let _ = bytes.withUnsafeBufferPointer { p in
|
||||
damus_parse_content(&bs, p.baseAddress)
|
||||
bolt11_ptr = bolt11_decode(nil, p.baseAddress, nil)
|
||||
}
|
||||
|
||||
guard bs.num_blocks == 1 else {
|
||||
blocks_free(&bs)
|
||||
|
||||
guard let bolt11 = maybe_pointee(bolt11_ptr) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let block = bs.blocks[0]
|
||||
|
||||
guard let converted = Block(block) else {
|
||||
blocks_free(&bs)
|
||||
return nil
|
||||
|
||||
var amount: Amount = .any
|
||||
var desc: InvoiceDescription = .description("")
|
||||
if let amt = maybe_pointee(bolt11.msat) {
|
||||
amount = .specific(Int64(amt.millisatoshis))
|
||||
}
|
||||
|
||||
guard case .invoice(let invoice) = converted else {
|
||||
blocks_free(&bs)
|
||||
return nil
|
||||
let expiry = bolt11.expiry
|
||||
let created_at = bolt11.timestamp
|
||||
|
||||
if var deschash = maybe_pointee(bolt11.description_hash) {
|
||||
let data = Data(bytes: &deschash.u, count: 32)
|
||||
desc = .description_hash(data)
|
||||
} else {
|
||||
desc = .description(bolt11.description.as_str())
|
||||
}
|
||||
|
||||
blocks_free(&bs)
|
||||
|
||||
let invoice = Invoice(description: desc, amount: amount, string: s, expiry: expiry, created_at: created_at)
|
||||
|
||||
tal_free(bolt11_ptr)
|
||||
|
||||
return invoice
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user