feat(onboarding): Switch profiles keeping biometrics valid (#21628)
* Rework login and logout flow to keep biometrics valid - Move logout logic to a new namespace, the implementation no longer uses `rf/defn` * Code style fixes * Fix warning: "null is not an image" in login * Fix biometric icons used all over the app --------- Co-authored-by: Yevheniia Berdnyk <ie.berdnyk@gmail.com>
This commit is contained in:
parent
58476a43da
commit
ac0a115f1d
|
@ -11,7 +11,6 @@
|
||||||
legacy.status-im.group-chats.core
|
legacy.status-im.group-chats.core
|
||||||
legacy.status-im.log-level.core
|
legacy.status-im.log-level.core
|
||||||
legacy.status-im.multiaccounts.login.core
|
legacy.status-im.multiaccounts.login.core
|
||||||
legacy.status-im.multiaccounts.logout.core
|
|
||||||
[legacy.status-im.multiaccounts.model :as multiaccounts.model]
|
[legacy.status-im.multiaccounts.model :as multiaccounts.model]
|
||||||
legacy.status-im.multiaccounts.update.core
|
legacy.status-im.multiaccounts.update.core
|
||||||
legacy.status-im.pairing.core
|
legacy.status-im.pairing.core
|
||||||
|
@ -110,14 +109,14 @@
|
||||||
(defn- on-biometric-auth-fail
|
(defn- on-biometric-auth-fail
|
||||||
[{:keys [code]}]
|
[{:keys [code]}]
|
||||||
(if (= code "USER_FALLBACK")
|
(if (= code "USER_FALLBACK")
|
||||||
(re-frame/dispatch [:multiaccounts.logout.ui/logout-confirmed])
|
(re-frame/dispatch [:profile/logout])
|
||||||
(utils/show-confirmation
|
(utils/show-confirmation
|
||||||
{:title (i18n/label :t/biometric-auth-confirm-title)
|
{:title (i18n/label :t/biometric-auth-confirm-title)
|
||||||
:content (i18n/label :t/biometric-auth-confirm-message)
|
:content (i18n/label :t/biometric-auth-confirm-message)
|
||||||
:confirm-button-text (i18n/label :t/biometric-auth-confirm-try-again)
|
:confirm-button-text (i18n/label :t/biometric-auth-confirm-try-again)
|
||||||
:cancel-button-text (i18n/label :t/biometric-auth-confirm-logout)
|
:cancel-button-text (i18n/label :t/biometric-auth-confirm-logout)
|
||||||
:on-accept #(rf/dispatch [:biometric/authenticate {:on-fail on-biometric-auth-fail}])
|
:on-accept #(rf/dispatch [:biometric/authenticate {:on-fail on-biometric-auth-fail}])
|
||||||
:on-cancel #(re-frame/dispatch [:multiaccounts.logout.ui/logout-confirmed])})))
|
:on-cancel #(re-frame/dispatch [:profile/logout])})))
|
||||||
|
|
||||||
(rf/defn on-return-from-background
|
(rf/defn on-return-from-background
|
||||||
[{:keys [db now] :as cofx}]
|
[{:keys [db now] :as cofx}]
|
||||||
|
|
|
@ -91,5 +91,4 @@
|
||||||
cofx
|
cofx
|
||||||
:fleet
|
:fleet
|
||||||
fleet
|
fleet
|
||||||
{:on-success
|
{:on-success #(re-frame/dispatch [:profile/logout])}))))
|
||||||
#(re-frame/dispatch [:logout])}))))
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
cofx
|
cofx
|
||||||
:log-level
|
:log-level
|
||||||
log-level
|
log-level
|
||||||
{:on-success #(re-frame/dispatch [:logout])}))))
|
{:on-success #(re-frame/dispatch [:profile/logout])}))))
|
||||||
|
|
||||||
(rf/defn show-change-log-level-confirmation
|
(rf/defn show-change-log-level-confirmation
|
||||||
{:events [:log-level.ui/log-level-selected]}
|
{:events [:log-level.ui/log-level-selected]}
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
(ns legacy.status-im.multiaccounts.logout.core
|
|
||||||
(:require
|
|
||||||
[native-module.core :as native-module]
|
|
||||||
[re-frame.core :as re-frame]
|
|
||||||
[status-im.common.keychain.events :as keychain]
|
|
||||||
[status-im.db :as db]
|
|
||||||
[utils.i18n :as i18n]
|
|
||||||
[utils.re-frame :as rf]))
|
|
||||||
|
|
||||||
(re-frame/reg-fx
|
|
||||||
::logout
|
|
||||||
(fn []
|
|
||||||
(native-module/logout)))
|
|
||||||
|
|
||||||
(rf/defn initialize-app-db
|
|
||||||
[{{:keys [keycard initials-avatar-font-file biometrics]
|
|
||||||
:network/keys [type status expensive?]
|
|
||||||
:centralized-metrics/keys [user-confirmed?]}
|
|
||||||
:db}]
|
|
||||||
{:db (assoc db/app-db
|
|
||||||
:centralized-metrics/user-confirmed? user-confirmed?
|
|
||||||
:network/type type
|
|
||||||
:network/status status
|
|
||||||
:network/expensive? expensive?
|
|
||||||
:initials-avatar-font-file initials-avatar-font-file
|
|
||||||
:keycard (dissoc keycard :secrets :pin :application-info)
|
|
||||||
:biometrics biometrics
|
|
||||||
:syncing nil)})
|
|
||||||
|
|
||||||
(rf/defn logout-method
|
|
||||||
{:events [::logout-method]}
|
|
||||||
[{:keys [db] :as cofx} {:keys [auth-method logout?]}]
|
|
||||||
(let [key-uid (get-in db [:profile/profile :key-uid])]
|
|
||||||
(rf/merge cofx
|
|
||||||
{:dispatch [:update-theme-and-init-root :progress]
|
|
||||||
:effects.shell/reset-state nil
|
|
||||||
:hide-popover nil
|
|
||||||
::logout nil
|
|
||||||
:profile.settings/webview-debug-changed false
|
|
||||||
:keychain/clear-user-password key-uid
|
|
||||||
:profile/get-profiles-overview #(rf/dispatch
|
|
||||||
[:profile/get-profiles-overview-success %])}
|
|
||||||
(keychain/save-auth-method key-uid auth-method)
|
|
||||||
(initialize-app-db))))
|
|
||||||
|
|
||||||
(rf/defn logout
|
|
||||||
{:events [:logout :multiaccounts.logout.ui/logout-confirmed
|
|
||||||
:multiaccounts.update.callback/save-settings-success]}
|
|
||||||
[_]
|
|
||||||
;; we need to disable notifications before starting the logout process
|
|
||||||
{:effects/push-notifications-disable nil
|
|
||||||
:dispatch [:alert-banners/remove-all]
|
|
||||||
:dispatch-later [{:ms 100
|
|
||||||
:dispatch [::logout-method
|
|
||||||
{:auth-method keychain/auth-method-none
|
|
||||||
:logout? true}]}]})
|
|
||||||
|
|
||||||
(rf/defn show-logout-confirmation
|
|
||||||
{:events [:multiaccounts.logout.ui/logout-pressed]}
|
|
||||||
[_]
|
|
||||||
{:ui/show-confirmation
|
|
||||||
{:title (i18n/label :t/logout-title)
|
|
||||||
:content (i18n/label :t/logout-are-you-sure)
|
|
||||||
:confirm-button-text (i18n/label :t/logout)
|
|
||||||
:on-accept #(re-frame/dispatch [:multiaccounts.logout.ui/logout-confirmed])
|
|
||||||
:on-cancel nil}})
|
|
|
@ -125,6 +125,6 @@
|
||||||
(i18n/label :t/password-reset-success-message)])
|
(i18n/label :t/password-reset-success-message)])
|
||||||
[react/view {:align-items :center}
|
[react/view {:align-items :center}
|
||||||
[quo/button
|
[quo/button
|
||||||
{:on-press #(re-frame/dispatch [:logout])
|
{:on-press #(re-frame/dispatch [:profile/logout])
|
||||||
:disabled resetting?}
|
:disabled resetting?}
|
||||||
(i18n/label :t/okay)]]]))
|
(i18n/label :t/okay)]]]))
|
||||||
|
|
|
@ -133,7 +133,7 @@
|
||||||
:params [{:enabled enabled?}]
|
:params [{:enabled enabled?}]
|
||||||
:on-success (fn []
|
:on-success (fn []
|
||||||
(log/info "light client set successfully" enabled?)
|
(log/info "light client set successfully" enabled?)
|
||||||
(re-frame/dispatch [:logout]))
|
(re-frame/dispatch [:profile/logout]))
|
||||||
:on-error #(log/error "failed to set light client"
|
:on-error #(log/error "failed to set light client"
|
||||||
{:error %
|
{:error %
|
||||||
:enabled? enabled?})}]})
|
:enabled? enabled?})}]})
|
||||||
|
@ -149,7 +149,7 @@
|
||||||
:params [{:enabled enabled?}]
|
:params [{:enabled enabled?}]
|
||||||
:on-success (fn []
|
:on-success (fn []
|
||||||
(log/info "store confirmation set successfully" enabled?)
|
(log/info "store confirmation set successfully" enabled?)
|
||||||
(re-frame/dispatch [:logout]))
|
(re-frame/dispatch [:profile/logout]))
|
||||||
:on-error #(log/error "failed to set store confirmation"
|
:on-error #(log/error "failed to set store confirmation"
|
||||||
{:error %
|
{:error %
|
||||||
:enabled? enabled?})}]})
|
:enabled? enabled?})}]})
|
||||||
|
|
|
@ -36,10 +36,11 @@
|
||||||
"Same as rn/image but cache the image source in a js/Set, so the image won't
|
"Same as rn/image but cache the image source in a js/Set, so the image won't
|
||||||
flicker when re-render on android"
|
flicker when re-render on android"
|
||||||
[props]
|
[props]
|
||||||
(let [[loaded-source set-loaded-source] (rn/use-state nil)
|
(let [[loaded-source set-loaded-source] (rn/use-state nil)]
|
||||||
on-source-loaded (rn/use-callback #(set-loaded-source %))]
|
|
||||||
(if platform/ios?
|
(if platform/ios?
|
||||||
[rn/image props]
|
[rn/image props]
|
||||||
[:<>
|
[:<>
|
||||||
[rn/image (assoc props :source loaded-source)]
|
[rn/image
|
||||||
[caching-image props on-source-loaded]])))
|
(cond-> props
|
||||||
|
loaded-source (assoc :source loaded-source))]
|
||||||
|
[caching-image props set-loaded-source]])))
|
||||||
|
|
|
@ -75,7 +75,9 @@
|
||||||
(-> (str key-uid "-auth")
|
(-> (str key-uid "-auth")
|
||||||
(keychain/get-credentials)
|
(keychain/get-credentials)
|
||||||
(.then (fn [value]
|
(.then (fn [value]
|
||||||
(if value (oops/oget value "password") auth-method-none)))
|
(if value
|
||||||
|
(oops/oget value "password")
|
||||||
|
auth-method-none)))
|
||||||
(.catch (constantly auth-method-none))))
|
(.catch (constantly auth-method-none))))
|
||||||
|
|
||||||
(defn save-user-password!
|
(defn save-user-password!
|
||||||
|
@ -86,10 +88,10 @@
|
||||||
[key-uid callback]
|
[key-uid callback]
|
||||||
(keychain/get-credentials key-uid
|
(keychain/get-credentials key-uid
|
||||||
(fn [value]
|
(fn [value]
|
||||||
(callback (when value
|
(some-> value
|
||||||
(-> value
|
(oops/oget "password")
|
||||||
(oops/oget "password")
|
(security/mask-data)
|
||||||
(security/mask-data)))))))
|
(callback)))))
|
||||||
|
|
||||||
(re-frame/reg-fx
|
(re-frame/reg-fx
|
||||||
:keychain/get-user-password
|
:keychain/get-user-password
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
[quo.foundations.colors :as colors]
|
[quo.foundations.colors :as colors]
|
||||||
[quo.theme :as quo.theme]
|
[quo.theme :as quo.theme]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
|
[status-im.common.biometric.utils :as biometric]
|
||||||
[status-im.common.standard-authentication.forgot-password-doc.view :as forgot-password-doc]
|
[status-im.common.standard-authentication.forgot-password-doc.view :as forgot-password-doc]
|
||||||
[status-im.common.standard-authentication.password-input.style :as style]
|
[status-im.common.standard-authentication.password-input.style :as style]
|
||||||
[utils.debounce :as debounce]
|
[utils.debounce :as debounce]
|
||||||
|
@ -54,7 +55,8 @@
|
||||||
{:password (security/mask-data
|
{:password (security/mask-data
|
||||||
entered-password)
|
entered-password)
|
||||||
:error ""}]
|
:error ""}]
|
||||||
100)))]
|
100)))
|
||||||
|
biometric-type (rf/sub [:biometrics/supported-type])]
|
||||||
[:<>
|
[:<>
|
||||||
[rn/view {:style {:flex-direction :row}}
|
[rn/view {:style {:flex-direction :row}}
|
||||||
[quo/input
|
[quo/input
|
||||||
|
@ -76,6 +78,6 @@
|
||||||
:icon-only? true
|
:icon-only? true
|
||||||
:background (when blur? :blur)
|
:background (when blur? :blur)
|
||||||
:type :outline}
|
:type :outline}
|
||||||
:i/face-id])]
|
(biometric/get-icon-by-type biometric-type)])]
|
||||||
(when error?
|
(when error?
|
||||||
[error-info error-message processing shell?])]))
|
[error-info error-message processing shell?])]))
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
[quo.core :as quo]
|
[quo.core :as quo]
|
||||||
[quo.theme :as quo.theme]
|
[quo.theme :as quo.theme]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
|
[status-im.common.biometric.utils :as biometric]
|
||||||
[status-im.constants :as constants]
|
[status-im.constants :as constants]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
|
@ -26,12 +27,15 @@
|
||||||
:on-auth-success on-auth-success
|
:on-auth-success on-auth-success
|
||||||
:on-auth-fail on-auth-fail
|
:on-auth-fail on-auth-fail
|
||||||
:auth-button-label auth-button-label}]))
|
:auth-button-label auth-button-label}]))
|
||||||
(vec (conj dependencies on-auth-success on-auth-fail)))]
|
(vec (conj dependencies on-auth-success on-auth-fail)))
|
||||||
|
biometric-type (rf/sub [:biometrics/supported-type])]
|
||||||
[quo/slide-button
|
[quo/slide-button
|
||||||
{:container-style container-style
|
{:container-style container-style
|
||||||
:size size
|
:size size
|
||||||
:customization-color customization-color
|
:customization-color customization-color
|
||||||
:on-complete on-complete
|
:on-complete on-complete
|
||||||
:track-icon (if biometric-auth? :i/face-id :password)
|
:track-icon (if biometric-auth?
|
||||||
|
(biometric/get-icon-by-type biometric-type)
|
||||||
|
:password)
|
||||||
:track-text track-text
|
:track-text track-text
|
||||||
:disabled? disabled?}]))
|
:disabled? disabled?}]))
|
||||||
|
|
|
@ -29,4 +29,4 @@
|
||||||
[quo/bottom-actions
|
[quo/bottom-actions
|
||||||
{:actions :one-action
|
{:actions :one-action
|
||||||
:button-one-label (i18n/label :t/log-out-remove)
|
:button-one-label (i18n/label :t/log-out-remove)
|
||||||
:button-one-props {:on-press #(rf/dispatch [:logout])}}]]))
|
:button-one-props {:on-press #(rf/dispatch [:profile/logout])}}]]))
|
||||||
|
|
|
@ -26,6 +26,6 @@
|
||||||
{:resize-mode :contain
|
{:resize-mode :contain
|
||||||
:source (resources/get-image :keycard-migration-succeeded)}]]
|
:source (resources/get-image :keycard-migration-succeeded)}]]
|
||||||
[quo/button
|
[quo/button
|
||||||
{:on-press #(rf/dispatch [:logout])
|
{:on-press #(rf/dispatch [:profile/logout])
|
||||||
:container-style {:margin-horizontal 20}}
|
:container-style {:margin-horizontal 20}}
|
||||||
(i18n/label :t/logout)]]))
|
(i18n/label :t/logout)]]))
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
|
|
||||||
(defn page-title
|
(defn page-title
|
||||||
[]
|
[]
|
||||||
[quo/text-combinations
|
[quo/text-combinations
|
||||||
|
@ -26,12 +25,13 @@
|
||||||
bio-type-label (biometric/get-label-by-type supported-biometric-type)
|
bio-type-label (biometric/get-label-by-type supported-biometric-type)
|
||||||
profile-color (or (:color (rf/sub [:onboarding/profile]))
|
profile-color (or (:color (rf/sub [:onboarding/profile]))
|
||||||
(rf/sub [:profile/customization-color]))
|
(rf/sub [:profile/customization-color]))
|
||||||
syncing-results? (= :screen/onboarding.syncing-results @state/root-id)]
|
syncing-results? (= :screen/onboarding.syncing-results @state/root-id)
|
||||||
|
biometric-type (rf/sub [:biometrics/supported-type])]
|
||||||
[rn/view {:style (style/buttons insets)}
|
[rn/view {:style (style/buttons insets)}
|
||||||
[quo/button
|
[quo/button
|
||||||
{:size 40
|
{:size 40
|
||||||
:accessibility-label :enable-biometrics-button
|
:accessibility-label :enable-biometrics-button
|
||||||
:icon-left :i/face-id
|
:icon-left (biometric/get-icon-by-type biometric-type)
|
||||||
:customization-color profile-color
|
:customization-color profile-color
|
||||||
:on-press #(rf/dispatch [:onboarding/enable-biometrics])}
|
:on-press #(rf/dispatch [:onboarding/enable-biometrics])}
|
||||||
(i18n/label :t/biometric-enable-button {:bio-type-label bio-type-label})]
|
(i18n/label :t/biometric-enable-button {:bio-type-label bio-type-label})]
|
||||||
|
|
|
@ -81,8 +81,8 @@
|
||||||
(rf/defn create-account-and-login
|
(rf/defn create-account-and-login
|
||||||
{:events [:onboarding/create-account-and-login]}
|
{:events [:onboarding/create-account-and-login]}
|
||||||
[{:keys [db] :as cofx}]
|
[{:keys [db] :as cofx}]
|
||||||
(let [{:keys [display-name seed-phrase password image-path color] :as profile}
|
(let [{:keys [seed-phrase]
|
||||||
(:onboarding/profile db)
|
:as profile} (:onboarding/profile db)
|
||||||
syncing-account-recovered? (and (seq (:syncing/key-uid db))
|
syncing-account-recovered? (and (seq (:syncing/key-uid db))
|
||||||
(= (:syncing/key-uid db)
|
(= (:syncing/key-uid db)
|
||||||
(get-in db [:onboarding/profile :key-uid])))]
|
(get-in db [:onboarding/profile :key-uid])))]
|
||||||
|
@ -112,20 +112,21 @@
|
||||||
(when-not (seq multiaccounts)
|
(when-not (seq multiaccounts)
|
||||||
{:dispatch [:update-theme-and-init-root :screen/onboarding.intro]}))))
|
{:dispatch [:update-theme-and-init-root :screen/onboarding.intro]}))))
|
||||||
|
|
||||||
(rf/defn password-set
|
(rf/reg-event-fx
|
||||||
{:events [:onboarding/password-set]}
|
:onboarding/password-set
|
||||||
[{:keys [db]} password]
|
(fn [{:keys [db]} [masked-password]]
|
||||||
(let [supported-type (get-in db [:biometrics :supported-type])]
|
(let [biometric-supported-type (get-in db [:biometrics :supported-type])]
|
||||||
{:db (-> db
|
{:db (-> db
|
||||||
(assoc-in [:onboarding/profile :password] password)
|
(assoc-in [:onboarding/profile :password] masked-password)
|
||||||
(assoc-in [:onboarding/profile :auth-method] constants/auth-method-password))
|
(assoc-in [:onboarding/profile :auth-method] constants/auth-method-password))
|
||||||
:dispatch (if supported-type
|
:fx [[:dispatch
|
||||||
[:navigate-to-within-stack
|
(if biometric-supported-type
|
||||||
[:screen/onboarding.enable-biometrics
|
[:navigate-to-within-stack
|
||||||
(get db
|
[:screen/onboarding.enable-biometrics
|
||||||
:onboarding/navigated-to-enter-seed-phrase-from-screen
|
(get db
|
||||||
:screen/onboarding.new-to-status)]]
|
:onboarding/navigated-to-enter-seed-phrase-from-screen
|
||||||
[:onboarding/create-account-and-login])}))
|
:screen/onboarding.new-to-status)]]
|
||||||
|
[:onboarding/create-account-and-login])]]})))
|
||||||
|
|
||||||
(rf/defn navigate-to-enable-biometrics
|
(rf/defn navigate-to-enable-biometrics
|
||||||
{:events [:onboarding/navigate-to-enable-biometrics]}
|
{:events [:onboarding/navigate-to-enable-biometrics]}
|
||||||
|
@ -190,8 +191,7 @@
|
||||||
key-uid (get-in db [:profile/profile :key-uid])
|
key-uid (get-in db [:profile/profile :key-uid])
|
||||||
syncing? (get-in db [:onboarding/profile :syncing?])
|
syncing? (get-in db [:onboarding/profile :syncing?])
|
||||||
auth-method (get-in db [:onboarding/profile :auth-method])
|
auth-method (get-in db [:onboarding/profile :auth-method])
|
||||||
biometric-enabled? (= auth-method
|
biometric-enabled? (= auth-method constants/auth-method-biometric)]
|
||||||
constants/auth-method-biometric)]
|
|
||||||
(cond-> {:db (assoc db :onboarding/generated-keys? true)}
|
(cond-> {:db (assoc db :onboarding/generated-keys? true)}
|
||||||
biometric-enabled?
|
biometric-enabled?
|
||||||
(assoc :keychain/save-password-and-auth-method
|
(assoc :keychain/save-password-and-auth-method
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
[status-im.contexts.profile.edit.name.events]
|
[status-im.contexts.profile.edit.name.events]
|
||||||
status-im.contexts.profile.effects
|
status-im.contexts.profile.effects
|
||||||
status-im.contexts.profile.login.events
|
status-im.contexts.profile.login.events
|
||||||
|
status-im.contexts.profile.logout.events
|
||||||
[status-im.contexts.profile.rpc :as profile.rpc]
|
[status-im.contexts.profile.rpc :as profile.rpc]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
|
@ -39,32 +40,54 @@
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:profile/profile-selected
|
:profile/profile-selected
|
||||||
(fn [{:keys [db]} [key-uid]]
|
(fn [{:keys [db]} [key-uid]]
|
||||||
{:db (update db :profile/login #(select-profile % key-uid))}))
|
{:db (update db :profile/login select-profile key-uid)}))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:profile/set-profile-overview-auth-method
|
||||||
|
(fn [{db :db} [key-uid auth-method]]
|
||||||
|
{:db (assoc-in db [:profile/profiles-overview key-uid :auth-method] auth-method)}))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:profile/get-profiles-auth-method
|
||||||
|
(fn [_ [key-uids]]
|
||||||
|
(let [auth-method-fx (fn [key-uid]
|
||||||
|
[:effects.biometric/check-if-available
|
||||||
|
{:key-uid key-uid
|
||||||
|
:on-success (fn [auth-method]
|
||||||
|
(rf/dispatch
|
||||||
|
[:profile/set-profile-overview-auth-method
|
||||||
|
key-uid
|
||||||
|
auth-method]))}])]
|
||||||
|
{:fx (map auth-method-fx key-uids)})))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:profile/set-already-logged-out
|
||||||
|
(fn [{:keys [db]}]
|
||||||
|
{:db (dissoc db :profile/logging-out?)}))
|
||||||
|
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:profile/get-profiles-overview-success
|
:profile/get-profiles-overview-success
|
||||||
(fn [{:keys [db]} [{:keys [accounts] {:keys [userConfirmed enabled]} :centralizedMetricsInfo}]]
|
(fn [{:keys [db]}
|
||||||
(let [db-with-settings (assoc db
|
[{accounts :accounts
|
||||||
:centralized-metrics/user-confirmed? userConfirmed
|
{:keys [userConfirmed enabled]} :centralizedMetricsInfo}]]
|
||||||
:centralized-metrics/enabled? enabled)
|
(let [profiles (reduce-profiles accounts)
|
||||||
profiles (reduce-profiles accounts)
|
profiles-key-uids (keys profiles)
|
||||||
{:keys [key-uid]} (first (sort-by :timestamp > (vals profiles)))
|
new-db (cond-> db
|
||||||
new-db (cond-> db-with-settings
|
:always
|
||||||
(seq profiles)
|
(assoc :centralized-metrics/user-confirmed? userConfirmed
|
||||||
(assoc :profile/profiles-overview profiles)
|
:centralized-metrics/enabled? enabled)
|
||||||
|
|
||||||
key-uid
|
(seq profiles)
|
||||||
(update :profile/login #(select-profile % key-uid)))]
|
(assoc :profile/profiles-overview profiles))]
|
||||||
{:db new-db
|
{:db new-db
|
||||||
:fx (if (profile.data-store/accepted-terms? accounts)
|
:fx [[:dispatch [:profile/get-profiles-auth-method profiles-key-uids]]
|
||||||
[[:dispatch [:update-theme-and-init-root :screen/profile.profiles]]
|
(if (profile.data-store/accepted-terms? accounts)
|
||||||
(when (and key-uid userConfirmed)
|
[:dispatch [:update-theme-and-init-root :screen/profile.profiles]]
|
||||||
[:effects.biometric/check-if-available
|
[:dispatch [:update-theme-and-init-root :screen/onboarding.intro]])
|
||||||
{:key-uid key-uid
|
;; dispatch-later makes sure that the logout button subscribed is always disabled
|
||||||
:on-success (fn [auth-method]
|
[:dispatch-later
|
||||||
(rf/dispatch [:profile.login/check-biometric-success key-uid
|
{:ms 100
|
||||||
auth-method]))}])]
|
:dispatch [:profile/set-already-logged-out]}]]})))
|
||||||
[[:dispatch [:update-theme-and-init-root :screen/onboarding.intro]]])})))
|
|
||||||
|
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:profile/update-setting-from-backup
|
:profile/update-setting-from-backup
|
||||||
|
|
|
@ -35,22 +35,20 @@
|
||||||
|
|
||||||
;; login phase 1: we want to load and show chats faster, so we split login into 2 phases
|
;; login phase 1: we want to load and show chats faster, so we split login into 2 phases
|
||||||
(rf/reg-event-fx :profile.login/login-existing-profile
|
(rf/reg-event-fx :profile.login/login-existing-profile
|
||||||
(fn [{:keys [db]} [settings account]]
|
(fn [{:keys [db]} [settings-data account]]
|
||||||
(let [{:networks/keys [_current-network _networks]
|
(let [settings (data-store.settings/rpc->settings settings-data)
|
||||||
:as settings}
|
profile-overview (profile.rpc/rpc->profiles-overview account)
|
||||||
(data-store.settings/rpc->settings settings)
|
log-level (or (:log-level settings) config/log-level)
|
||||||
profile-overview (profile.rpc/rpc->profiles-overview account)
|
pairing-completed? (= (get-in db [:syncing :pairing-status]) :completed)
|
||||||
log-level (or (:log-level settings) config/log-level)
|
new-db (-> db
|
||||||
pairing-completed? (= (get-in db [:syncing :pairing-status]) :completed)]
|
(assoc :chats/loading? true
|
||||||
{:db (cond-> (-> db
|
:profile/profile (merge profile-overview
|
||||||
(assoc :chats/loading? true
|
settings
|
||||||
:profile/profile (merge profile-overview
|
{:log-level log-level}))
|
||||||
settings
|
(assoc-in [:activity-center :loading?] true)
|
||||||
{:log-level log-level}))
|
(dissoc :centralized-metrics/onboarding-enabled?))]
|
||||||
(assoc-in [:activity-center :loading?] true)
|
{:db (cond-> new-db
|
||||||
(dissoc :centralized-metrics/onboarding-enabled?))
|
pairing-completed? (dissoc :syncing))
|
||||||
pairing-completed?
|
|
||||||
(dissoc :syncing))
|
|
||||||
:fx (into [[:json-rpc/call
|
:fx (into [[:json-rpc/call
|
||||||
[{:method "wakuext_startMessenger"
|
[{:method "wakuext_startMessenger"
|
||||||
:js-response true
|
:js-response true
|
||||||
|
@ -201,11 +199,11 @@
|
||||||
(fn [{:keys [db]}]
|
(fn [{:keys [db]}]
|
||||||
(let [key-uid (get-in db [:profile/login :key-uid])
|
(let [key-uid (get-in db [:profile/login :key-uid])
|
||||||
keycard? (get-in db [:profile/profiles-overview key-uid :keycard-pairing])]
|
keycard? (get-in db [:profile/profiles-overview key-uid :keycard-pairing])]
|
||||||
(if keycard?
|
{:fx [(if keycard?
|
||||||
{:keychain/get-keycard-keys
|
[:keychain/get-keycard-keys
|
||||||
[key-uid #(rf/dispatch [:keycard.login/on-get-keys-from-keychain-success key-uid %])]}
|
[key-uid #(rf/dispatch [:keycard.login/on-get-keys-from-keychain-success key-uid %])]]
|
||||||
{:keychain/get-user-password
|
[:keychain/get-user-password
|
||||||
[key-uid #(rf/dispatch [:profile.login/get-user-password-success %])]}))))
|
[key-uid #(rf/dispatch [:profile.login/get-user-password-success %])]])]})))
|
||||||
|
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:profile.login/biometric-auth-fail
|
:profile.login/biometric-auth-fail
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
(ns status-im.contexts.profile.logout.effects
|
||||||
|
(:require [native-module.core :as native-module]
|
||||||
|
[re-frame.core :as rf]))
|
||||||
|
|
||||||
|
(rf/reg-fx :effects.profile/logout native-module/logout)
|
|
@ -0,0 +1,47 @@
|
||||||
|
(ns status-im.contexts.profile.logout.events
|
||||||
|
(:require [status-im.contexts.profile.logout.effects]
|
||||||
|
[status-im.db :as db]
|
||||||
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:profile.logout/disable-notifications
|
||||||
|
(fn [_]
|
||||||
|
{:fx [[:effects/push-notifications-disable nil]
|
||||||
|
[:dispatch [:alert-banners/remove-all]]]}))
|
||||||
|
|
||||||
|
(defn- restart-app-db
|
||||||
|
[{:keys [initials-avatar-font-file keycard biometrics
|
||||||
|
network/status network/expensive?
|
||||||
|
centralized-metrics/user-confirmed?]
|
||||||
|
network-type :network/network-type
|
||||||
|
:as _db}]
|
||||||
|
(assoc db/app-db
|
||||||
|
:profile/logging-out? true
|
||||||
|
:centralized-metrics/user-confirmed? user-confirmed?
|
||||||
|
:network/type network-type
|
||||||
|
:network/status status
|
||||||
|
:network/expensive? expensive?
|
||||||
|
:initials-avatar-font-file initials-avatar-font-file
|
||||||
|
:keycard (dissoc keycard :secrets :pin :application-info)
|
||||||
|
:biometrics biometrics
|
||||||
|
:syncing nil))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:profile.logout/reset-state
|
||||||
|
(fn [{db :db}]
|
||||||
|
{:db (restart-app-db db)
|
||||||
|
:fx [[:hide-popover nil]
|
||||||
|
[:effects.profile/logout nil]
|
||||||
|
[:profile.settings/webview-debug-changed false]
|
||||||
|
[:profile/get-profiles-overview #(rf/dispatch [:profile/get-profiles-overview-success %])]]}))
|
||||||
|
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:profile/logout
|
||||||
|
(fn [{db :db}]
|
||||||
|
{:db (assoc db :profile/logging-out? true)
|
||||||
|
;; We need to disable notifications before starting the logout process
|
||||||
|
:fx [[:dispatch [:profile.logout/disable-notifications]]
|
||||||
|
[:dispatch-later
|
||||||
|
{:ms 100
|
||||||
|
:dispatch [:profile.logout/reset-state]}]]}))
|
||||||
|
|
|
@ -138,8 +138,7 @@
|
||||||
:color customization-color
|
:color customization-color
|
||||||
:profile-picture profile-picture})
|
:profile-picture profile-picture})
|
||||||
:on-card-press (fn []
|
:on-card-press (fn []
|
||||||
(rf/dispatch
|
(rf/dispatch-sync [:profile/profile-selected key-uid])
|
||||||
[:profile/profile-selected key-uid])
|
|
||||||
(rf/dispatch
|
(rf/dispatch
|
||||||
[:profile.login/login-with-biometric-if-available key-uid])
|
[:profile.login/login-with-biometric-if-available key-uid])
|
||||||
(set-hide-profiles))}]))
|
(set-hide-profiles))}]))
|
||||||
|
@ -157,10 +156,8 @@
|
||||||
(pop-animation-fn)))
|
(pop-animation-fn)))
|
||||||
(reset! push-animation-fn-atom nil)
|
(reset! push-animation-fn-atom nil)
|
||||||
(reset! pop-animation-fn-atom nil))))
|
(reset! pop-animation-fn-atom nil))))
|
||||||
[reanimated/view
|
[reanimated/view {:style (style/profiles-container translate-x)}
|
||||||
{:style (style/profiles-container translate-x)}
|
[rn/view {:style style/profiles-header}
|
||||||
[rn/view
|
|
||||||
{:style style/profiles-header}
|
|
||||||
[quo/text
|
[quo/text
|
||||||
{:size :heading-1
|
{:size :heading-1
|
||||||
:weight :semi-bold
|
:weight :semi-bold
|
||||||
|
@ -183,22 +180,21 @@
|
||||||
:render-fn profile-card}]]))
|
:render-fn profile-card}]]))
|
||||||
|
|
||||||
(defn password-input
|
(defn password-input
|
||||||
[processing error]
|
[processing error auth-method]
|
||||||
(let [auth-method (rf/sub [:auth-method])
|
(let [on-press-biometrics (fn []
|
||||||
on-press-biometrics (fn []
|
(rf/dispatch
|
||||||
(rf/dispatch [:biometric/authenticate
|
[:biometric/authenticate
|
||||||
{:on-success #(rf/dispatch
|
{:on-success #(rf/dispatch
|
||||||
[:profile.login/biometric-success])
|
[:profile.login/biometric-success])
|
||||||
:on-fail #(rf/dispatch
|
:on-fail #(rf/dispatch
|
||||||
[:profile.login/biometric-auth-fail
|
[:profile.login/biometric-auth-fail %])}]))]
|
||||||
%])}]))]
|
|
||||||
|
|
||||||
[standard-authentication/password-input
|
[standard-authentication/password-input
|
||||||
{:processing processing
|
{:processing processing
|
||||||
:error error
|
:error error
|
||||||
:shell? true
|
:shell? true
|
||||||
:blur? true
|
:blur? true
|
||||||
:on-press-biometrics (when (= auth-method constants/auth-method-biometric) on-press-biometrics)}]))
|
:on-press-biometrics (when (= auth-method constants/auth-method-biometric)
|
||||||
|
on-press-biometrics)}]))
|
||||||
|
|
||||||
(defn- get-error-message
|
(defn- get-error-message
|
||||||
[error]
|
[error]
|
||||||
|
@ -210,7 +206,7 @@
|
||||||
|
|
||||||
(defn login-section
|
(defn login-section
|
||||||
[{:keys [show-profiles]}]
|
[{:keys [show-profiles]}]
|
||||||
(let [{:keys [key-uid name keycard-pairing
|
(let [{:keys [key-uid name keycard-pairing auth-method
|
||||||
customization-color]} (rf/sub [:profile/login-profile])
|
customization-color]} (rf/sub [:profile/login-profile])
|
||||||
sign-in-enabled? (rf/sub [:sign-in-enabled?])
|
sign-in-enabled? (rf/sub [:sign-in-enabled?])
|
||||||
profile-picture (rf/sub [:profile/login-profiles-picture key-uid])
|
profile-picture (rf/sub [:profile/login-profiles-picture key-uid])
|
||||||
|
@ -266,7 +262,7 @@
|
||||||
{:pin pin
|
{:pin pin
|
||||||
:on-success #(rf/dispatch [:keycard.login/on-get-keys-success %])
|
:on-success #(rf/dispatch [:keycard.login/on-get-keys-success %])
|
||||||
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error %])}]))}]))}]
|
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error %])}]))}]))}]
|
||||||
[password-input processing error])]
|
[password-input processing error auth-method])]
|
||||||
(when-not keycard-pairing
|
(when-not keycard-pairing
|
||||||
[quo/button
|
[quo/button
|
||||||
{:size 40
|
{:size 40
|
||||||
|
@ -282,7 +278,7 @@
|
||||||
(defn view
|
(defn view
|
||||||
[]
|
[]
|
||||||
(rn/use-mount #(rf/dispatch [:centralized-metrics/check-modal metrics-modal/view]))
|
(rn/use-mount #(rf/dispatch [:centralized-metrics/check-modal metrics-modal/view]))
|
||||||
(let [[show-profiles? set-show-profiles] (rn/use-state false)
|
(let [[show-profiles? set-show-profiles] (rn/use-state true)
|
||||||
show-profiles (rn/use-callback #(set-show-profiles true))
|
show-profiles (rn/use-callback #(set-show-profiles true))
|
||||||
hide-profiles (rn/use-callback #(set-show-profiles false))]
|
hide-profiles (rn/use-callback #(set-show-profiles false))]
|
||||||
[:<>
|
[:<>
|
||||||
|
|
|
@ -15,8 +15,7 @@
|
||||||
|
|
||||||
(rf/reg-event-fx :profile.settings/profile-update
|
(rf/reg-event-fx :profile.settings/profile-update
|
||||||
(fn [{:keys [db]} [setting setting-value {:keys [dont-sync? on-success]}]]
|
(fn [{:keys [db]} [setting setting-value {:keys [dont-sync? on-success]}]]
|
||||||
{:db (-> db
|
{:db (set-setting-value db setting setting-value)
|
||||||
(set-setting-value setting setting-value))
|
|
||||||
:fx [[:json-rpc/call
|
:fx [[:json-rpc/call
|
||||||
[{:method "settings_saveSetting"
|
[{:method "settings_saveSetting"
|
||||||
:params [setting setting-value]
|
:params [setting setting-value]
|
||||||
|
@ -40,14 +39,14 @@
|
||||||
|
|
||||||
(rf/reg-event-fx :profile.settings/toggle-test-networks
|
(rf/reg-event-fx :profile.settings/toggle-test-networks
|
||||||
(fn [{:keys [db]}]
|
(fn [{:keys [db]}]
|
||||||
(let [value (get-in db [:profile/profile :test-networks-enabled?])
|
(let [test-networks-disabled? (not (get-in db [:profile/profile :test-networks-enabled?]))]
|
||||||
on-success #(rf/dispatch [:logout])]
|
|
||||||
{:fx [[:ui/show-confirmation
|
{:fx [[:ui/show-confirmation
|
||||||
{:title (i18n/label :t/testnet-mode-prompt-title)
|
{:title (i18n/label :t/testnet-mode-prompt-title)
|
||||||
:content (i18n/label :t/testnet-mode-prompt-content)
|
:content (i18n/label :t/testnet-mode-prompt-content)
|
||||||
:on-accept #(rf/dispatch [:profile.settings/profile-update :test-networks-enabled?
|
:on-accept (fn []
|
||||||
(not value)
|
(rf/dispatch [:profile.settings/profile-update :test-networks-enabled?
|
||||||
{:on-success on-success}])
|
test-networks-disabled?
|
||||||
|
{:on-success #(rf/dispatch [:profile/logout])}]))
|
||||||
:on-cancel nil}]]})))
|
:on-cancel nil}]]})))
|
||||||
|
|
||||||
(rf/reg-event-fx :profile.settings/change-preview-privacy
|
(rf/reg-event-fx :profile.settings/change-preview-privacy
|
||||||
|
@ -58,8 +57,7 @@
|
||||||
|
|
||||||
(rf/reg-event-fx :profile.settings/change-profile-pictures-show-to
|
(rf/reg-event-fx :profile.settings/change-profile-pictures-show-to
|
||||||
(fn [{:keys [db]} [id]]
|
(fn [{:keys [db]} [id]]
|
||||||
{:db (-> db
|
{:db (assoc-in db [:profile/profile :profile-pictures-show-to] id)
|
||||||
(assoc-in [:profile/profile :profile-pictures-show-to] id))
|
|
||||||
:fx [[:json-rpc/call
|
:fx [[:json-rpc/call
|
||||||
[{:method "wakuext_changeIdentityImageShowTo"
|
[{:method "wakuext_changeIdentityImageShowTo"
|
||||||
:params [id]
|
:params [id]
|
||||||
|
@ -97,8 +95,7 @@
|
||||||
(rf/reg-event-fx :profile.settings/save-profile-picture
|
(rf/reg-event-fx :profile.settings/save-profile-picture
|
||||||
(fn [{:keys [db]} [path ax ay bx by]]
|
(fn [{:keys [db]} [path ax ay bx by]]
|
||||||
(let [key-uid (get-in db [:profile/profile :key-uid])]
|
(let [key-uid (get-in db [:profile/profile :key-uid])]
|
||||||
{:db (-> db
|
{:db (assoc db :bottom-sheet/show? false)
|
||||||
(assoc :bottom-sheet/show? false))
|
|
||||||
:fx [[:json-rpc/call
|
:fx [[:json-rpc/call
|
||||||
[{:method "multiaccounts_storeIdentityImage"
|
[{:method "multiaccounts_storeIdentityImage"
|
||||||
:params [key-uid (string/replace-first path #"file://" "") ax ay bx
|
:params [key-uid (string/replace-first path #"file://" "") ax ay bx
|
||||||
|
@ -109,8 +106,7 @@
|
||||||
(rf/reg-event-fx :profile.settings/save-profile-picture-from-url
|
(rf/reg-event-fx :profile.settings/save-profile-picture-from-url
|
||||||
(fn [{:keys [db]} [url]]
|
(fn [{:keys [db]} [url]]
|
||||||
(let [key-uid (get-in db [:profile/profile :key-uid])]
|
(let [key-uid (get-in db [:profile/profile :key-uid])]
|
||||||
{:db (-> db
|
{:db (assoc db :bottom-sheet/show? false)
|
||||||
(assoc :bottom-sheet/show? false))
|
|
||||||
:fx [[:json-rpc/call
|
:fx [[:json-rpc/call
|
||||||
[{:method "multiaccounts_storeIdentityImageFromURL"
|
[{:method "multiaccounts_storeIdentityImageFromURL"
|
||||||
:params [key-uid url]
|
:params [key-uid url]
|
||||||
|
@ -147,3 +143,14 @@
|
||||||
(fn [_ [currency]]
|
(fn [_ [currency]]
|
||||||
{:fx [[:dispatch [:profile.settings/profile-update :currency currency]]
|
{:fx [[:dispatch [:profile.settings/profile-update :currency currency]]
|
||||||
[:dispatch [:wallet/get-wallet-token-for-all-accounts]]]}))
|
[:dispatch [:wallet/get-wallet-token-for-all-accounts]]]}))
|
||||||
|
|
||||||
|
;; Logout process
|
||||||
|
(rf/reg-event-fx
|
||||||
|
:profile.settings/ask-logout
|
||||||
|
(fn [_ _]
|
||||||
|
{:fx [[:ui/show-confirmation
|
||||||
|
{:title (i18n/label :t/logout-title)
|
||||||
|
:content (i18n/label :t/logout-are-you-sure)
|
||||||
|
:confirm-button-text (i18n/label :t/logout)
|
||||||
|
:on-accept #(rf/dispatch [:profile/logout])
|
||||||
|
:on-cancel nil}]]}))
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
(defn- handle-logout
|
(defn- handle-logout
|
||||||
[]
|
[]
|
||||||
(rf/dispatch [:multiaccounts.logout.ui/logout-pressed])
|
(rf/dispatch [:profile.settings/ask-logout])
|
||||||
(rf/dispatch [:change-password/reset]))
|
(rf/dispatch [:change-password/reset]))
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
|
@ -21,6 +21,7 @@
|
||||||
[minimum-loading-timeout-done?
|
[minimum-loading-timeout-done?
|
||||||
set-minimum-loading-timeout-done] (rn/use-state false)
|
set-minimum-loading-timeout-done] (rn/use-state false)
|
||||||
loading? (rf/sub [:settings/change-password-loading])
|
loading? (rf/sub [:settings/change-password-loading])
|
||||||
|
logging-out? (rf/sub [:profile/logging-out?])
|
||||||
done? (and (not loading?) minimum-loading-timeout-done?)]
|
done? (and (not loading?) minimum-loading-timeout-done?)]
|
||||||
(rn/use-mount (fn []
|
(rn/use-mount (fn []
|
||||||
(js/setTimeout
|
(js/setTimeout
|
||||||
|
@ -39,8 +40,7 @@
|
||||||
:description-text (if done?
|
:description-text (if done?
|
||||||
(i18n/label :t/change-password-done-description)
|
(i18n/label :t/change-password-done-description)
|
||||||
(i18n/label :t/change-password-loading-description))}]
|
(i18n/label :t/change-password-loading-description))}]
|
||||||
[rn/view
|
[rn/view {:style style/loading-content}
|
||||||
{:style style/loading-content}
|
|
||||||
(when-not done?
|
(when-not done?
|
||||||
[quo/information-box
|
[quo/information-box
|
||||||
{:type :error
|
{:type :error
|
||||||
|
@ -50,5 +50,6 @@
|
||||||
(when done?
|
(when done?
|
||||||
[quo/logout-button
|
[quo/logout-button
|
||||||
{:container-style style/logout-container
|
{:container-style style/logout-container
|
||||||
|
:disabled? logging-out?
|
||||||
:on-press handle-logout}])]]))
|
:on-press handle-logout}])]]))
|
||||||
|
|
||||||
|
|
|
@ -32,20 +32,23 @@
|
||||||
(let [current-y (oops/oget event "nativeEvent.contentOffset.y")]
|
(let [current-y (oops/oget event "nativeEvent.contentOffset.y")]
|
||||||
(reanimated/set-shared-value scroll-y current-y)))
|
(reanimated/set-shared-value scroll-y current-y)))
|
||||||
|
|
||||||
|
(defn- logout-press
|
||||||
|
[]
|
||||||
|
(rf/dispatch [:profile.settings/ask-logout]))
|
||||||
|
|
||||||
(defn- footer
|
(defn- footer
|
||||||
[{:keys [bottom]} logout-press]
|
[{:keys [bottom]}]
|
||||||
(rn/delay-render
|
(rn/delay-render
|
||||||
[rn/view {:style (style/footer-container bottom)}
|
(let [logging-out? (rf/sub [:profile/logging-out?])]
|
||||||
[quo/logout-button {:on-press logout-press}]]))
|
[rn/view {:style (style/footer-container bottom)}
|
||||||
|
[quo/logout-button
|
||||||
|
{:on-press logout-press
|
||||||
|
:disabled? logging-out?}]])))
|
||||||
|
|
||||||
(defn- get-item-layout
|
(defn- get-item-layout
|
||||||
[_ index]
|
[_ index]
|
||||||
#js {:length 100 :offset (* 100 index) :index index})
|
#js {:length 100 :offset (* 100 index) :index index})
|
||||||
|
|
||||||
(defn logout-press
|
|
||||||
[]
|
|
||||||
(rf/dispatch [:multiaccounts.logout.ui/logout-pressed]))
|
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[]
|
[]
|
||||||
(let [theme (quo.theme/use-theme)
|
(let [theme (quo.theme/use-theme)
|
||||||
|
@ -83,7 +86,7 @@
|
||||||
:shows-vertical-scroll-indicator false
|
:shows-vertical-scroll-indicator false
|
||||||
:render-fn settings-category-view
|
:render-fn settings-category-view
|
||||||
:get-item-layout get-item-layout
|
:get-item-layout get-item-layout
|
||||||
:footer [footer insets logout-press]
|
:footer [footer insets]
|
||||||
:scroll-event-throttle 16
|
:scroll-event-throttle 16
|
||||||
:on-scroll on-scroll
|
:on-scroll on-scroll
|
||||||
:bounces false
|
:bounces false
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
(defn logout
|
(defn logout
|
||||||
[]
|
[]
|
||||||
(rf/dispatch [:logout]))
|
(rf/dispatch [:profile/logout]))
|
||||||
|
|
||||||
(defn on-confirm-change
|
(defn on-confirm-change
|
||||||
[enable?]
|
[enable?]
|
||||||
|
|
|
@ -88,6 +88,7 @@
|
||||||
(reg-root-key-sub :profile/profiles-overview :profile/profiles-overview)
|
(reg-root-key-sub :profile/profiles-overview :profile/profiles-overview)
|
||||||
(reg-root-key-sub :profile/login :profile/login)
|
(reg-root-key-sub :profile/login :profile/login)
|
||||||
(reg-root-key-sub :profile/profile :profile/profile)
|
(reg-root-key-sub :profile/profile :profile/profile)
|
||||||
|
(reg-root-key-sub :profile/logging-out? :profile/logging-out?)
|
||||||
(reg-root-key-sub :profile/wallet-accounts :profile/wallet-accounts)
|
(reg-root-key-sub :profile/wallet-accounts :profile/wallet-accounts)
|
||||||
|
|
||||||
(reg-root-key-sub :multiaccount/reset-password-form-vals :multiaccount/reset-password-form-vals)
|
(reg-root-key-sub :multiaccount/reset-password-form-vals :multiaccount/reset-password-form-vals)
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
(:require
|
(:require
|
||||||
[cljs.test :refer [is] :as test]
|
[cljs.test :refer [is] :as test]
|
||||||
legacy.status-im.events
|
legacy.status-im.events
|
||||||
[legacy.status-im.multiaccounts.logout.core :as logout]
|
|
||||||
legacy.status-im.subs.root
|
legacy.status-im.subs.root
|
||||||
[native-module.core :as native-module]
|
[native-module.core :as native-module]
|
||||||
[promesa.core :as promesa]
|
[promesa.core :as promesa]
|
||||||
|
@ -96,7 +95,7 @@
|
||||||
(defn logout
|
(defn logout
|
||||||
[]
|
[]
|
||||||
(log/info (str "==== before dispatch logout ===="))
|
(log/info (str "==== before dispatch logout ===="))
|
||||||
(rf/dispatch [:logout]))
|
(rf/dispatch [:profile/logout]))
|
||||||
|
|
||||||
(defn log-headline
|
(defn log-headline
|
||||||
[test-name]
|
[test-name]
|
||||||
|
@ -259,7 +258,7 @@
|
||||||
(setup-account)
|
(setup-account)
|
||||||
(logout)
|
(logout)
|
||||||
(log/info (str "==== before wait-for logout ===="))
|
(log/info (str "==== before wait-for logout ===="))
|
||||||
(wait-for [::logout/logout-method])
|
(wait-for [:profile.logout/reset-state])
|
||||||
(log/info (str "==== after wait-for logout ===="))))))
|
(log/info (str "==== after wait-for logout ===="))))))
|
||||||
|
|
||||||
;;;; Fixtures
|
;;;; Fixtures
|
||||||
|
@ -287,7 +286,7 @@
|
||||||
(test/async done
|
(test/async done
|
||||||
(promesa/do (logout)
|
(promesa/do (logout)
|
||||||
(log/info (str "==== before wait-for logout ===="))
|
(log/info (str "==== before wait-for logout ===="))
|
||||||
(wait-for [::logout/logout-method])
|
(wait-for [:profile.logout/reset-state])
|
||||||
(log/info (str "==== after wait-for logout ===="))
|
(log/info (str "==== after wait-for logout ===="))
|
||||||
(done))))})
|
(done))))})
|
||||||
([] (fixture-session [:new-account])))
|
([] (fixture-session [:new-account])))
|
||||||
|
|
|
@ -170,8 +170,7 @@ class TestActivityCenterContactRequestMultipleDevicePR(MultipleSharedDeviceTestC
|
||||||
self.home_2.just_fyi("Device 2 sign in, user name is " + self.username_2)
|
self.home_2.just_fyi("Device 2 sign in, user name is " + self.username_2)
|
||||||
self.home_2.reopen_app(sign_in=False)
|
self.home_2.reopen_app(sign_in=False)
|
||||||
self.device_2.show_profiles_button.wait_and_click()
|
self.device_2.show_profiles_button.wait_and_click()
|
||||||
self.device_2.get_user_profile_by_name(username=self.username_2).click()
|
self.device_2.sign_in(user_name=self.username_2)
|
||||||
self.device_2.sign_in()
|
|
||||||
|
|
||||||
self.loop.run_until_complete(run_in_parallel(((_device_1_creates_user, {}),
|
self.loop.run_until_complete(run_in_parallel(((_device_1_creates_user, {}),
|
||||||
(_device_2_sign_in, {}))))
|
(_device_2_sign_in, {}))))
|
||||||
|
@ -466,7 +465,7 @@ class TestActivityMultipleDevicePRTwo(MultipleSharedDeviceTestCase):
|
||||||
community_name = 'closed community'
|
community_name = 'closed community'
|
||||||
self.channel_name = "dogs"
|
self.channel_name = "dogs"
|
||||||
self.home_1.create_community(community_type="closed")
|
self.home_1.create_community(community_type="closed")
|
||||||
self.home_1.reopen_app()
|
self.home_1.reopen_app(user_name=self.username_1)
|
||||||
self.community_1.invite_to_community(community_name, self.username_2)
|
self.community_1.invite_to_community(community_name, self.username_2)
|
||||||
|
|
||||||
self.home_2.just_fyi("Request access to community")
|
self.home_2.just_fyi("Request access to community")
|
||||||
|
|
|
@ -687,7 +687,7 @@ class TestOneToOneChatMultipleSharedDevicesNewUiTwo(MultipleSharedDeviceTestCase
|
||||||
chat = self.home_2.get_chat_from_home_view(self.username_1)
|
chat = self.home_2.get_chat_from_home_view(self.username_1)
|
||||||
if chat.is_element_displayed():
|
if chat.is_element_displayed():
|
||||||
self.errors.append("Deleted '%s' chat is shown, but the chat has been deleted" % self.username_1)
|
self.errors.append("Deleted '%s' chat is shown, but the chat has been deleted" % self.username_1)
|
||||||
self.home_2.reopen_app()
|
self.home_2.reopen_app(user_name=self.username_2)
|
||||||
if chat.is_element_displayed(15):
|
if chat.is_element_displayed(15):
|
||||||
self.errors.append(
|
self.errors.append(
|
||||||
"Deleted chat '%s' is shown after re-login, but the chat has been deleted" % self.username_1)
|
"Deleted chat '%s' is shown after re-login, but the chat has been deleted" % self.username_1)
|
||||||
|
|
|
@ -186,7 +186,7 @@ class TestGroupChatMultipleDeviceMergedNewUI(MultipleSharedDeviceTestCase):
|
||||||
)))
|
)))
|
||||||
|
|
||||||
self.chats[0].just_fyi("Admin relogins")
|
self.chats[0].just_fyi("Admin relogins")
|
||||||
self.chats[0].reopen_app()
|
self.chats[0].reopen_app(user_name=self.usernames[0])
|
||||||
self.homes[0].get_chat(self.chat_name).click()
|
self.homes[0].get_chat(self.chat_name).click()
|
||||||
|
|
||||||
self.chats[0].just_fyi("Admin checks reactions count after relogin")
|
self.chats[0].just_fyi("Admin checks reactions count after relogin")
|
||||||
|
@ -277,7 +277,7 @@ class TestGroupChatMultipleDeviceMergedNewUI(MultipleSharedDeviceTestCase):
|
||||||
# workaround for app closed after navigating back from gallery
|
# workaround for app closed after navigating back from gallery
|
||||||
if not self.chats[2].chat_message_input.is_element_displayed():
|
if not self.chats[2].chat_message_input.is_element_displayed():
|
||||||
self.drivers[2].activate_app(app_package)
|
self.drivers[2].activate_app(app_package)
|
||||||
SignInView(self.drivers[2]).sign_in()
|
SignInView(self.drivers[2]).sign_in(user_name=self.usernames[2])
|
||||||
self.homes[2].chats_tab.click()
|
self.homes[2].chats_tab.click()
|
||||||
self.homes[2].get_chat(self.chat_name).click()
|
self.homes[2].get_chat(self.chat_name).click()
|
||||||
|
|
||||||
|
@ -291,7 +291,7 @@ class TestGroupChatMultipleDeviceMergedNewUI(MultipleSharedDeviceTestCase):
|
||||||
# workaround for app closed after navigating back from gallery
|
# workaround for app closed after navigating back from gallery
|
||||||
if not self.chats[2].chats_tab.is_element_displayed():
|
if not self.chats[2].chats_tab.is_element_displayed():
|
||||||
self.drivers[2].activate_app(app_package)
|
self.drivers[2].activate_app(app_package)
|
||||||
SignInView(self.drivers[2]).sign_in()
|
SignInView(self.drivers[2]).sign_in(user_name=self.usernames[2])
|
||||||
self.homes[2].chats_tab.click()
|
self.homes[2].chats_tab.click()
|
||||||
|
|
||||||
self.errors.verify_no_errors()
|
self.errors.verify_no_errors()
|
||||||
|
@ -331,7 +331,7 @@ class TestGroupChatMultipleDeviceMergedNewUI(MultipleSharedDeviceTestCase):
|
||||||
# workaround for app closed after opening notifications
|
# workaround for app closed after opening notifications
|
||||||
if not self.homes[0].chats_tab.is_element_displayed():
|
if not self.homes[0].chats_tab.is_element_displayed():
|
||||||
self.drivers[0].activate_app(app_package)
|
self.drivers[0].activate_app(app_package)
|
||||||
SignInView(self.drivers[0]).sign_in()
|
SignInView(self.drivers[0]).sign_in(user_name=self.usernames[0])
|
||||||
self.homes[0].chats_tab.click()
|
self.homes[0].chats_tab.click()
|
||||||
self.homes[0].get_chat(self.chat_name).click()
|
self.homes[0].get_chat(self.chat_name).click()
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ class TestCommunityOneDeviceMerged(MultipleSharedDeviceTestCase):
|
||||||
|
|
||||||
self.channel.send_message(text_message)
|
self.channel.send_message(text_message)
|
||||||
self.channel.chat_element_by_text(text_message).wait_for_visibility_of_element()
|
self.channel.chat_element_by_text(text_message).wait_for_visibility_of_element()
|
||||||
self.channel.reopen_app()
|
self.channel.reopen_app(user_name=self.username)
|
||||||
if not self.channel.chat_element_by_text(text_message).is_element_displayed(30):
|
if not self.channel.chat_element_by_text(text_message).is_element_displayed(30):
|
||||||
self.drivers[0].fail("Not navigated to channel view after reopening app")
|
self.drivers[0].fail("Not navigated to channel view after reopening app")
|
||||||
|
|
||||||
|
@ -158,7 +158,8 @@ class TestCommunityOneDeviceMerged(MultipleSharedDeviceTestCase):
|
||||||
def test_restore_multiaccount_with_waku_backup_remove_profile_switch(self):
|
def test_restore_multiaccount_with_waku_backup_remove_profile_switch(self):
|
||||||
self.home.reopen_app(sign_in=False)
|
self.home.reopen_app(sign_in=False)
|
||||||
self.home.just_fyi("Restore user with predefined communities and contacts")
|
self.home.just_fyi("Restore user with predefined communities and contacts")
|
||||||
self.sign_in.recover_access(passphrase=waku_user.seed, second_user=True)
|
recover_user_name = 'Recover user'
|
||||||
|
self.sign_in.recover_access(passphrase=waku_user.seed, second_user=True, username=recover_user_name)
|
||||||
|
|
||||||
self.home.just_fyi("Check contacts/blocked users")
|
self.home.just_fyi("Check contacts/blocked users")
|
||||||
self.home.chats_tab.click()
|
self.home.chats_tab.click()
|
||||||
|
@ -216,10 +217,7 @@ class TestCommunityOneDeviceMerged(MultipleSharedDeviceTestCase):
|
||||||
profile.perform_backup_button.click()
|
profile.perform_backup_button.click()
|
||||||
|
|
||||||
self.home.just_fyi("Check that can login with different user")
|
self.home.just_fyi("Check that can login with different user")
|
||||||
self.home.reopen_app(sign_in=False)
|
self.home.reopen_app(user_name=self.username)
|
||||||
self.sign_in.show_profiles_button.wait_and_click()
|
|
||||||
self.sign_in.element_by_text(self.username).click()
|
|
||||||
self.sign_in.sign_in()
|
|
||||||
self.home.navigate_back_to_home_view()
|
self.home.navigate_back_to_home_view()
|
||||||
self.home.communities_tab.click()
|
self.home.communities_tab.click()
|
||||||
if self.home.element_by_text(waku_user.communities['admin_open']).is_element_displayed(30):
|
if self.home.element_by_text(waku_user.communities['admin_open']).is_element_displayed(30):
|
||||||
|
@ -227,7 +225,6 @@ class TestCommunityOneDeviceMerged(MultipleSharedDeviceTestCase):
|
||||||
|
|
||||||
self.home.just_fyi("Check that can remove user from logged out state")
|
self.home.just_fyi("Check that can remove user from logged out state")
|
||||||
self.home.reopen_app(sign_in=False)
|
self.home.reopen_app(sign_in=False)
|
||||||
self.sign_in.show_profiles_button.wait_and_click()
|
|
||||||
user_card = self.sign_in.get_user_profile_by_name(username=self.username)
|
user_card = self.sign_in.get_user_profile_by_name(username=self.username)
|
||||||
user_card.open_user_options()
|
user_card.open_user_options()
|
||||||
self.sign_in.remove_profile_button.click()
|
self.sign_in.remove_profile_button.click()
|
||||||
|
@ -237,8 +234,6 @@ class TestCommunityOneDeviceMerged(MultipleSharedDeviceTestCase):
|
||||||
|
|
||||||
self.home.just_fyi("Check that removed user is not shown in the list anymore")
|
self.home.just_fyi("Check that removed user is not shown in the list anymore")
|
||||||
self.home.reopen_app(sign_in=False)
|
self.home.reopen_app(sign_in=False)
|
||||||
self.sign_in.explore_new_status_button.click_until_presence_of_element(self.sign_in.show_profiles_button)
|
|
||||||
self.sign_in.show_profiles_button.wait_and_click()
|
|
||||||
if self.sign_in.element_by_text(self.username).is_element_displayed():
|
if self.sign_in.element_by_text(self.username).is_element_displayed():
|
||||||
self.errors.append("Removed user is re-appeared after relogin!")
|
self.errors.append("Removed user is re-appeared after relogin!")
|
||||||
|
|
||||||
|
@ -248,15 +243,14 @@ class TestCommunityOneDeviceMerged(MultipleSharedDeviceTestCase):
|
||||||
def test_community_discovery(self):
|
def test_community_discovery(self):
|
||||||
try:
|
try:
|
||||||
# workaround for case if a user is logged out in the previous test
|
# workaround for case if a user is logged out in the previous test
|
||||||
self.sign_in.get_user_profile_by_index(index=1).click()
|
self.sign_in.sign_in(user_name=self.username)
|
||||||
self.sign_in.sign_in()
|
|
||||||
except NoSuchElementException:
|
except NoSuchElementException:
|
||||||
pass
|
pass
|
||||||
self.home.navigate_back_to_home_view()
|
self.home.navigate_back_to_home_view()
|
||||||
self.home.just_fyi("Turn off testnet in the profile settings")
|
self.home.just_fyi("Turn off testnet in the profile settings")
|
||||||
profile = self.home.profile_button.click()
|
profile = self.home.profile_button.click()
|
||||||
profile.switch_network()
|
profile.switch_network()
|
||||||
self.sign_in.sign_in()
|
self.sign_in.sign_in(user_name=self.username)
|
||||||
|
|
||||||
self.home.just_fyi("Check Discover Communities content")
|
self.home.just_fyi("Check Discover Communities content")
|
||||||
self.home.communities_tab.click()
|
self.home.communities_tab.click()
|
||||||
|
@ -1192,7 +1186,7 @@ class TestCommunityMultipleDeviceMergedTwo(MultipleSharedDeviceTestCase):
|
||||||
|
|
||||||
self.home_1.just_fyi("Device 1 goes back online")
|
self.home_1.just_fyi("Device 1 goes back online")
|
||||||
self.home_1.driver.activate_app(app_package)
|
self.home_1.driver.activate_app(app_package)
|
||||||
self.device_1.sign_in()
|
self.device_1.sign_in(user_name=self.username_1)
|
||||||
|
|
||||||
self.home_2.just_fyi("Device 2 checks that he's joined the community")
|
self.home_2.just_fyi("Device 2 checks that he's joined the community")
|
||||||
exp_text = "You joined “%s”" % community_name
|
exp_text = "You joined “%s”" % community_name
|
||||||
|
|
|
@ -131,7 +131,7 @@ class TestDeepLinksOneDevice(MultipleSharedDeviceTestCase):
|
||||||
self.driver.terminate_app(app_package)
|
self.driver.terminate_app(app_package)
|
||||||
community_url = "https://status.app/c/Ow==#zQ3shbmfT3hvh4mKa1v6uAjjyztQEroh8Mfn6Ckegjd7LT3XK"
|
community_url = "https://status.app/c/Ow==#zQ3shbmfT3hvh4mKa1v6uAjjyztQEroh8Mfn6Ckegjd7LT3XK"
|
||||||
self.home.open_link_from_google_search_app(community_url, app_package)
|
self.home.open_link_from_google_search_app(community_url, app_package)
|
||||||
self.sign_in.sign_in()
|
self.sign_in.sign_in(user_name=self.username)
|
||||||
if not self.community_view.join_button.is_element_displayed(10):
|
if not self.community_view.join_button.is_element_displayed(10):
|
||||||
self.errors.append("Closed community was not requested to join by the url %s" % community_url)
|
self.errors.append("Closed community was not requested to join by the url %s" % community_url)
|
||||||
|
|
||||||
|
|
|
@ -83,8 +83,8 @@ class TestWalletMultipleDevice(MultipleSharedDeviceTestCase):
|
||||||
self.wallet_2.wallet_tab.is_element_displayed()
|
self.wallet_2.wallet_tab.is_element_displayed()
|
||||||
time.sleep(10)
|
time.sleep(10)
|
||||||
self.loop.run_until_complete(
|
self.loop.run_until_complete(
|
||||||
run_in_parallel(((self.home_1.reopen_app,),
|
run_in_parallel(((self.home_1.reopen_app, {'user_name': self.sender_username}),
|
||||||
(self.home_2.reopen_app,))))
|
(self.home_2.reopen_app, {'user_name': self.receiver_username}))))
|
||||||
self.wallet_1.wallet_tab.wait_and_click()
|
self.wallet_1.wallet_tab.wait_and_click()
|
||||||
self.wallet_2.wallet_tab.wait_and_click()
|
self.wallet_2.wallet_tab.wait_and_click()
|
||||||
self.wallet_1.select_network(network_name='Arbitrum')
|
self.wallet_1.select_network(network_name='Arbitrum')
|
||||||
|
@ -216,7 +216,7 @@ class TestWalletOneDevice(MultipleSharedDeviceTestCase):
|
||||||
def test_wallet_balance_mainnet(self):
|
def test_wallet_balance_mainnet(self):
|
||||||
self.profile_view = self.home_view.profile_button.click()
|
self.profile_view = self.home_view.profile_button.click()
|
||||||
self.profile_view.switch_network()
|
self.profile_view.switch_network()
|
||||||
self.sign_in_view.sign_in()
|
self.sign_in_view.sign_in(user_name=self.sender_username)
|
||||||
self.sign_in_view.wallet_tab.click()
|
self.sign_in_view.wallet_tab.click()
|
||||||
|
|
||||||
self.wallet_view.just_fyi("Checking total balance")
|
self.wallet_view.just_fyi("Checking total balance")
|
||||||
|
|
|
@ -703,14 +703,14 @@ class BaseView(object):
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
raise TimeoutException(msg="Status app is not terminated after %s sec" % wait_time)
|
raise TimeoutException(msg="Status app is not terminated after %s sec" % wait_time)
|
||||||
|
|
||||||
def reopen_app(self, password=common_password, sign_in=True):
|
def reopen_app(self, password=common_password, sign_in=True, user_name=None):
|
||||||
app_package = self.driver.current_package
|
app_package = self.driver.current_package
|
||||||
self.driver.terminate_app(app_package)
|
self.driver.terminate_app(app_package)
|
||||||
self.wait_for_application_to_not_run(app_package=app_package)
|
self.wait_for_application_to_not_run(app_package=app_package)
|
||||||
self.driver.activate_app(app_package)
|
self.driver.activate_app(app_package)
|
||||||
if sign_in:
|
if sign_in:
|
||||||
sign_in_view = self.get_sign_in_view()
|
sign_in_view = self.get_sign_in_view()
|
||||||
sign_in_view.sign_in(password)
|
sign_in_view.sign_in(user_name, password)
|
||||||
|
|
||||||
def close_share_popup(self):
|
def close_share_popup(self):
|
||||||
self.driver.info("Closing share popup")
|
self.driver.info("Closing share popup")
|
||||||
|
|
|
@ -269,7 +269,6 @@ class SignInView(BaseView):
|
||||||
self.create_profile_button.click_until_presence_of_element(self.generate_keys_button)
|
self.create_profile_button.click_until_presence_of_element(self.generate_keys_button)
|
||||||
self.not_now_button.wait_and_click()
|
self.not_now_button.wait_and_click()
|
||||||
else:
|
else:
|
||||||
self.show_profiles_button.wait_and_click(20)
|
|
||||||
self.plus_profiles_button.click()
|
self.plus_profiles_button.click()
|
||||||
self.create_new_profile_button.click()
|
self.create_new_profile_button.click()
|
||||||
self.use_recovery_phrase_button.click()
|
self.use_recovery_phrase_button.click()
|
||||||
|
@ -302,8 +301,9 @@ class SignInView(BaseView):
|
||||||
self.enter_sync_code_input.send_keys(sync_code)
|
self.enter_sync_code_input.send_keys(sync_code)
|
||||||
self.confirm_button.click()
|
self.confirm_button.click()
|
||||||
|
|
||||||
def sign_in(self, password=common_password):
|
def sign_in(self, user_name, password=common_password):
|
||||||
self.driver.info("## Sign in (password: %s)" % password, device=False)
|
self.driver.info("## Sign in (password: %s)" % password, device=False)
|
||||||
|
self.get_user_profile_by_name(user_name).click()
|
||||||
self.password_input.wait_for_visibility_of_element(10)
|
self.password_input.wait_for_visibility_of_element(10)
|
||||||
self.password_input.send_keys(password)
|
self.password_input.send_keys(password)
|
||||||
self.login_button.click()
|
self.login_button.click()
|
||||||
|
|
Loading…
Reference in New Issue