diff --git a/resources/images/icons/messages-new@2x.png b/resources/images/icons/messages-new@2x.png new file mode 100644 index 000000000000..dc88d8dfd4da Binary files /dev/null and b/resources/images/icons/messages-new@2x.png differ diff --git a/resources/images/icons/messages-new@3x.png b/resources/images/icons/messages-new@3x.png new file mode 100644 index 000000000000..62f1a70604c1 Binary files /dev/null and b/resources/images/icons/messages-new@3x.png differ diff --git a/resources/images/icons/wallet-new@2x.png b/resources/images/icons/wallet-new@2x.png new file mode 100644 index 000000000000..7b9d408ad4c8 Binary files /dev/null and b/resources/images/icons/wallet-new@2x.png differ diff --git a/resources/images/icons/wallet-new@3x.png b/resources/images/icons/wallet-new@3x.png new file mode 100644 index 000000000000..e154e4ed3aec Binary files /dev/null and b/resources/images/icons/wallet-new@3x.png differ diff --git a/src/quo/react_native.cljs b/src/quo/react_native.cljs index ab87e70d36c0..8219ad5fc3b8 100644 --- a/src/quo/react_native.cljs +++ b/src/quo/react_native.cljs @@ -74,6 +74,9 @@ (def animated-view (reagent/adapt-react-class (.-View ^js animated))) +(def animated-image-view + (reagent/adapt-react-class (.-Image ^js animated))) + (def ui-manager (.-UIManager ^js rn)) (def layout-animation (.-LayoutAnimation ^js rn)) @@ -102,6 +105,8 @@ :property (:opacity layout-animation-properties)} :delete #js {:type (:ease-in-ease-out layout-animation-types) :property (:opacity layout-animation-properties)}}}) +(defonce enable-layout-animations + (when platform/android? (.setLayoutAnimationEnabledExperimental ^js ui-manager true))) (def activity-indicator (reagent/adapt-react-class (.-ActivityIndicator ^js rn))) diff --git a/src/quo2/foundations/colors.cljs b/src/quo2/foundations/colors.cljs index e18060d7f6c6..eeddc85cfa46 100644 --- a/src/quo2/foundations/colors.cljs +++ b/src/quo2/foundations/colors.cljs @@ -33,6 +33,13 @@ (def neutral-50-opa-30 (alpha neutral-50 0.3)) (def neutral-50-opa-40 (alpha neutral-50 0.4)) +;;70 with transparency +(def neutral-70-opa-60 (alpha neutral-70 0.6)) +(def neutral-70-opa-70 (alpha neutral-70 0.7)) +(def neutral-70-opa-80 (alpha neutral-70 0.8)) +(def neutral-70-opa-90 (alpha neutral-70 0.9)) +(def neutral-70-opa-95 (alpha neutral-70 0.95)) + ;;80 with transparency (def neutral-80-opa-60 (alpha neutral-80 0.6)) (def neutral-80-opa-70 (alpha neutral-80 0.7)) @@ -173,4 +180,14 @@ (def info-50-opa-10 (alpha info-50 0.1)) (def info-50-opa-20 (alpha info-50 0.2)) (def info-50-opa-30 (alpha info-50 0.3)) -(def info-50-opa-40 (alpha info-50 0.4)) \ No newline at end of file +(def info-50-opa-40 (alpha info-50 0.4)) + +;;;;Switcher +(def switcher-background "#040B14") + +;;switcher-screen with transparency +(def switcher-background-opa-60 (alpha switcher-background 0.6)) +(def switcher-background-opa-70 (alpha switcher-background 0.7)) +(def switcher-background-opa-80 (alpha switcher-background 0.8)) +(def switcher-background-opa-90 (alpha switcher-background 0.9)) +(def switcher-background-opa-95 (alpha switcher-background 0.95)) diff --git a/src/quo2/screens/main.cljs b/src/quo2/screens/main.cljs index b92da32453f7..33260842873b 100644 --- a/src/quo2/screens/main.cljs +++ b/src/quo2/screens/main.cljs @@ -58,7 +58,7 @@ [rn/view (for [{:keys [name]} screens] ^{:key name} - [rn/touchable-opacity {:on-press #(re-frame/dispatch [:navigate-to name])} + [rn/touchable-opacity {:on-press #(re-frame/dispatch [:navigate-to-nav2 name])} [rn/view {:style {:padding-vertical 8}} [quo/text (str "Preview " name)]]])]]) diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index 72e2f618933c..402697d0f1bd 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -62,7 +62,9 @@ [status-im.navigation.core :as navigation.core] [status-im.multiaccounts.login.core :as login.core] [status-im.signing.core :as signing] - status-im.wallet-connect.core)) + status-im.wallet-connect.core + status-im.navigation2 + status-im.navigation2.core)) (re-frame/reg-fx :dismiss-keyboard diff --git a/src/status_im/navigation2.cljs b/src/status_im/navigation2.cljs new file mode 100644 index 000000000000..e948aeb3fda8 --- /dev/null +++ b/src/status_im/navigation2.cljs @@ -0,0 +1,27 @@ +(ns status-im.navigation2 + (:require [status-im.utils.fx :as fx])) + +(fx/defn init-root-nav2 + {:events [:init-root-nav2]} + [_ root-id] + {:init-root-fx-nav2 root-id}) + +(fx/defn change-tab-nav2 + {:events [:navigate-change-tab-nav2]} + [_ tab-id] + {:change-tab-fx-nav2 tab-id}) + +(fx/defn open-modal-nav2 + {:events [:open-modal-nav2]} + [_ modal] + {:open-modal-fx-nav2 modal}) + +(fx/defn close-modal-nav2 + {:events [:close-modal-nav2]} + [_ modal] + {:close-modal-fx-nav2 modal}) + +(fx/defn navigate-to-nav2 + {:events [:navigate-to-nav2]} + [cofx go-to-view-id _] + {:navigate-to-fx-nav2 go-to-view-id}) diff --git a/src/status_im/navigation2/core.cljs b/src/status_im/navigation2/core.cljs new file mode 100644 index 000000000000..716d56dd96a9 --- /dev/null +++ b/src/status_im/navigation2/core.cljs @@ -0,0 +1,45 @@ +(ns status-im.navigation2.core + (:require [re-frame.core :as re-frame] + [status-im.navigation2.roots :as roots] + ["react-native-navigation" :refer (Navigation)])) + +(def tab-key-idx {:home 0 + :communities 1 + :wallet 2 + :browser 3}) + +;; 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 navigate [comp] + (.push Navigation + (name :home-stack) + (clj->js {:component {:id comp + :name comp}}))) + +(re-frame/reg-fx + :init-root-fx-nav2 + (fn [new-root-id] + (.setRoot Navigation (clj->js (get (roots/roots) new-root-id))))) + +(re-frame/reg-fx + :change-tab-fx-nav2 + (fn [tab-id] + (.mergeOptions Navigation "quo2-tabs-stack" (clj->js {:bottomTabs {:currentTabId tab-id}})))) + +(re-frame/reg-fx :open-modal-fx2 open-modal) + +(re-frame/reg-fx :close-modal-fx2 close-modal) + +(re-frame/reg-fx :navigate-to-fx-nav2 navigate) diff --git a/src/status_im/navigation2/home_stack.cljs b/src/status_im/navigation2/home_stack.cljs new file mode 100644 index 000000000000..4c669f0dfbfb --- /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 [quo2.preview/main-screen] + :communities-stack [home/home] + :wallet-stack [wallet.accounts/accounts-overview] + :browser-stack [empty-tab/empty-tab])])) + +(defn home [] + [:<> + [stack-view] + [bottom-tabs/bottom-tabs] + [switcher/switcher]]) diff --git a/src/status_im/navigation2/roots.cljs b/src/status_im/navigation2/roots.cljs new file mode 100644 index 000000000000..3ad0ca5f305e --- /dev/null +++ b/src/status_im/navigation2/roots.cljs @@ -0,0 +1,9 @@ +(ns status-im.navigation2.roots) + +(defn roots [] + {:quo2-tabs-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 000000000000..726916dbbb4d --- /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/subs.cljs b/src/status_im/subs.cljs index 6b23adb647c6..0aa36e2e145f 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-stacks :navigation2/navigation2-stacks) ;;NOTE this one is not related to ethereum network ;; it is about cellular network/ wifi network @@ -2955,4 +2956,14 @@ :bookmarks/active :<- [:bookmarks] (fn [bookmarks] - (into {} (remove #(:removed (second %)) bookmarks)))) \ No newline at end of file + (into {} (remove #(:removed (second %)) bookmarks)))) + + +;; NAVIGATION2 + + +(re-frame/reg-sub + :navigation2/switcher-cards + :<- [:navigation2/navigation2-stacks] + (fn [_] + {:chats-stack {:type :root}})) diff --git a/src/status_im/switcher/animation.cljs b/src/status_im/switcher/animation.cljs new file mode 100644 index 000000000000..f58a5537ce2a --- /dev/null +++ b/src/status_im/switcher/animation.cljs @@ -0,0 +1,45 @@ +(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 switcher-button-opacity (anim/create-value 1)) +(def switcher-close-button-icon-opacity (anim/create-value 0)) +(def switcher-close-button-background-opacity (anim/create-value 0)) +(def bottom-tabs-position (anim/create-value 0)) +(def switcher-screen-radius (reagent/atom 1)) +(def layout-animation #js {:duration 300 + :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?] + (let [{:keys [width height]} (constants/dimensions) + target-radius (- (max width height) + constants/switcher-button-radius)] + (rn/configure-next layout-animation) + (reset! switcher-screen-radius (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?] + (anim/start + (anim/parallel + [(timing-animation bottom-tabs-opacity (if show? 0 1)) + (timing-animation switcher-button-opacity (if show? 0 1)) + (timing-animation switcher-close-button-icon-opacity (if show? 1 0)) + (timing-animation switcher-close-button-background-opacity (if show? 0.2 0)) + (timing-animation bottom-tabs-position (if show? (constants/bottom-tabs-height) 0))]))) + +(defn animate [show?] + (animate-layout show?) + (animate-components show?)) diff --git a/src/status_im/switcher/bottom_tabs.cljs b/src/status_im/switcher/bottom_tabs.cljs new file mode 100644 index 000000000000..62f266438eed --- /dev/null +++ b/src/status_im/switcher/bottom_tabs.cljs @@ -0,0 +1,31 @@ +(ns status-im.switcher.bottom-tabs + (:require [quo.react-native :as rn] + [reagent.core :as reagent] + [status-im.switcher.styles :as styles] + [status-im.utils.handlers :refer [>evt]] + [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) + (>evt [:navigate-change-tab-nav2 tab-id]))) + +;; TODO(parvesh) - reimplement tab with counter, once design is complete +(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/messages-new :chats-stack] + [bottom-tab :main-icons/communities :communities-stack] + [rn/view {:width 10}] + [bottom-tab :main-icons/wallet-new :wallet-stack] + [bottom-tab :main-icons/browser :browser-stack]]) diff --git a/src/status_im/switcher/constants.cljs b/src/status_im/switcher/constants.cljs new file mode 100644 index 000000000000..bb9b75434844 --- /dev/null +++ b/src/status_im/switcher/constants.cljs @@ -0,0 +1,21 @@ +(ns status-im.switcher.constants + (:require [status-im.utils.handlers :refer [ + [switcher-screen] + [switcher-button]]) diff --git a/src/status_im/ui/screens/profile/user/views.cljs b/src/status_im/ui/screens/profile/user/views.cljs index 62c52f023580..372c554f8630 100644 --- a/src/status_im/ui/screens/profile/user/views.cljs +++ b/src/status_im/ui/screens/profile/user/views.cljs @@ -122,7 +122,7 @@ :title "Quo2.0 Preview" :accessibility-label :appearance-settings-button :chevron true - :on-press #(re-frame/dispatch [:navigate-to :quo2-preview])}]) + :on-press #(re-frame/dispatch [:init-root-nav2 :quo2-tabs-stack])}]) [quo/list-item {:icon :main-icons/appearance :title (i18n/label :t/appearance) diff --git a/src/status_im/ui/screens/screens.cljs b/src/status_im/ui/screens/screens.cljs index 7f9f700e1b13..f0d20a33d3f6 100644 --- a/src/status_im/ui/screens/screens.cljs +++ b/src/status_im/ui/screens/screens.cljs @@ -121,6 +121,7 @@ [status-im.ui.screens.wallet.recipient.views :as recipient] [status-im.ui.screens.wallet.send.views :as wallet.send] [quo2.screens.main :as quo2.preview] + [status-im.navigation2.screens :as navigation2.screens] [status-im.utils.config :as config])) (def components @@ -911,5 +912,7 @@ quo.preview/main-screens) (when config/quo-preview-enabled? quo2.preview/screens) + (when config/quo-preview-enabled? + navigation2.screens/screens) (when config/quo-preview-enabled? quo2.preview/main-screens)))