more mention progress

Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
William Casarin
2022-05-07 13:50:19 -07:00
parent 73652513d9
commit 0eb1372937
21 changed files with 611 additions and 144 deletions

View File

@@ -14,7 +14,7 @@ struct Profile: Decodable {
let picture: String?
static func displayName(profile: Profile?, pubkey: String) -> String {
return profile?.name ?? String(pubkey.prefix(16))
return profile?.name ?? abbrev_pubkey(pubkey)
}
}

View File

@@ -49,6 +49,10 @@ class NostrEvent: Codable, Identifiable, CustomStringConvertible {
let kind: Int
let content: String
lazy var blocks: [Block] = {
return parse_mentions(content: self.content, tags: self.tags)
}()
var description: String {
let p = pow.map { String($0) } ?? "?"
return "NostrEvent { id: \(id) pubkey \(pubkey) kind \(kind) tags \(tags) pow \(p) content '\(content)' }"

View File

@@ -0,0 +1,96 @@
//
// NostrLink.swift
// damus
//
// Created by William Casarin on 2022-05-05.
//
import Foundation
enum NostrLink {
case ref(ReferencedId)
case filter(NostrFilter)
}
func encode_pubkey_uri(_ ref: ReferencedId) -> String {
return "p:" + ref.ref_id
}
// TODO: bech32 and relay hints
func encode_event_id_uri(_ ref: ReferencedId) -> String {
return "e:" + ref.ref_id
}
func parse_nostr_ref_uri_type(_ p: Parser) -> String? {
if parse_char(p, "p") {
return "p"
}
if parse_char(p, "e") {
return "e"
}
return nil
}
func parse_hexstr(_ p: Parser, len: Int) -> String? {
var i: Int = 0
if len % 2 != 0 {
return nil
}
let start = p.pos
while i < len {
guard parse_hex_char(p) != nil else {
p.pos = start
return nil
}
i += 1
}
return String(substring(p.str, start: start, end: p.pos))
}
func parse_nostr_ref_uri(_ p: Parser) -> ReferencedId? {
let start = p.pos
if !parse_str(p, "nostr:") {
return nil
}
guard let typ = parse_nostr_ref_uri_type(p) else {
p.pos = start
return nil
}
if !parse_char(p, ":") {
p.pos = start
return nil
}
guard let pk = parse_hexstr(p, len: 64) else {
p.pos = start
return nil
}
// TODO: parse relays from nostr uris
return ReferencedId(ref_id: pk, relay_id: nil, key: typ)
}
func decode_nostr_uri(_ s: String) -> NostrLink? {
let uri = s.replacingOccurrences(of: "nostr:", with: "")
let parts = uri.split(separator: ":")
.reduce(into: Array<String>()) { acc, str in
guard let decoded = str.removingPercentEncoding else {
return
}
acc.append(decoded)
return
}
return tag_to_refid(parts).map { .ref($0) }
}

View File

@@ -9,62 +9,6 @@ import Foundation
import UIKit
import Combine
class ImageCache {
private let lock = NSLock()
lazy var cache: NSCache<AnyObject, AnyObject> = {
let cache = NSCache<AnyObject, AnyObject>()
cache.totalCostLimit = 1024 * 1024 * 100 // 100MB
return cache
}()
func lookup(for url: URL) -> UIImage? {
lock.lock(); defer { lock.unlock() }
if let decoded = cache.object(forKey: url as AnyObject) as? UIImage {
return decoded
}
return nil
}
func remove(for url: URL) {
lock.lock(); defer { lock.unlock() }
cache.removeObject(forKey: url as AnyObject)
}
func insert(_ image: UIImage?, for url: URL) {
guard let image = image else { return remove(for: url) }
let decodedImage = image.decodedImage(Int(PFP_SIZE!))
lock.lock(); defer { lock.unlock() }
cache.setObject(decodedImage, forKey: url as AnyObject)
}
subscript(_ key: URL) -> UIImage? {
get {
return lookup(for: key)
}
set {
return insert(newValue, for: key)
}
}
}
func load_image(cache: ImageCache, from url: URL) -> AnyPublisher<UIImage?, Never> {
if let image = cache[url] {
return Just(image).eraseToAnyPublisher()
}
return URLSession.shared.dataTaskPublisher(for: url)
.map { (data, response) -> UIImage? in return UIImage(data: data) }
.catch { error in return Just(nil) }
.handleEvents(receiveOutput: { image in
guard let image = image else { return }
cache[url] = image
})
.subscribe(on: DispatchQueue.global(qos: .background))
.receive(on: RunLoop.main)
.eraseToAnyPublisher()
}
class Profiles: ObservableObject {
@Published var profiles: [String: TimestampedProfile] = [:]