initial reply revamp
It now understands mentions Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
xcuserdata
|
xcuserdata
|
||||||
Preview\ Content
|
Preview\ Content
|
||||||
|
damus/TestingPrivate.swift
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
4C363A922825FCF2006E126D /* ProfileUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C363A912825FCF2006E126D /* ProfileUpdate.swift */; };
|
4C363A922825FCF2006E126D /* ProfileUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C363A912825FCF2006E126D /* ProfileUpdate.swift */; };
|
||||||
4C363A94282704FA006E126D /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C363A93282704FA006E126D /* Post.swift */; };
|
4C363A94282704FA006E126D /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C363A93282704FA006E126D /* Post.swift */; };
|
||||||
4C363A962827096D006E126D /* PostBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C363A952827096D006E126D /* PostBlock.swift */; };
|
4C363A962827096D006E126D /* PostBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C363A952827096D006E126D /* PostBlock.swift */; };
|
||||||
|
4C363A9828283441006E126D /* TestingPrivate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C363A9728283441006E126D /* TestingPrivate.swift */; };
|
||||||
4C3BEFD22819DB9B00B3DE84 /* ProfileModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFD12819DB9B00B3DE84 /* ProfileModel.swift */; };
|
4C3BEFD22819DB9B00B3DE84 /* ProfileModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFD12819DB9B00B3DE84 /* ProfileModel.swift */; };
|
||||||
4C3BEFD42819DE8F00B3DE84 /* NostrKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFD32819DE8F00B3DE84 /* NostrKind.swift */; };
|
4C3BEFD42819DE8F00B3DE84 /* NostrKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFD32819DE8F00B3DE84 /* NostrKind.swift */; };
|
||||||
4C3BEFD6281D995700B3DE84 /* ActionBarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFD5281D995700B3DE84 /* ActionBarModel.swift */; };
|
4C3BEFD6281D995700B3DE84 /* ActionBarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFD5281D995700B3DE84 /* ActionBarModel.swift */; };
|
||||||
@@ -99,6 +100,7 @@
|
|||||||
4C363A912825FCF2006E126D /* ProfileUpdate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileUpdate.swift; sourceTree = "<group>"; };
|
4C363A912825FCF2006E126D /* ProfileUpdate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileUpdate.swift; sourceTree = "<group>"; };
|
||||||
4C363A93282704FA006E126D /* Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = "<group>"; };
|
4C363A93282704FA006E126D /* Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = "<group>"; };
|
||||||
4C363A952827096D006E126D /* PostBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostBlock.swift; sourceTree = "<group>"; };
|
4C363A952827096D006E126D /* PostBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostBlock.swift; sourceTree = "<group>"; };
|
||||||
|
4C363A9728283441006E126D /* TestingPrivate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestingPrivate.swift; sourceTree = "<group>"; };
|
||||||
4C3BEFD12819DB9B00B3DE84 /* ProfileModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileModel.swift; sourceTree = "<group>"; };
|
4C3BEFD12819DB9B00B3DE84 /* ProfileModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileModel.swift; sourceTree = "<group>"; };
|
||||||
4C3BEFD32819DE8F00B3DE84 /* NostrKind.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NostrKind.swift; sourceTree = "<group>"; };
|
4C3BEFD32819DE8F00B3DE84 /* NostrKind.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NostrKind.swift; sourceTree = "<group>"; };
|
||||||
4C3BEFD5281D995700B3DE84 /* ActionBarModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionBarModel.swift; sourceTree = "<group>"; };
|
4C3BEFD5281D995700B3DE84 /* ActionBarModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionBarModel.swift; sourceTree = "<group>"; };
|
||||||
@@ -279,6 +281,7 @@
|
|||||||
4CE6DEEC27F7A08200C66700 /* Preview Content */,
|
4CE6DEEC27F7A08200C66700 /* Preview Content */,
|
||||||
4CEE2AF4280B29E600AB5EEF /* TimeAgo.swift */,
|
4CEE2AF4280B29E600AB5EEF /* TimeAgo.swift */,
|
||||||
4CE4F8CC281352B30009DFBB /* Notifications.swift */,
|
4CE4F8CC281352B30009DFBB /* Notifications.swift */,
|
||||||
|
4C363A9728283441006E126D /* TestingPrivate.swift */,
|
||||||
);
|
);
|
||||||
path = damus;
|
path = damus;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -464,6 +467,7 @@
|
|||||||
4C75EFAD28049CFB0006080F /* PostButton.swift in Sources */,
|
4C75EFAD28049CFB0006080F /* PostButton.swift in Sources */,
|
||||||
4C75EFB92804A2740006080F /* EventView.swift in Sources */,
|
4C75EFB92804A2740006080F /* EventView.swift in Sources */,
|
||||||
4C7FF7D52823313F009601DB /* Mentions.swift in Sources */,
|
4C7FF7D52823313F009601DB /* Mentions.swift in Sources */,
|
||||||
|
4C363A9828283441006E126D /* TestingPrivate.swift in Sources */,
|
||||||
4C363A9028247A1D006E126D /* NostrLink.swift in Sources */,
|
4C363A9028247A1D006E126D /* NostrLink.swift in Sources */,
|
||||||
4C0A3F8C280F5FCA000448DE /* ChatroomView.swift in Sources */,
|
4C0A3F8C280F5FCA000448DE /* ChatroomView.swift in Sources */,
|
||||||
4C0A3F91280F6528000448DE /* ChatView.swift in Sources */,
|
4C0A3F91280F6528000448DE /* ChatView.swift in Sources */,
|
||||||
|
|||||||
@@ -67,7 +67,8 @@ struct ContentView: View {
|
|||||||
let timer = Timer.publish(every: 60, on: .main, in: .common).autoconnect()
|
let timer = Timer.publish(every: 60, on: .main, in: .common).autoconnect()
|
||||||
|
|
||||||
let sub_id = UUID().description
|
let sub_id = UUID().description
|
||||||
let pubkey = "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245"
|
let pubkey = MY_PUBKEY
|
||||||
|
let privkey = MY_PRIVKEY
|
||||||
|
|
||||||
var NotificationTab: some View {
|
var NotificationTab: some View {
|
||||||
ZStack(alignment: .center) {
|
ZStack(alignment: .center) {
|
||||||
|
|||||||
@@ -130,8 +130,8 @@ class ThreadModel: ObservableObject {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if let reply_id = ev.find_direct_reply() {
|
for reply in ev.direct_replies() {
|
||||||
self.replies.add(id: ev.id, reply_id: reply_id)
|
self.replies.add(id: ev.id, reply_id: reply.ref_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.events.append(ev)
|
self.events.append(ev)
|
||||||
|
|||||||
@@ -53,6 +53,10 @@ class NostrEvent: Codable, Identifiable, CustomStringConvertible {
|
|||||||
return parse_mentions(content: self.content, tags: self.tags)
|
return parse_mentions(content: self.content, tags: self.tags)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
lazy var event_refs: [EventRef] = {
|
||||||
|
return interpret_event_refs(blocks: self.blocks, tags: self.tags)
|
||||||
|
}()
|
||||||
|
|
||||||
var description: String {
|
var description: String {
|
||||||
let p = pow.map { String($0) } ?? "?"
|
let p = pow.map { String($0) } ?? "?"
|
||||||
return "NostrEvent { id: \(id) pubkey \(pubkey) kind \(kind) tags \(tags) pow \(p) content '\(content)' }"
|
return "NostrEvent { id: \(id) pubkey \(pubkey) kind \(kind) tags \(tags) pow \(p) content '\(content)' }"
|
||||||
@@ -79,28 +83,12 @@ class NostrEvent: Codable, Identifiable, CustomStringConvertible {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
/// find a non-root reply
|
public func direct_replies() -> [ReferencedId] {
|
||||||
public func find_direct_reply() -> String? {
|
return event_refs.reduce(into: []) { acc, evref in
|
||||||
var i = tags.count - 1
|
if let direct_reply = evref.is_direct_reply {
|
||||||
var first: String? = nil
|
acc.append(direct_reply)
|
||||||
var matches: Int = 0
|
|
||||||
|
|
||||||
while i >= 0 {
|
|
||||||
let tag = tags[i]
|
|
||||||
if tag.count >= 2 && tag[0] == "e" {
|
|
||||||
if first == nil {
|
|
||||||
first = tag[1]
|
|
||||||
}
|
|
||||||
matches += 1
|
|
||||||
}
|
}
|
||||||
i -= 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if matches <= 1 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return first
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func last_refid() -> ReferencedId? {
|
public func last_refid() -> ReferencedId? {
|
||||||
@@ -120,29 +108,6 @@ class NostrEvent: Codable, Identifiable, CustomStringConvertible {
|
|||||||
return tag_to_refid(tags[last])
|
return tag_to_refid(tags[last])
|
||||||
}
|
}
|
||||||
|
|
||||||
public func directly_references(_ id: String) -> Bool {
|
|
||||||
// conditions: if it only has 1 e ref
|
|
||||||
// OR it has more than 1 e ref, ignoring the first
|
|
||||||
|
|
||||||
var nrefs = 0
|
|
||||||
var i = 0
|
|
||||||
var first_matched = false
|
|
||||||
var matched = true
|
|
||||||
|
|
||||||
for tag in tags {
|
|
||||||
if tag.count >= 2 && tag[0] == "e" {
|
|
||||||
nrefs += 1
|
|
||||||
if tag[1] == id {
|
|
||||||
matched = true
|
|
||||||
first_matched = nrefs == 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
return (nrefs == 1 && matched) || (nrefs > 1 && matched && !first_matched)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func references(id: String, key: String) -> Bool {
|
public func references(id: String, key: String) -> Bool {
|
||||||
for tag in tags {
|
for tag in tags {
|
||||||
if tag.count >= 2 && tag[0] == key {
|
if tag.count >= 2 && tag[0] == key {
|
||||||
@@ -156,13 +121,7 @@ class NostrEvent: Codable, Identifiable, CustomStringConvertible {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public var is_reply: Bool {
|
public var is_reply: Bool {
|
||||||
for tag in tags {
|
return event_is_reply(self)
|
||||||
if tag[0] == "e" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public var referenced_ids: [ReferencedId] {
|
public var referenced_ids: [ReferencedId] {
|
||||||
@@ -438,3 +397,146 @@ func gather_reply_ids(our_pubkey: String, from: NostrEvent) -> [ReferencedId] {
|
|||||||
return ids
|
return ids
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum EventRef {
|
||||||
|
case mention(Mention)
|
||||||
|
case thread_id(ReferencedId)
|
||||||
|
case reply(ReferencedId)
|
||||||
|
case reply_to_root(ReferencedId)
|
||||||
|
|
||||||
|
var is_mention: Mention? {
|
||||||
|
if case .mention(let m) = self {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var is_direct_reply: ReferencedId? {
|
||||||
|
switch self {
|
||||||
|
case .mention:
|
||||||
|
return nil
|
||||||
|
case .thread_id:
|
||||||
|
return nil
|
||||||
|
case .reply(let refid):
|
||||||
|
return refid
|
||||||
|
case .reply_to_root(let refid):
|
||||||
|
return refid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var is_thread_id: ReferencedId? {
|
||||||
|
switch self {
|
||||||
|
case .mention(let mention):
|
||||||
|
return nil
|
||||||
|
case .thread_id(let referencedId):
|
||||||
|
return referencedId
|
||||||
|
case .reply(let referencedId):
|
||||||
|
return nil
|
||||||
|
case .reply_to_root(let referencedId):
|
||||||
|
return referencedId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var is_reply: ReferencedId? {
|
||||||
|
switch self {
|
||||||
|
case .mention:
|
||||||
|
return nil
|
||||||
|
case .thread_id:
|
||||||
|
return nil
|
||||||
|
case .reply(let refid):
|
||||||
|
return refid
|
||||||
|
case .reply_to_root(let refid):
|
||||||
|
return refid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func has_any_e_refs(_ tags: [[String]]) -> Bool {
|
||||||
|
for tag in tags {
|
||||||
|
if tag.count >= 2 && tag[0] == "e" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func build_mention_indices(_ blocks: [Block], type: MentionType) -> Set<Int> {
|
||||||
|
return blocks.reduce(into: []) { acc, block in
|
||||||
|
switch block {
|
||||||
|
case .mention(let m):
|
||||||
|
if m.type == type {
|
||||||
|
acc.insert(m.index)
|
||||||
|
}
|
||||||
|
case .text:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func interp_event_refs_without_mentions(_ refs: [ReferencedId]) -> [EventRef] {
|
||||||
|
if refs.count == 0 {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
if refs.count == 1 {
|
||||||
|
return [.reply_to_root(refs[0])]
|
||||||
|
}
|
||||||
|
|
||||||
|
var evrefs: [EventRef] = []
|
||||||
|
var first: Bool = true
|
||||||
|
for ref in refs {
|
||||||
|
if first {
|
||||||
|
evrefs.append(.thread_id(ref))
|
||||||
|
first = false
|
||||||
|
} else {
|
||||||
|
evrefs.append(.reply(ref))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return evrefs
|
||||||
|
}
|
||||||
|
|
||||||
|
func interp_event_refs_with_mentions(tags: [[String]], mention_indices: Set<Int>) -> [EventRef] {
|
||||||
|
var mentions: [EventRef] = []
|
||||||
|
var ev_refs: [ReferencedId] = []
|
||||||
|
var i: Int = 0
|
||||||
|
|
||||||
|
for tag in tags {
|
||||||
|
if tag.count >= 2 && tag[0] == "e" {
|
||||||
|
let ref = tag_to_refid(tag)!
|
||||||
|
if mention_indices.contains(i) {
|
||||||
|
let mention = Mention(index: i, type: .event, ref: ref)
|
||||||
|
mentions.append(.mention(mention))
|
||||||
|
} else {
|
||||||
|
ev_refs.append(ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
var replies = interp_event_refs_without_mentions(ev_refs)
|
||||||
|
replies.append(contentsOf: mentions)
|
||||||
|
return replies
|
||||||
|
}
|
||||||
|
|
||||||
|
func interpret_event_refs(blocks: [Block], tags: [[String]]) -> [EventRef] {
|
||||||
|
if tags.count == 0 {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
/// build a set of indices for each event mention
|
||||||
|
let mention_indices = build_mention_indices(blocks, type: .event)
|
||||||
|
|
||||||
|
/// simpler case with no mentions
|
||||||
|
if mention_indices.count == 0 {
|
||||||
|
let ev_refs = get_referenced_ids(tags: tags, key: "e")
|
||||||
|
return interp_event_refs_without_mentions(ev_refs)
|
||||||
|
}
|
||||||
|
|
||||||
|
return interp_event_refs_with_mentions(tags: tags, mention_indices: mention_indices)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func event_is_reply(_ ev: NostrEvent) -> Bool {
|
||||||
|
return ev.event_refs.contains { evref in
|
||||||
|
return evref.is_reply != nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -129,19 +129,27 @@ func make_reply_map(active: NostrEvent, events: [NostrEvent]) -> [String: ()]
|
|||||||
return is_reply
|
return is_reply
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_root = active.is_root_event()
|
|
||||||
|
|
||||||
for ev in events {
|
for ev in events {
|
||||||
if is_root && ev.directly_references(active.id) {
|
/// does this event reply to the active event?
|
||||||
is_reply[ev.id] = ()
|
for ev_ref in ev.event_refs {
|
||||||
start = i
|
if let reply = ev_ref.is_reply {
|
||||||
} else if !is_root && ev.references(id: active.id, key: "e") {
|
if reply.ref_id == active.id {
|
||||||
is_reply[ev.id] = ()
|
is_reply[ev.id] = ()
|
||||||
start = i
|
start = i
|
||||||
} else if active.references(id: ev.id, key: "e") {
|
}
|
||||||
is_reply[ev.id] = ()
|
}
|
||||||
start = i
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// does the active event reply to this event?
|
||||||
|
for active_ref in active.event_refs {
|
||||||
|
if let reply = active_ref.is_reply {
|
||||||
|
if reply.ref_id == ev.id {
|
||||||
|
is_reply[ev.id] = ()
|
||||||
|
start = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
i += 1
|
i += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,27 +194,6 @@ func determine_highlight(reply_map: [String: ()], current: NostrEvent, active: N
|
|||||||
} else {
|
} else {
|
||||||
return .none
|
return .none
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
if current.id == active.id {
|
|
||||||
return .main
|
|
||||||
}
|
|
||||||
if active.is_root_event() {
|
|
||||||
if active.directly_references(current.id) {
|
|
||||||
return .reply
|
|
||||||
} else if current.directly_references(active.id) {
|
|
||||||
return .reply
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if active.references(id: current.id, key: "e") {
|
|
||||||
return .reply
|
|
||||||
} else if current.references(id: active.id, key: "e") {
|
|
||||||
return .reply
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return .none
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func calculated_collapsed_events(collapsed: Bool, active: NostrEvent?, events: [NostrEvent]) -> [CollapsedEvent] {
|
func calculated_collapsed_events(collapsed: Bool, active: NostrEvent?, events: [NostrEvent]) -> [CollapsedEvent] {
|
||||||
|
|||||||
@@ -33,6 +33,80 @@ class damusTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testMentionIsntReply() throws {
|
||||||
|
let content = "this is #[0] a mention"
|
||||||
|
let tags = [["e", "event_id"]]
|
||||||
|
let blocks = parse_mentions(content: content, tags: tags)
|
||||||
|
let event_refs = interpret_event_refs(blocks: blocks, tags: tags)
|
||||||
|
|
||||||
|
XCTAssertEqual(event_refs.count, 1)
|
||||||
|
|
||||||
|
let ref = event_refs[0]
|
||||||
|
|
||||||
|
XCTAssertNil(ref.is_reply)
|
||||||
|
XCTAssertNil(ref.is_thread_id)
|
||||||
|
XCTAssertNil(ref.is_direct_reply)
|
||||||
|
XCTAssertEqual(ref.is_mention!.type, .event)
|
||||||
|
XCTAssertEqual(ref.is_mention!.ref.ref_id, "event_id")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testRootReplyWithMention() throws {
|
||||||
|
let content = "this is #[1] a mention"
|
||||||
|
let tags = [["e", "thread_id"], ["e", "mentioned_id"]]
|
||||||
|
let blocks = parse_mentions(content: content, tags: tags)
|
||||||
|
let event_refs = interpret_event_refs(blocks: blocks, tags: tags)
|
||||||
|
|
||||||
|
XCTAssertEqual(event_refs.count, 2)
|
||||||
|
XCTAssertNotNil(event_refs[0].is_reply)
|
||||||
|
XCTAssertNotNil(event_refs[0].is_thread_id)
|
||||||
|
XCTAssertNotNil(event_refs[0].is_reply)
|
||||||
|
XCTAssertNotNil(event_refs[0].is_direct_reply)
|
||||||
|
XCTAssertEqual(event_refs[0].is_reply!.ref_id, "thread_id")
|
||||||
|
XCTAssertEqual(event_refs[0].is_thread_id!.ref_id, "thread_id")
|
||||||
|
XCTAssertNotNil(event_refs[1].is_mention)
|
||||||
|
XCTAssertEqual(event_refs[1].is_mention!.type, .event)
|
||||||
|
XCTAssertEqual(event_refs[1].is_mention!.ref.ref_id, "mentioned_id")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testThreadedReply() throws {
|
||||||
|
let content = "this is some content"
|
||||||
|
let tags = [["e", "thread_id"], ["e", "reply_id"]]
|
||||||
|
let blocks = parse_mentions(content: content, tags: tags)
|
||||||
|
let event_refs = interpret_event_refs(blocks: blocks, tags: tags)
|
||||||
|
|
||||||
|
XCTAssertEqual(event_refs.count, 2)
|
||||||
|
let r1 = event_refs[0]
|
||||||
|
let r2 = event_refs[1]
|
||||||
|
|
||||||
|
XCTAssertEqual(r1.is_thread_id!.ref_id, "thread_id")
|
||||||
|
XCTAssertEqual(r2.is_reply!.ref_id, "reply_id")
|
||||||
|
XCTAssertEqual(r2.is_direct_reply!.ref_id, "reply_id")
|
||||||
|
XCTAssertNil(r1.is_direct_reply)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testRootReply() throws {
|
||||||
|
let content = "this is a reply"
|
||||||
|
let tags = [["e", "thread_id"]]
|
||||||
|
let blocks = parse_mentions(content: content, tags: tags)
|
||||||
|
let event_refs = interpret_event_refs(blocks: blocks, tags: tags)
|
||||||
|
|
||||||
|
XCTAssertEqual(event_refs.count, 1)
|
||||||
|
let r = event_refs[0]
|
||||||
|
|
||||||
|
XCTAssertEqual(r.is_direct_reply!.ref_id, "thread_id")
|
||||||
|
XCTAssertEqual(r.is_reply!.ref_id, "thread_id")
|
||||||
|
XCTAssertEqual(r.is_thread_id!.ref_id, "thread_id")
|
||||||
|
XCTAssertNil(r.is_mention)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testNoReply() throws {
|
||||||
|
let content = "this is a #[0] reply"
|
||||||
|
let blocks = parse_mentions(content: content, tags: [])
|
||||||
|
let event_refs = interpret_event_refs(blocks: blocks, tags: [])
|
||||||
|
|
||||||
|
XCTAssertEqual(event_refs.count, 0)
|
||||||
|
}
|
||||||
|
|
||||||
func testParseMention() throws {
|
func testParseMention() throws {
|
||||||
let parsed = parse_mentions(content: "this is #[0] a mention", tags: [["e", "event_id"]])
|
let parsed = parse_mentions(content: "this is #[0] a mention", tags: [["e", "event_id"]])
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user