Huge refactor to add better structure to the project. Separating features with their associated view and model structure. This should be better organization and will allow us to improve the overall architecture in the future. I forsee many more improvements that can follow this change. e.g. MVVM Arch As well as cleaning up duplicate, unused, functionality. Many files have global functions that can also be moved or be renamed. damus/ ├── Features/ │ ├── <Feature>/ │ │ ├── Views/ │ │ └── Models/ ├── Shared/ │ ├── Components/ │ ├── Media/ │ ├── Buttons/ │ ├── Extensions/ │ ├── Empty Views/ │ ├── ErrorHandling/ │ ├── Modifiers/ │ └── Utilities/ ├── Core/ │ ├── Nostr/ │ ├── NIPs/ │ ├── DIPs/ │ ├── Types/ │ ├── Networking/ │ └── Storage/ Signed-off-by: ericholguin <ericholguin@apache.org>
127 lines
3.2 KiB
Swift
127 lines
3.2 KiB
Swift
//
|
|
// Profiles.swift
|
|
// damus
|
|
//
|
|
// Created by William Casarin on 2022-04-17.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
class ValidationModel: ObservableObject {
|
|
@Published var validated: NIP05?
|
|
|
|
init() {
|
|
self.validated = nil
|
|
}
|
|
}
|
|
|
|
class ProfileData {
|
|
var status: UserStatusModel
|
|
var validation_model: ValidationModel
|
|
var zapper: Pubkey?
|
|
|
|
init() {
|
|
status = .init()
|
|
validation_model = .init()
|
|
zapper = nil
|
|
}
|
|
}
|
|
|
|
class Profiles {
|
|
private var ndb: Ndb
|
|
|
|
static let db_freshness_threshold: TimeInterval = 24 * 60 * 8
|
|
|
|
@MainActor
|
|
private var profiles: [Pubkey: ProfileData] = [:]
|
|
|
|
// Map of validated NIP-05 address to pubkey.
|
|
@MainActor
|
|
var nip05_pubkey: [String: Pubkey] = [:]
|
|
|
|
init(ndb: Ndb) {
|
|
self.ndb = ndb
|
|
}
|
|
|
|
@MainActor
|
|
func is_validated(_ pk: Pubkey) -> NIP05? {
|
|
self.profile_data(pk).validation_model.validated
|
|
}
|
|
|
|
@MainActor
|
|
func invalidate_nip05(_ pk: Pubkey) {
|
|
self.profile_data(pk).validation_model.validated = nil
|
|
}
|
|
|
|
@MainActor
|
|
func set_validated(_ pk: Pubkey, nip05: NIP05?) {
|
|
self.profile_data(pk).validation_model.validated = nip05
|
|
}
|
|
|
|
@MainActor
|
|
func profile_data(_ pubkey: Pubkey) -> ProfileData {
|
|
guard let data = profiles[pubkey] else {
|
|
let data = ProfileData()
|
|
profiles[pubkey] = data
|
|
return data
|
|
}
|
|
|
|
return data
|
|
}
|
|
|
|
@MainActor
|
|
func lookup_zapper(pubkey: Pubkey) -> Pubkey? {
|
|
profile_data(pubkey).zapper
|
|
}
|
|
|
|
func lookup_with_timestamp(_ pubkey: Pubkey) -> NdbTxn<ProfileRecord?>? {
|
|
ndb.lookup_profile(pubkey)
|
|
}
|
|
|
|
func lookup_by_key(key: ProfileKey) -> NdbTxn<ProfileRecord?>? {
|
|
ndb.lookup_profile_by_key(key: key)
|
|
}
|
|
|
|
func search<Y>(_ query: String, limit: Int, txn: NdbTxn<Y>) -> [Pubkey] {
|
|
ndb.search_profile(query, limit: limit, txn: txn)
|
|
}
|
|
|
|
func lookup(id: Pubkey, txn_name: String? = nil) -> NdbTxn<Profile?>? {
|
|
guard let txn = ndb.lookup_profile(id, txn_name: txn_name) else {
|
|
return nil
|
|
}
|
|
return txn.map({ pr in pr?.profile })
|
|
}
|
|
|
|
func lookup_key_by_pubkey(_ pubkey: Pubkey) -> ProfileKey? {
|
|
ndb.lookup_profile_key(pubkey)
|
|
}
|
|
|
|
func has_fresh_profile<Y>(id: Pubkey, txn: NdbTxn<Y>) -> Bool {
|
|
guard let fetched_at = ndb.read_profile_last_fetched(txn: txn, pubkey: id)
|
|
else {
|
|
return false
|
|
}
|
|
|
|
// In situations where a batch of profiles was fetched all at once,
|
|
// this will reduce the herding of the profile requests
|
|
let fuzz = Double.random(in: -60...60)
|
|
let threshold = Profiles.db_freshness_threshold + fuzz
|
|
let fetch_date = Date(timeIntervalSince1970: Double(fetched_at))
|
|
|
|
let since = Date.now.timeIntervalSince(fetch_date)
|
|
let fresh = since < threshold
|
|
|
|
//print("fresh = \(fresh): fetch_date \(since) < threshold \(threshold) \(id)")
|
|
|
|
return fresh
|
|
}
|
|
}
|
|
|
|
|
|
@MainActor
|
|
func invalidate_zapper_cache(pubkey: Pubkey, profiles: Profiles, lnurl: LNUrls) {
|
|
profiles.profile_data(pubkey).zapper = nil
|
|
lnurl.endpoints.removeValue(forKey: pubkey)
|
|
}
|