commit 19ba020bd04f82f191c57015a11753fd6d9b6c68
parent 43a5bbd53a91d727db76c0f31e84433bb0d91f8b
Author: Daniel D’Aquino <daniel@daquino.me>
Date: Mon, 22 Apr 2024 23:09:30 +0000
contacts: save first list to storage during onboarding
This commit adds a mechanism to add the contact list to storage as soon
as it is generated, and thus it reduces the risk of poor network
conditions causing issues.
Changelog-Fixed: Improve reliability of contact list creation during onboarding
Closes: https://github.com/damus-io/damus/issues/2057
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Link: 20240422230912.65056-3-daniel@daquino.me
Signed-off-by: William Casarin <jb55@jb55.com>
Diffstat:
4 files changed, 47 insertions(+), 16 deletions(-)
diff --git a/damus/ContentView.swift b/damus/ContentView.swift
@@ -680,10 +680,7 @@ struct ContentView: View {
let relay_filters = RelayFilters(our_pubkey: pubkey)
let bootstrap_relays = load_bootstrap_relays(pubkey: pubkey)
- // dumb stuff needed for property wrappers
- UserSettingsStore.pubkey = pubkey
- let settings = UserSettingsStore()
- UserSettingsStore.shared = settings
+ let settings = UserSettingsStore.globally_load_for(pubkey: pubkey)
let new_relay_filters = load_relay_filters(pubkey) == nil
for relay in bootstrap_relays {
diff --git a/damus/Models/UserSettingsStore.swift b/damus/Models/UserSettingsStore.swift
@@ -96,6 +96,14 @@ class UserSettingsStore: ObservableObject {
static var shared: UserSettingsStore? = nil
static var bool_options = Set<String>()
+ static func globally_load_for(pubkey: Pubkey) -> UserSettingsStore {
+ // dumb stuff needed for property wrappers
+ UserSettingsStore.pubkey = pubkey
+ let settings = UserSettingsStore()
+ UserSettingsStore.shared = settings
+ return settings
+ }
+
@StringSetting(key: "default_wallet", default_value: .system_default_wallet)
var default_wallet: Wallet
diff --git a/damus/Nostr/RelayPool.swift b/damus/Nostr/RelayPool.swift
@@ -226,19 +226,23 @@ class RelayPool {
print("queueing request for \(relay)")
request_queue.append(QueuedRequest(req: r, relay: relay, skip_ephemeral: skip_ephemeral))
}
+
+ func send_raw_to_local_ndb(_ req: NostrRequestType) {
+ // send to local relay (nostrdb)
+ switch req {
+ case .typical(let r):
+ if case .event = r, let rstr = make_nostr_req(r) {
+ let _ = ndb.process_client_event(rstr)
+ }
+ case .custom(let string):
+ let _ = ndb.process_client_event(string)
+ }
+ }
func send_raw(_ req: NostrRequestType, to: [RelayURL]? = nil, skip_ephemeral: Bool = true) {
let relays = to.map{ get_relays($0) } ?? self.relays
- // send to local relay (nostrdb)
- switch req {
- case .typical(let r):
- if case .event = r, let rstr = make_nostr_req(r) {
- let _ = ndb.process_client_event(rstr)
- }
- case .custom(let string):
- let _ = ndb.process_client_event(string)
- }
+ self.send_raw_to_local_ndb(req)
for relay in relays {
if req.is_read && !(relay.descriptor.info.read ?? true) {
diff --git a/damus/Views/SaveKeysView.swift b/damus/Views/SaveKeysView.swift
@@ -21,6 +21,13 @@ struct SaveKeysView: View {
@FocusState var pubkey_focused: Bool
@FocusState var privkey_focused: Bool
+ let first_contact_event: NdbNote?
+
+ init(account: CreateAccountModel) {
+ self.account = account
+ self.first_contact_event = make_first_contact_event(keypair: account.keypair)
+ }
+
var body: some View {
ZStack(alignment: .top) {
VStack(alignment: .center) {
@@ -102,6 +109,13 @@ struct SaveKeysView: View {
}
func complete_account_creation(_ account: CreateAccountModel) {
+ guard let first_contact_event else {
+ error = NSLocalizedString("Could not create your initial contact list event. This is a software bug, please contact Damus support via support@damus.io or through our Nostr account for help.", comment: "Error message to the user indicating that the initial contact list failed to be created.")
+ return
+ }
+ // Save contact list to storage right away so that we don't need to depend on the network to complete this important step
+ self.save_to_storage(first_contact_event: first_contact_event, for: account)
+
let bootstrap_relays = load_bootstrap_relays(pubkey: account.pubkey)
for relay in bootstrap_relays {
add_rw_relay(self.pool, relay)
@@ -115,6 +129,15 @@ struct SaveKeysView: View {
self.pool.connect()
}
+
+ func save_to_storage(first_contact_event: NdbNote, for account: CreateAccountModel) {
+ // Send to NostrDB so that we have a local copy in storage
+ self.pool.send_raw_to_local_ndb(.typical(.event(first_contact_event)))
+
+ // Save the ID to user settings so that we can easily find it later.
+ let settings = UserSettingsStore.globally_load_for(pubkey: account.pubkey)
+ settings.latest_contact_event_id_hex = first_contact_event.id.hex()
+ }
func handle_event(relay: RelayURL, ev: NostrConnectionEvent) {
switch ev {
@@ -122,15 +145,14 @@ struct SaveKeysView: View {
switch wsev {
case .connected:
let metadata = create_account_to_metadata(account)
- let contacts_ev = make_first_contact_event(keypair: account.keypair)
if let keypair = account.keypair.to_full(),
let metadata_ev = make_metadata_event(keypair: keypair, metadata: metadata) {
self.pool.send(.event(metadata_ev))
}
- if let contacts_ev {
- self.pool.send(.event(contacts_ev))
+ if let first_contact_event {
+ self.pool.send(.event(first_contact_event))
}
do {