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:
Ulises Manuel 2024-11-20 13:51:06 -06:00 committed by GitHub
parent 58476a43da
commit ac0a115f1d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 245 additions and 231 deletions

View File

@ -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}]

View File

@ -91,5 +91,4 @@
cofx cofx
:fleet :fleet
fleet fleet
{:on-success {:on-success #(re-frame/dispatch [:profile/logout])}))))
#(re-frame/dispatch [:logout])}))))

View File

@ -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]}

View File

@ -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}})

View File

@ -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)]]]))

View File

@ -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?})}]})

View File

@ -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]])))

View File

@ -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

View File

@ -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?])]))

View File

@ -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?}]))

View File

@ -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])}}]]))

View File

@ -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)]]))

View File

@ -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})]

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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]}]]}))

View File

@ -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))]
[:<> [:<>

View File

@ -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}]]}))

View File

@ -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}])]]))

View File

@ -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

View File

@ -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?]

View File

@ -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)

View File

@ -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])))

View File

@ -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")

View File

@ -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)

View File

@ -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()

View File

@ -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

View File

@ -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)

View File

@ -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")

View File

@ -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")

View File

@ -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()