[Fixes: #12550] Backup contacts through waku

Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
This commit is contained in:
Andrea Maria Piana 2021-10-25 09:46:33 +01:00
parent 179f1d26ae
commit e125164273
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
23 changed files with 218 additions and 133 deletions

View File

@ -26,7 +26,7 @@
[cofx {:keys [key id]} public]
(fx/merge cofx
{::persistence/chat-initalized! true}
(chat/start-chat key)))
(chat/start-chat key nil)))
(fx/defn start-public-chat
{:events [::start-public-chat]}

View File

@ -78,9 +78,9 @@
(if-not validation-result
(if new-contact?
(fx/merge cofx
(contact/add-contact chat-key nil)
(contact/add-contact chat-key nil nil)
(navigation/navigate-to-cofx :contacts-list {}))
(chat/start-chat cofx chat-key))
(chat/start-chat cofx chat-key nil))
{:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
:content (case validation-result
:invalid

View File

@ -0,0 +1,26 @@
(ns status-im.backup.core
(:require [re-frame.core :as re-frame]
[taoensso.timbre :as log]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.utils.fx :as fx]))
(fx/defn handle-backup-failed
{:events [::backup-failed]}
[{:keys [db]}]
{:db (dissoc db :backup/performing-backup)})
(fx/defn handle-backup-perfomed
{:events [::backup-performed]}
[{:keys [db]}]
{:db (dissoc db :backup/performing-backup)})
(fx/defn handle-perform-backup-pressed
{:events [:multiaccounts.ui/perform-backup-pressed]}
[{:keys [db]}]
{:db (assoc db :backup/performing-backup true)
::json-rpc/call [{:method (json-rpc/call-ext-method "backupData")
:params []
:on-error #(do
(log/error "failed to perfom backup" %)
(re-frame/dispatch [::backup-failed %]))
:on-success #(re-frame/dispatch [::backup-performed %])}]})

View File

@ -4,6 +4,7 @@
[status-im.multiaccounts.model :as multiaccounts.model]
[status-im.chat.models.message-list :as message-list]
[status-im.data-store.chats :as chats-store]
[status-im.data-store.contacts :as contacts-store]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.i18n.i18n :as i18n]
[quo.design-system.colors :as colors]
@ -254,9 +255,15 @@
(fx/defn handle-one-to-one-chat-created
{:events [::one-to-one-chat-created]}
[{:keys [db]} chat-id response]
(let [chat (chats-store/<-rpc (first (:chats response)))]
{:db (-> db
(let [chat (chats-store/<-rpc (first (:chats response)))
contact-rpc (first (:contacts response))
contact (when contact-rpc (contacts-store/<-rpc contact-rpc))]
{:db (cond-> db
contact
(assoc-in [:contacts/contacts chat-id] contact)
:always
(assoc-in [:chats chat-id] chat)
:always
(update :chats-home-list conj chat-id))
:dispatch [:chat.ui/navigate-to-chat chat-id]}))
@ -269,11 +276,11 @@
(fx/defn start-chat
"Start a chat, making sure it exists"
{:events [:chat.ui/start-chat]}
[{:keys [db] :as cofx} chat-id]
[{:keys [db] :as cofx} chat-id ens-name]
;; don't allow to open chat with yourself
(when (not= (multiaccounts.model/current-public-key cofx) chat-id)
{::json-rpc/call [{:method "wakuext_createOneToOneChat"
:params [{:id chat-id}]
:params [{:id chat-id :ensName ens-name}]
:on-success #(re-frame/dispatch [::one-to-one-chat-created chat-id %])
:on-error #(log/error "failed to create one-to-on chat" chat-id %)}]}))

View File

@ -45,12 +45,11 @@
(fx/defn block-contact
{:events [:contact.ui/block-contact-confirmed]}
[{:keys [db now] :as cofx} public-key]
[{:keys [db] :as cofx} public-key]
(let [contact (-> (contact.db/public-key->contact
(:contacts/contacts db)
public-key)
(assoc :last-updated now
:blocked true
(assoc :blocked true
:added false))
from-one-to-one-chat? (not (get-in db [:chats (:current-chat-id db) :group-chat]))]
(fx/merge cofx
@ -59,20 +58,26 @@
(update :contacts/blocked (fnil conj #{}) public-key)
;; update the contact in contacts list
(assoc-in [:contacts/contacts public-key] contact))}
(contacts-store/block contact #(do (re-frame/dispatch [::contact-blocked contact (map chats-store/<-rpc %)])
(contacts-store/block public-key #(do (re-frame/dispatch [::contact-blocked contact (map chats-store/<-rpc %)])
(re-frame/dispatch [:hide-popover])))
;; reset navigation to avoid going back to non existing one to one chat
(if from-one-to-one-chat?
(navigation/pop-to-root-tab :chat-stack)
(navigation/navigate-back)))))
(fx/defn unblock-contact
{:events [:contact.ui/unblock-contact-pressed ::contact-unblocked]}
[{:keys [db now] :as cofx} public-key]
(let [contact (-> (get-in db [:contacts/contacts public-key])
(assoc :last-updated now :blocked false))]
(fx/merge cofx
(fx/defn contact-unblocked
{:events [::contact-unblocked]}
[{:keys [db]} contact-id]
(let [contact (-> (get-in db [:contacts/contacts contact-id])
(assoc :blocked false))]
{:db (-> db
(update :contacts/blocked disj public-key)
(assoc-in [:contacts/contacts public-key] contact))}
(contacts-store/save-contact contact nil))))
(update :contacts/blocked disj contact-id)
(assoc-in [:contacts/contacts contact-id] contact))}))
(fx/defn unblock-contact
{:events [:contact.ui/unblock-contact-pressed]}
[cofx contact-id]
(contacts-store/unblock
cofx
contact-id
#(re-frame/dispatch [::contact-unblocked contact-id])))

View File

@ -20,12 +20,10 @@
(let [{:keys [public-key ens-name]} new-identity]
(fx/merge cofx
#(if new-contact?
(contact/add-contact % public-key nickname)
(chat/start-chat % public-key))
(contact/add-contact % public-key nickname ens-name)
(chat/start-chat % public-key ens-name))
#(when new-contact?
(navigation/navigate-back %))
#(when ens-name
(contact/name-verified % public-key ens-name)))))
(navigation/navigate-back %)))))
(fx/defn pinned-messages-pressed
{:events [:contact.ui/pinned-messages-pressed]}

View File

@ -3,11 +3,9 @@
[status-im.contact.db :as contact.db]
[status-im.data-store.contacts :as contacts-store]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.mailserver.core :as mailserver]
[status-im.navigation :as navigation]
[status-im.utils.fx :as fx]
[taoensso.timbre :as log]
[clojure.string :as string]
[status-im.constants :as constants]
[status-im.contact.block :as contact.block]))
@ -54,10 +52,7 @@
(conj nil)
(and blocked (not was-blocked))
(conj [::contact.block/contact-blocked contact chats])
(and was-blocked (not blocked))
(conj [::contact.block/contact-unblocked public-key]))))
(conj [::contact.block/contact-blocked contact chats]))))
[[:offload-messages constants/timeline-chat-id]]
contacts)]
(merge
@ -71,17 +66,6 @@
(when (> (count events) 1)
{:dispatch-n events}))))
(fx/defn upsert-contact
[{:keys [db] :as cofx}
{:keys [public-key] :as contact}]
(fx/merge cofx
{:db (-> db
(update-in [:contacts/contacts public-key] merge contact))}
(fn [cf]
(contacts-store/save-contact cf
(get-in cf [:db :contacts/contacts public-key])
#(re-frame/dispatch [::send-contact-request public-key])))))
(fx/defn send-contact-request
{:events [::send-contact-request]}
[{:keys [db] :as cofx} public-key]
@ -92,22 +76,17 @@
(fx/defn add-contact
"Add a contact and set pending to false"
{:events [:contact.ui/add-to-contact-pressed]
:interceptors [(re-frame/inject-cofx :random-id-generator)]}
[{:keys [db] :as cofx} public-key nickname]
{:events [:contact.ui/add-to-contact-pressed]}
[{:keys [db] :as cofx} public-key nickname ens-name]
(when (not= (get-in db [:multiaccount :public-key]) public-key)
(let [contact (cond-> (get-in db [:contacts/contacts public-key]
(build-contact cofx public-key))
(and nickname (not (string/blank? nickname)))
(assoc :nickname nickname)
:else
(assoc :added true))]
(fx/merge cofx
{:db (dissoc db :contacts/new-identity)
:dispatch-n [[:start-profile-chat public-key]
[:offload-messages constants/timeline-chat-id]]}
(upsert-contact contact)
(mailserver/process-next-messages-request)))))
(contacts-store/add
cofx
public-key
nickname
ens-name
#(do
(re-frame/dispatch [:sanitize-messages-and-process-response %])
(re-frame/dispatch [:offload-messages constants/timeline-chat-id])))))
(fx/defn remove-contact
"Remove a contact from current account's contact list"
@ -119,16 +98,6 @@
:on-success #(log/debug "contact removed successfully")}]
:dispatch [:offload-messages constants/timeline-chat-id]})
(fx/defn create-contact
"Create entry in contacts"
[{:keys [db] :as cofx} public-key]
(when (not= (get-in db [:multiaccount :public-key]) public-key)
(let [contact (build-contact cofx public-key)]
(log/info "create contact" contact)
(fx/merge cofx
{:db (dissoc db :contacts/new-identity)}
(upsert-contact contact)))))
(fx/defn initialize-contacts [cofx]
(contacts-store/fetch-contacts-rpc cofx #(re-frame/dispatch [::contacts-loaded %])))
@ -141,29 +110,12 @@
:new-chat-name "")}
(navigation/navigate-to-cofx :contact-toggle-list nil)))
(fx/defn name-verified
{:events [:contacts/ens-name-verified]}
[{:keys [db now] :as cofx} public-key ens-name]
(let [contact (-> (or (get-in db [:contacts/contacts public-key])
(build-contact cofx public-key))
(assoc :name ens-name
:ens-verified true))]
(fx/merge cofx
{:db (-> db
(update-in [:contacts/contacts public-key] merge contact))
::json-rpc/call [{:method "wakuext_ensVerified"
:params [public-key ens-name]
:on-success #(log/debug "ens name verified successuful")}]})))
(fx/defn update-nickname
{:events [:contacts/update-nickname]}
[{:keys [db] :as cofx} public-key nickname]
(let [contact (-> (build-contact cofx public-key)
(merge (get-in db [:contacts/contacts public-key])))]
(fx/merge cofx
{:db (assoc-in db [:contacts/contacts public-key]
(if (string/blank? nickname)
(dissoc contact :nickname)
(assoc contact :nickname nickname)))}
(upsert-contact {:public-key public-key})
(navigation/navigate-back))))
(contacts-store/set-nickname
public-key
nickname
#(re-frame/dispatch [:sanitize-messages-and-process-response %]))
(navigation/navigate-back)))

View File

@ -13,15 +13,6 @@
:lastUpdated :last-updated
:localNickname :nickname}))
(defn ->rpc [contact]
(clojure.set/rename-keys contact {:public-key :id
:ens-verified :ensVerified
:ens-verified-at :ensVerifiedAt
:last-ens-clock-value :lastENSClockValue
:ens-verification-retries :ensVerificationRetries
:last-updated :lastUpdated
:nickname :localNickname}))
(fx/defn fetch-contacts-rpc
[_ on-success]
{::json-rpc/call [{:method (json-rpc/call-ext-method "contacts")
@ -29,18 +20,37 @@
:on-success #(on-success (map <-rpc %))
:on-failure #(log/error "failed to fetch contacts" %)}]})
(fx/defn save-contact
[_ {:keys [public-key] :as contact} on-success]
{::json-rpc/call [{:method (json-rpc/call-ext-method "saveContact")
:params [(->rpc contact)]
(fx/defn add
[_ public-key nickname ens-name on-success]
{::json-rpc/call [{:method (json-rpc/call-ext-method "addContact")
:params [{:id public-key :nickname nickname :ensName ens-name}]
:js-response true
:on-success #(do
(log/debug "saved contact" public-key "successfuly")
(log/info "saved contact" public-key "successfuly")
(when on-success
(on-success)))
:on-failure #(log/error "failed to save contact" public-key %)}]})
(on-success %)))
:on-failure #(log/error "failed to add contact" public-key %)}]})
(fx/defn block [_ contact on-success]
(fx/defn set-nickname
[_ public-key nickname on-success]
{::json-rpc/call [{:method (json-rpc/call-ext-method "setContactLocalNickname")
:params [{:id public-key :nickname nickname}]
:js-response true
:on-success #(do
(log/debug "set contact nickname" public-key "successfuly" nickname)
(when on-success
(on-success %)))
:on-failure #(log/error "failed to set contact nickname " public-key nickname %)}]})
(fx/defn block [_ contact-id on-success]
{::json-rpc/call [{:method (json-rpc/call-ext-method "blockContact")
:params [(->rpc contact)]
:params [contact-id]
:on-success on-success
:on-failure #(log/error "failed to block contact" % contact)}]})
:on-failure #(log/error "failed to block contact" % contact-id)}]})
(fx/defn unblock [_ contact-id on-success]
{::json-rpc/call [{:method (json-rpc/call-ext-method "unblockContact")
:params [contact-id]
:on-success on-success
:js-response true
:on-failure #(log/error "failed to unblock contact" % contact-id)}]})

View File

@ -2,21 +2,6 @@
(:require [cljs.test :refer-macros [deftest is testing]]
[status-im.data-store.contacts :as c]))
(deftest contact->rpc
(let [contact {:public-key "pk"
:address "address"
:name "name"
:identicon "identicon"
:last-updated 1}
expected-contact {:id "pk"
:address "address"
:name "name"
:identicon "identicon"
:lastUpdated 1}]
(testing "->rpc"
(is (= expected-contact (c/->rpc contact))))))
(deftest contact<-rpc
(let [contact {:id "pk"
:address "address"

View File

@ -56,6 +56,7 @@
"wakuext_disableInstallation" {}
"wakuext_sendChatMessage" {}
"wakuext_sendChatMessages" {}
"wakuext_backupData" {}
"wakuext_confirmJoiningGroup" {}
"wakuext_addAdminsToGroupChat" {}
"wakuext_addMembersToGroupChat" {}
@ -90,9 +91,12 @@
"wakuext_unmuteChat" {}
"wakuext_contacts" {}
"wakuext_removeContact" {}
"wakuext_setContactLocalNickname" {}
"wakuext_clearHistory" {}
"wakuext_prepareContent" {}
"wakuext_blockContact" {}
"wakuext_unblockContact" {}
"wakuext_addContact" {}
"wakuext_updateMailservers" {}
"wakuext_sendEmojiReaction" {}
"wakuext_sendEmojiReactionRetraction" {}

View File

@ -7,6 +7,7 @@
[status-im.ui.components.react :as react]
[status-im.utils.fx :as fx]
status-im.utils.logging.core
status-im.backup.core
[status-im.wallet.core :as wallet]
[status-im.keycard.core :as keycard]
[status-im.utils.dimensions :as dimensions]

View File

@ -191,6 +191,7 @@
:latest-derived-path 0
:signing-phrase signing-phrase
:send-push-notifications? true
:backup-enabled? true
:installation-id (random-guid-generator)
;; default mailserver (history node) setting
:use-mailservers? true

View File

@ -47,6 +47,11 @@
(assoc-in db [:multiaccount setting] setting-value)
(update db :multiaccount dissoc setting))}))
(fx/defn toggle-backup-enabled
{:events [:multiaccounts.ui/switch-backup-enabled]}
[cofx enabled?]
(multiaccount-update cofx :backup-enabled? enabled? {}))
(fx/defn toggle-opensea-nfts-visibility
{:events [::toggle-opensea-nfts-visiblity]}
[cofx visible?]

View File

@ -43,7 +43,7 @@
(fx/defn handle-private-chat [{:keys [db] :as cofx} {:keys [chat-id]}]
(if-not (new-chat.db/own-public-key? db chat-id)
(chat/start-chat cofx chat-id)
(chat/start-chat cofx chat-id nil)
{:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
:content (i18n/label :t/can-not-add-yourself)}}))

View File

@ -53,7 +53,7 @@
(fx/defn process
{:events [:signals/signal-received]}
[cofx event-str]
[{:keys [db] :as cofx} event-str]
;; We only convert to clojure when strictly necessary or we know it
;; won't impact performance, as it is a fairly costly operation on large-ish
;; data structures
@ -62,6 +62,7 @@
type (.-type data)]
(case type
"node.login" (status-node-started cofx (js->clj event-js :keywordize-keys true))
"backup.performed" {:db (assoc-in db [:multiaccount :last-backup] (.-lastBackup event-js))}
"envelope.sent" (transport.message/update-envelopes-status cofx (:ids (js->clj event-js :keywordize-keys true)) :sent)
"envelope.expired" (transport.message/update-envelopes-status cofx (:ids (js->clj event-js :keywordize-keys true)) :not-sent)
"message.delivered" (let [{:keys [chatID messageID]} (js->clj event-js :keywordize-keys true)]

View File

@ -260,6 +260,8 @@
(reg-root-key-sub :bug-report/description-error :bug-report/description-error)
(reg-root-key-sub :bug-report/details :bug-report/details)
(reg-root-key-sub :backup/performing-backup :backup/performing-backup)
(re-frame/reg-sub
:communities
:<- [:raw-communities]

View File

@ -0,0 +1,52 @@
(ns status-im.ui.screens.backup-settings.view
(:require-macros [status-im.utils.views :as views])
(:require [status-im.ui.components.react :as react]
[quo.design-system.colors :as colors]
[status-im.utils.datetime :as datetime]
[status-im.i18n.i18n :as i18n]
[quo.core :as quo]
[re-frame.core :as re-frame]))
(defn perform-backup! []
(re-frame/dispatch [:multiaccounts.ui/perform-backup-pressed]))
(defn footer [performing-backup?]
[react/touchable-highlight {:on-press (when-not performing-backup?
perform-backup!)
:style {:height 52}}
[react/view
{:style {:justify-content :center
:flex 1
:align-items :center}}
[react/text
{:color colors/blue
:text-align :center}
(if performing-backup?
(i18n/label :t/backing-up)
(i18n/label :t/perform-backup))]]])
(views/defview backup-settings []
(views/letsubs
[{:keys [last-backup backup-enabled?]}
[:multiaccount]
performing-backup? [:backup/performing-backup]]
[:<>
[react/scroll-view
[quo/list-item
{:size :small
:title (i18n/label :t/backup-through-waku)
:accessibility-label :backup-enabled
:container-margin-bottom 8
:on-press
#(re-frame/dispatch
[:multiaccounts.ui/switch-backup-enabled (not backup-enabled?)])
:accessory :switch
:active backup-enabled?}]
[quo/list-item
{:size :small
:title (i18n/label :t/last-backup-performed)
:accessory :text
:subtitle (if (pos? last-backup)
(datetime/time-ago-long (datetime/to-date last-backup))
(i18n/label :t/never))}]]
[footer performing-backup?]]))

View File

@ -95,6 +95,7 @@
[status-im.ui.screens.progress.views :as progress]
[status-im.ui.screens.qr-scanner.views :as qr-scanner]
[status-im.ui.screens.referrals.public-chat :as referrals.public-chat]
[status-im.ui.screens.backup-settings.view :as backup-settings]
[status-im.ui.screens.reset-password.views :as reset-password]
[status-im.ui.screens.rpc-usage-info :as rpc-usage-info]
[status-im.ui.screens.status.new.views :as status.new]
@ -546,6 +547,9 @@
{:name :mobile-network-settings
:options {:topBar {:title {:text (i18n/label :t/mobile-network-settings)}}}
:component mobile-network-settings/mobile-network-settings}
{:name :backup-settings
:options {:topBar {:title {:text (i18n/label :t/backup-settings)}}}
:component backup-settings/backup-settings}
{:name :backup-seed
;;TODO dynamic navigation
:options {:topBar {:visible false}}

View File

@ -9,6 +9,7 @@
(views/defview sync-settings []
(views/letsubs [{:keys [syncing-on-mobile-network?
backup-enabled?
default-sync-period
use-mailservers?]} [:multiaccount]
current-mailserver-name [:mailserver/current-name]]
@ -23,6 +24,15 @@
:accessory-text (if syncing-on-mobile-network?
(i18n/label :t/mobile-network-use-mobile)
(i18n/label :t/mobile-network-use-wifi))}]
[quo/list-item {:size :small
:title (i18n/label :t/backup-settings)
:accessibility-label :backup-settings-button
:on-press #(re-frame/dispatch [:navigate-to :backup-settings])
:chevron true
:accessory :text
:accessory-text (if backup-enabled?
(i18n/label :t/backup-enabled)
(i18n/label :t/backup-disabled))}]
[quo/list-item {:size :small
:title (i18n/label :t/default-sync-period)
:accessibility-label :default-sync-period-button

View File

@ -140,6 +140,20 @@
int
(format-time-ago unit))))
(defn time-ago-long [time]
(let [seconds-ago (seconds-ago time)
unit (first (drop-while #(and (>= seconds-ago (:limit %))
(:limit %))
units))
diff (-> (/ seconds-ago (:in-second unit))
Math/floor
int)
name (label-pluralize diff (:name unit))]
(label :t/datetime-ago-format {:ago (label :t/datetime-ago)
:number diff
:time-intervals name})))
(defn to-date [ms]
(from-long ms))

View File

@ -57,7 +57,7 @@
(log/info "universal-links: handling private chat" chat-id)
(when chat-id
(if-not (new-chat.db/own-public-key? db chat-id)
(chat/start-chat cofx chat-id)
(chat/start-chat cofx chat-id nil)
{:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
:content (i18n/label :t/can-not-add-yourself)}})))

View File

@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im",
"repo": "status-go",
"version": "v0.89.20",
"commit-sha1": "e940434becc1522eeb26c4ce5f98fc3bc6b273a3",
"src-sha256": "0y0139gbbpyfpsgv6fgrc0jhhkfd3b8ci7qcjjrgxgmdff65krl4"
"version": "v0.90.0",
"commit-sha1": "6724cf4c753da412926e931996367a48c798f650",
"src-sha256": "013yfkw79rsqrw73cdnhrkrncfma5yikghgvn9s3b6vmfx5kznkr"
}

View File

@ -1275,6 +1275,13 @@
"keycard-backup-success-body": "Backup card created successfully. You can now use it with your account just like the primary card.",
"type-a-message": "Message",
"ulc-enabled": "ULC enabled",
"backup-enabled": "Enabled",
"backup-disabled": "Disabled",
"backup-settings": "Backup settings",
"backup-through-waku": "Backup through waku",
"perform-backup": "Perform backup",
"backing-up": "Backing up...",
"last-backup-performed": "Last backup performed:",
"unable-to-read-this-code": "Unable to read this code",
"unblock-contact": "Unblock this user",
"unknown-status-go-error": "Unknown status-go error",
@ -1676,6 +1683,7 @@
"hide": "Hide",
"account-is-used": "The account is being used with Dapps in the browser.",
"normal": "Normal",
"never": "Never",
"fee-options": "Suggested fee options",
"fee-cap": "Fee cap",
"tip-cap": "Tip cap",