From cbe17cbe020189f5d7aaacba2f82da63061e47ac Mon Sep 17 00:00:00 2001 From: Andrey Shovkoplyas Date: Tue, 15 Oct 2019 14:35:33 +0200 Subject: [PATCH] [#8940] Redesign Back, swipe-to-the-left and hardware device Back buttons to align the behavior Signed-off-by: Andrey Shovkoplyas --- android/build.gradle | 2 +- src/status_im/android/core.cljs | 3 +- src/status_im/multiaccounts/create/core.cljs | 24 ++----- src/status_im/multiaccounts/recover/core.cljs | 7 +- src/status_im/ui/screens/navigation.cljs | 66 ++----------------- .../ui/screens/routing/back_actions.cljs | 29 ++++++++ src/status_im/ui/screens/routing/core.cljs | 48 +++++++------- 7 files changed, 70 insertions(+), 109 deletions(-) create mode 100644 src/status_im/ui/screens/routing/back_actions.cljs diff --git a/android/build.gradle b/android/build.gradle index cde7c30eac..210b2c772d 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -68,6 +68,6 @@ allprojects { // for geth, function, and status-go flatDir { dirs "libs", System.env.STATUS_GO_ANDROID_LIBDIR } - maven { url "https://jitpack.io" } + maven { url "https://www.jitpack.io" } } } diff --git a/src/status_im/android/core.cljs b/src/status_im/android/core.cljs index 0ad2145fa8..54505cbfea 100644 --- a/src/status_im/android/core.cljs +++ b/src/status_im/android/core.cljs @@ -11,7 +11,8 @@ [status-im.core :as core] [status-im.react-native.js-dependencies :as rn-dependencies] [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] (dispatch [:app-state-change state])) diff --git a/src/status_im/multiaccounts/create/core.cljs b/src/status_im/multiaccounts/create/core.cljs index ec6c4dd34f..884dd7734d 100644 --- a/src/status_im/multiaccounts/create/core.cljs +++ b/src/status_im/multiaccounts/create/core.cljs @@ -19,9 +19,6 @@ [status-im.utils.utils :as utils] [status-im.utils.platform :as platform])) -(defn get-signing-phrase [cofx] - (assoc cofx :signing-phrase (signing-phrase/generate))) - (def step-kw-to-num {:generate-key 1 :choose-key 2 @@ -66,8 +63,7 @@ :back-action :intro-wizard/navigate-back :forward-action :intro-wizard/step-forward-pressed :encrypt-with-password? true - :first-time-setup? first-time-setup?}) - ::navigation/add-wizard-back-event [:intro-wizard/step-back-pressed]} + :first-time-setup? first-time-setup?})} (navigation/navigate-to-cofx :create-multiaccount-generate-key nil))) (fx/defn dec-step @@ -82,16 +78,10 @@ (= step :confirm-code) (assoc-in [:intro-wizard :confirm-failure?] false))}) (when (= :generate-key-step) - {: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}) + {:db (dissoc db :intro-wizard)})))) (fx/defn intro-step-back - {:events [:intro-wizard/step-back-pressed]} + {:events [:intro-wizard/navigate-back]} [{:keys [db] :as cofx} skip-alert?] (let [step (get-in db [:intro-wizard :step])] ;; Cannot go back after account has been created @@ -101,16 +91,14 @@ (utils/show-question (i18n/label :t/are-you-sure-to-cancel) (i18n/label :t/you-will-start-from-scratch) - #(re-frame/dispatch [:intro-wizard/step-back-pressed true]) - #(re-frame/dispatch [:navigation/reset-processing-flag])) + #(re-frame/dispatch [:intro-wizard/navigate-back true])) (fx/merge cofx dec-step navigation/navigate-back))))) (fx/defn exit-wizard [{:keys [db] :as cofx}] (fx/merge cofx - {:db (dissoc db :intro-wizard) - ::navigation/remove-wizard-back-event nil} + {:db (dissoc db :intro-wizard)} (navigation/navigate-to-cofx :home nil))) (fx/defn init-key-generation @@ -331,7 +319,7 @@ (re-frame/reg-cofx ::get-signing-phrase (fn [cofx _] - (get-signing-phrase cofx))) + (assoc cofx :signing-phrase (signing-phrase/generate)))) (fx/defn create-multiaccount-success {:events [::store-multiaccount-success] diff --git a/src/status_im/multiaccounts/recover/core.cljs b/src/status_im/multiaccounts/recover/core.cljs index 41cb019848..08dbe5578f 100644 --- a/src/status_im/multiaccounts/recover/core.cljs +++ b/src/status_im/multiaccounts/recover/core.cljs @@ -129,7 +129,6 @@ :first-time-setup? false :back-action :intro-wizard/navigate-back :forward-action :multiaccounts.recover/enter-phrase-next-pressed}) - ::navigation/add-wizard-back-event [:multiaccounts.recover/cancel-pressed] :dispatch [:bottom-sheet/hide-sheet]} (navigation/navigate-to-cofx :recover-multiaccount-enter-phrase nil))) @@ -157,8 +156,7 @@ [{:keys [db] :as cofx}] (let [step (get-in db [:intro-wizard :step])] (if (= step :enter-phrase) - {:db (dissoc db :intro-wizard) - ::navigation/remove-wizard-back-event nil} + {:db (dissoc db :intro-wizard)} {:db (update db :intro-wizard assoc :step (case step :recovery-success :enter-phrase @@ -180,8 +178,7 @@ (utils/show-question (i18n/label :t/are-you-sure-to-cancel) (i18n/label :t/you-will-start-from-scratch) - #(re-frame/dispatch [:multiaccounts.recover/cancel-pressed true]) - #(re-frame/dispatch [:navigation/reset-processing-flag])) + #(re-frame/dispatch [:multiaccounts.recover/cancel-pressed true])) (fx/merge cofx dec-step navigation/navigate-back))))) diff --git a/src/status_im/ui/screens/navigation.cljs b/src/status_im/ui/screens/navigation.cljs index 1668eba457..56526ccc1c 100644 --- a/src/status_im/ui/screens/navigation.cljs +++ b/src/status_im/ui/screens/navigation.cljs @@ -1,25 +1,10 @@ (ns status-im.ui.screens.navigation (: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.navigation :as navigation] - [status-im.utils.platform :as platform] [taoensso.timbre :as log] [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! (fn [db] (:view-id db))) @@ -32,7 +17,7 @@ (defn- -preload-data! [{:keys [was-modal?] :as db} & args] (if was-modal? - (dissoc db :was-modal?) ;;TODO check how it worked with this bug + (dissoc db :was-modal?) (apply preload-data! db args))) (fx/defn navigate-to-cofx @@ -44,7 +29,9 @@ screen-params))] {:db (if (= view-id go-to-view-id) 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]})) (fx/defn navigate-reset @@ -69,8 +56,6 @@ (def navigation-interceptors [unload-data-interceptor (re-frame/enrich preload-data!)]) -;; effects - (re-frame/reg-fx ::navigate-to (fn [[view-id params]] @@ -89,8 +74,6 @@ (log/debug :navigate-reset config) (navigation/navigate-reset config))) -;; event handlers - (handlers/register-handler-fx :navigate-to navigation-interceptors @@ -105,15 +88,14 @@ (fx/defn navigate-back [{{: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) first-in-stack (first navigation-stack)] (if (= view-id first-in-stack) (-> db (assoc :view-id previous-view-id) (assoc :navigation-stack navigation-stack')) - (assoc db :view-id first-in-stack))))) + (assoc db :view-id first-in-stack)))}) (handlers/register-handler-fx :navigate-back @@ -140,38 +122,4 @@ {:db (-> db (assoc :prev-tab-view-id (:view-id db)) (assoc :prev-view-id (:view-id db)))} - (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))) + (navigate-to-cofx view-id {})))) \ No newline at end of file diff --git a/src/status_im/ui/screens/routing/back_actions.cljs b/src/status_im/ui/screens/routing/back_actions.cljs new file mode 100644 index 0000000000..97c85999ce --- /dev/null +++ b/src/status_im/ui/screens/routing/back_actions.cljs @@ -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}) \ No newline at end of file diff --git a/src/status_im/ui/screens/routing/core.cljs b/src/status_im/ui/screens/routing/core.cljs index dd37b769bc..192c437ecd 100644 --- a/src/status_im/ui/screens/routing/core.cljs +++ b/src/status_im/ui/screens/routing/core.cljs @@ -1,7 +1,7 @@ (ns status-im.ui.screens.routing.core (:require [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.utils.navigation :as navigation] [cljs-react-navigation.reagent :as nav-reagent] @@ -22,6 +22,7 @@ [status-im.react-native.js-dependencies :as js-dependencies])) (defonce view-id (reagent.core/atom nil)) +(defonce back-button-listener (atom nil)) (defn navigation-events [current-view-id modal? screen-focused?] [:> navigation/navigation-events @@ -36,12 +37,22 @@ (re-frame/dispatch [:screens/on-will-focus current-view-id])) :on-did-focus (fn [] + (reset! + back-button-listener + (.addEventListener + js-dependencies/back-handler + "hardwareBackPress" + (fn [] + (not (get back-actions/back-actions current-view-id))))) (when-not modal? (status-bar/set-status-bar current-view-id))) :on-will-blur (fn [payload] (reset! screen-focused? false) (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 ;; on navigating away; this is a privacy measure (doseq [[text-input default-value] @react/text-input-refs] @@ -118,6 +129,13 @@ (utils/update-if-present :initialRouteName 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] (let [res (nav-reagent/stack-navigator routes @@ -139,24 +157,8 @@ (let [route (aget routes idx) route-name (keyword (.-routeName route))] (tabbar/minimize-bar route-name)))))} - (prepare-config config))) - default-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) + (prepare-config config)))] + (set! (-> res .-router .-getStateForAction) (new-get-state-for-action (.-getStateForAction (.-router res)))) res)) (defn twopane-navigator [routes config] @@ -218,11 +220,7 @@ :else (nav-reagent/stack-screen (wrap screen-name screen-config)))] [screen-name (cond-> {:screen res} - ;; TODO issue #8947 - ;; replace this hack with configuration - (#{:create-multiaccount-choose-key - :recover-multiaccount-select-storage} - screen-name) + (not (get back-actions/back-actions screen-name)) (assoc :navigationOptions {:gesturesEnabled false}) (:navigation screen-config) (assoc :navigationOptions @@ -267,4 +265,4 @@ :onTransitionStart (fn [])})}]]) {:initialRouteName (if (= view-id :intro) :intro-stack - :login-stack)}))) + :login-stack)}))) \ No newline at end of file