Sync public chats
Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
This commit is contained in:
parent
87e6c6cdee
commit
5f910a0bec
|
@ -240,10 +240,11 @@
|
|||
|
||||
(fx/defn start-public-chat
|
||||
"Starts a new public chat"
|
||||
[cofx topic opts]
|
||||
[cofx topic {:keys [dont-navigate?] :as opts}]
|
||||
(fx/merge cofx
|
||||
(add-public-chat topic)
|
||||
(navigate-to-chat topic opts)
|
||||
#(when-not dont-navigate?
|
||||
(navigate-to-chat % topic opts))
|
||||
(public-chat/join-public-chat topic)
|
||||
(when platform/desktop?
|
||||
(desktop.events/change-tab :home))))
|
||||
|
|
|
@ -671,7 +671,10 @@
|
|||
(handlers/register-handler-fx
|
||||
:chat.ui/start-public-chat
|
||||
(fn [cofx [_ topic opts]]
|
||||
(chat/start-public-chat cofx topic opts)))
|
||||
(fx/merge
|
||||
cofx
|
||||
(chat/start-public-chat topic opts)
|
||||
(pairing/sync-public-chat topic))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:chat.ui/remove-chat
|
||||
|
|
|
@ -6,15 +6,18 @@
|
|||
[status-im.ui.screens.navigation :as navigation]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.utils.platform :as utils.platform]
|
||||
[status-im.chat.models :as models.chat]
|
||||
[status-im.accounts.db :as accounts.db]
|
||||
[status-im.transport.message.protocol :as protocol]
|
||||
[status-im.data-store.installations :as data-store.installations]
|
||||
[status-im.native-module.core :as native-module]
|
||||
[status-im.utils.identicon :as identicon]
|
||||
[status-im.data-store.contacts :as data-store.contacts]
|
||||
[status-im.data-store.accounts :as data-store.accounts]
|
||||
[status-im.transport.message.pairing :as transport.pairing]))
|
||||
|
||||
(def contact-batch-n 4)
|
||||
(def max-installations 2)
|
||||
|
||||
(defn- parse-response [response-js]
|
||||
(-> response-js
|
||||
|
@ -94,29 +97,41 @@
|
|||
(not (get-in db [:pairing/installations installation-id])))
|
||||
(fx/merge cofx
|
||||
(upsert-installation new-installation)
|
||||
#(when-not (get-in % [:db :pairing/prompt-user-pop-up])
|
||||
#(when-not (or (get-in % [:db :pairing/prompt-user-pop-up])
|
||||
(= :installations (:view-id db)))
|
||||
(prompt-user-on-new-installation %))))))))
|
||||
|
||||
(defn sync-installation-account-message [{:keys [db]}]
|
||||
(let [account (-> db
|
||||
:account/account
|
||||
(select-keys account-mergeable-keys))]
|
||||
(transport.pairing/SyncInstallation. {} account)))
|
||||
(transport.pairing/SyncInstallation. {} account {})))
|
||||
|
||||
(defn- contact-batch->sync-installation-message [batch]
|
||||
(let [contacts-to-sync (reduce (fn [acc {:keys [public-key] :as contact}]
|
||||
(assoc acc public-key (dissoc contact :photo-path)))
|
||||
{}
|
||||
batch)]
|
||||
(transport.pairing/SyncInstallation. contacts-to-sync nil)))
|
||||
(transport.pairing/SyncInstallation. contacts-to-sync {} {})))
|
||||
|
||||
(defn- chats->sync-installation-messages [{:keys [db]}]
|
||||
(->> db
|
||||
:chats
|
||||
vals
|
||||
(filter :public?)
|
||||
(filter :is-active)
|
||||
(map #(select-keys % [:chat-id :public?]))
|
||||
(map #(transport.pairing/SyncInstallation. {} {} %))))
|
||||
|
||||
(defn sync-installation-messages [{:keys [db] :as cofx}]
|
||||
(let [contacts (:contacts/contacts db)
|
||||
contact-batches (partition-all contact-batch-n (->> contacts
|
||||
vals
|
||||
(remove :dapp?)))]
|
||||
(conj (mapv contact-batch->sync-installation-message contact-batches)
|
||||
(sync-installation-account-message cofx))))
|
||||
(concat (mapv contact-batch->sync-installation-message contact-batches)
|
||||
|
||||
[(sync-installation-account-message cofx)]
|
||||
(chats->sync-installation-messages cofx))))
|
||||
|
||||
(defn enable [{:keys [db]} installation-id]
|
||||
{:db (assoc-in db
|
||||
|
@ -154,8 +169,12 @@
|
|||
(native-module/disable-installation installation-id
|
||||
(partial handle-disable-installation-response installation-id)))
|
||||
|
||||
(defn enable-fx [_ installation-id]
|
||||
{:pairing/enable-installation installation-id})
|
||||
(defn enable-fx [cofx installation-id]
|
||||
(if (< (count (filter :enabled? (get-in cofx [:db :pairing/installations]))) max-installations)
|
||||
{:pairing/enable-installation installation-id}
|
||||
{:utils/show-popup {:title (i18n/label :t/pairing-maximum-number-reached-title)
|
||||
|
||||
:content (i18n/label :t/pairing-maximum-number-reached-content)}}))
|
||||
|
||||
(defn disable-fx [_ installation-id]
|
||||
{:pairing/disable-installation installation-id})
|
||||
|
@ -184,6 +203,11 @@
|
|||
(has-paired-installations? cofx))
|
||||
(protocol/send payload nil cofx))))
|
||||
|
||||
(fx/defn sync-public-chat [cofx chat-id]
|
||||
(let [sync-message (transport.pairing/SyncInstallation. {} {} {:public? true
|
||||
:chat-id chat-id})]
|
||||
(send-installation-message-fx cofx sync-message)))
|
||||
|
||||
(defn send-installation-messages [cofx]
|
||||
;; The message needs to be broken up in chunks as we hit the whisper size limit
|
||||
(let [sync-messages (sync-installation-messages cofx)
|
||||
|
@ -204,16 +228,20 @@
|
|||
{}
|
||||
contacts))
|
||||
|
||||
(defn handle-sync-installation [{:keys [db] :as cofx} {:keys [contacts account]} sender]
|
||||
(defn handle-sync-installation [{:keys [db] :as cofx} {:keys [contacts account chat]} sender]
|
||||
(let [dev-mode? (get-in db [:account/account :dev-mode?])]
|
||||
(when (and (config/pairing-enabled? dev-mode?)
|
||||
(= sender (accounts.db/current-public-key cofx)))
|
||||
(let [new-contacts (merge-contacts (:contacts/contacts db) (ensure-photo-path contacts))
|
||||
new-account (merge-account (:account/account db) account)]
|
||||
{:db (assoc db
|
||||
:contacts/contacts new-contacts
|
||||
:account/account new-account)
|
||||
:data-store/tx [(data-store.contacts/save-contacts-tx (vals new-contacts))]}))))
|
||||
(fx/merge cofx
|
||||
{:db (assoc db
|
||||
:contacts/contacts new-contacts
|
||||
:account/account new-account)
|
||||
:data-store/base-tx [(data-store.accounts/save-account-tx new-account)]
|
||||
:data-store/tx [(data-store.contacts/save-contacts-tx (vals new-contacts))]}
|
||||
#(when (:public? chat)
|
||||
(models.chat/start-public-chat % (:chat-id chat) {:dont-navigate? true})))))))
|
||||
|
||||
(defn handle-pair-installation [{:keys [db] :as cofx} {:keys [installation-id device-type]} timestamp sender]
|
||||
(let [dev-mode? (get-in db [:account/account :dev-mode?])]
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
(select-keys
|
||||
(get-in cofx [:db :contacts/contacts])
|
||||
[chat-id])
|
||||
nil
|
||||
nil)]
|
||||
(fx/merge cofx
|
||||
(protocol/init-chat {:chat-id chat-id
|
||||
|
@ -47,6 +48,7 @@
|
|||
(select-keys
|
||||
(get-in cofx [:db :contacts/contacts])
|
||||
[chat-id])
|
||||
nil
|
||||
nil)
|
||||
success-event [:transport/contact-message-sent chat-id]
|
||||
chat (get-in db [:transport/chats chat-id])
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
(log/warn "failed sync installation validation" (spec/explain :message/pair-installation this)))))
|
||||
|
||||
(defrecord SyncInstallation
|
||||
[contacts account]
|
||||
[contacts account chat]
|
||||
protocol/StatusMessage
|
||||
(validate [this]
|
||||
(if (spec/valid? :message/sync-installation this)
|
||||
|
|
|
@ -86,8 +86,8 @@
|
|||
(deftype SyncInstallationHandler []
|
||||
Object
|
||||
(tag [this v] "p1")
|
||||
(rep [this {:keys [contacts account]}]
|
||||
#js [contacts account]))
|
||||
(rep [this {:keys [contacts account chat]}]
|
||||
#js [contacts account chat]))
|
||||
|
||||
(deftype PairInstallationHandler []
|
||||
Object
|
||||
|
@ -154,8 +154,8 @@
|
|||
(contact/ContactUpdate. name profile-image address fcm-token))
|
||||
"g5" (fn [[chat-id membership-updates message]]
|
||||
(group-chat/GroupMembershipUpdate. chat-id membership-updates message))
|
||||
"p1" (fn [[contacts account]]
|
||||
(pairing/SyncInstallation. contacts account))
|
||||
"p1" (fn [[contacts account chat]]
|
||||
(pairing/SyncInstallation. contacts account chat))
|
||||
"p2" (fn [[installation-id device-type]]
|
||||
(pairing/PairInstallation. installation-id device-type))}}))
|
||||
|
||||
|
|
|
@ -77,11 +77,12 @@
|
|||
[react/text {:style styles/qr-code-copy-text}
|
||||
(i18n/label :copy-qr)]]]]]))
|
||||
|
||||
(defn installations-section [installations]
|
||||
(defn installations-section [your-installation-id installations]
|
||||
[react/view
|
||||
[pairing.views/pair-this-device]
|
||||
[pairing.views/sync-devices]
|
||||
[react/view {:style pairing.styles/installation-list}
|
||||
[pairing.views/your-device your-installation-id]
|
||||
(for [installation installations]
|
||||
^{:key (:installation-id installation)}
|
||||
[react/view {:style {:margin-bottom 10}}
|
||||
|
@ -176,10 +177,11 @@
|
|||
[logging-display]])))
|
||||
|
||||
(views/defview installations []
|
||||
(views/letsubs [installations [:pairing/installations]]
|
||||
(views/letsubs [installations [:pairing/installations]
|
||||
installation-id [:pairing/installation-id]]
|
||||
[react/scroll-view
|
||||
(when (config/pairing-enabled? true)
|
||||
(installations-section installations))]))
|
||||
(installations-section installation-id installations))]))
|
||||
|
||||
(views/defview backup-recovery-phrase []
|
||||
[profile.recovery/backup-seed])
|
||||
|
|
|
@ -8,3 +8,7 @@
|
|||
(->> installations
|
||||
vals
|
||||
(sort-by (comp unchecked-negate :last-paired)))))
|
||||
|
||||
(re-frame/reg-sub :pairing/installation-id
|
||||
:<- [:get :account/account]
|
||||
:installation-id)
|
||||
|
|
|
@ -2,13 +2,16 @@
|
|||
(:require-macros [status-im.utils.views :as views])
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.i18n :as i18n]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.ui.screens.main-tabs.styles :as main-tabs.styles]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.icons.vector-icons :as icons]
|
||||
[status-im.ui.screens.home.styles :as home.styles]
|
||||
[status-im.utils.platform :as utils.platform]
|
||||
[status-im.utils.gfycat.core :as gfycat]
|
||||
[status-im.ui.components.button.view :as buttons]
|
||||
[status-im.ui.components.checkbox.view :as checkbox.views]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.status-bar.view :as status-bar]
|
||||
|
@ -17,6 +20,8 @@
|
|||
[status-im.ui.screens.profile.components.views :as profile.components]
|
||||
[status-im.ui.screens.pairing.styles :as styles]))
|
||||
|
||||
(def syncing (reagent/atom false))
|
||||
|
||||
(defn icon-style [{:keys [width height] :as style}]
|
||||
(if utils.platform/desktop?
|
||||
{:container-style {:width width
|
||||
|
@ -26,25 +31,37 @@
|
|||
style))
|
||||
|
||||
(defn synchronize-installations! []
|
||||
(reset! syncing true)
|
||||
;; Currently we don't know how long it takes, so we just disable for 10s, to avoid
|
||||
;; spamming
|
||||
(js/setTimeout #(reset! syncing false) 10000)
|
||||
(re-frame/dispatch [:pairing.ui/synchronize-installation-pressed]))
|
||||
|
||||
(defn pair! []
|
||||
(re-frame/dispatch [:pairing.ui/pair-devices-pressed]))
|
||||
|
||||
(defn enable-installation! [installation-id _]
|
||||
(defn enable-installation! [installation-id]
|
||||
(re-frame/dispatch [:pairing.ui/enable-installation-pressed installation-id]))
|
||||
|
||||
(defn disable-installation! [installation-id _]
|
||||
(defn disable-installation! [installation-id]
|
||||
(re-frame/dispatch [:pairing.ui/disable-installation-pressed installation-id]))
|
||||
|
||||
(defn footer []
|
||||
[react/touchable-highlight {:on-press synchronize-installations!
|
||||
(defn toggle-enabled! [installation-id enabled? _]
|
||||
(if enabled?
|
||||
(disable-installation! installation-id)
|
||||
(enable-installation! installation-id)))
|
||||
|
||||
(defn footer [syncing]
|
||||
[react/touchable-highlight {:on-press (when-not @syncing
|
||||
synchronize-installations!)
|
||||
:style main-tabs.styles/tabs-container}
|
||||
[react/view
|
||||
{:style styles/footer-content}
|
||||
[react/text
|
||||
{:style styles/footer-text}
|
||||
(i18n/label :t/sync-all-devices)]]])
|
||||
(if @syncing
|
||||
(i18n/label :t/syncing-devices)
|
||||
(i18n/label :t/sync-all-devices))]]])
|
||||
|
||||
(defn pair-this-device []
|
||||
[react/touchable-highlight {:on-press pair!
|
||||
|
@ -68,14 +85,30 @@
|
|||
[icons/icon :icons/wnode (icon-style (styles/pairing-button-icon true))]]]
|
||||
[react/view {:style styles/pairing-actions-text}
|
||||
[react/view
|
||||
[react/text {:style styles/pair-this-device-title} (i18n/label :t/sync-all-devices)]]]]])
|
||||
[react/text {:style styles/pair-this-device-title}
|
||||
(if @syncing
|
||||
(i18n/label :t/syncing-devices)
|
||||
(i18n/label :t/sync-all-devices))]]]]])
|
||||
|
||||
(defn your-device [installation-id]
|
||||
[react/view {:style styles/installation-item}
|
||||
[react/view {:style (styles/pairing-button true)}
|
||||
[icons/icon (if utils.platform/desktop?
|
||||
:icons/desktop
|
||||
:icons/mobile)
|
||||
(icon-style (styles/pairing-button-icon true))]]
|
||||
[react/view {:style styles/pairing-actions-text}
|
||||
[react/view
|
||||
[react/text {:style styles/installation-item-name-text}
|
||||
(str
|
||||
(gfycat/generate-gfy installation-id)
|
||||
" ("
|
||||
(i18n/label :t/you)
|
||||
")")]]]])
|
||||
|
||||
(defn render-row [{:keys [device-type enabled? installation-id]}]
|
||||
[react/touchable-highlight
|
||||
{:on-press (if enabled?
|
||||
(partial disable-installation! installation-id)
|
||||
(partial enable-installation! installation-id))
|
||||
:accessibility-label :installation-item}
|
||||
{:accessibility-label :installation-item}
|
||||
[react/view {:style styles/installation-item}
|
||||
[react/view {:style (styles/pairing-button enabled?)}
|
||||
[icons/icon (if (= "desktop"
|
||||
|
@ -86,28 +119,35 @@
|
|||
[react/view {:style styles/pairing-actions-text}
|
||||
[react/view
|
||||
[react/text {:style styles/installation-item-name-text}
|
||||
(gfycat/generate-gfy installation-id)]]
|
||||
[react/view
|
||||
[react/text {:style styles/installation-status}
|
||||
(if enabled?
|
||||
(i18n/label :t/syncing-enabled)
|
||||
(i18n/label :t/syncing-disabled))]]]]])
|
||||
(gfycat/generate-gfy installation-id)]]]
|
||||
[react/view
|
||||
(if utils.platform/ios?
|
||||
;; On IOS switches seems to be broken, they take up value of dev-mode? (so if dev mode is on they all show to be on).
|
||||
;; Replacing therefore with checkbox until I have more time to investigate
|
||||
(checkbox.views/plain-checkbox {:checked? enabled?
|
||||
:on-value-change (partial toggle-enabled! installation-id enabled?)})
|
||||
[react/switch {:on-tint-color colors/blue
|
||||
:value enabled?
|
||||
:on-value-change (partial toggle-enabled! installation-id enabled?)}])]]])
|
||||
|
||||
(defn render-rows [installations]
|
||||
(defn render-rows [installation-id installations]
|
||||
[react/scroll-view {:style styles/wrapper}
|
||||
[list/flat-list {:data installations
|
||||
:default-separator? false
|
||||
:key-fn :installation-id
|
||||
:render-fn render-row}]])
|
||||
[your-device installation-id]
|
||||
(when (seq installations)
|
||||
[list/flat-list {:data installations
|
||||
:default-separator? false
|
||||
:key-fn :installation-id
|
||||
:render-fn render-row}])])
|
||||
|
||||
(defn installations-list [installations]
|
||||
(defn installations-list [installation-id installations]
|
||||
[react/view {:style styles/installation-list}
|
||||
[react/view {:style styles/paired-devices-title}
|
||||
[react/text (i18n/label :t/paired-devices)]]
|
||||
(render-rows installations)])
|
||||
(render-rows installation-id installations)])
|
||||
|
||||
(views/defview installations []
|
||||
(views/letsubs [installations [:pairing/installations]]
|
||||
(views/letsubs [installation-id [:pairing/installation-id]
|
||||
installations [:pairing/installations]]
|
||||
[react/view {:flex 1}
|
||||
[status-bar/status-bar]
|
||||
[toolbar/toolbar {}
|
||||
|
@ -115,6 +155,5 @@
|
|||
[toolbar/content-title (i18n/label :t/devices)]]
|
||||
[react/scroll-view {:style {:background-color :white}}
|
||||
[pair-this-device]
|
||||
(when (seq installations)
|
||||
[installations-list installations])]
|
||||
(when (seq installations) [footer])]))
|
||||
[installations-list installation-id installations]]
|
||||
(when (seq installations) [footer syncing])]))
|
||||
|
|
|
@ -153,7 +153,15 @@
|
|||
(let [cofx {:db {:account/account new-account}}
|
||||
sync-message {:account old-account}]
|
||||
(is (= new-account (get-in (pairing/handle-sync-installation cofx sync-message "us")
|
||||
[:db :account/account])))))))))
|
||||
[:db :account/account])))))))
|
||||
(testing "syncing public chats"
|
||||
(let [cofx {:db {:account/account {:public-key "us"}}}]
|
||||
(testing "a new chat"
|
||||
(let [sync-message {:chat {:public? true
|
||||
:chat-id "status"
|
||||
:is-active true}}]
|
||||
(is (get-in (pairing/handle-sync-installation cofx sync-message "us")
|
||||
[:db :chats "status"]))))))))
|
||||
|
||||
(deftest handle-pair-installation-test
|
||||
(with-redefs [config/pairing-enabled? (constantly true)]
|
||||
|
@ -183,6 +191,9 @@
|
|||
:name "name"
|
||||
:photo-path "photo-path"
|
||||
:last-updated 1}
|
||||
:chats {"status" {:public? true
|
||||
:is-active true
|
||||
:chat-id "status"}}
|
||||
:contacts/contacts {"contact-1" {:name "contact-1"
|
||||
:public-key "contact-1"}
|
||||
"contact-2" {:name "contact-2"
|
||||
|
@ -201,12 +212,14 @@
|
|||
:public-key "contact-3"}
|
||||
"contact-4" {:name "contact-4"
|
||||
:public-key "contact-4"}}
|
||||
nil)
|
||||
{} {})
|
||||
(transport.pairing/SyncInstallation. {"contact-5" {:name "contact-5"
|
||||
:public-key "contact-5"}} nil)
|
||||
:public-key "contact-5"}} {} {})
|
||||
(transport.pairing/SyncInstallation. {} {:photo-path "photo-path"
|
||||
:name "name"
|
||||
:last-updated 1})]]
|
||||
:last-updated 1} {})
|
||||
(transport.pairing/SyncInstallation. {} {} {:public? true
|
||||
:chat-id "status"})]]
|
||||
(is (= expected (pairing/sync-installation-messages cofx))))))
|
||||
|
||||
(deftest handle-bundles-added-test
|
||||
|
|
|
@ -9,10 +9,14 @@
|
|||
"pair": "Pair devices",
|
||||
"pair-this-device": "Pair this device",
|
||||
"pair-this-device-description": "Pair your devices to sync contacts and chats between them",
|
||||
"you": "you",
|
||||
"syncing-enabled": "Syncing enabled",
|
||||
"syncing-disabled": "Syncing disabled",
|
||||
"sync-all-devices": "Sync all devices",
|
||||
"syncing-devices": "Syncing...",
|
||||
"paired-devices": "Paired devices",
|
||||
"pairing-maximum-number-reached-title": "Max number of devices reached",
|
||||
"pairing-maximum-number-reached-content": "Please disable one of your devices before enabling a new one.",
|
||||
"pairing-new-installation-detected-title": "New device detected",
|
||||
"pairing-new-installation-detected-content": "A new device has been detected.\nIn order to use your devices correctly, it's important to pair and enable them before using them.\nPlease go to the device section under settings to pair your devices.",
|
||||
"pairing-go-to-installation": "Go to pairing settings",
|
||||
|
|
Loading…
Reference in New Issue