[#8940] Redesign Back, swipe-to-the-left and hardware device Back buttons to align the behavior

Signed-off-by: Andrey Shovkoplyas <motor4ik@gmail.com>
This commit is contained in:
Andrey Shovkoplyas 2019-10-15 14:35:33 +02:00
parent 8fc823f94b
commit cbe17cbe02
No known key found for this signature in database
GPG Key ID: EAAB7C8622D860A4
7 changed files with 70 additions and 109 deletions

View File

@ -68,6 +68,6 @@ allprojects {
// for geth, function, and status-go // for geth, function, and status-go
flatDir { dirs "libs", System.env.STATUS_GO_ANDROID_LIBDIR } flatDir { dirs "libs", System.env.STATUS_GO_ANDROID_LIBDIR }
maven { url "https://jitpack.io" } maven { url "https://www.jitpack.io" }
} }
} }

View File

@ -11,7 +11,8 @@
[status-im.core :as core] [status-im.core :as core]
[status-im.react-native.js-dependencies :as rn-dependencies] [status-im.react-native.js-dependencies :as rn-dependencies]
[status-im.utils.snoopy :as snoopy] [status-im.utils.snoopy :as snoopy]
[status-im.i18n :as i18n])) [status-im.i18n :as i18n]
[status-im.ui.screens.routing.core :as routing]))
(defn app-state-change-handler [state] (defn app-state-change-handler [state]
(dispatch [:app-state-change state])) (dispatch [:app-state-change state]))

View File

