ndb: switch to nostrdb notes
This is a refactor of the codebase to use a more memory-efficient representation of notes. It should also be much faster at decoding since we're using a custom C json parser now. Changelog-Changed: Improved memory usage and performance when processing events
This commit is contained in:
@@ -106,11 +106,7 @@ struct EventActionBar: View {
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $show_share_sheet, onDismiss: { self.show_share_sheet = false }) {
|
||||
if let note_id = bech32_note_id(event.id) {
|
||||
if let url = URL(string: "https://damus.io/" + note_id) {
|
||||
ShareSheet(activityItems: [url])
|
||||
}
|
||||
}
|
||||
ShareSheet(activityItems: [URL(string: "https://damus.io/" + event.id.bech32)!])
|
||||
}
|
||||
.sheet(isPresented: $show_repost_action, onDismiss: { self.show_repost_action = false }) {
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ struct ShareAction: View {
|
||||
|
||||
ShareActionButton(img: "link", text: NSLocalizedString("Copy Link", comment: "Button to copy link to note")) {
|
||||
dismiss()
|
||||
UIPasteboard.general.string = "https://damus.io/" + (bech32_note_id(event.id) ?? event.id)
|
||||
UIPasteboard.general.string = "https://damus.io/" + event.id.bech32
|
||||
}
|
||||
|
||||
let bookmarkImg = isBookmarked ? "bookmark.fill" : "bookmark"
|
||||
|
||||
@@ -36,18 +36,18 @@ struct GradientFollowButton: View {
|
||||
)
|
||||
}
|
||||
.onReceive(handle_notify(.followed)) { ref in
|
||||
guard target.pubkey == ref.ref_id else { return }
|
||||
guard target.follow_ref == ref else { return }
|
||||
self.follow_state = .follows
|
||||
}
|
||||
.onReceive(handle_notify(.unfollowed)) { ref in
|
||||
guard target.pubkey == ref.ref_id else { return }
|
||||
guard target.follow_ref == ref else { return }
|
||||
self.follow_state = .unfollows
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct GradientFollowButtonPreviews: View {
|
||||
let target: FollowTarget = .pubkey("")
|
||||
let target: FollowTarget = .pubkey(.empty)
|
||||
var body: some View {
|
||||
VStack {
|
||||
Text(verbatim: "Unfollows")
|
||||
|
||||
@@ -135,8 +135,7 @@ struct CreateAccountView_Previews: PreviewProvider {
|
||||
}
|
||||
|
||||
func KeyText(_ pubkey: Binding<Pubkey>) -> some View {
|
||||
let decoded = hex_decode(pubkey.wrappedValue)!
|
||||
let bechkey = bech32_encode(hrp: PUBKEY_HRP, decoded)
|
||||
let bechkey = bech32_encode(hrp: PUBKEY_HRP, pubkey.wrappedValue.bytes)
|
||||
return Text(bechkey)
|
||||
.textSelection(.enabled)
|
||||
.multilineTextAlignment(.center)
|
||||
|
||||
@@ -18,7 +18,7 @@ struct DMView: View {
|
||||
var Mention: some View {
|
||||
Group {
|
||||
if let mention = first_eref_mention(ev: event, privkey: damus_state.keypair.privkey) {
|
||||
BuilderEventView(damus: damus_state, event_id: mention.ref.id)
|
||||
BuilderEventView(damus: damus_state, event_id: mention.ref)
|
||||
} else {
|
||||
EmptyView()
|
||||
}
|
||||
|
||||
@@ -72,10 +72,10 @@ func should_show_images(settings: UserSettingsStore, contacts: Contacts, ev: Nos
|
||||
}
|
||||
|
||||
extension View {
|
||||
func pubkey_context_menu(bech32_pubkey: Pubkey) -> some View {
|
||||
func pubkey_context_menu(pubkey: Pubkey) -> some View {
|
||||
return self.contextMenu {
|
||||
Button {
|
||||
UIPasteboard.general.string = bech32_pubkey
|
||||
UIPasteboard.general.string = pubkey.npub
|
||||
} label: {
|
||||
Label(NSLocalizedString("Copy Account ID", comment: "Context menu option for copying the ID of the account that created the note."), image: "copy2")
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ struct EventTop: View {
|
||||
|
||||
func ProfileName(is_anon: Bool) -> some View {
|
||||
let profile = state.profiles.lookup(id: self.pubkey)
|
||||
let pk = is_anon ? "anon" : self.pubkey
|
||||
let pk = is_anon ? ANON_PUBKEY : self.pubkey
|
||||
return EventProfileName(pubkey: pk, profile: profile, damus: state, size: .normal)
|
||||
}
|
||||
|
||||
|
||||
@@ -37,9 +37,9 @@ func reply_desc(profiles: Profiles, event: NostrEvent, locale: Locale = Locale.c
|
||||
return NSLocalizedString("Replying to self", bundle: bundle, comment: "Label to indicate that the user is replying to themself.")
|
||||
}
|
||||
|
||||
let names: [String] = pubkeys.map {
|
||||
let prof = profiles.lookup(id: $0)
|
||||
return Profile.displayName(profile: prof, pubkey: $0).username.truncate(maxLength: 50)
|
||||
let names: [String] = pubkeys.map { pk in
|
||||
let prof = profiles.lookup(id: pk)
|
||||
return Profile.displayName(profile: prof, pubkey: pk).username.truncate(maxLength: 50)
|
||||
}
|
||||
|
||||
let uniqueNames = NSOrderedSet(array: names).array as! [String]
|
||||
|
||||
@@ -27,9 +27,7 @@ struct EventMenuContext: View {
|
||||
var body: some View {
|
||||
HStack {
|
||||
Menu {
|
||||
|
||||
MenuItems(event: event, keypair: keypair, target_pubkey: target_pubkey, bookmarks: bookmarks, muted_threads: muted_threads, settings: settings)
|
||||
|
||||
} label: {
|
||||
Label("", systemImage: "ellipsis")
|
||||
.foregroundColor(Color.gray)
|
||||
@@ -77,13 +75,13 @@ struct MenuItems: View {
|
||||
}
|
||||
|
||||
Button {
|
||||
UIPasteboard.general.string = bech32_pubkey(target_pubkey)
|
||||
UIPasteboard.general.string = target_pubkey.npub
|
||||
} label: {
|
||||
Label(NSLocalizedString("Copy user public key", comment: "Context menu option for copying the ID of the user who created the note."), image: "user")
|
||||
}
|
||||
|
||||
Button {
|
||||
UIPasteboard.general.string = bech32_note_id(event.id) ?? event.id
|
||||
UIPasteboard.general.string = event.id.bech32
|
||||
} label: {
|
||||
Label(NSLocalizedString("Copy note ID", comment: "Context menu option for copying the ID of the note."), image: "note-book")
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ struct EventShell<Content: View>: View {
|
||||
!options.contains(.no_action_bar)
|
||||
}
|
||||
|
||||
func get_mention() -> Mention? {
|
||||
func get_mention() -> Mention<NoteId>? {
|
||||
if self.options.contains(.nested) || self.options.contains(.no_mentions) {
|
||||
return nil
|
||||
}
|
||||
@@ -42,8 +42,8 @@ struct EventShell<Content: View>: View {
|
||||
return first_eref_mention(ev: event, privkey: state.keypair.privkey)
|
||||
}
|
||||
|
||||
func Mention(_ mention: Mention) -> some View {
|
||||
return BuilderEventView(damus: state, event_id: mention.ref.id)
|
||||
func Mention(_ mention: Mention<NoteId>) -> some View {
|
||||
return BuilderEventView(damus: state, event_id: mention.ref)
|
||||
}
|
||||
|
||||
var ActionBar: some View {
|
||||
|
||||
@@ -20,12 +20,12 @@ struct LongformEvent {
|
||||
|
||||
for tag in ev.tags {
|
||||
guard tag.count >= 2 else { continue }
|
||||
switch tag[0] {
|
||||
case "title": longform.title = tag[1]
|
||||
case "image": longform.image = URL(string: tag[1])
|
||||
case "summary": longform.summary = tag[1]
|
||||
switch tag[0].string() {
|
||||
case "title": longform.title = tag[1].string()
|
||||
case "image": longform.image = URL(string: tag[1].string())
|
||||
case "summary": longform.summary = tag[1].string()
|
||||
case "published_at":
|
||||
longform.published_at = Double(tag[1]).map { d in Date(timeIntervalSince1970: d) }
|
||||
longform.published_at = Double(tag[1].string()).map { d in Date(timeIntervalSince1970: d) }
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ struct SelectedEventView: View {
|
||||
EventBody(damus_state: damus, event: event, size: size, options: [.wide])
|
||||
|
||||
if let mention = first_eref_mention(ev: event, privkey: damus.keypair.privkey) {
|
||||
BuilderEventView(damus: damus, event_id: mention.ref.id)
|
||||
BuilderEventView(damus: damus, event_id: mention.ref)
|
||||
.padding(.horizontal)
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ struct TextEvent: View {
|
||||
|
||||
func event_has_tag(ev: NostrEvent, tag: String) -> Bool {
|
||||
for t in ev.tags {
|
||||
if t.count >= 1 && t[0] == tag {
|
||||
if t.count >= 1 && t[0].matches_str(tag) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,18 +31,16 @@ struct FollowButtonView: View {
|
||||
.stroke(follow_state == .unfollows ? .clear : borderColor(), lineWidth: 1)
|
||||
}
|
||||
}
|
||||
.onReceive(handle_notify(.followed)) { pk in
|
||||
guard pk.key == "p", target.pubkey == pk.ref_id else {
|
||||
return
|
||||
}
|
||||
|
||||
.onReceive(handle_notify(.followed)) { follow in
|
||||
guard case .pubkey(let pk) = follow,
|
||||
pk == target.pubkey else { return }
|
||||
|
||||
self.follow_state = .follows
|
||||
}
|
||||
.onReceive(handle_notify(.unfollowed)) { pk in
|
||||
guard pk.key == "p", target.pubkey == pk.ref_id else {
|
||||
return
|
||||
}
|
||||
|
||||
.onReceive(handle_notify(.unfollowed)) { unfollow in
|
||||
guard case .pubkey(let pk) = unfollow,
|
||||
pk == target.pubkey else { return }
|
||||
|
||||
self.follow_state = .unfollows
|
||||
}
|
||||
}
|
||||
@@ -65,7 +63,7 @@ struct FollowButtonView: View {
|
||||
}
|
||||
|
||||
struct FollowButtonPreviews: View {
|
||||
let target: FollowTarget = .pubkey("")
|
||||
let target: FollowTarget = .pubkey(test_pubkey)
|
||||
var body: some View {
|
||||
VStack {
|
||||
Text(verbatim: "Unfollows")
|
||||
|
||||
@@ -146,10 +146,8 @@ func parse_key(_ thekey: String) -> ParsedKey? {
|
||||
|
||||
if let bech_key = decode_bech32_key(key) {
|
||||
switch bech_key {
|
||||
case .pub(let pk):
|
||||
return .pub(pk)
|
||||
case .sec(let sec):
|
||||
return .priv(sec)
|
||||
case .pub(let pk): return .pub(pk)
|
||||
case .sec(let sec): return .priv(sec)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,11 +193,12 @@ func process_login(_ key: ParsedKey, is_pubkey: Bool) async throws {
|
||||
save_pubkey(pubkey: nip05.pubkey)
|
||||
|
||||
case .hex(let hexstr):
|
||||
if is_pubkey {
|
||||
if is_pubkey, let pubkey = hex_decode_pubkey(hexstr) {
|
||||
try clear_saved_privkey()
|
||||
save_pubkey(pubkey: hexstr)
|
||||
} else {
|
||||
try handle_privkey(hexstr)
|
||||
|
||||
save_pubkey(pubkey: pubkey)
|
||||
} else if let privkey = hex_decode_privkey(hexstr) {
|
||||
try handle_privkey(privkey)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,10 +208,8 @@ func process_login(_ key: ParsedKey, is_pubkey: Bool) async throws {
|
||||
guard let pk = privkey_to_pubkey(privkey: privkey) else {
|
||||
throw LoginError.invalid_key
|
||||
}
|
||||
|
||||
if let pub = bech32_pubkey(pk), let priv = bech32_privkey(privkey) {
|
||||
CredentialHandler().save_credential(pubkey: pub, privkey: priv)
|
||||
}
|
||||
|
||||
CredentialHandler().save_credential(pubkey: pk, privkey: privkey)
|
||||
save_pubkey(pubkey: pk)
|
||||
}
|
||||
|
||||
@@ -232,7 +229,7 @@ struct NIP05Result: Decodable {
|
||||
|
||||
struct NIP05User {
|
||||
let pubkey: Pubkey
|
||||
let relays: [String]
|
||||
//let relays: [String]
|
||||
}
|
||||
|
||||
func get_nip05_pubkey(id: String) async -> NIP05User? {
|
||||
@@ -245,30 +242,24 @@ func get_nip05_pubkey(id: String) async -> NIP05User? {
|
||||
let user = parts[0]
|
||||
let host = parts[1]
|
||||
|
||||
guard let url = URL(string: "https://\(host)/.well-known/nostr.json?name=\(user)") else {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let (data, _) = try? await URLSession.shared.data(for: URLRequest(url: url)) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let json: NIP05Result = decode_data(data) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let pubkey = json.names[user] else {
|
||||
guard let url = URL(string: "https://\(host)/.well-known/nostr.json?name=\(user)"),
|
||||
let (data, _) = try? await URLSession.shared.data(for: URLRequest(url: url)),
|
||||
let json: NIP05Result = decode_data(data),
|
||||
let pubkey_hex = json.names[user],
|
||||
let pubkey = hex_decode_pubkey(pubkey_hex)
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
var relays: [String] = []
|
||||
if let rs = json.relays {
|
||||
if let rs = rs[pubkey] {
|
||||
relays = rs
|
||||
}
|
||||
}
|
||||
|
||||
return NIP05User(pubkey: pubkey, relays: relays)
|
||||
if let rs = json.relays, let rs = rs[pubkey] {
|
||||
relays = rs
|
||||
}
|
||||
*/
|
||||
|
||||
return NIP05User(pubkey: pubkey/*, relays: relays*/)
|
||||
}
|
||||
|
||||
struct KeyInput: View {
|
||||
|
||||
@@ -13,15 +13,12 @@ struct MutelistView: View {
|
||||
|
||||
func RemoveAction(pubkey: Pubkey) -> some View {
|
||||
Button {
|
||||
guard let mutelist = damus_state.contacts.mutelist else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let keypair = damus_state.keypair.to_full() else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let new_ev = remove_from_mutelist(keypair: keypair, prev: mutelist, to_remove: pubkey) else {
|
||||
guard let mutelist = damus_state.contacts.mutelist,
|
||||
let keypair = damus_state.keypair.to_full(),
|
||||
let new_ev = remove_from_mutelist(keypair: keypair,
|
||||
prev: mutelist,
|
||||
to_remove: .pubkey(pubkey))
|
||||
else {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -48,22 +45,15 @@ struct MutelistView: View {
|
||||
}
|
||||
.navigationTitle(NSLocalizedString("Muted Users", comment: "Navigation title of view to see list of muted users."))
|
||||
.onAppear {
|
||||
users = get_mutelist_users(damus_state.contacts.mutelist)
|
||||
users = get_mutelist_users(damus_state.contacts.mutelist)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func get_mutelist_users(_ mlist: NostrEvent?) -> [String] {
|
||||
guard let mutelist = mlist else {
|
||||
return []
|
||||
}
|
||||
|
||||
return mutelist.tags.reduce(into: Array<String>()) { pks, tag in
|
||||
if tag.count >= 2 && tag[0] == "p" {
|
||||
pks.append(tag[1])
|
||||
}
|
||||
}
|
||||
func get_mutelist_users(_ mutelist: NostrEvent?) -> Array<Pubkey> {
|
||||
guard let mutelist else { return [] }
|
||||
return Array(mutelist.referenced_pubkeys)
|
||||
}
|
||||
|
||||
struct MutelistView_Previews: PreviewProvider {
|
||||
|
||||
@@ -230,7 +230,7 @@ struct NoteContentView: View {
|
||||
for block in blocks.blocks {
|
||||
switch block {
|
||||
case .mention(let m):
|
||||
if m.type == .pubkey && m.ref.ref_id == profile.pubkey {
|
||||
if case .pubkey(let pk) = m.ref, pk == profile.pubkey {
|
||||
load(force_artifacts: true)
|
||||
return
|
||||
}
|
||||
@@ -265,21 +265,21 @@ func url_str(_ url: URL) -> CompatibleText {
|
||||
return CompatibleText(attributed: attributedString)
|
||||
}
|
||||
|
||||
func mention_str(_ m: Mention, profiles: Profiles) -> CompatibleText {
|
||||
switch m.type {
|
||||
case .pubkey:
|
||||
let pk = m.ref.ref_id
|
||||
func mention_str(_ m: Mention<MentionRef>, profiles: Profiles) -> CompatibleText {
|
||||
switch m.ref {
|
||||
case .pubkey(let pk):
|
||||
let npub = bech32_pubkey(pk)
|
||||
let profile = profiles.lookup(id: pk)
|
||||
let disp = Profile.displayName(profile: profile, pubkey: pk).username.truncate(maxLength: 50)
|
||||
var attributedString = AttributedString(stringLiteral: "@\(disp)")
|
||||
attributedString.link = URL(string: "damus:\(encode_pubkey_uri(m.ref))")
|
||||
attributedString.link = URL(string: "damus:nostr:\(npub)")
|
||||
attributedString.foregroundColor = DamusColors.purple
|
||||
|
||||
return CompatibleText(attributed: attributedString)
|
||||
case .event:
|
||||
let bevid = bech32_note_id(m.ref.ref_id) ?? m.ref.ref_id
|
||||
case .note(let note_id):
|
||||
let bevid = bech32_note_id(note_id)
|
||||
var attributedString = AttributedString(stringLiteral: "@\(abbrev_pubkey(bevid))")
|
||||
attributedString.link = URL(string: "damus:\(encode_event_id_uri(m.ref))")
|
||||
attributedString.link = URL(string: "damus:nostr:\(bevid)")
|
||||
attributedString.foregroundColor = DamusColors.purple
|
||||
|
||||
return CompatibleText(attributed: attributedString)
|
||||
@@ -394,7 +394,7 @@ func note_artifact_is_separated(kind: NostrKind?) -> Bool {
|
||||
|
||||
func render_note_content(ev: NostrEvent, profiles: Profiles, privkey: Privkey?) -> NoteArtifacts {
|
||||
let blocks = ev.blocks(privkey)
|
||||
|
||||
|
||||
if ev.known_kind == .longform {
|
||||
return .longform(LongformContent(ev.content))
|
||||
}
|
||||
@@ -427,7 +427,9 @@ func reduce_text_block(blocks: [Block], ind: Int, txt: String, one_note_ref: Boo
|
||||
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, m.type == .event, one_note_ref {
|
||||
} else if case .mention(let m) = next,
|
||||
case .note = m.ref,
|
||||
one_note_ref {
|
||||
trimmed = trim_suffix(trimmed)
|
||||
}
|
||||
}
|
||||
@@ -450,7 +452,7 @@ func render_blocks(blocks bs: Blocks, profiles: Profiles) -> NoteArtifactsSepara
|
||||
|
||||
switch block {
|
||||
case .mention(let m):
|
||||
if m.type == .event && one_note_ref {
|
||||
if case .note = m.ref, one_note_ref {
|
||||
return str
|
||||
}
|
||||
return str + mention_str(m, profiles: profiles)
|
||||
|
||||
@@ -10,10 +10,10 @@ import SwiftUI
|
||||
struct ParticipantsView: View {
|
||||
|
||||
let damus_state: DamusState
|
||||
|
||||
@Binding var references: [ReferencedId]
|
||||
@Binding var originalReferences: [ReferencedId]
|
||||
|
||||
let original_pubkeys: [Pubkey]
|
||||
|
||||
@Binding var filtered_pubkeys: Set<Pubkey>
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
Text("Replying to", comment: "Text indicating that the view is used for editing which participants are replied to in a note.")
|
||||
@@ -23,7 +23,7 @@ struct ParticipantsView: View {
|
||||
|
||||
Button {
|
||||
// Remove all "p" refs, keep "e" refs
|
||||
references = originalReferences.eRefs
|
||||
filtered_pubkeys = Set(original_pubkeys)
|
||||
} label: {
|
||||
Text("Remove all", comment: "Button label to remove all participants from a note reply.")
|
||||
}
|
||||
@@ -34,7 +34,7 @@ struct ParticipantsView: View {
|
||||
.clipShape(Capsule())
|
||||
|
||||
Button {
|
||||
references = originalReferences
|
||||
filtered_pubkeys = []
|
||||
} label: {
|
||||
Text("Add all", comment: "Button label to re-add all original participants as profiles to reply to in a note")
|
||||
}
|
||||
@@ -48,26 +48,19 @@ struct ParticipantsView: View {
|
||||
}
|
||||
VStack {
|
||||
ScrollView {
|
||||
ForEach(originalReferences.pRefs) { participant in
|
||||
let pubkey = participant.id
|
||||
ForEach(original_pubkeys) { pubkey in
|
||||
HStack {
|
||||
UserView(damus_state: damus_state, pubkey: pubkey)
|
||||
|
||||
Image("check-circle.fill")
|
||||
.font(.system(size: 30))
|
||||
.foregroundColor(references.contains(participant) ? DamusColors.purple : .gray)
|
||||
.foregroundColor(filtered_pubkeys.contains(pubkey) ? .gray : DamusColors.purple)
|
||||
}
|
||||
.onTapGesture {
|
||||
if references.contains(participant) {
|
||||
references = references.filter {
|
||||
$0 != participant
|
||||
}
|
||||
if filtered_pubkeys.contains(pubkey) {
|
||||
filtered_pubkeys.remove(pubkey)
|
||||
} else {
|
||||
if references.contains(participant) {
|
||||
// Don't add it twice
|
||||
} else {
|
||||
references.append(participant)
|
||||
}
|
||||
filtered_pubkeys.insert(pubkey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,8 +50,8 @@ struct PostView: View {
|
||||
@State var error: String? = nil
|
||||
@State var uploadedMedias: [UploadedMedia] = []
|
||||
@State var image_upload_confirm: Bool = false
|
||||
@State var originalReferences: [ReferencedId] = []
|
||||
@State var references: [ReferencedId] = []
|
||||
@State var references: [RefId] = []
|
||||
@State var filtered_pubkeys: Set<Pubkey> = []
|
||||
@State var focusWordAttributes: (String?, NSRange?) = (nil, nil)
|
||||
@State var newCursorIndex: Int?
|
||||
@State var postTextViewCanScroll: Bool = true
|
||||
@@ -76,7 +76,13 @@ struct PostView: View {
|
||||
}
|
||||
|
||||
func send_post() {
|
||||
let new_post = build_post(post: self.post, action: action, uploadedMedias: uploadedMedias, references: references)
|
||||
let refs = references.filter { ref in
|
||||
if case .pubkey(let pk) = ref, filtered_pubkeys.contains(pk) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
let new_post = build_post(post: self.post, action: action, uploadedMedias: uploadedMedias, references: refs)
|
||||
|
||||
notify(.post(.post(new_post)))
|
||||
|
||||
@@ -155,8 +161,7 @@ struct PostView: View {
|
||||
}
|
||||
|
||||
let profile = damus_state.profiles.lookup(id: pubkey)
|
||||
let bech32_pubkey = bech32_pubkey(pubkey) ?? ""
|
||||
return user_tag_attr_string(profile: profile, pubkey: bech32_pubkey)
|
||||
return user_tag_attr_string(profile: profile, pubkey: pubkey)
|
||||
}
|
||||
|
||||
func clear_draft() {
|
||||
@@ -310,7 +315,17 @@ struct PostView: View {
|
||||
self.post = initialString()
|
||||
self.tagModel.diff = post.string.count
|
||||
}
|
||||
|
||||
|
||||
var pubkeys: [Pubkey] {
|
||||
self.references.reduce(into: [Pubkey]()) { pks, ref in
|
||||
guard case .pubkey(let pk) = ref else {
|
||||
return
|
||||
}
|
||||
|
||||
pks.append(pk)
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
GeometryReader { (deviceSize: GeometryProxy) in
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
@@ -321,7 +336,7 @@ struct PostView: View {
|
||||
ScrollViewReader { scroller in
|
||||
ScrollView {
|
||||
if case .replying_to(let replying_to) = self.action {
|
||||
ReplyView(replying_to: replying_to, damus: damus_state, originalReferences: $originalReferences, references: $references)
|
||||
ReplyView(replying_to: replying_to, damus: damus_state, original_pubkeys: pubkeys, filtered_pubkeys: $filtered_pubkeys)
|
||||
}
|
||||
|
||||
Editor(deviceSize: deviceSize)
|
||||
@@ -385,10 +400,8 @@ struct PostView: View {
|
||||
switch action {
|
||||
case .replying_to(let replying_to):
|
||||
references = gather_reply_ids(our_pubkey: damus_state.pubkey, from: replying_to)
|
||||
originalReferences = references
|
||||
case .quoting(let quoting):
|
||||
references = gather_quote_ids(our_pubkey: damus_state.pubkey, from: quoting)
|
||||
originalReferences = references
|
||||
case .posting(let target):
|
||||
guard !loaded_draft else { break }
|
||||
|
||||
@@ -551,13 +564,7 @@ func load_draft_for_post(drafts: Drafts, action: PostAction) -> DraftArtifacts?
|
||||
}
|
||||
|
||||
|
||||
func build_post(post: NSMutableAttributedString, action: PostAction, uploadedMedias: [UploadedMedia], references: [ReferencedId]) -> NostrPost {
|
||||
var kind: NostrKind = .text
|
||||
|
||||
if case .replying_to(let ev) = action, ev.known_kind == .chat {
|
||||
kind = .chat
|
||||
}
|
||||
|
||||
func build_post(post: NSMutableAttributedString, action: PostAction, uploadedMedias: [UploadedMedia], references: [RefId]) -> NostrPost {
|
||||
post.enumerateAttributes(in: NSRange(location: 0, length: post.length), options: []) { attributes, range, stop in
|
||||
if let link = attributes[.link] as? String {
|
||||
let normalized_link: String
|
||||
@@ -586,9 +593,9 @@ func build_post(post: NSMutableAttributedString, action: PostAction, uploadedMed
|
||||
content.append(" " + imagesString + " ")
|
||||
}
|
||||
|
||||
if case .quoting(let ev) = action, let id = bech32_note_id(ev.id) {
|
||||
content.append(" nostr:" + id)
|
||||
if case .quoting(let ev) = action {
|
||||
content.append(" nostr:" + bech32_note_id(ev.id))
|
||||
}
|
||||
|
||||
return NostrPost(content: content, references: references, kind: kind, tags: img_meta_tags)
|
||||
return NostrPost(content: content, references: references, kind: .text, tags: img_meta_tags)
|
||||
}
|
||||
|
||||
@@ -31,10 +31,7 @@ struct UserSearch: View {
|
||||
}
|
||||
|
||||
func on_user_tapped(user: SearchedUser) {
|
||||
guard let pk = bech32_pubkey(user.pubkey) else {
|
||||
return
|
||||
}
|
||||
|
||||
let pk = user.pubkey
|
||||
let user_tag = user_tag_attr_string(profile: user.profile, pubkey: pk)
|
||||
|
||||
appendUserTag(withTag: user_tag)
|
||||
@@ -159,7 +156,7 @@ func user_tag_attr_string(profile: Profile?, pubkey: Pubkey) -> NSMutableAttribu
|
||||
return NSMutableAttributedString(string: tagString, attributes: [
|
||||
NSAttributedString.Key.font: UIFont.systemFont(ofSize: 18.0),
|
||||
NSAttributedString.Key.foregroundColor: UIColor.label,
|
||||
NSAttributedString.Key.link: "damus:nostr:\(pubkey)"
|
||||
NSAttributedString.Key.link: "damus:nostr:\(pubkey.npub)"
|
||||
])
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ struct AboutView: View {
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
let blocks = parse_note_content(content: about, tags: [])
|
||||
let blocks = parse_note_content(content: .content(about, nil))
|
||||
about_string = render_blocks(blocks: blocks, profiles: state.profiles).content.attributed
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ struct ProfileNameView: View {
|
||||
Spacer()
|
||||
|
||||
KeyView(pubkey: pubkey)
|
||||
.pubkey_context_menu(bech32_pubkey: pubkey)
|
||||
.pubkey_context_menu(pubkey: pubkey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,8 @@ struct EditProfilePictureView: View {
|
||||
private func get_profile_url() -> URL? {
|
||||
if let profile_url {
|
||||
return profile_url
|
||||
} else if let state = damus_state, let picture = state.profiles.lookup(id: pubkey)?.picture {
|
||||
} else if let state = damus_state,
|
||||
let picture = state.profiles.lookup(id: pubkey)?.picture {
|
||||
return URL(string: picture)
|
||||
} else {
|
||||
return profile_url ?? URL(string: robohash(pubkey))
|
||||
|
||||
@@ -190,7 +190,7 @@ struct ProfileView: View {
|
||||
return
|
||||
}
|
||||
|
||||
guard let new_ev = remove_from_mutelist(keypair: keypair, prev: mutelist, to_remove: profile.pubkey) else {
|
||||
guard let new_ev = remove_from_mutelist(keypair: keypair, prev: mutelist, to_remove: .pubkey(profile.pubkey)) else {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -260,10 +260,11 @@ struct ProfileView: View {
|
||||
func actionSection(profile_data: Profile?) -> some View {
|
||||
return Group {
|
||||
|
||||
if let profile = profile_data {
|
||||
if let lnurl = profile.lnurl, lnurl != "" {
|
||||
lnButton(lnurl: lnurl, profile: profile)
|
||||
}
|
||||
if let profile = profile_data,
|
||||
let lnurl = profile.lnurl,
|
||||
lnurl != ""
|
||||
{
|
||||
lnButton(lnurl: lnurl, profile: profile)
|
||||
}
|
||||
|
||||
dmButton
|
||||
@@ -353,7 +354,7 @@ struct ProfileView: View {
|
||||
|
||||
HStack {
|
||||
if let contact = profile.contacts {
|
||||
let contacts = contact.referenced_pubkeys.map { $0.ref_id }
|
||||
let contacts = Array(contact.referenced_pubkeys)
|
||||
let following_model = FollowingModel(damus_state: damus_state, contacts: contacts)
|
||||
NavigationLink(value: Route.Following(following: following_model)) {
|
||||
HStack {
|
||||
@@ -466,11 +467,8 @@ struct ProfileView: View {
|
||||
// our profilemodel needs a bit more help
|
||||
}
|
||||
.sheet(isPresented: $show_share_sheet) {
|
||||
if let npub = bech32_pubkey(profile.pubkey) {
|
||||
if let url = URL(string: "https://damus.io/" + npub) {
|
||||
ShareSheet(activityItems: [url])
|
||||
}
|
||||
}
|
||||
let url = URL(string: "https://damus.io/" + profile.pubkey.npub)!
|
||||
ShareSheet(activityItems: [url])
|
||||
}
|
||||
.fullScreenCover(isPresented: $show_qr_code) {
|
||||
QRCodeView(damus_state: damus_state, pubkey: profile.pubkey)
|
||||
@@ -517,7 +515,7 @@ struct KeyView: View {
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
let bech32 = bech32_pubkey(pubkey) ?? pubkey
|
||||
let bech32 = pubkey.npub
|
||||
|
||||
HStack {
|
||||
Text(verbatim: "\(abbrev_pubkey(bech32, amount: 16))")
|
||||
|
||||
@@ -10,9 +10,13 @@ import CoreImage.CIFilterBuiltins
|
||||
|
||||
struct ProfileScanResult: Equatable {
|
||||
let pubkey: Pubkey
|
||||
|
||||
init(hex: String) {
|
||||
self.pubkey = hex
|
||||
|
||||
init?(hex: String) {
|
||||
guard let pk = hex_decode(hex).map({ bytes in Pubkey(Data(bytes)) }) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.pubkey = pk
|
||||
}
|
||||
|
||||
init?(string: String) {
|
||||
@@ -25,14 +29,17 @@ struct ProfileScanResult: Equatable {
|
||||
str.removeFirst("nostr:".count)
|
||||
}
|
||||
|
||||
if let _ = hex_decode(str), str.count == 64 {
|
||||
self = .init(hex: str)
|
||||
if let decoded = hex_decode(str),
|
||||
str.count == 64
|
||||
{
|
||||
self.pubkey = Pubkey(Data(decoded))
|
||||
return
|
||||
}
|
||||
|
||||
if str.starts(with: "npub"), let b32 = try? bech32_decode(str) {
|
||||
let hex = hex_encode(b32.data)
|
||||
self = .init(hex: hex)
|
||||
if str.starts(with: "npub"),
|
||||
let b32 = try? bech32_decode(str)
|
||||
{
|
||||
self.pubkey = Pubkey(b32.data)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -56,14 +63,6 @@ struct QRCodeView: View {
|
||||
|
||||
let generator = UIImpactFeedbackGenerator(style: .light)
|
||||
|
||||
var maybe_key: String? {
|
||||
guard let key = bech32_pubkey(pubkey) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return key
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
func navImage(systemImage: String) -> some View {
|
||||
Image(systemName: systemImage)
|
||||
@@ -143,18 +142,16 @@ struct QRCodeView: View {
|
||||
|
||||
Spacer()
|
||||
|
||||
if let key = maybe_key {
|
||||
Image(uiImage: generateQRCode(pubkey: "nostr:" + key))
|
||||
.interpolation(.none)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 300, height: 300)
|
||||
.cornerRadius(10)
|
||||
.overlay(RoundedRectangle(cornerRadius: 10)
|
||||
.stroke(DamusColors.white, lineWidth: 5.0))
|
||||
.shadow(radius: 10)
|
||||
}
|
||||
|
||||
Image(uiImage: generateQRCode(pubkey: "nostr:" + pubkey.npub))
|
||||
.interpolation(.none)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 300, height: 300)
|
||||
.cornerRadius(10)
|
||||
.overlay(RoundedRectangle(cornerRadius: 10)
|
||||
.stroke(DamusColors.white, lineWidth: 5.0))
|
||||
.shadow(radius: 10)
|
||||
|
||||
Spacer()
|
||||
|
||||
Text("Follow me on Nostr", comment: "Text on QR code view to prompt viewer looking at screen to follow the user.")
|
||||
|
||||
@@ -91,6 +91,7 @@ struct RelayDetailView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let relay_connection {
|
||||
Section(NSLocalizedString("Relay", comment: "Label to display relay address.")) {
|
||||
HStack {
|
||||
@@ -101,7 +102,7 @@ struct RelayDetailView: View {
|
||||
}
|
||||
}
|
||||
|
||||
if let nip11 = nip11 {
|
||||
if let nip11 {
|
||||
if nip11.is_paid {
|
||||
Section(content: {
|
||||
RelayPaidDetail(payments_url: nip11.payments_url)
|
||||
@@ -172,7 +173,7 @@ struct RelayDetailView: View {
|
||||
|
||||
struct RelayDetailView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let metadata = RelayMetadata(name: "name", description: "desc", pubkey: "pubkey", contact: "contact", supported_nips: [1,2,3], software: "software", version: "version", limitation: Limitations.empty, payments_url: "https://jb55.com")
|
||||
let metadata = RelayMetadata(name: "name", description: "desc", pubkey: test_pubkey, contact: "contact", supported_nips: [1,2,3], software: "software", version: "version", limitation: Limitations.empty, payments_url: "https://jb55.com")
|
||||
RelayDetailView(state: test_damus_state(), relay: "relay", nip11: metadata)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ struct RelayView: View {
|
||||
}
|
||||
}
|
||||
|
||||
func RemoveButton(privkey: String, showText: Bool) -> some View {
|
||||
func RemoveButton(privkey: Privkey, showText: Bool) -> some View {
|
||||
Button(action: {
|
||||
guard let ev = state.contacts.event else {
|
||||
return
|
||||
|
||||
@@ -10,17 +10,23 @@ import SwiftUI
|
||||
struct ReplyView: View {
|
||||
let replying_to: NostrEvent
|
||||
let damus: DamusState
|
||||
|
||||
@Binding var originalReferences: [ReferencedId]
|
||||
@Binding var references: [ReferencedId]
|
||||
|
||||
let original_pubkeys: [Pubkey]
|
||||
@Binding var filtered_pubkeys: Set<Pubkey>
|
||||
@State var participantsShown: Bool = false
|
||||
|
||||
|
||||
var references: [Pubkey] {
|
||||
original_pubkeys.filter { pk in
|
||||
!filtered_pubkeys.contains(pk)
|
||||
}
|
||||
}
|
||||
|
||||
var ReplyingToSection: some View {
|
||||
HStack {
|
||||
Group {
|
||||
let names = references.pRefs
|
||||
let names = references
|
||||
.map { pubkey in
|
||||
let pk = pubkey.ref_id
|
||||
let pk = pubkey
|
||||
let prof = damus.profiles.lookup(id: pk)
|
||||
return "@" + Profile.displayName(profile: prof, pubkey: pk).username.truncate(maxLength: 50)
|
||||
}
|
||||
@@ -40,11 +46,15 @@ struct ReplyView: View {
|
||||
}
|
||||
.sheet(isPresented: $participantsShown) {
|
||||
if #available(iOS 16.0, *) {
|
||||
ParticipantsView(damus_state: damus, references: $references, originalReferences: $originalReferences)
|
||||
ParticipantsView(damus_state: damus,
|
||||
original_pubkeys: self.original_pubkeys,
|
||||
filtered_pubkeys: $filtered_pubkeys)
|
||||
.presentationDetents([.medium, .large])
|
||||
.presentationDragIndicator(.visible)
|
||||
} else {
|
||||
ParticipantsView(damus_state: damus, references: $references, originalReferences: $originalReferences)
|
||||
ParticipantsView(damus_state: damus,
|
||||
original_pubkeys: self.original_pubkeys,
|
||||
filtered_pubkeys: $filtered_pubkeys)
|
||||
}
|
||||
}
|
||||
.padding(.leading, 75)
|
||||
@@ -81,10 +91,16 @@ struct ReplyView: View {
|
||||
struct ReplyView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
VStack {
|
||||
ReplyView(replying_to: test_note, damus: test_damus_state(), originalReferences: .constant([]), references: .constant([]))
|
||||
ReplyView(replying_to: test_note,
|
||||
damus: test_damus_state(),
|
||||
original_pubkeys: [],
|
||||
filtered_pubkeys: .constant([]))
|
||||
.frame(height: 300)
|
||||
|
||||
ReplyView(replying_to: test_longform_event.event, damus: test_damus_state(), originalReferences: .constant([]), references: .constant([]))
|
||||
ReplyView(replying_to: test_longform_event.event,
|
||||
damus: test_damus_state(),
|
||||
original_pubkeys: [],
|
||||
filtered_pubkeys: .constant([]))
|
||||
.frame(height: 300)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,12 +51,8 @@ struct ReportView: View {
|
||||
return
|
||||
}
|
||||
|
||||
guard let note_id = bech32_note_id(ev.id) else {
|
||||
return
|
||||
}
|
||||
|
||||
report_sent = true
|
||||
report_id = note_id
|
||||
report_id = bech32_note_id(ev.id)
|
||||
}
|
||||
|
||||
var send_report_button_text: String {
|
||||
@@ -131,9 +127,9 @@ struct ReportView_Previews: PreviewProvider {
|
||||
let ds = test_damus_state()
|
||||
VStack {
|
||||
|
||||
ReportView(postbox: ds.postbox, target: ReportTarget.user(""), keypair: test_keypair.to_full()!)
|
||||
ReportView(postbox: ds.postbox, target: ReportTarget.user(test_pubkey), keypair: test_keypair.to_full()!)
|
||||
|
||||
ReportView(postbox: ds.postbox, target: ReportTarget.user(""), keypair: test_keypair.to_full()!, report_sent: true, report_id: "report_id")
|
||||
ReportView(postbox: ds.postbox, target: ReportTarget.user(test_pubkey), keypair: test_keypair.to_full()!, report_sent: true, report_id: "report_id")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ struct SaveKeysView: View {
|
||||
Text("This is your account ID, you can give this to your friends so that they can follow you. Tap to copy.", comment: "Label to describe that a public key is the user's account ID and what they can do with it.")
|
||||
.padding(.bottom, 10)
|
||||
|
||||
SaveKeyView(text: account.pubkey_bech32, textContentType: .username, is_copied: $pub_copied, focus: $pubkey_focused)
|
||||
SaveKeyView(text: account.pubkey.npub, textContentType: .username, is_copied: $pub_copied, focus: $pubkey_focused)
|
||||
.padding(.bottom, 10)
|
||||
|
||||
if pub_copied {
|
||||
@@ -49,7 +49,7 @@ struct SaveKeysView: View {
|
||||
Text("This is your secret account key. You need this to access your account. Don't share this with anyone! Save it in a password manager and keep it safe!", comment: "Label to describe that a private key is the user's secret account key and what they should do with it.")
|
||||
.padding(.bottom, 10)
|
||||
|
||||
SaveKeyView(text: account.privkey_bech32, textContentType: .newPassword, is_copied: $priv_copied, focus: $privkey_focused)
|
||||
SaveKeyView(text: account.privkey.nsec, textContentType: .newPassword, is_copied: $priv_copied, focus: $privkey_focused)
|
||||
.padding(.bottom, 10)
|
||||
}
|
||||
|
||||
@@ -115,8 +115,8 @@ struct SaveKeysView: View {
|
||||
|
||||
self.pool.register_handler(sub_id: "signup", handler: handle_event)
|
||||
|
||||
credential_handler.save_credential(pubkey: account.pubkey_bech32, privkey: account.privkey_bech32)
|
||||
|
||||
credential_handler.save_credential(pubkey: account.pubkey, privkey: account.privkey)
|
||||
|
||||
self.loading = true
|
||||
|
||||
self.pool.connect()
|
||||
|
||||
@@ -14,15 +14,14 @@ enum SearchState {
|
||||
case not_found
|
||||
}
|
||||
|
||||
enum SearchType {
|
||||
case event
|
||||
case profile
|
||||
case nip05
|
||||
enum SearchType: Equatable {
|
||||
case event(NoteId)
|
||||
case profile(Pubkey)
|
||||
case nip05(String)
|
||||
}
|
||||
|
||||
struct SearchingEventView: View {
|
||||
let state: DamusState
|
||||
let evid: String
|
||||
let search_type: SearchType
|
||||
|
||||
@State var search_state: SearchState = .searching
|
||||
@@ -38,18 +37,18 @@ struct SearchingEventView: View {
|
||||
}
|
||||
}
|
||||
|
||||
func handle_search(_ evid: String) {
|
||||
func handle_search(search: SearchType) {
|
||||
self.search_state = .searching
|
||||
|
||||
switch search_type {
|
||||
case .nip05:
|
||||
if let pk = state.profiles.nip05_pubkey[evid] {
|
||||
switch search {
|
||||
case .nip05(let nip05):
|
||||
if let pk = state.profiles.nip05_pubkey[nip05] {
|
||||
if state.profiles.lookup(id: pk) != nil {
|
||||
self.search_state = .found_profile(pk)
|
||||
}
|
||||
} else {
|
||||
Task {
|
||||
guard let nip05 = NIP05.parse(evid) else {
|
||||
guard let nip05 = NIP05.parse(nip05) else {
|
||||
self.search_state = .not_found
|
||||
return
|
||||
}
|
||||
@@ -71,16 +70,16 @@ struct SearchingEventView: View {
|
||||
}
|
||||
}
|
||||
|
||||
case .event:
|
||||
find_event(state: state, query: .event(evid: evid)) { res in
|
||||
case .event(let note_id):
|
||||
find_event(state: state, query: .event(evid: note_id)) { res in
|
||||
guard case .event(let ev) = res else {
|
||||
self.search_state = .not_found
|
||||
return
|
||||
}
|
||||
self.search_state = .found(ev)
|
||||
}
|
||||
case .profile:
|
||||
find_event(state: state, query: .profile(pubkey: evid)) { res in
|
||||
case .profile(let pubkey):
|
||||
find_event(state: state, query: .profile(pubkey: pubkey)) { res in
|
||||
guard case .profile(_, let ev) = res else {
|
||||
self.search_state = .not_found
|
||||
return
|
||||
@@ -113,11 +112,11 @@ struct SearchingEventView: View {
|
||||
Text("\(search_name) not found", comment: "When a note or profile is not found when searching for it via its note id")
|
||||
}
|
||||
}
|
||||
.onChange(of: evid, debounceTime: 0.5) { evid in
|
||||
handle_search(evid)
|
||||
.onChange(of: search_type, debounceTime: 0.5) { stype in
|
||||
handle_search(search: stype)
|
||||
}
|
||||
.onAppear {
|
||||
handle_search(evid)
|
||||
handle_search(search: search_type)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,6 +124,6 @@ struct SearchingEventView: View {
|
||||
struct SearchingEventView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let state = test_damus_state()
|
||||
SearchingEventView(state: state, evid: test_note.id, search_type: .event)
|
||||
SearchingEventView(state: state, search_type: .event(test_note.id))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ enum Search: Identifiable {
|
||||
case profile(Pubkey)
|
||||
case note(NoteId)
|
||||
case nip05(String)
|
||||
case hex(String)
|
||||
case hex(Data)
|
||||
case multi(MultiSearch)
|
||||
|
||||
var id: String {
|
||||
@@ -67,28 +67,22 @@ struct InnerSearchResults: View {
|
||||
HashtagSearch(ht)
|
||||
|
||||
case .nip05(let addr):
|
||||
SearchingEventView(state: damus_state, evid: addr, search_type: .nip05)
|
||||
|
||||
case .profile(let prof):
|
||||
let decoded = try? bech32_decode(prof)
|
||||
let hex = hex_encode(decoded!.data)
|
||||
|
||||
SearchingEventView(state: damus_state, evid: hex, search_type: .profile)
|
||||
SearchingEventView(state: damus_state, search_type: .nip05(addr))
|
||||
|
||||
case .profile(let pubkey):
|
||||
SearchingEventView(state: damus_state, search_type: .profile(pubkey))
|
||||
|
||||
case .hex(let h):
|
||||
//let prof_view = ProfileView(damus_state: damus_state, pubkey: h)
|
||||
//let ev_view = ThreadView(damus: damus_state, event_id: h)
|
||||
|
||||
|
||||
VStack(spacing: 10) {
|
||||
SearchingEventView(state: damus_state, evid: h, search_type: .event)
|
||||
|
||||
SearchingEventView(state: damus_state, evid: h, search_type: .profile)
|
||||
SearchingEventView(state: damus_state, search_type: .event(NoteId(h)))
|
||||
|
||||
SearchingEventView(state: damus_state, search_type: .profile(Pubkey(h)))
|
||||
}
|
||||
|
||||
case .note(let nid):
|
||||
let decoded = try? bech32_decode(nid)
|
||||
let hex = hex_encode(decoded!.data)
|
||||
|
||||
SearchingEventView(state: damus_state, evid: hex, search_type: .event)
|
||||
SearchingEventView(state: damus_state, search_type: .event(nid))
|
||||
|
||||
case .multi(let multi):
|
||||
VStack {
|
||||
HashtagSearch(multi.hashtag)
|
||||
@@ -146,20 +140,18 @@ func search_for_string(profiles: Profiles, _ new: String) -> Search? {
|
||||
return .hashtag(make_hashtagable(new))
|
||||
}
|
||||
|
||||
if hex_decode(new) != nil, new.count == 64 {
|
||||
if let new = hex_decode_id(new) {
|
||||
return .hex(new)
|
||||
}
|
||||
|
||||
|
||||
if new.starts(with: "npub") {
|
||||
if (try? bech32_decode(new)) != nil {
|
||||
return .profile(new)
|
||||
if let decoded = bech32_pubkey_decode(new) {
|
||||
return .profile(decoded)
|
||||
}
|
||||
}
|
||||
|
||||
if new.starts(with: "note") {
|
||||
if (try? bech32_decode(new)) != nil {
|
||||
return .note(new)
|
||||
}
|
||||
if new.starts(with: "note"), let decoded = try? bech32_decode(new) {
|
||||
return .note(NoteId(decoded.data))
|
||||
}
|
||||
|
||||
let multisearch = MultiSearch(hashtag: make_hashtagable(new), profiles: search_profiles(profiles: profiles, search: new))
|
||||
@@ -181,13 +173,19 @@ func make_hashtagable(_ str: String) -> String {
|
||||
|
||||
func search_profiles(profiles: Profiles, search: String) -> [SearchedUser] {
|
||||
// Search by hex pubkey.
|
||||
if search.count == 64 && hex_decode(search) != nil, let profile = profiles.lookup(id: search) {
|
||||
return [SearchedUser(profile: profile, pubkey: search)]
|
||||
if let pubkey = hex_decode_pubkey(search),
|
||||
let profile = profiles.lookup(id: pubkey)
|
||||
{
|
||||
return [SearchedUser(profile: profile, pubkey: pubkey)]
|
||||
}
|
||||
|
||||
// Search by npub pubkey.
|
||||
if search.starts(with: "npub"), let bech32_key = decode_bech32_key(search), case Bech32Key.pub(let hex) = bech32_key, let profile = profiles.lookup(id: hex) {
|
||||
return [SearchedUser(profile: profile, pubkey: hex)]
|
||||
if search.starts(with: "npub"),
|
||||
let bech32_key = decode_bech32_key(search),
|
||||
case Bech32Key.pub(let pk) = bech32_key,
|
||||
let profile = profiles.lookup(id: pk)
|
||||
{
|
||||
return [SearchedUser(profile: profile, pubkey: pk)]
|
||||
}
|
||||
|
||||
let new = search.lowercased()
|
||||
|
||||
@@ -14,7 +14,7 @@ struct ThreadView: View {
|
||||
@Environment(\.dismiss) var dismiss
|
||||
|
||||
var parent_events: [NostrEvent] {
|
||||
state.events.parent_events(event: thread.event)
|
||||
state.events.parent_events(event: thread.event, privkey: state.keypair.privkey)
|
||||
}
|
||||
|
||||
var child_events: [NostrEvent] {
|
||||
@@ -34,7 +34,7 @@ struct ThreadView: View {
|
||||
selected: false)
|
||||
.padding(.horizontal)
|
||||
.onTapGesture {
|
||||
thread.set_active_event(parent_event)
|
||||
thread.set_active_event(parent_event, privkey: self.state.keypair.privkey)
|
||||
scroll_to_event(scroller: reader, id: parent_event.id, delay: 0.1, animate: false)
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ struct ThreadView: View {
|
||||
)
|
||||
.padding(.horizontal)
|
||||
.onTapGesture {
|
||||
thread.set_active_event(child_event)
|
||||
thread.set_active_event(child_event, privkey: state.keypair.privkey)
|
||||
scroll_to_event(scroller: reader, id: child_event.id, delay: 0.1, animate: false)
|
||||
}
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@ struct WalletView: View {
|
||||
}
|
||||
}
|
||||
|
||||
let test_wallet_connect_url = WalletConnectURL(pubkey: "pk", relay: .init("wss://relay.damus.io")!, keypair: test_damus_state().keypair.to_full()!, lud16: "jb55@sendsats.com")
|
||||
let test_wallet_connect_url = WalletConnectURL(pubkey: test_pubkey, relay: .init("wss://relay.damus.io")!, keypair: test_damus_state().keypair.to_full()!, lud16: "jb55@sendsats.com")
|
||||
|
||||
struct WalletView_Previews: PreviewProvider {
|
||||
static let tds = test_damus_state()
|
||||
|
||||
@@ -16,7 +16,7 @@ struct ZapsView: View {
|
||||
init(state: DamusState, target: ZapTarget) {
|
||||
self.state = state
|
||||
self.model = ZapsModel(state: state, target: target)
|
||||
self._zaps = ObservedObject(wrappedValue: state.events.get_cache_data(target.id).zaps_model)
|
||||
self._zaps = ObservedObject(wrappedValue: state.events.get_cache_data(NoteId(target.id)).zaps_model)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
@@ -40,6 +40,6 @@ struct ZapsView: View {
|
||||
|
||||
struct ZapsView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ZapsView(state: test_damus_state(), target: .profile("pk"))
|
||||
ZapsView(state: test_damus_state(), target: .profile(test_pubkey))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user