From cd54aa9b92dc10acf1bd55299dc0f9f2c392d778 Mon Sep 17 00:00:00 2001 From: Lungu Cristian Date: Fri, 26 Apr 2024 13:24:52 +0200 Subject: [PATCH] Add pairing/unpairing of devices (#19692) * feat: added pairing/unpairing of synced devices * feat: remove flatlists & add confirmation/toast --- .../contexts/syncing/device/view.cljs | 42 ++++++++++++--- src/status_im/contexts/syncing/events.cljs | 51 +++++++++++++++++++ .../syncing/syncing_devices_list/style.cljs | 8 +-- .../syncing/syncing_devices_list/view.cljs | 31 +++++++---- translations/en.json | 4 ++ 5 files changed, 113 insertions(+), 23 deletions(-) diff --git a/src/status_im/contexts/syncing/device/view.cljs b/src/status_im/contexts/syncing/device/view.cljs index d03cd6856a..10a65974e6 100644 --- a/src/status_im/contexts/syncing/device/view.cljs +++ b/src/status_im/contexts/syncing/device/view.cljs @@ -1,17 +1,47 @@ (ns status-im.contexts.syncing.device.view (:require [quo.core :as quo] + [react-native.core :as rn] [status-im.contexts.syncing.device.style :as style] - [utils.i18n :as i18n])) + [utils.i18n :as i18n] + [utils.re-frame :as rf])) + +(defn- hide-sheet + [] + (rf/dispatch [:hide-bottom-sheet])) + +(defn- unpair-confirmation + [installation-id name] + (fn [] + (let [unpair-device #(rf/dispatch [:syncing/disable-installation installation-id])] + [rn/view + [quo/drawer-top + {:title (i18n/label :t/unpair-device) + :description (i18n/label :t/unpair-device-description {:name name})}] + [quo/bottom-actions + {:actions :two-actions + :button-one-label (i18n/label :t/unpair) + :button-one-props {:type :danger + :on-press unpair-device} + :button-two-label (i18n/label :t/cancel) + :button-two-props {:type :grey + :on-press hide-sheet}}]]))) (defn view [{:keys [name + installation-id this-device? device-type enabled? show-button?]}] - (let [paired? (and (not this-device?) enabled?) - unpaired? (not enabled?)] + (let [paired? (and (not this-device?) enabled?) + unpaired? (not enabled?) + show-unpair-confirmation (fn [] + (rf/dispatch [:show-bottom-sheet + {:theme :dark + :content (unpair-confirmation installation-id name)}])) + pair-device (fn [] + (rf/dispatch [:syncing/enable-installation installation-id]))] [quo/settings-item (cond-> {:container-style style/device-container @@ -24,13 +54,13 @@ (and show-button? unpaired?) (assoc :action :button :action-props - {:title (i18n/label :t/pair) - :on-press #(js/alert "feature not added yet")}) + {:button-text (i18n/label :t/pair) + :on-press pair-device}) (and show-button? paired?) (assoc :action :button :action-props {:button-text (i18n/label :t/unpair) - :on-press #(js/alert "feature not added yet")}) + :on-press show-unpair-confirmation}) this-device? (assoc :tag :positive :tag-props {:label (i18n/label :t/this-device)}))])) diff --git a/src/status_im/contexts/syncing/events.cljs b/src/status_im/contexts/syncing/events.cljs index c39012d246..d591aa430c 100644 --- a/src/status_im/contexts/syncing/events.cljs +++ b/src/status_im/contexts/syncing/events.cljs @@ -9,6 +9,7 @@ [status-im.constants :as constants] [status-im.contexts.syncing.utils :as sync-utils] [taoensso.timbre :as log] + [utils.i18n :as i18n] [utils.re-frame :as rf] [utils.security.core :as security] [utils.transforms :as transforms])) @@ -111,3 +112,53 @@ (native-module/get-connection-string-for-bootstrapping-another-device config-map handle-connection))))) + +(rf/reg-event-fx + :syncing/enable-installation + (fn [_ [installation-id]] + {:fx [[:json-rpc/call + [{:method "wakuext_enableInstallation" + :params [installation-id] + :on-success #(rf/dispatch [:syncing/on-enable-installation-success installation-id]) + :on-error #(rf/dispatch [:syncing/on-toggle-installation-failed % installation-id])}]]]})) + +(rf/reg-event-fx + :syncing/disable-installation + (fn [_ [installation-id]] + {:fx [[:json-rpc/call + [{:method "wakuext_disableInstallation" + :params [installation-id] + :on-success #(rf/dispatch [:syncing/on-disable-installation-success installation-id]) + :on-error #(rf/dispatch [:syncing/on-toggle-installation-failed % installation-id])}]]]})) + +(rf/reg-event-fx + :syncing/on-enable-installation-success + (fn [{:keys [db]} [installation-id]] + {:db (assoc-in db + [:pairing/installations installation-id :enabled?] + true) + :fx [[:dispatch + [:toasts/upsert + {:type :positive + :theme :dark + :text (i18n/label :t/pair-device-toast)}]]]})) + +(rf/reg-event-fx + :syncing/on-disable-installation-success + (fn [{:keys [db]} [installation-id]] + {:db (assoc-in db + [:pairing/installations installation-id :enabled?] + false) + :fx [[:dispatch [:hide-bottom-sheet]] + [:dispatch + [:toasts/upsert + {:type :positive + :theme :dark + :text (i18n/label :t/unpair-device-toast)}]]]})) + +(rf/reg-event-fx + :syncing/on-toggle-installation-failed + (fn [_ [error installation-id]] + (log/error "Failed to toggle installation" + {:error error + :installation-id installation-id}))) diff --git a/src/status_im/contexts/syncing/syncing_devices_list/style.cljs b/src/status_im/contexts/syncing/syncing_devices_list/style.cljs index 0b972c5675..185d5ad9bb 100644 --- a/src/status_im/contexts/syncing/syncing_devices_list/style.cljs +++ b/src/status_im/contexts/syncing/syncing_devices_list/style.cljs @@ -9,9 +9,8 @@ :flex 1}) (def page-container - {:flex 1 - :justify-content :flex-start - :margin-horizontal 20}) + {:flex 1 + :padding-horizontal 20}) (def title-container {:flex-direction :row @@ -20,9 +19,6 @@ :margin-top 12 :margin-bottom 12}) -(def navigation-bar - {:height 56}) - (def subtitle {:margin-top 20 :color colors/white-opa-40}) diff --git a/src/status_im/contexts/syncing/syncing_devices_list/view.cljs b/src/status_im/contexts/syncing/syncing_devices_list/view.cljs index 02a5c8e963..03f3be0fc6 100644 --- a/src/status_im/contexts/syncing/syncing_devices_list/view.cljs +++ b/src/status_im/contexts/syncing/syncing_devices_list/view.cljs @@ -9,6 +9,14 @@ [utils.i18n :as i18n] [utils.re-frame :as rf])) +(defn go-back + [] + (rf/dispatch [:navigate-back])) + +(defn open-setup-syncing + [] + (rf/dispatch [:open-modal :settings-setup-syncing])) + (defn view [] (let [devices (rf/sub [:pairing/installations]) @@ -25,8 +33,11 @@ {:type :no-title :background :blur :icon-name :i/arrow-left - :on-press #(rf/dispatch [:navigate-back])}] - [rn/view {:style style/page-container} + :on-press go-back}] + [rn/scroll-view + {:content-container-style style/page-container + :style {:flex 1} + :shows-vertical-scroll-indicator false} [rn/view {:style style/title-container} [quo/text {:size :heading-1 @@ -38,7 +49,7 @@ :type :primary :customization-color profile-color :icon-only? true - :on-press #(rf/dispatch [:open-modal :settings-setup-syncing])} + :on-press open-setup-syncing} :i/add]] [device/view (merge user-device {:this-device? true})] (when (seq paired-devices) @@ -48,10 +59,9 @@ :weight :medium :style style/subtitle} (i18n/label :t/paired-with-this-device)] - [rn/flat-list - {:key-fn str - :render-fn device/view - :data paired-devices}]]) + (for [device-props paired-devices] + ^{:key (:installation-id device-props)} + [device/view device-props])]) (when (seq unpaired-devices) [rn/view [quo/text @@ -59,7 +69,6 @@ :weight :medium :style style/subtitle} (i18n/label :t/not-paired-with-this-device)] - [rn/flat-list - {:key-fn str - :render-fn device/view - :data unpaired-devices}]])]])) + (for [device-props unpaired-devices] + ^{:key (:installation-id device-props)} + [device/view device-props])])]])) diff --git a/translations/en.json b/translations/en.json index 1b5eaf40ad..71c0e68ffc 100644 --- a/translations/en.json +++ b/translations/en.json @@ -1118,6 +1118,7 @@ "own-your-crypto": "Own your crypto", "pair": "Pair", "pair-devices": "Pair devices", + "pair-device-toast": "Device successfully paired", "pair-card": "Pair to this device", "pair-code": "Pair code", "pair-code-explanation": "Pairs card to a different device (up to 5) to unlock keys and sign transactions with the same Keycard", @@ -1476,6 +1477,9 @@ "unpair": "Unpair", "unpair-card": "Unpair card", "unpair-card-confirmation": "This operation will unpair card from current device. Requires 6-digit passcode authorization. Do you want to proceed?", + "unpair-device": "Unpair device?", + "unpair-device-description": "This device will no longer synchronize with {{name}} until you pair them again.", + "unpair-device-toast": "Device successfully unpaired", "unpaired-keycard-text": "The Keycard you tapped is not associated with this phone", "unpaired-keycard-title": "Looks like your card has been unpaired", "unpair-keycard": "Unpair Keycard from this phone",