@ -19,9 +19,6 @@
[status-im.utils.utils :as utils] [status-im.utils.utils :as utils]
[status-im.utils.platform :as platform])) [status-im.utils.platform :as platform]))
(defn get-signing-phrase [cofx]
(assoc cofx :signing-phrase (signing-phrase/generate)))
(def step-kw-to-num (def step-kw-to-num
{:generate-key 1 {:generate-key 1
:choose-key 2 :choose-key 2
@ -66,8 +63,7 @@
:back-action :intro-wizard/navigate-back :back-action :intro-wizard/navigate-back
:forward-action :intro-wizard/step-forward-pressed :forward-action :intro-wizard/step-forward-pressed
:encrypt-with-password? true :encrypt-with-password? true
:first-time-setup? first-time-setup?}) :first-time-setup? first-time-setup?})}
::navigation/add-wizard-back-event [:intro-wizard/step-back-pressed]}
(navigation/navigate-to-cofx :create-multiaccount-generate-key nil))) (navigation/navigate-to-cofx :create-multiaccount-generate-key nil)))
(fx/defn dec-step (fx/defn dec-step
@ -82,16 +78,10 @@
(= step :confirm-code) (= step :confirm-code)
(assoc-in [:intro-wizard :confirm-failure?] false))}) (assoc-in [:intro-wizard :confirm-failure?] false))})
(when (= :generate-key-step) (when (= :generate-key-step)
{:db (dissoc db :intro-wizard) {:db (dissoc db :intro-wizard)}))))
::navigation/remove-wizard-back-event nil}))))
(fx/defn navigate-back
{:events [:intro-wizard/navigate-back]}
[cofx]
{::navigation/navigate-back nil})
(fx/defn intro-step-back (fx/defn intro-step-back
{:events [:intro-wizard/step-back-pressed]} {:events [:intro-wizard/navigate-back]}
[{:keys [db] :as cofx} skip-alert?] [{:keys [db] :as cofx} skip-alert?]
(let [step (get-in db [:intro-wizard :step])] (let [step (get-in db [:intro-wizard :step])]
;; Cannot go back after account has been created ;; Cannot go back after account has been created
@ -101,16 +91,14 @@
(utils/show-question (utils/show-question
(i18n/label :t/are-you-sure-to-cancel) (i18n/label :t/are-you-sure-to-cancel)
(i18n/label :t/you-will-start-from-scratch) (i18n/label :t/you-will-start-from-scratch)
#(re-frame/dispatch [:intro-wizard/step-back-pressed true]) #(re-frame/dispatch [:intro-wizard/navigate-back true]))
#(re-frame/dispatch [:navigation/reset-processing-flag]))
(fx/merge cofx (fx/merge cofx
dec-step dec-step
navigation/navigate-back))))) navigation/navigate-back)))))
(fx/defn exit-wizard [{:keys [db] :as cofx}] (fx/defn exit-wizard [{:keys [db] :as cofx}]
(fx/merge cofx (fx/merge cofx
{:db (dissoc db :intro-wizard) {:db (dissoc db :intro-wizard)}
::navigation/remove-wizard-back-event nil}
(navigation/navigate-to-cofx :home nil))) (navigation/navigate-to-cofx :home nil)))
(fx/defn init-key-generation (fx/defn init-key-generation
@ -331,7 +319,7 @@
(re-frame/reg-cofx (re-frame/reg-cofx
::get-signing-phrase ::get-signing-phrase
(fn [cofx _] (fn [cofx _]
(get-signing-phrase cofx))) (assoc cofx :signing-phrase (signing-phrase/generate))))
(fx/defn create-multiaccount-success (fx/defn create-multiaccount-success
{:events [::store-multiaccount-success] {:events [::store-multiaccount-success]

View File

@ -129,7 +129,6 @@
:first-time-setup? false :first-time-setup? false
:back-action :intro-wizard/navigate-back :back-action :intro-wizard/navigate-back
:forward-action :multiaccounts.recover/enter-phrase-next-pressed}) :forward-action :multiaccounts.recover/enter-phrase-next-pressed})
::navigation/add-wizard-back-event [:multiaccounts.recover/cancel-pressed]
:dispatch [:bottom-sheet/hide-sheet]} :dispatch [:bottom-sheet/hide-sheet]}
(navigation/navigate-to-cofx :recover-multiaccount-enter-phrase nil))) (navigation/navigate-to-cofx :recover-multiaccount-enter-phrase nil)))
@ -157,8 +156,7 @@
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [step (get-in db [:intro-wizard :step])] (let [step (get-in db [:intro-wizard :step])]
(if (= step :enter-phrase) (if (= step :enter-phrase)
{:db (dissoc db :intro-wizard) {:db (dissoc db :intro-wizard)}
::navigation/remove-wizard-back-event nil}
{:db (update db :intro-wizard assoc :step {:db (update db :intro-wizard assoc :step
(case step (case step
:recovery-success :enter-phrase :recovery-success :enter-phrase
@ -180,8 +178,7 @@
(utils/show-question (utils/show-question
(i18n/label :t/are-you-sure-to-cancel) (i18n/label :t/are-you-sure-to-cancel)
(i18n/label :t/you-will-start-from-scratch) (i18n/label :t/you-will-start-from-scratch)
#(re-frame/dispatch [:multiaccounts.recover/cancel-pressed true]) #(re-frame/dispatch [:multiaccounts.recover/cancel-pressed true]))
#(re-frame/dispatch [:navigation/reset-processing-flag]))
(fx/merge cofx (fx/merge cofx
dec-step dec-step
navigation/navigate-back))))) navigation/navigate-back)))))

View File

@ -1,25 +1,10 @@
(ns status-im.ui.screens.navigation (ns status-im.ui.screens.navigation
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.react-native.js-dependencies :as js-dependencies]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.utils.navigation :as navigation] [status-im.utils.navigation :as navigation]
[status-im.utils.platform :as platform]
[taoensso.timbre :as log] [taoensso.timbre :as log]
[status-im.utils.fx :as fx])) [status-im.utils.fx :as fx]))
;; private helper fns
(defn- push-view [db view-id]
(-> db
(update :navigation-stack conj view-id)
(assoc :view-id view-id)))
;; public fns
(fx/defn navigate-forget
[{:keys [db]} view-id]
{:db (assoc db :view-id view-id)})
(defmulti unload-data! (defmulti unload-data!
(fn [db] (:view-id db))) (fn [db] (:view-id db)))
@ -32,7 +17,7 @@
(defn- -preload-data! [{:keys [was-modal?] :as db} & args] (defn- -preload-data! [{:keys [was-modal?] :as db} & args]
(if was-modal? (if was-modal?
(dissoc db :was-modal?) ;;TODO check how it worked with this bug (dissoc db :was-modal?)
(apply preload-data! db args))) (apply preload-data! db args)))
(fx/defn navigate-to-cofx (fx/defn navigate-to-cofx
@ -44,7 +29,9 @@
screen-params))] screen-params))]
{:db (if (= view-id go-to-view-id) {:db (if (= view-id go-to-view-id)
db db
(push-view db go-to-view-id)) (-> db
(update :navigation-stack conj go-to-view-id)
(assoc :view-id go-to-view-id)))
::navigate-to [go-to-view-id screen-params]})) ::navigate-to [go-to-view-id screen-params]}))
(fx/defn navigate-reset (fx/defn navigate-reset
@ -69,8 +56,6 @@
(def navigation-interceptors (def navigation-interceptors
[unload-data-interceptor (re-frame/enrich preload-data!)]) [unload-data-interceptor (re-frame/enrich preload-data!)])
;; effects
(re-frame/reg-fx (re-frame/reg-fx
::navigate-to ::navigate-to
(fn [[view-id params]] (fn [[view-id params]]
@ -89,8 +74,6 @@
(log/debug :navigate-reset config) (log/debug :navigate-reset config)
(navigation/navigate-reset config))) (navigation/navigate-reset config)))
;; event handlers
(handlers/register-handler-fx (handlers/register-handler-fx
:navigate-to :navigate-to
navigation-interceptors navigation-interceptors
@ -105,15 +88,14 @@
(fx/defn navigate-back (fx/defn navigate-back
[{{:keys [navigation-stack view-id] :as db} :db}] [{{:keys [navigation-stack view-id] :as db} :db}]
(assoc {::navigate-back nil
{::navigate-back nil}
:db (let [[previous-view-id :as navigation-stack'] (pop navigation-stack) :db (let [[previous-view-id :as navigation-stack'] (pop navigation-stack)
first-in-stack (first navigation-stack)] first-in-stack (first navigation-stack)]
(if (= view-id first-in-stack) (if (= view-id first-in-stack)
(-> db (-> db
(assoc :view-id previous-view-id) (assoc :view-id previous-view-id)
(assoc :navigation-stack navigation-stack')) (assoc :navigation-stack navigation-stack'))
(assoc db :view-id first-in-stack))))) (assoc db :view-id first-in-stack)))})
(handlers/register-handler-fx (handlers/register-handler-fx
:navigate-back :navigate-back
@ -140,38 +122,4 @@
{:db (-> db {:db (-> db
(assoc :prev-tab-view-id (:view-id db)) (assoc :prev-tab-view-id (:view-id db))
(assoc :prev-view-id (:view-id db)))} (assoc :prev-view-id (:view-id db)))}
(navigate-to-cofx view-id {})))) (navigate-to-cofx view-id {}))))
;; This atom stores event vector
;; to be dispatched when a react-navigation's BACK
;; actions is invoked
(def wizard-back-event (atom nil))
;; This atom exists in order to avoid
;; endless loop when processing NavigationActions/BACK
;; in react-navigation's getStateForAction fn
(def processing-back-event? (atom false))
(fx/defn reset-processing-flag
{:events [:navigation/reset-processing-flag]}
[{:keys [db] :as cofx}]
{::reset-processing-flag nil})
(re-frame/reg-fx
::reset-processing-flag
(fn []
(reset! processing-back-event? false)))
;; Below two effects are added when we need
;; to override default react-navigation's BACK action
;; processing
(re-frame/reg-fx
::add-wizard-back-event
(fn [event]
(reset! wizard-back-event event)))
(re-frame/reg-fx
::remove-wizard-back-event
(fn [event]
(reset! processing-back-event? false)
(reset! wizard-back-event nil)))

