From 2a818149921e153846e64a2ecb81a8b29feb17af Mon Sep 17 00:00:00 2001 From: Parvesh Monu Date: Tue, 10 May 2022 15:08:19 +0530 Subject: [PATCH] Switcher & navigation 2 foundation (#13167) --- .../images/icons/redesign-messages@2x.png | Bin 0 -> 813 bytes .../images/icons/redesign-messages@3x.png | Bin 0 -> 1178 bytes resources/images/icons/redesign-wallet@2x.png | Bin 0 -> 735 bytes resources/images/icons/redesign-wallet@3x.png | Bin 0 -> 1052 bytes src/mocks/js_dependencies.cljs | 1 + src/quo/react_native.cljs | 10 +- src/quo2/components/button.cljs | 28 ++--- src/quo2/components/text.cljs | 5 +- src/quo2/foundations/colors.cljs | 19 +++- src/status_im/chat/models.cljs | 10 ++ src/status_im/events.cljs | 4 +- src/status_im/navigation2.cljs | 49 +++++++++ src/status_im/navigation2/core.cljs | 77 +++++++++++++ src/status_im/navigation2/home_stack.cljs | 27 +++++ src/status_im/navigation2/roots.cljs | 9 ++ src/status_im/navigation2/screens.cljs | 6 + .../navigation2/stack_with_switcher.cljs | 7 ++ src/status_im/navigation2/utils.cljs | 3 + src/status_im/subs.cljs | 17 +++ src/status_im/switcher/animation.cljs | 47 ++++++++ src/status_im/switcher/bottom_tabs.cljs | 30 +++++ .../switcher/cards/messaging_card.cljs | 30 +++++ src/status_im/switcher/cards/styles.cljs | 103 ++++++++++++++++++ src/status_im/switcher/constants.cljs | 32 ++++++ src/status_im/switcher/styles.cljs | 97 +++++++++++++++++ src/status_im/switcher/switcher.cljs | 44 ++++++++ .../switcher/switcher_container.cljs | 34 ++++++ src/status_im/switcher/utils.cljs | 6 + .../ui/screens/profile/user/views.cljs | 1 + src/status_im/ui/screens/screens.cljs | 7 +- 30 files changed, 684 insertions(+), 19 deletions(-) create mode 100644 resources/images/icons/redesign-messages@2x.png create mode 100644 resources/images/icons/redesign-messages@3x.png create mode 100644 resources/images/icons/redesign-wallet@2x.png create mode 100644 resources/images/icons/redesign-wallet@3x.png create mode 100644 src/status_im/navigation2.cljs create mode 100644 src/status_im/navigation2/core.cljs create mode 100644 src/status_im/navigation2/home_stack.cljs create mode 100644 src/status_im/navigation2/roots.cljs create mode 100644 src/status_im/navigation2/screens.cljs create mode 100644 src/status_im/navigation2/stack_with_switcher.cljs create mode 100644 src/status_im/navigation2/utils.cljs create mode 100644 src/status_im/switcher/animation.cljs create mode 100644 src/status_im/switcher/bottom_tabs.cljs create mode 100644 src/status_im/switcher/cards/messaging_card.cljs create mode 100644 src/status_im/switcher/cards/styles.cljs create mode 100644 src/status_im/switcher/constants.cljs create mode 100644 src/status_im/switcher/styles.cljs create mode 100644 src/status_im/switcher/switcher.cljs create mode 100644 src/status_im/switcher/switcher_container.cljs create mode 100644 src/status_im/switcher/utils.cljs diff --git a/resources/images/icons/redesign-messages@2x.png b/resources/images/icons/redesign-messages@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc88d8dfd4dabdec61d8f818a6843388bff0b403 GIT binary patch literal 813 zcmV+|1JeA7P)Vi|K~#7F?V5{m z;~)@*|I4@lT?M9tQwOGlqyy_JNC|QWN(atWaMyuy6*yNxlnRm#eCz=6f>8u|I+=Vk zJ0oF0yUQY0VBm{o`G#>3N^&J@bDf#;M#-y^XC;s3{$h|yDkU#Uj*;@DWN+FoMggtJ zaiCBiTlAz)2uWz~iI(3fR2t||v1CSaoWjb7+U%74!bH%6?-2H4t>hLu_PZb>3ezUk zSA}*Xdn1$_5LSGH{s`#N426}zNC=$AI^7RZ+$V2&hQL5XpyNq~*z{RpL?besD_>%I zO7EEm^mLd%VdqfZ;u}#Rkz!~EBjAUVOla$b4qZCJ)$V!TK)seA>rz>jcLTK z-eY-cB#eTDYq7xcNF>aKJ=|6HQsATDyiojPjxQVq;u5Q&VfHhk4&_;Q=9-el@1aTp z?oj23<2X=a5MGgM zObm|!IrYo{9zud$rx>sVZ_d8L2ZtN*VZ08uEwc(0BK{Rh%&`s-opbaCr}yj&;xo`W z)&aoXce)N$$j~qUp2L6~EjbzwAsUtkrg&-YyST^n@Q`ls&ekLiO`lPini>fy{u7q} z8siAKPTh1hkQixKU?lc%9U6uIL4Av5@F(v!r7_=1EHOX5Kk9Acq_~>^e_txe`_gMX z_Z-+^;Jy@}12yJl2Uq!CZ$kdw<Lt+BQRESgBFZ&Ih(RLxA*Oj`Z@1*mGRiG@CYd=7Llm1ci&(tZQ zC!FQRh~3d>ygqWcXU9HNzfkfQ1IciT`wiarMuFi+t<-*tg(=V;5+R|F6YHQsjQv*w r8ZA=Fo(J2}vuDR76kgBx;*;&Njlnp{Bh&Qk{NH&N!NH(xLL7NHeOb}-RlL?$okn#%D1fD>EgpuO! z9Gx5p$kNr*MF;_K;=~Due8F*{G+mVbmPzuz+cdr5NQ@~E3lOF0I{zD?E{YBoXq%_U zG;I(NahjHC+NbH=QrhQv&fqB=84K7IMVEGInj`C`lV?m}B%y9$8JivyBMW;nJf3|e zLFOw-zFnB{1rFxTsf%AF$QtPj6!qE*^U?!?$BJOF&gV13KMIs5`^Yx zaxPNT@Z(ENz!Z^{fel($&KQm$=v(Iw(?i$g*f$B5;a2fUoC2LlTofnfP20)Ro$wHIes`Suasz|A1IdG=`J5Mo$D^>% zXfCVjKbGDYHemB$aKh`(=4Y)ubbXOuC{lUAXb9b^ey7*J9%g z?Iak+WFFuNB*H$9p#Qz5+QmpX;b==wMnJ0D2aC~-q}wtHg+FZvmQ;mKE$ovf z(0oT)wN|qjNuVcTpF(&@w^cQPq&14g%zstgALzF}c@DSqy_I4Ai7Wef`w0dtQSa+( zgae^ozfRLSF=RuWAq*7ibz7n%zaXnj@E^92YTY_thzRl}e+R!sQjqJ^3*F)cpZ!RR zo;e1vf-F)D|5(65kI+5v_igYnI&Ym1#82ySb3?pX?2H5<_WS%exA$a z6w1;eS+AxQTxyv>z2i2$A|8S?`J zF5a#-f=A7Lx&%XzuY^GeV-td1p^A^2T){D8e?N$j`A_kQ95OtQJ!+dL_PiI2v~Fo^ sfvRw~_zrpTXkpxYd^GSACr*UJUoZt_Z2ldd1poj507*qoM6N<$g8wfbo&W#< literal 0 HcmV?d00001 diff --git a/resources/images/icons/redesign-wallet@2x.png b/resources/images/icons/redesign-wallet@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7b9d408ad4c873caa681b25b0c4bb5667594fce2 GIT binary patch literal 735 zcmV<50wDc~P)LAl|_41Z^isH;6kyy@`_v+)Q9PL9#)@MUb2%kPx=O@5SGH z_aNkC-N6Ck04`j3-+aJ$DkI94pKTi<4QOCt}! z4QMLlW_slsXF}nNsQ*J5 z6lyz$mh9JwJo7aUu*K;i)S;Cs)c8$Y5Pgl5e586Tvi16QK1kzhPidITKF%XUczWb7v&ib^^l zdtD)sk`CO9I-#D#qbcdYEt=~+pSVUlQFIF zcVoivSAlkwPzdEbMsja|h5z$m5IF+>MV*irjd~;q^#;dfyAzk9&AaTfLd=1t6!Ji` z@F`Sio~#tk2ZhLF!w%FGri+ R1#bWV002ovPDHLkV1f~rOQHY( literal 0 HcmV?d00001 diff --git a/resources/images/icons/redesign-wallet@3x.png b/resources/images/icons/redesign-wallet@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..e154e4ed3aec2eec0ab9b6999b800f9f63b9550a GIT binary patch literal 1052 zcmV+%1mpXOP)tQ+<{32b}A65An8Dt3X)VHr30q|sRKI|2v=ac0)-vKL_U@;aTpHs z%fl9R5BXK0o0Z9|B3`FH^ftE#kj8Lveqw zKdId^AR>ZI?J>3eNNtzeitM4iDwc5zqnYIuFsa=E`#^0+OK)nEgW}YFP@i8CvK;Vq zWH_I@a-8_{&xR}))|F4n@CDELDW>|#Y*PEmu*o^ckd;@wrK-#eJaI#{%U&^FVycDe zERvx-88->HF(74>vTAjZx*0l9rv8%fkTPp^x#L7E(-9}9Or+LzGL(l^=xE_4q1Gy0 ztk4s32sx(?se_g}T6vLng9XzeqJtM{uk{_%V?(i?k$cj)a^bad%u-KGJJt+~w4@{F znACk+ccIqTGSstgX+tC7bkZwdi_KH68@oV)q>jqEx*?_|se8i2P~UlVJI`|N$J8G3 z1Lw+3T@u1UD)^1;jcYiK4^#-GsoivlB4$`bm?hoYY8S^}&Kq3NRG{Ashs9qP=!L*% z&X0!hu=wpCz7WW#2Ms|?xj0hpHPtVfh?>+8vOor194W6&?HBdPkaJvhLKA_;N<=Xw zh&Z3{*fcpKTr}^ocy70aDv+V*JqgXisudv%;yUc1-rW$ue*^cR=t)8nz zn|cl<%-UdRF!ii86t~K;1=Ax^jx`!Gi6|<&VS2dp@?zIbE|hT6Vl!eo#B^K(wdCzB z!CSSsN2wQ0VG*ZvPqgJYhL$W#Ze$4;i(aRbr>@I(_E^HhqSvKW?r||pV=F>gSasft zAjFg}qZ9QPjF*V&%`7)~BBpx1VJ?(mc*J95uxvwhnHxRWHXG_h?G?>7tVxSBp}3*$ z89!W5+)$TqE;iJcPljZBS@313->5cbyW^F-drb~Fl@;N`u@^!oZXi|F8MCxd`YdLAM%%gB!BUi2WDnwW@ct)4*UZe Wv6Rw3hX&370000js {:options {:topBar {:visible false}}}))) + +;; TODO (parvesh) - improve open-modal and close-modal +(defn open-modal [comp] + (.showModal Navigation + (clj->js {:stack {:children + [{:component + {:name comp + :id comp + :options {:topBar {:visible false}}}}]}}))) + +(defn close-modal [_]) + +(defn close-all-modals [] + (.dismissAllModals Navigation)) + +(defn get-id [comp id] + (str comp "-" id)) + +(defn get-options [show-topbar? options] + (if show-topbar? + (merge options + (nav-roots/status-bar-options) + (nav-roots/merge-top-bar (nav-roots/topbar-options) options)) + {:topBar {:visible false}})) + +(defn change-stack-root [[comp _]] + (let [{:keys [options]} (get views/screens comp)] + (.setStackRoot Navigation + (name comp) + (clj->js {:stack {:id comp + :children [{:component {:id comp + :name comp + :options (get-options false options)}}]}})))) + +(defn navigate [[comp _]] + (let [{:keys [options]} (get views/screens comp)] + (reset! nav2-utils/container-stack-view-id comp) + (.push Navigation + (name :home-stack) + (clj->js {:stack {:id comp + :children [{:component {:id comp + :name comp + :options (get-options false options)}}]}})))) + +(defn navigate-from-switcher [[comp id from-home?]] + (if from-home? + (navigate [comp id]) + (change-stack-root [comp id]))) + +(re-frame/reg-fx + :init-root-fx-nav2 + (fn [new-root-id] + (reset! nav2-utils/container-stack-view-id new-root-id) + (.setRoot Navigation (clj->js (get (roots/roots) new-root-id))))) + +(re-frame/reg-fx :open-modal-fx-nav2 open-modal) + +(re-frame/reg-fx :close-modal-fx-nav2 close-modal) + +(re-frame/reg-fx :navigate-to-fx-nav2 navigate) + +(re-frame/reg-fx :navigate-from-switcher-fx navigate-from-switcher) diff --git a/src/status_im/navigation2/home_stack.cljs b/src/status_im/navigation2/home_stack.cljs new file mode 100644 index 0000000000..5ae554a9e8 --- /dev/null +++ b/src/status_im/navigation2/home_stack.cljs @@ -0,0 +1,27 @@ +(ns status-im.navigation2.home-stack + (:require [quo.react-native :as rn] + [quo2.screens.main :as quo2.preview] + [status-im.switcher.switcher :as switcher] + [status-im.ui.screens.home.views :as home] + [status-im.switcher.constants :as switcher-constants] + [status-im.ui.screens.browser.empty-tab.views :as empty-tab] + [status-im.ui.screens.wallet.accounts.views :as wallet.accounts] + [status-im.switcher.bottom-tabs :as bottom-tabs])) + +;; TODO(parvesh) - improve stack changing performance (load all stacks at once) +(defn stack-view [] + (let [{:keys [width height]} (switcher-constants/dimensions)] + ;; bottom-tabs-height (switcher-constants/bottom-tabs-height)] + [rn/view {:style {:width width + :height (- height 80)}} ;; TODO(parvesh) - add height for ios + (case @bottom-tabs/selected-tab-id + :chats-stack [home/home] + :communities-stack [quo2.preview/main-screen] + :wallet-stack [wallet.accounts/accounts-overview] + :browser-stack [empty-tab/empty-tab])])) + +(defn home [] + [:<> + [stack-view] + [bottom-tabs/bottom-tabs] + [switcher/switcher :home-stack]]) diff --git a/src/status_im/navigation2/roots.cljs b/src/status_im/navigation2/roots.cljs new file mode 100644 index 0000000000..637aa04063 --- /dev/null +++ b/src/status_im/navigation2/roots.cljs @@ -0,0 +1,9 @@ +(ns status-im.navigation2.roots) + +(defn roots [] + {:home-stack + {:root + {:stack {:id :home-stack + :children [{:component {:name :home-stack + :id :home-stack + :options {:topBar {:visible false}}}}]}}}}) diff --git a/src/status_im/navigation2/screens.cljs b/src/status_im/navigation2/screens.cljs new file mode 100644 index 0000000000..726916dbbb --- /dev/null +++ b/src/status_im/navigation2/screens.cljs @@ -0,0 +1,6 @@ +(ns status-im.navigation2.screens + (:require [status-im.navigation2.home-stack :as home-stack])) + +(def screens [{:name :home-stack + :insets {:top false} + :component home-stack/home}]) diff --git a/src/status_im/navigation2/stack_with_switcher.cljs b/src/status_im/navigation2/stack_with_switcher.cljs new file mode 100644 index 0000000000..7e9377b631 --- /dev/null +++ b/src/status_im/navigation2/stack_with_switcher.cljs @@ -0,0 +1,7 @@ +(ns status-im.navigation2.stack-with-switcher + (:require [status-im.switcher.switcher :as switcher])) + +(defn overlap-stack [comp view-id] + [:<> + [comp] + [switcher/switcher view-id]]) diff --git a/src/status_im/navigation2/utils.cljs b/src/status_im/navigation2/utils.cljs new file mode 100644 index 0000000000..aebe9a65dd --- /dev/null +++ b/src/status_im/navigation2/utils.cljs @@ -0,0 +1,3 @@ +(ns status-im.navigation2.utils) + +(defonce container-stack-view-id (atom nil)) diff --git a/src/status_im/subs.cljs b/src/status_im/subs.cljs index 7e93ea9a96..9b9b3003da 100644 --- a/src/status_im/subs.cljs +++ b/src/status_im/subs.cljs @@ -87,6 +87,7 @@ (reg-root-key-sub :home-items-show-number :home-items-show-number) (reg-root-key-sub :waku/v2-peer-stats :peer-stats) (reg-root-key-sub :visibility-status-updates :visibility-status-updates) +(reg-root-key-sub :navigation2/navigation2-stacks :navigation2/navigation2-stacks) ;;NOTE this one is not related to ethereum network ;; it is about cellular network/ wifi network @@ -2946,3 +2947,19 @@ :<- [:bookmarks] (fn [bookmarks] (into {} (remove #(:removed (second %)) bookmarks)))) + +;; NAVIGATION2 + + +(re-frame/reg-sub + :navigation2/switcher-cards + :<- [:navigation2/navigation2-stacks] + (fn [stacks [_ toggle-switcher-screen]] + (sort-by :clock > + (reduce (fn [acc stack-vector] + (let [{:keys [type clock id]} (get stack-vector 1)] + (conj acc {:type type + :clock clock + :id id + :toggle-switcher-screen toggle-switcher-screen}))) + '() stacks)))) diff --git a/src/status_im/switcher/animation.cljs b/src/status_im/switcher/animation.cljs new file mode 100644 index 0000000000..dffc7d75d5 --- /dev/null +++ b/src/status_im/switcher/animation.cljs @@ -0,0 +1,47 @@ +(ns status-im.switcher.animation + (:require [quo.react-native :as rn] + [reagent.core :as reagent] + [status-im.switcher.constants :as constants] + [status-im.ui.components.animation :as anim])) + +(def bottom-tabs-opacity (anim/create-value 1)) +(def bottom-tabs-position (anim/create-value 0)) + +;; TODO(parvesh): Use 300, after using dispatch-later for opening card(otherwise pending animation issue) +;; or OnAnimationEnd +(def layout-animation #js {:duration 250 + :create #js {:type (:ease-in-ease-out rn/layout-animation-types) + :property (:scale-xy rn/layout-animation-properties)} + :update #js {:type (:ease-in-ease-out rn/layout-animation-types) + :property (:scale-xy rn/layout-animation-properties)} + :delete #js {:type (:ease-in-ease-out rn/layout-animation-types) + :property (:scale-xy rn/layout-animation-properties)}}) + +(defn animate-layout [show? anim-values] + (let [{:keys [width height]} (constants/dimensions) + target-radius (- (max width height) + constants/switcher-button-radius)] + (rn/configure-next layout-animation) + (reset! (:switcher-screen-radius anim-values) (if show? target-radius 1)) + (reagent/flush))) + +(defn timing-animation [property toValue] + (anim/timing property {:toValue toValue + :duration 300 + :useNativeDriver true})) + +(defn animate-components [show? view-id anim-values] + (anim/start + (anim/parallel + (into + [(timing-animation (:switcher-button-opacity anim-values) (if show? 0 1)) + (timing-animation (:switcher-close-button-icon-opacity anim-values) (if show? 1 0)) + (timing-animation (:switcher-close-button-background-opacity anim-values) (if show? 0.2 0))] + (when (= view-id :home-stack) + [(timing-animation bottom-tabs-opacity (if show? 0 1)) + (timing-animation bottom-tabs-position (if show? (constants/bottom-tabs-height) 0))]))))) + +(defn animate [show? view-id anim-values] + (reagent/flush) + (animate-layout show? anim-values) + (animate-components show? view-id anim-values)) diff --git a/src/status_im/switcher/bottom_tabs.cljs b/src/status_im/switcher/bottom_tabs.cljs new file mode 100644 index 0000000000..a61dfc506e --- /dev/null +++ b/src/status_im/switcher/bottom_tabs.cljs @@ -0,0 +1,30 @@ +(ns status-im.switcher.bottom-tabs + (:require [quo.react-native :as rn] + [reagent.core :as reagent] + [status-im.switcher.styles :as styles] + [status-im.ui.components.icons.icons :as icons])) + +(def selected-tab-id (reagent/atom :chats-stack)) + +(defn bottom-tab-pressed [tab-id] + (when-not (= tab-id @selected-tab-id) + (reset! selected-tab-id tab-id))) + +;; TODO(parvesh) - reimplement tab with counter, once design is complete +;; (implement natively, for performance improvement) +(defn bottom-tab [icon tab-id] + [rn/touchable-opacity {:style {:padding 15} + :active-opacity 1 + :on-press #(bottom-tab-pressed tab-id)} + [icons/icon icon (styles/bottom-tab-icon + (if (= tab-id @selected-tab-id) + :bottom-tabs-selected-tab + :bottom-tabs-non-selected-tab))]]) + +(defn bottom-tabs [] + [rn/animated-view {:style (styles/bottom-tabs)} + [bottom-tab :main-icons/redesign-messages :chats-stack] + [bottom-tab :main-icons/communities :communities-stack] + [rn/view {:width 10}] + [bottom-tab :main-icons/redesign-wallet :wallet-stack] + [bottom-tab :main-icons/browser :browser-stack]]) diff --git a/src/status_im/switcher/cards/messaging_card.cljs b/src/status_im/switcher/cards/messaging_card.cljs new file mode 100644 index 0000000000..642aa810ee --- /dev/null +++ b/src/status_im/switcher/cards/messaging_card.cljs @@ -0,0 +1,30 @@ +(ns status-im.switcher.cards.messaging-card + (:require [quo.react-native :as rn] + [quo2.components.text :as text] + [status-im.constants :as constants] + [quo2.components.button :as button] + [status-im.utils.handlers :refer [>evt evt [:chat.ui/navigate-to-chat-nav2 id true])) + +;; TODO - add last message for other content types +(defn last-message [{:keys [content content-type]}] + (cond + (= constants/content-type-text content-type) + [text/text (styles/messaging-card-last-message-text-props) (:text content)])) + +(defn card [{:keys [id toggle-switcher-screen]}] + (let [chat ( + [switcher-screen switcher-opened? view-id anim-values] + [switcher-button switcher-opened? view-id anim-values]])) diff --git a/src/status_im/switcher/switcher_container.cljs b/src/status_im/switcher/switcher_container.cljs new file mode 100644 index 0000000000..136ae0bc0b --- /dev/null +++ b/src/status_im/switcher/switcher_container.cljs @@ -0,0 +1,34 @@ +(ns status-im.switcher.switcher-container + (:require [quo.react-native :as rn] + status-im.switcher.cards.messaging-card + [status-im.switcher.styles :as styles] + [status-im.utils.handlers :refer [