View File

@ -0,0 +1,29 @@
(ns status-im.ui.screens.routing.back-actions)
(def back-actions {:chat :default
:login :default
:recover-multiaccount-enter-phrase :default
:create-multiaccount-generate-key :default
:new-chat :default
:new-public-chat :default
:wallet-account :default
:add-new-account :default
:add-new-account-password :default
:about-app :default
:help-center :default
:advanced-settings :default
:sync-settings :default
:mobile-network-settings :default
:offline-messaging-settings :default
:edit-mailserver :default
:installations :default
:privacy-and-security :default
:dapps-permissions :default
:contacts-list :default
:blocked-users-list :default
:ens-main :default
:ens-register :default
:wallet-settings-assets :default
:wallet-add-custom-token :default
:currency-settings :default
:backup-seed :default})

View File

@ -1,7 +1,7 @@
(ns status-im.ui.screens.routing.core (ns status-im.ui.screens.routing.core
(:require (:require
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.ui.screens.navigation :as screens.navigation] [status-im.ui.screens.routing.back-actions :as back-actions]
[status-im.ui.components.styles :as common-styles] [status-im.ui.components.styles :as common-styles]
[status-im.utils.navigation :as navigation] [status-im.utils.navigation :as navigation]
[cljs-react-navigation.reagent :as nav-reagent] [cljs-react-navigation.reagent :as nav-reagent]
@ -22,6 +22,7 @@
[status-im.react-native.js-dependencies :as js-dependencies])) [status-im.react-native.js-dependencies :as js-dependencies]))
(defonce view-id (reagent.core/atom nil)) (defonce view-id (reagent.core/atom nil))
(defonce back-button-listener (atom nil))
(defn navigation-events [current-view-id modal? screen-focused?] (defn navigation-events [current-view-id modal? screen-focused?]
[:> navigation/navigation-events [:> navigation/navigation-events
@ -36,12 +37,22 @@
(re-frame/dispatch [:screens/on-will-focus current-view-id])) (re-frame/dispatch [:screens/on-will-focus current-view-id]))
:on-did-focus :on-did-focus
(fn [] (fn []
(reset!
back-button-listener
(.addEventListener
js-dependencies/back-handler
"hardwareBackPress"
(fn []
(not (get back-actions/back-actions current-view-id)))))
(when-not modal? (when-not modal?
(status-bar/set-status-bar current-view-id))) (status-bar/set-status-bar current-view-id)))
:on-will-blur :on-will-blur
(fn [payload] (fn [payload]
(reset! screen-focused? false) (reset! screen-focused? false)
(log/debug :on-will-blur current-view-id) (log/debug :on-will-blur current-view-id)
(when @back-button-listener
(.remove @back-button-listener)
(reset! back-button-listener nil))
;; Reset currently mounted text inputs to their default values ;; Reset currently mounted text inputs to their default values
;; on navigating away; this is a privacy measure ;; on navigating away; this is a privacy measure
(doseq [[text-input default-value] @react/text-input-refs] (doseq [[text-input default-value] @react/text-input-refs]
@ -118,6 +129,13 @@
(utils/update-if-present :initialRouteName name) (utils/update-if-present :initialRouteName name)
(utils/update-if-present :mode name))) (utils/update-if-present :mode name)))
(defn new-get-state-for-action [default-get-state-for-action]
(fn [action state]
(let [event (get back-actions/back-actions @view-id)]
(when (and (= (.-type action) (.-BACK navigation/navigation-actions)) event (not= :default event))
(re-frame/dispatch [event]))
(default-get-state-for-action action state))))
(defn stack-navigator [routes config] (defn stack-navigator [routes config]
(let [res (nav-reagent/stack-navigator (let [res (nav-reagent/stack-navigator
routes routes
@ -139,24 +157,8 @@
(let [route (aget routes idx) (let [route (aget routes idx)
route-name (keyword (.-routeName route))] route-name (keyword (.-routeName route))]
(tabbar/minimize-bar route-name)))))} (tabbar/minimize-bar route-name)))))}
(prepare-config config))) (prepare-config config)))]
default-get-state-for-action (.-getStateForAction (.-router res)) (set! (-> res .-router .-getStateForAction) (new-get-state-for-action (.-getStateForAction (.-router res))))
new-get-state-for-action (fn [action state]
;; Override default getStateForAction on this stack navigator
;; if we have a custom event set in wizard-back-event atom
(if (and (= (.-type action) (.-BACK navigation/navigation-actions))
@screens.navigation/wizard-back-event)
(if @screens.navigation/processing-back-event?
(do
(reset! screens.navigation/processing-back-event? false)
(default-get-state-for-action action state))
(do
(reset! screens.navigation/processing-back-event? true)
(re-frame/dispatch @screens.navigation/wizard-back-event)
;; Return nil so that BACK event processing ends here
nil))
(default-get-state-for-action action state)))]
(set! (-> res .-router .-getStateForAction) new-get-state-for-action)
res)) res))
(defn twopane-navigator [routes config] (defn twopane-navigator [routes config]
@ -218,11 +220,7 @@
:else :else
(nav-reagent/stack-screen (wrap screen-name screen-config)))] (nav-reagent/stack-screen (wrap screen-name screen-config)))]
[screen-name (cond-> {:screen res} [screen-name (cond-> {:screen res}
;; TODO issue #8947 (not (get back-actions/back-actions screen-name))
;; replace this hack with configuration
(#{:create-multiaccount-choose-key
:recover-multiaccount-select-storage}
screen-name)
(assoc :navigationOptions {:gesturesEnabled false}) (assoc :navigationOptions {:gesturesEnabled false})
(:navigation screen-config) (:navigation screen-config)
(assoc :navigationOptions (assoc :navigationOptions
@ -267,4 +265,4 @@
:onTransitionStart (fn [])})}]]) :onTransitionStart (fn [])})}]])
{:initialRouteName (if (= view-id :intro) {:initialRouteName (if (= view-id :intro)
:intro-stack :intro-stack
:login-stack)}))) :login-stack)})))