From aaf0b8e4236a90d944744203e5519975ae0b36a1 Mon Sep 17 00:00:00 2001 From: mmilad75 <55688834+mmilad75@users.noreply.github.com> Date: Wed, 6 Dec 2023 14:09:52 +0330 Subject: [PATCH 01/12] Implement transaction progress component (#17933) * copy codes * refactor preview * refactor deprecated codes in view * change condition structure in view-internal * comment unused codes * refactor title * fix title style * fix icon style * fix context tag * fix icon and row * refactor icon-internal * rename network-state and network-type * fix progress-container style * fix progress-box-container style * fix progress container naming and style * change progress-bar component * fix progress box component * convert to functional component and bring back the animation * fix progress box for arbitrum-optimism network * fix text-steps * fix status-row * refactor code style * refactor get-network-text * resolve comment * add translations * remove btn-title prop * fix dark mode border color * fix dark mode icon color * move interval to preview * add tests ns * add tests * fix lint issues * fix rendering issue * fix lint issue * add arbitrum and optimism as separate networks * create const for progress percentage * fix progress bar component and preview * refactor text-steps * refactor names * fix lint issues * rename arbitrum-progress-percentage and optimism-progress-percentage * update tests * convert hard-coded color to customization-color * fix progress_bar tests * separate state for each network * add progress percentage for each network and refactor params of functions * separate epoch number for each network * update tests * fix lint issues * refactor codes * fix lint issues * resolve comments * add confirmation progress * use confirmation-progress component in transaction-progress * fix preview * add tests * fix lint issue * resolve comment * refactor networks * change sending state style * update tests * fix lint issues * remove unused code * add helper for calculate counter step * add assoc-props to view-networks * change text-internal props order * fix colors/resolve-color usage * refactor view codes * add get-networks to preview * add max-value to progress bar style * remove threading macros in the previews * remove inline functional components in the previews * remove optimism-arbitrum checks in the view * fix lint issues * add max-progress and min-progress to confirmation-progress * refactor text-steps * fix counter structure in transaction-progress * fix counter structure in confirmation-progress * fix resolve-color usage * fix lint issue * fix tests * resolve comments * fix color issue * fix margins * fix lint issue --- resources/images/icons2/16x16/diamond@2x.png | Bin 0 -> 851 bytes resources/images/icons2/16x16/diamond@3x.png | Bin 0 -> 1173 bytes .../confirmation_progress/component_spec.cljs | 99 +++++++++ .../wallet/confirmation_progress/style.cljs | 9 + .../wallet/confirmation_progress/view.cljs | 69 ++++++ .../wallet/progress_bar/component_spec.cljs | 12 +- .../components/wallet/progress_bar/style.cljs | 43 ++-- .../components/wallet/progress_bar/view.cljs | 6 +- .../transaction_progress/component_spec.cljs | 200 ++++++++++++++++++ .../wallet/transaction_progress/style.cljs | 38 ++++ .../wallet/transaction_progress/view.cljs | 187 ++++++++++++++++ src/quo/core.cljs | 4 + src/quo/core_spec.cljs | 2 + src/status_im2/contexts/quo_preview/main.cljs | 5 + .../wallet/confirmation_progress.cljs | 85 ++++++++ .../quo_preview/wallet/progress_bar.cljs | 10 +- .../wallet/transaction_progress.cljs | 155 ++++++++++++++ translations/en.json | 7 + 18 files changed, 909 insertions(+), 22 deletions(-) create mode 100644 resources/images/icons2/16x16/diamond@2x.png create mode 100644 resources/images/icons2/16x16/diamond@3x.png create mode 100644 src/quo/components/wallet/confirmation_progress/component_spec.cljs create mode 100644 src/quo/components/wallet/confirmation_progress/style.cljs create mode 100644 src/quo/components/wallet/confirmation_progress/view.cljs create mode 100644 src/quo/components/wallet/transaction_progress/component_spec.cljs create mode 100644 src/quo/components/wallet/transaction_progress/style.cljs create mode 100644 src/quo/components/wallet/transaction_progress/view.cljs create mode 100644 src/status_im2/contexts/quo_preview/wallet/confirmation_progress.cljs create mode 100644 src/status_im2/contexts/quo_preview/wallet/transaction_progress.cljs diff --git a/resources/images/icons2/16x16/diamond@2x.png b/resources/images/icons2/16x16/diamond@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d1968f43ead92c6231dbf14c6e5cfe2792733217 GIT binary patch literal 851 zcmV-Z1FZasP)c+G4KzBwMC+=O{G$h03}R} z2~rE4zzaxh5hVng_>OytZ7#9TzO-S2Pl|lLU*GrMz4vkk_}4*(nLNAHN^{P$;+H0b zo1BwmcN4-J0JJWebwbGI&Q`ptyQh|bnT78K4rEz0P0)iyfUoRsPpw5w3>7e!YncZJ zYy+EcI9TK3G*d6fE!7078b~d+ZnfKX?Fi%uG@y3&YBQ&r5a^_S> z_Vo{Tpxe=MH^4@ShB%H3gU8`J0^zdCUm!;$op=JJ0E~9fkMzS}&f)M7lV6-vQ{v9` zF}QtgENlvt*4yytX;FbMjf3KbktPp4NN`R z`h8(h`Bev0z%keAh*(Ja1%x2sY=lqD1Ql>hCQVF1B>o5>&Mm3Ps?7!rDze2(i#` zR2CLoA`m;4LK1Df1j5HHx8r+vtnTdX$IR{?Q1DCOZue$p|Nl2{XJ%&sjyNI_3{t=- z^4{IuZG&?@z&YdqxWO3j<(&04FT!{YznhFP{N(eRrd1Yax+{=q#qLYX#ZfkTPK0-7qW$bE)2S(kG?&ympUtOh``yq;5U2w_JCzIrs0r56Q|$#wjQ`x+%R~ZEr0@}k94?oBcoCU zzI<)K2r=Y;OGYlRKbb%^V=lw?ue*WUpb!@v)#E**mTw4lZb45_# z@x3g>MZGS2XcYel^N|p`Oa1G4+Xm?gi=tn=Ek-{oqEyF$>c0M<)C;(5KW>1l7lf@AySuCKad*l?`hvf~)QW!2p+>dE-VusH|cy2tgKmfXm&$-iUqs-cTA2sVvnA zYcqrp1Cm_7B38S0IRj7b%clXAr8+{Jm(?ah2T=(FsYkh?(H&U(Z42ipf-)wkj5peA z*ds&Fw?Ps?qc?@53{VQhF%c$SHU;rcG2O?a0gXv-Z>X9`Lwpn5TXG+Y25fs36p%HM zns{igO6T3j!dR$jylmTQi#f-{+sR{a_VoXFxCN&rzNJyCxQ~UwmljHOOJ9*4PTkNr z?ls{@67fiFdG^F9_X*)@&F4AKm#-);ha#AT_1G@W|9W8%mOup z4%$CHb(@Uy12MrEZSLBGq#>+a4F=( literal 0 HcmV?d00001 diff --git a/src/quo/components/wallet/confirmation_progress/component_spec.cljs b/src/quo/components/wallet/confirmation_progress/component_spec.cljs new file mode 100644 index 00000000000..60010c48747 --- /dev/null +++ b/src/quo/components/wallet/confirmation_progress/component_spec.cljs @@ -0,0 +1,99 @@ +(ns quo.components.wallet.confirmation-progress.component-spec + (:require [quo.core :as quo] + [reagent.core :as reagent] + [test-helpers.component :as h])) + +(defn- get-test-data + [{:keys [state network] + :or {state :pending network :mainnet}}] + {:counter (reagent/atom 0) + :total-box 85 + :progress-value "10" + :network network + :state state + :customization-color :blue}) + +(h/describe "Confirmation Progress" + (h/test "component renders when state is sending and network is optimism" + (h/render [quo/confirmation-propgress + (get-test-data {:state :sending + :network :optimism})]) + (h/is-truthy (h/get-by-label-text :progress-box))) + + (h/test "component renders when state is confirmed and network is optimism" + (h/render [quo/confirmation-propgress + (get-test-data {:state :confirmed + :network :optimism})]) + (h/is-truthy (h/get-by-label-text :progress-box))) + + (h/test "component renders when state is finalising and network is optimism" + (h/render [quo/confirmation-propgress + (get-test-data {:state :finalising + :network :optimism})]) + (h/is-truthy (h/get-by-label-text :progress-box))) + + (h/test "component renders when state is finalized and network is optimism" + (h/render [quo/confirmation-propgress + (get-test-data {:state :finalized + :network :optimism})]) + (h/is-truthy (h/get-by-label-text :progress-box))) + + (h/test "component renders when state is error and network is optimism" + (h/render [quo/confirmation-propgress + (get-test-data {:state :error + :network :optimism})]) + (h/is-truthy (h/get-by-label-text :progress-box))) + + (h/test "component renders when state is sending and network is arbitrum" + (h/render [quo/confirmation-propgress + (get-test-data {:state :sending + :network :arbitrum})]) + (h/is-truthy (h/get-by-label-text :progress-box))) + + (h/test "component renders when state is confirmed and network is arbitrum" + (h/render [quo/confirmation-propgress + (get-test-data {:state :confirmed + :network :arbitrum})]) + (h/is-truthy (h/get-by-label-text :progress-box))) + + (h/test "component renders when state is finalising and network is arbitrum" + (h/render [quo/confirmation-propgress + (get-test-data {:state :finalising + :network :arbitrum})]) + (h/is-truthy (h/get-by-label-text :progress-box))) + + (h/test "component renders when state is finalized and network is arbitrum" + (h/render [quo/confirmation-propgress + (get-test-data {:state :finalized + :network :arbitrum})]) + (h/is-truthy (h/get-by-label-text :progress-box))) + + (h/test "component renders when state is error and network is arbitrum" + (h/render [quo/confirmation-propgress + (get-test-data {:state :error + :network :arbitrum})]) + (h/is-truthy (h/get-by-label-text :progress-box))) + + (h/test "component renders when state is pending and network is mainnet" + (h/render [quo/confirmation-propgress (get-test-data {})]) + (h/is-truthy (h/get-by-label-text :mainnet-progress-box))) + + (h/test "component renders when state is sending and network is mainnet" + (h/render [quo/confirmation-propgress (get-test-data {:state :sending})]) + (h/is-truthy (h/get-by-label-text :mainnet-progress-box))) + + (h/test "component renders when state is confirmed and network is mainnet" + (h/render [quo/confirmation-propgress (get-test-data {:state :confirmed})]) + (h/is-truthy (h/get-by-label-text :mainnet-progress-box))) + + (h/test "component renders when state is finalising and network is mainnet" + (h/render [quo/confirmation-propgress (get-test-data {:state :finalising})]) + (h/is-truthy (h/get-by-label-text :mainnet-progress-box))) + + (h/test "component renders when state is finalized and network is mainnet" + (h/render [quo/confirmation-propgress (get-test-data {:state :finalized})]) + (h/is-truthy (h/get-by-label-text :mainnet-progress-box))) + + (h/test "component renders when state is error and network is mainnet" + (h/render [quo/confirmation-propgress (get-test-data {:state :error})]) + (h/is-truthy (h/get-by-label-text :mainnet-progress-box)))) diff --git a/src/quo/components/wallet/confirmation_progress/style.cljs b/src/quo/components/wallet/confirmation_progress/style.cljs new file mode 100644 index 00000000000..511ba496f86 --- /dev/null +++ b/src/quo/components/wallet/confirmation_progress/style.cljs @@ -0,0 +1,9 @@ +(ns quo.components.wallet.confirmation-progress.style) + +(def progress-box-container + {:flex-direction :row + :align-items :center + :padding-horizontal 12 + :padding-bottom 10 + :padding-top 4 + :flex-wrap :wrap}) diff --git a/src/quo/components/wallet/confirmation_progress/view.cljs b/src/quo/components/wallet/confirmation_progress/view.cljs new file mode 100644 index 00000000000..0a438415879 --- /dev/null +++ b/src/quo/components/wallet/confirmation_progress/view.cljs @@ -0,0 +1,69 @@ +(ns quo.components.wallet.confirmation-progress.view + (:require [quo.components.wallet.confirmation-progress.style :as style] + [quo.components.wallet.progress-bar.view :as progress-box] + [quo.theme :as quo.theme] + [react-native.core :as rn])) + +(def ^:private max-progress 100) +(def ^:private min-progress 0) + +(defn- calculate-box-state + [state counter index] + (cond + (and (= state :sending) (>= counter index) (< index 3)) :confirmed + (and (= state :confirmed) (>= counter index) (< index 5)) :confirmed + (and (= state :finalising) (>= counter index) (< index 5)) :confirmed + (and (= state :finalising) (>= counter index) (> index 4) (< index 20)) :finalized + (and (= state :finalized) (>= counter index) (< index 5)) :confirmed + (and (= state :finalized) (>= counter index) (> index 4)) :finalized + (and (= state :error) (>= counter index) (< index 2)) :error + :else :pending)) + +(defn- calculate-box-state-sidenet + [state] + (case state + :error :error + (:confirmed :finalising :finalized) :finalized + :pending)) + +(defn- calculate-progressed-value + [state progress-value] + (case state + :finalising progress-value + :finalized max-progress + min-progress)) + +(defn- progress-boxes-mainnet + [{:keys [state counter total-box]}] + [rn/view + {:accessibility-label :mainnet-progress-box + :style style/progress-box-container} + (let [numbers (range 1 total-box)] + (doall (for [n numbers] + [progress-box/view + {:state (calculate-box-state state counter n) + :customization-color :blue + :key n}])))]) + +(defn- progress-boxes-sidenet + [{:keys [state progress-value]}] + [rn/view + {:accessibility-label :progress-box + :style style/progress-box-container} + [progress-box/view + {:state (calculate-box-state-sidenet state) + :customization-color :success}] + [progress-box/view + {:state (calculate-box-state-sidenet state) + :full-width? true + :progressed-value (calculate-progressed-value state progress-value) + :customization-color :blue}]]) + +(defn- view-internal + [{:keys [network] :as props}] + (case network + :mainnet [progress-boxes-mainnet props] + (:arbitrum :optimism) [progress-boxes-sidenet props] + nil)) + +(def view (quo.theme/with-theme view-internal)) diff --git a/src/quo/components/wallet/progress_bar/component_spec.cljs b/src/quo/components/wallet/progress_bar/component_spec.cljs index 39d48caf6af..b5612b36615 100644 --- a/src/quo/components/wallet/progress_bar/component_spec.cljs +++ b/src/quo/components/wallet/progress_bar/component_spec.cljs @@ -39,7 +39,7 @@ :width 8 :borderRadius 3 :borderColor colors/neutral-80-opa-5 - :backgroundColor (colors/custom-color (:customization-color props) 50)}))) + :backgroundColor (colors/resolve-color (:customization-color props) theme)}))) (h/test "finalized state with customtization-color blue in dark mode" (let [theme :dark @@ -51,7 +51,7 @@ :width 8 :borderRadius 3 :borderColor colors/neutral-80-opa-5 - :backgroundColor (colors/custom-color (:customization-color props) 60)}))) + :backgroundColor (colors/resolve-color (:customization-color props) theme)}))) (h/test "finalized state with customtization-color army in light mode" (let [theme :light @@ -63,7 +63,7 @@ :width 8 :borderRadius 3 :borderColor colors/neutral-80-opa-5 - :backgroundColor (colors/custom-color (:customization-color props) 50)}))) + :backgroundColor (colors/resolve-color (:customization-color props) theme)}))) (h/test "confirmed state in light mode" (let [theme :light @@ -75,7 +75,7 @@ :width 8 :borderRadius 3 :borderColor colors/neutral-80-opa-5 - :backgroundColor colors/success-50}))) + :backgroundColor (colors/resolve-color :success theme)}))) (h/test "confirmed state in dark mode" (let [theme :dark @@ -99,7 +99,7 @@ :width 8 :borderRadius 3 :borderColor colors/neutral-80-opa-5 - :backgroundColor colors/danger-50}))) + :backgroundColor (colors/resolve-color :danger theme)}))) (h/test "error state in dark mode" (let [theme :dark @@ -111,4 +111,4 @@ :width 8 :borderRadius 3 :borderColor colors/white-opa-5 - :backgroundColor colors/danger-60})))) + :backgroundColor (colors/resolve-color :danger theme)})))) diff --git a/src/quo/components/wallet/progress_bar/style.cljs b/src/quo/components/wallet/progress_bar/style.cljs index 71b1aa2796c..8a1ebe76c1d 100644 --- a/src/quo/components/wallet/progress_bar/style.cljs +++ b/src/quo/components/wallet/progress_bar/style.cljs @@ -3,31 +3,48 @@ [quo.foundations.colors :as colors])) (defn- border-and-background-color - [customization-color] + [customization-color theme] {:light {:pending {:border-color colors/neutral-80-opa-5 :background-color colors/neutral-5} :confirmed {:border-color colors/neutral-80-opa-5 - :background-color (colors/custom-color :success 50)} + :background-color (colors/resolve-color :success theme)} :finalized {:border-color colors/neutral-80-opa-5 - :background-color (colors/custom-color customization-color 50)} + :background-color (colors/resolve-color customization-color theme)} :error {:border-color colors/neutral-80-opa-5 - :background-color (colors/custom-color :danger 50)}} + :background-color (colors/resolve-color :danger theme)}} :dark {:pending {:border-color colors/neutral-70 :background-color colors/neutral-80} :confirmed {:border-color colors/white-opa-5 - :background-color (colors/custom-color :success 60)} + :background-color (colors/resolve-color :success theme)} :finalized {:border-color colors/neutral-80-opa-5 - :background-color (colors/custom-color customization-color 60)} + :background-color (colors/resolve-color customization-color theme)} :error {:border-color colors/white-opa-5 - :background-color (colors/custom-color :danger 60)}}}) + :background-color (colors/resolve-color :danger theme)}}}) + +(def max-value 100) (defn root-container - [{:keys [customization-color state theme]}] - (let [{:keys [background-color border-color]} (get-in (border-and-background-color customization-color) - [theme state])] + [{:keys [customization-color state theme full-width?]}] + (let [{:keys [background-color border-color]} (get-in (border-and-background-color customization-color + theme) + [theme (if full-width? :pending state)])] + {:height 12 + :flex (when full-width? 1) + :width (when (not full-width?) 8) + :border-radius 3 + :border-width 1 + :border-color border-color + :background-color background-color + :margin-horizontal 1 + :margin-vertical 2})) + +(defn progressed-bar + [{:keys [customization-color state theme progressed-value]}] + (let [{:keys [background-color]} (get-in (border-and-background-color customization-color theme) + [theme state]) + progress (if (> progressed-value max-value) max-value progressed-value)] {:height 12 - :width 8 + :margin-top -1 + :width (str progress "%") :border-radius 3 - :border-width 1 - :border-color border-color :background-color background-color})) diff --git a/src/quo/components/wallet/progress_bar/view.cljs b/src/quo/components/wallet/progress_bar/view.cljs index 98cf8e599db..f923091016e 100644 --- a/src/quo/components/wallet/progress_bar/view.cljs +++ b/src/quo/components/wallet/progress_bar/view.cljs @@ -5,9 +5,11 @@ [react-native.core :as rn])) (defn- view-internal - [props] + [{:keys [full-width?] :as props}] [rn/view {:accessibility-label :progress-bar - :style (style/root-container props)}]) + :style (style/root-container props)} + (when full-width? + [rn/view {:style (style/progressed-bar props)}])]) (def view (quo.theme/with-theme view-internal)) diff --git a/src/quo/components/wallet/transaction_progress/component_spec.cljs b/src/quo/components/wallet/transaction_progress/component_spec.cljs new file mode 100644 index 00000000000..eb82518e10e --- /dev/null +++ b/src/quo/components/wallet/transaction_progress/component_spec.cljs @@ -0,0 +1,200 @@ +(ns quo.components.wallet.transaction-progress.component-spec + (:require [quo.core :as quo] + [reagent.core :as reagent] + [test-helpers.component :as h])) + +(defn- get-test-data + [{:keys [state network] + :or {state :pending network :mainnet}}] + {:title "Title" + :tag-name "Doodle" + :tag-number "120" + :network network + :customization-color :blue + :networks [{:network :mainnet + :state state + :counter (reagent/atom 0) + :total-box 85 + :progress 30 + :epoch-number "123"} + {:network :optimism + :state state + :progress "50" + :epoch-number "123"} + {:network :arbitrum + :state state + :progress "30" + :epoch-number "123"}] + :on-press (fn [] + (js/alert "Transaction progress item pressed"))}) + +(h/describe "Transaction Progress" + (h/test "component renders without props" + (h/render [quo/transaction-progress]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is pending and network is mainnet" + (h/render [quo/transaction-progress (get-test-data {:network :optimism-arbitrum})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is sending and network is optimism-arbitrum" + (h/render [quo/transaction-progress + (get-test-data {:state :sending + :network :optimism-arbitrum})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is confirmed and network is optimism-arbitrum" + (h/render [quo/transaction-progress + (get-test-data {:state :confirmed + :network :optimism-arbitrum})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is finalising and network is optimism-arbitrum" + (h/render [quo/transaction-progress + (get-test-data {:state :finalising + :network :optimism-arbitrum})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is finalized and network is optimism-arbitrum" + (h/render [quo/transaction-progress + (get-test-data {:state :finalized + :network :optimism-arbitrum})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is error and network is optimism-arbitrum" + (h/render [quo/transaction-progress + (get-test-data {:state :error + :network :optimism-arbitrum})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is sending and network is optimism" + (h/render [quo/transaction-progress + (get-test-data {:state :sending + :network :optimism})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is confirmed and network is optimism" + (h/render [quo/transaction-progress + (get-test-data {:state :confirmed + :network :optimism})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is finalising and network is optimism" + (h/render [quo/transaction-progress + (get-test-data {:state :finalising + :network :optimism})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is finalized and network is optimism" + (h/render [quo/transaction-progress + (get-test-data {:state :finalized + :network :optimism})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is error and network is optimism" + (h/render [quo/transaction-progress + (get-test-data {:state :error + :network :optimism})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is sending and network is arbitrum" + (h/render [quo/transaction-progress + (get-test-data {:state :sending + :network :arbitrum})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is confirmed and network is arbitrum" + (h/render [quo/transaction-progress + (get-test-data {:state :confirmed + :network :arbitrum})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is finalising and network is arbitrum" + (h/render [quo/transaction-progress + (get-test-data {:state :finalising + :network :arbitrum})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is finalized and network is arbitrum" + (h/render [quo/transaction-progress + (get-test-data {:state :finalized + :network :arbitrum})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is error and network is arbitrum" + (h/render [quo/transaction-progress + (get-test-data {:state :error + :network :arbitrum})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is pending and network is mainnet" + (h/render [quo/transaction-progress (get-test-data {})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is sending and network is mainnet" + (h/render [quo/transaction-progress (get-test-data {:state :sending})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is confirmed and network is mainnet" + (h/render [quo/transaction-progress (get-test-data {:state :confirmed})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is finalising and network is mainnet" + (h/render [quo/transaction-progress (get-test-data {:state :finalising})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is finalized and network is mainnet" + (h/render [quo/transaction-progress (get-test-data {:state :finalized})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "component renders when state is error and network is mainnet" + (h/render [quo/transaction-progress (get-test-data {:state :error})]) + (h/is-truthy (h/get-by-label-text :transaction-progress))) + + (h/test "mainnet progress box is visible network is mainnet" + (h/render [quo/transaction-progress (get-test-data {})]) + (h/is-truthy (h/get-by-label-text :mainnet-progress-box))) + + (h/test "arbitrum-optimism progress box is visible network is optimism-arbitrum" + (h/render [quo/transaction-progress (get-test-data {:network :optimism-arbitrum})]) + (h/is-truthy (h/get-all-by-label-text :progress-box))) + + (h/test "arbitrum progress box is visible network is arbitrum" + (h/render [quo/transaction-progress (get-test-data {:network :arbitrum})]) + (h/is-truthy (h/get-all-by-label-text :progress-box))) + + (h/test "optimism progress box is visible network is optimism" + (h/render [quo/transaction-progress (get-test-data {:network :optimism})]) + (h/is-truthy (h/get-all-by-label-text :progress-box))) + + (h/test "title is visible network is optimism-arbitrum" + (h/render [quo/transaction-progress (get-test-data {:network :optimism-arbitrum})]) + (h/is-truthy (h/get-by-text "Title"))) + + (h/test "title is visible network is mainnet" + (h/render [quo/transaction-progress (get-test-data {})]) + (h/is-truthy (h/get-by-text "Title"))) + + (h/test "title is visible network is optimism" + (h/render [quo/transaction-progress (get-test-data {:network :optimism})]) + (h/is-truthy (h/get-by-text "Title"))) + + (h/test "title is visible network is arbitrum" + (h/render [quo/transaction-progress (get-test-data {:network :arbitrum})]) + (h/is-truthy (h/get-by-text "Title"))) + + (h/test "context tag is visible network is optimism-arbitrum" + (h/render [quo/transaction-progress (get-test-data {:network :optimism-arbitrum})]) + (h/is-truthy (h/get-by-label-text :context-tag))) + + (h/test "context tag is visible network is mainnet" + (h/render [quo/transaction-progress (get-test-data {})]) + (h/is-truthy (h/get-by-label-text :context-tag))) + + (h/test "context tag is visible network is optimism" + (h/render [quo/transaction-progress (get-test-data {:network :optimism})]) + (h/is-truthy (h/get-by-label-text :context-tag))) + + (h/test "context tag is visible network is optimism" + (h/render [quo/transaction-progress (get-test-data {:network :arbitrum})]) + (h/is-truthy (h/get-by-label-text :context-tag)))) diff --git a/src/quo/components/wallet/transaction_progress/style.cljs b/src/quo/components/wallet/transaction_progress/style.cljs new file mode 100644 index 00000000000..dd6c07c55b2 --- /dev/null +++ b/src/quo/components/wallet/transaction_progress/style.cljs @@ -0,0 +1,38 @@ +(ns quo.components.wallet.transaction-progress.style + (:require [quo.foundations.colors :as colors])) + +(def title-text-container + {:flex 1}) + +(def icon + {:margin-right 4}) + +(defn box-style + [theme] + {:border-radius 16 + :border-width 1 + :border-color (colors/theme-colors colors/neutral-10 colors/neutral-80 theme)}) + +(def title-container + {:align-items :center + :flex-direction :row + :padding-left 12 + :padding-top 8 + :padding-right 8 + :padding-bottom 4}) + +(def status-row-container + {:flex-direction :row + :align-items :center + :flex 1 + :padding-horizontal 12 + :padding-top 8 + :padding-bottom 4}) + +(defn context-tag-container + [theme] + {:padding-horizontal 12 + :padding-bottom 8 + :flex-direction :row + :border-bottom-width 1 + :border-color (colors/theme-colors colors/neutral-10 colors/neutral-80 theme)}) diff --git a/src/quo/components/wallet/transaction_progress/view.cljs b/src/quo/components/wallet/transaction_progress/view.cljs new file mode 100644 index 00000000000..2f6048b3788 --- /dev/null +++ b/src/quo/components/wallet/transaction_progress/view.cljs @@ -0,0 +1,187 @@ +(ns quo.components.wallet.transaction-progress.view + (:require [quo.components.buttons.button.view :as button] + [quo.components.icon :as icons] + [quo.components.markdown.text :as text] + [quo.components.tags.context-tag.view :as context-tag] + [quo.components.wallet.confirmation-progress.view :as confirmation-progress] + [quo.components.wallet.transaction-progress.style :as style] + [quo.foundations.colors :as colors] + [quo.theme :as quo.theme] + [react-native.core :as rn] + [utils.i18n :as i18n])) + +(def ^:private max-mainnet-verifications 4) +(def ^:private max-sidenet-verifications 1) + +(defn- icon-internal + ([icon] + (icon-internal icon nil 20)) + ([icon color] + (icon-internal icon color 20)) + ([icon color size] + [rn/view {:style style/icon} + [icons/icon + icon + {:color color + :size size + :no-color (when (not color) true)}]])) + +(defn- text-internal + [{:keys [weight size accessibility-label color] + :or {weight :semi-bold + size :paragraph-1}} + title] + [text/text + {:accessibility-label accessibility-label + :ellipsize-mode :tail + :number-of-lines 1 + :weight weight + :size size + :style {:color color}} + title]) + +(defn- network-type-text + [state] + (case state + (:sending :pending) (i18n/label :t/pending-on) + (:confirmed :finalising) (i18n/label :t/confirmed-on) + :finalized (i18n/label :t/finalized-on) + :error (i18n/label :t/failed-on) + nil)) + +(defn- calculate-counter + [counter] + (if (< counter 4) counter max-mainnet-verifications)) + +(defn mainnet-label + [counter] + (str counter "/" max-mainnet-verifications)) + +(defn subnet-label + [counter] + (str counter "/" max-sidenet-verifications)) + +(defn- text-steps + [network state epoch-number counter] + (let [steps (case network + :mainnet + {:pending (mainnet-label 0) + :sending (mainnet-label (calculate-counter counter)) + :confirmed (mainnet-label (calculate-counter counter)) + :finalising (mainnet-label (calculate-counter counter)) + :finalized (i18n/label :t/epoch-number {:number epoch-number}) + :error (mainnet-label 0)} + (or :optimism :arbitrum) + {:pending (subnet-label 0) + :sending (subnet-label 0) + :confirmed (subnet-label 0) + :finalising (subnet-label 1) + :finalized (i18n/label :t/epoch-number {:number epoch-number}) + :error (subnet-label 0)} + nil)] + (get steps state))) + +(defn- get-status-icon + [theme state] + (case state + (:pending :sending) {:icon :i/pending-state + :color (colors/theme-colors colors/neutral-50 + colors/neutral-40 + theme)} + (:confirmed :finalising) {:icon :i/positive-state + :color (colors/resolve-color :success theme)} + :finalized {:icon :i/diamond} + :error {:icon :i/negative-state + :color (colors/resolve-color :danger theme)} + nil)) + +(defn- get-network + [networks network] + (some #(when (= (:network %) network) %) + networks)) + +(defn- calculate-error-state + [networks] + (some #(= (:state %) :error) networks)) + +(defn- title-internal + [{:keys [title theme networks]}] + [rn/view {:style style/title-container} + [icon-internal :i/placeholder (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)] + [rn/view {:style style/title-text-container} + [text-internal nil title]] + (when (calculate-error-state networks) + [button/button + {:size 24 + :icon-left :i/refresh} + (i18n/label :t/retry)])]) + +(defn- tag-internal + [tag-photo tag-name tag-number theme] + [rn/view {:style (style/context-tag-container theme)} + [context-tag/view + {:size 24 + :collectible tag-photo + :collectible-name tag-name + :collectible-number tag-number + :type :collectible}]]) + +(defn- get-network-text + [network] + (case network + :arbitrum (i18n/label :t/arbitrum) + :mainnet (i18n/label :t/mainnet) + :optimism (i18n/label :t/optimism) + nil)) + +(defn- status-row + [{:keys [theme state network epoch-number counter]}] + (let [{:keys [icon color]} (get-status-icon theme state)] + [rn/view {:style style/status-row-container} + [icon-internal icon color 16] + [rn/view {:style style/title-text-container} + [text-internal + {:weight :regular + :size :paragraph-2} + (str (network-type-text state) " " (get-network-text network))]] + [rn/view + [text-internal + {:weight :regular + :size :paragraph-2 + :color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)} + (text-steps network state epoch-number counter)]]])) + +(defn- view-network + [{:keys [theme state epoch-number counter total-box progress network]}] + [:<> + [status-row + {:theme theme + :state state + :network network + :epoch-number epoch-number + :counter counter}] + [confirmation-progress/view + {:state state + :network network + :counter counter + :total-box total-box + :progress-value progress}]]) + +(defn- view-internal + [{:keys [title on-press accessibility-label theme tag-photo tag-name tag-number networks] + :or {accessibility-label :transaction-progress}}] + [rn/touchable-without-feedback + {:on-press on-press + :accessibility-label accessibility-label} + [rn/view {:style (style/box-style theme)} + [title-internal + {:title title + :theme theme + :networks networks}] + [tag-internal tag-photo tag-name tag-number theme] + (for [network networks] + ^{:key (:network network)} + (let [assoc-props #(get-network networks %)] + [view-network (assoc-props (:network network))]))]]) + +(def view (quo.theme/with-theme view-internal)) diff --git a/src/quo/core.cljs b/src/quo/core.cljs index a72ea57ac77..85e39309877 100644 --- a/src/quo/core.cljs +++ b/src/quo/core.cljs @@ -146,6 +146,7 @@ quo.components.wallet.account-origin.view quo.components.wallet.account-overview.view quo.components.wallet.address-text.view + quo.components.wallet.confirmation-progress.view quo.components.wallet.keypair.view quo.components.wallet.network-amount.view quo.components.wallet.network-bridge.view @@ -154,6 +155,7 @@ quo.components.wallet.progress-bar.view quo.components.wallet.summary-info.view quo.components.wallet.token-input.view + quo.components.wallet.transaction-progress.view quo.components.wallet.transaction-summary.view quo.components.wallet.wallet-activity.view quo.components.wallet.wallet-overview.view)) @@ -389,6 +391,7 @@ (def account-origin quo.components.wallet.account-origin.view/view) (def account-overview quo.components.wallet.account-overview.view/view) (def address-text quo.components.wallet.address-text.view/view) +(def confirmation-propgress quo.components.wallet.confirmation-progress.view/view) (def keypair quo.components.wallet.keypair.view/view) (def network-amount quo.components.wallet.network-amount.view/view) (def network-bridge quo.components.wallet.network-bridge.view/view) @@ -399,4 +402,5 @@ (def token-input quo.components.wallet.token-input.view/view) (def wallet-overview quo.components.wallet.wallet-overview.view/view) (def wallet-activity quo.components.wallet.wallet-activity.view/view) +(def transaction-progress quo.components.wallet.transaction-progress.view/view) (def transaction-summary quo.components.wallet.transaction-summary.view/view) diff --git a/src/quo/core_spec.cljs b/src/quo/core_spec.cljs index d642ebfc3cf..a7ab024cf4a 100644 --- a/src/quo/core_spec.cljs +++ b/src/quo/core_spec.cljs @@ -80,6 +80,7 @@ [quo.components.wallet.account-card.component-spec] [quo.components.wallet.account-origin.component-spec] [quo.components.wallet.account-overview.component-spec] + [quo.components.wallet.confirmation-progress.component-spec] [quo.components.wallet.keypair.component-spec] [quo.components.wallet.network-amount.component-spec] [quo.components.wallet.network-bridge.component-spec] @@ -87,6 +88,7 @@ [quo.components.wallet.progress-bar.component-spec] [quo.components.wallet.summary-info.component-spec] [quo.components.wallet.token-input.component-spec] + [quo.components.wallet.transaction-progress.component-spec] [quo.components.wallet.transaction-summary.component-spec] [quo.components.wallet.wallet-activity.component-spec] [quo.components.wallet.wallet-overview.component-spec])) diff --git a/src/status_im2/contexts/quo_preview/main.cljs b/src/status_im2/contexts/quo_preview/main.cljs index 3a9406f7e7a..c9754bc8d00 100644 --- a/src/status_im2/contexts/quo_preview/main.cljs +++ b/src/status_im2/contexts/quo_preview/main.cljs @@ -170,6 +170,7 @@ [status-im2.contexts.quo-preview.wallet.account-origin :as account-origin] [status-im2.contexts.quo-preview.wallet.account-overview :as account-overview] + [status-im2.contexts.quo-preview.wallet.confirmation-progress :as confirmation-progress] [status-im2.contexts.quo-preview.wallet.keypair :as keypair] [status-im2.contexts.quo-preview.wallet.network-amount :as network-amount] [status-im2.contexts.quo-preview.wallet.network-bridge :as network-bridge] @@ -178,6 +179,7 @@ [status-im2.contexts.quo-preview.wallet.progress-bar :as progress-bar] [status-im2.contexts.quo-preview.wallet.summary-info :as summary-info] [status-im2.contexts.quo-preview.wallet.token-input :as token-input] + [status-im2.contexts.quo-preview.wallet.transaction-progress :as transaction-progress] [status-im2.contexts.quo-preview.wallet.transaction-summary :as transaction-summary] [status-im2.contexts.quo-preview.wallet.wallet-activity :as wallet-activity] @@ -464,6 +466,8 @@ {:name :account-origin :component account-origin/view} {:name :account-overview :component account-overview/view} + {:name :confirmation-progress + :component confirmation-progress/view} {:name :keypair :component keypair/view} {:name :network-amount :component network-amount/view} {:name :network-bridge :component network-bridge/view} @@ -473,6 +477,7 @@ {:name :summary-info :component summary-info/view} {:name :token-input :component token-input/view} {:name :wallet-activity :component wallet-activity/view} + {:name :transaction-progress :component transaction-progress/view} {:name :transaction-summary :component transaction-summary/view} {:name :wallet-overview :component wallet-overview/view}] diff --git a/src/status_im2/contexts/quo_preview/wallet/confirmation_progress.cljs b/src/status_im2/contexts/quo_preview/wallet/confirmation_progress.cljs new file mode 100644 index 00000000000..5a5a99f7a31 --- /dev/null +++ b/src/status_im2/contexts/quo_preview/wallet/confirmation_progress.cljs @@ -0,0 +1,85 @@ +(ns status-im2.contexts.quo-preview.wallet.confirmation-progress + (:require + [quo.core :as quo] + [react-native.core :as rn] + [reagent.core :as reagent] + [status-im2.contexts.quo-preview.preview :as preview])) + +(def descriptor + [{:type :text + :key :progress-value} + {:type :select + :key :network + :options [{:key :mainnet} + {:key :optimism} + {:key :arbitrum}]} + {:type :select + :key :state + :options [{:key :pending} + {:key :sending} + {:key :confirmed} + {:key :finalising} + {:key :finalized} + {:key :error}]} + (preview/customization-color-option)]) + +(def total-box 85) +(def counter (reagent/atom 0)) +(def interval-id (reagent/atom nil)) +(def interval-ms 50) + +(defn- stop-interval + [] + (when @interval-id + (js/clearInterval @interval-id) + (reset! interval-id nil))) + +(defn- clear-counter + [] + (reset! counter 0)) + +(defn- update-counter + [state] + (let [new-counter-value (inc @counter)] + (if (or (and (= state :pending) (> new-counter-value 0)) + (and (= state :sending) (> new-counter-value 2)) + (and (= state :confirmed) (> new-counter-value 4)) + (and (= state :finalising) (> new-counter-value 18)) + (and (= state :finalized) (> new-counter-value total-box)) + (and (= state :error) (> new-counter-value 2))) + (stop-interval) + (reset! counter new-counter-value)))) + +(defn- start-interval + [state] + (reset! interval-id + (js/setInterval + (fn [] + (update-counter state)) + interval-ms))) + +(defn- f-view + [state] + (fn [] + (rn/use-effect + (fn [] + (start-interval (:state @state)) + (clear-counter) + (fn [] + (stop-interval))) + [(:state @state)]) + [preview/preview-container {:state state :descriptor descriptor} + [quo/confirmation-propgress + (assoc @state + :counter + @counter)]])) + +(defn view + [] + (let [state (reagent/atom + {:total-box total-box + :progress-value "10" + :network :mainnet + :state :pending + :customization-color :blue})] + [:f> f-view state])) diff --git a/src/status_im2/contexts/quo_preview/wallet/progress_bar.cljs b/src/status_im2/contexts/quo_preview/wallet/progress_bar.cljs index d9b4f2cad84..eec0741ed49 100644 --- a/src/status_im2/contexts/quo_preview/wallet/progress_bar.cljs +++ b/src/status_im2/contexts/quo_preview/wallet/progress_bar.cljs @@ -1,6 +1,7 @@ (ns status-im2.contexts.quo-preview.wallet.progress-bar (:require [quo.core :as quo] + [react-native.core :as rn] [reagent.core :as reagent] [status-im2.contexts.quo-preview.preview :as preview])) @@ -11,11 +12,17 @@ {:key :confirmed} {:key :finalized} {:key :error}]} + {:key :full-width? + :type :boolean} + {:key :progressed-value + :type :text} (preview/customization-color-option)]) (defn view [] (let [state (reagent/atom {:state :pending + :full-width? false + :progressed-value "10" :customization-color :blue})] (fn [] [preview/preview-container @@ -23,4 +30,5 @@ :descriptor descriptor :component-container-style {:padding-top 40 :align-items :center}} - [quo/progress-bar @state]]))) + [rn/view {:style {:flex-direction :row}} + [quo/progress-bar @state]]]))) diff --git a/src/status_im2/contexts/quo_preview/wallet/transaction_progress.cljs b/src/status_im2/contexts/quo_preview/wallet/transaction_progress.cljs new file mode 100644 index 00000000000..ad66ad41977 --- /dev/null +++ b/src/status_im2/contexts/quo_preview/wallet/transaction_progress.cljs @@ -0,0 +1,155 @@ +(ns status-im2.contexts.quo-preview.wallet.transaction-progress + (:require + [quo.core :as quo] + [react-native.core :as rn] + [reagent.core :as reagent] + [status-im2.common.resources :as resources] + [status-im2.contexts.quo-preview.preview :as preview])) + +(def descriptor + [{:type :text + :key :title} + {:type :text + :key :tag-name} + {:type :text + :key :epoch-number-mainnet} + {:type :text + :key :epoch-number-optimism} + {:type :text + :key :epoch-number-arbitrum} + {:type :text + :key :tag-number} + {:type :text + :key :optimism-progress-percentage} + {:type :text + :key :arbitrum-progress-percentage} + {:type :select + :key :network + :options [{:key :mainnet} + {:key :optimism} + {:key :arbitrum} + {:key :optimism-arbitrum}]} + {:type :select + :key :state-mainnet + :options [{:key :pending} + {:key :sending} + {:key :confirmed} + {:key :finalising} + {:key :finalized} + {:key :error}]} + {:type :select + :key :state-optimism + :options [{:key :pending} + {:key :sending} + {:key :confirmed} + {:key :finalising} + {:key :finalized} + {:key :error}]} + {:type :select + :key :state-arbitrum + :options [{:key :pending} + {:key :sending} + {:key :confirmed} + {:key :finalising} + {:key :finalized} + {:key :error}]} + (preview/customization-color-option)]) + +(def total-box 85) +(def counter (reagent/atom 0)) +(def interval-id (reagent/atom nil)) +(def interval-ms 50) + +(defn- stop-interval + [] + (when @interval-id + (js/clearInterval @interval-id) + (reset! interval-id nil))) + +(defn- clear-counter + [] + (reset! counter 0)) + +(defn- update-counter + [state] + (let [new-counter-value (inc @counter)] + (if (or (and (= state :pending) (> new-counter-value 0)) + (and (= state :sending) (> new-counter-value 2)) + (and (= state :confirmed) (> new-counter-value 4)) + (and (= state :finalising) (> new-counter-value 18)) + (and (= state :finalized) (> new-counter-value total-box)) + (and (= state :error) (> new-counter-value 2))) + (stop-interval) + (reset! counter new-counter-value)))) + +(defn- start-interval + [state] + (reset! interval-id + (js/setInterval + (fn [] + (update-counter state)) + interval-ms))) + +(defn- get-networks + [state] + (case (:network state) + :mainnet [{:network :mainnet + :state (:state-mainnet state) + :counter @counter + :total-box total-box + :epoch-number (:epoch-number-mainnet state)}] + :optimism [{:network :optimism + :state (:state-optimism state) + :progress (:optimism-progress-percentage state) + :epoch-number (:epoch-number-optimism state)}] + :arbitrum [{:network :arbitrum + :state (:state-arbitrum state) + :progress (:arbitrum-progress-percentage state) + :epoch-number (:epoch-number-arbitrum state)}] + :optimism-arbitrum [{:network :optimism + :state (:state-optimism state) + :progress (:optimism-progress-percentage state) + :epoch-number (:epoch-number-optimism state)} + {:network :arbitrum + :state (:state-arbitrum state) + :progress (:arbitrum-progress-percentage state) + :epoch-number (:epoch-number-arbitrum state)}])) + +(defn- f-view + [state] + (fn [] + (rn/use-effect + (fn [] + (start-interval (:state-mainnet @state)) + (clear-counter) + (fn [] + (stop-interval))) + [(:state-mainnet @state)]) + [preview/preview-container {:state state :descriptor descriptor} + [quo/transaction-progress + (assoc @state + :networks + (get-networks @state))]])) + +(defn view + [] + (let [state (reagent/atom + {:title "Title" + :counter 40 + :total-box total-box + :tag-name "Doodle" + :tag-number "120" + :epoch-number-mainnet "181,329" + :epoch-number-optimism "181,329" + :epoch-number-arbitrum "181,329" + :optimism-progress-percentage "10" + :arbitrum-progress-percentage "10" + :network :mainnet + :state-mainnet :pending + :state-arbitrum :pending + :state-optimism :pending + :customization-color :blue + :tag-photo (resources/get-mock-image :collectible) + :on-press (fn [] + (js/alert "Transaction progress item pressed"))})] + [:f> f-view state])) diff --git a/translations/en.json b/translations/en.json index 2f86b33ba30..8dd205bff4c 100644 --- a/translations/en.json +++ b/translations/en.json @@ -2389,6 +2389,13 @@ "keypairs": "Keypairs", "keypairs-description": "Select keypair to derive your new account from", "confirm-account-origin": "Confirm account origin", + "confirmed-on": "Confirmed on", + "pending-on": "Pending on", + "finalized-on": "Finalized on", + "failed-on": "Failed on", + "epoch-number": "Epoch {{number}}", + "arbitrum": "Arbitrum", + "optimism": "Optimism", "address-placeholder": "0x123abc... or bob.eth", "invalid-address": "It’s not Ethereum address or ENS name", "address-already-in-use": "Address already being used", From ab61d8d5c05e00a5e1b3c64e78232b4f789bcc91 Mon Sep 17 00:00:00 2001 From: Omar Basem Date: Wed, 6 Dec 2023 16:02:53 +0400 Subject: [PATCH 02/12] Wallet: Set color and emoji (#17906) * wallet: set color and emoji --- src/status_im2/contexts/profile/create/events.cljs | 4 +++- src/status_im2/contexts/profile/recover/events.cljs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/status_im2/contexts/profile/create/events.cljs b/src/status_im2/contexts/profile/create/events.cljs index d23026da8d2..2405b16b8cb 100644 --- a/src/status_im2/contexts/profile/create/events.cljs +++ b/src/status_im2/contexts/profile/create/events.cljs @@ -1,6 +1,7 @@ (ns status-im2.contexts.profile.create.events (:require [native-module.core :as native-module] + [status-im2.contexts.emoji-picker.utils :as emoji-picker.utils] [status-im2.contexts.profile.config :as profile.config] status-im2.contexts.profile.create.effects [utils.re-frame :as rf] @@ -14,4 +15,5 @@ :displayName display-name :password (native-module/sha3 (security/safe-unmask-data password)) :imagePath (profile.config/strip-file-prefix image-path) - :customizationColor color)}) + :customizationColor color + :emoji (emoji-picker.utils/random-emoji))}) diff --git a/src/status_im2/contexts/profile/recover/events.cljs b/src/status_im2/contexts/profile/recover/events.cljs index ff8b295f8cb..95aa7300e44 100644 --- a/src/status_im2/contexts/profile/recover/events.cljs +++ b/src/status_im2/contexts/profile/recover/events.cljs @@ -1,6 +1,7 @@ (ns status-im2.contexts.profile.recover.events (:require [native-module.core :as native-module] + [status-im2.contexts.emoji-picker.utils :as emoji-picker.utils] [status-im2.contexts.profile.config :as profile.config] status-im2.contexts.profile.recover.effects [utils.re-frame :as rf] @@ -18,4 +19,5 @@ :mnemonic (security/safe-unmask-data seed-phrase) :password (native-module/sha3 (security/safe-unmask-data password)) :imagePath (profile.config/strip-file-prefix image-path) - :customizationColor color})}) + :customizationColor color + :emoji (emoji-picker.utils/random-emoji)})}) From 195f0cfa407ad023969f3a6859b06c4051e1f038 Mon Sep 17 00:00:00 2001 From: Roman Volosovskyi Date: Wed, 6 Dec 2023 10:49:50 +0100 Subject: [PATCH 03/12] Mark mnemonic as shown on revealing it to the user --- src/status_im/ui/screens/profile/seed/views.cljs | 3 ++- src/status_im2/contexts/profile/settings/events.cljs | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/status_im/ui/screens/profile/seed/views.cljs b/src/status_im/ui/screens/profile/seed/views.cljs index 736aaf7fc0e..5ac136bbc16 100644 --- a/src/status_im/ui/screens/profile/seed/views.cljs +++ b/src/status_im/ui/screens/profile/seed/views.cljs @@ -46,7 +46,8 @@ :key :your-data-belongs-to-you-description}] [react/view {:style styles/intro-button} [quo/button - {:on-press #(re-frame/dispatch [:set-in [:my-profile/seed :step] :12-words])} + {:on-press #(do (re-frame/dispatch [:set-in [:my-profile/seed :step] :12-words]) + (re-frame/dispatch [:profile.settings/mnemonic-was-shown]))} (i18n/label :t/ok-continue)]]]) (defn six-words diff --git a/src/status_im2/contexts/profile/settings/events.cljs b/src/status_im2/contexts/profile/settings/events.cljs index eaa5f02e20e..b00da569722 100644 --- a/src/status_im2/contexts/profile/settings/events.cljs +++ b/src/status_im2/contexts/profile/settings/events.cljs @@ -138,3 +138,10 @@ {:events [:profile.settings/update-local-picture]} [cofx pics] (optimistic-profile-update cofx :images pics)) + +(rf/defn mark-mnemonic-as-shown + {:events [:profile.settings/mnemonic-was-shown]} + [cofx] + {:json-rpc/call [{:method "settings_mnemonicWasShown" + :on-success #(log/debug "mnemonic was marked as shown") + :on-error #(log/error "mnemonic was not marked as shown" %)}]}) From 4376ee8908a8b63d9902b3f08136f63db7aa1661 Mon Sep 17 00:00:00 2001 From: Yevheniia Berdnyk Date: Wed, 6 Dec 2023 16:57:31 +0200 Subject: [PATCH 04/12] e2e: disabled checks because of issues with restored contacts and channel links --- .../critical/chats/test_public_chat_browsing.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/test/appium/tests/critical/chats/test_public_chat_browsing.py b/test/appium/tests/critical/chats/test_public_chat_browsing.py index 61b1dc16240..0eb18940c46 100644 --- a/test/appium/tests/critical/chats/test_public_chat_browsing.py +++ b/test/appium/tests/critical/chats/test_public_chat_browsing.py @@ -197,13 +197,13 @@ def test_restore_multiaccount_with_waku_backup_remove_switch(self): self.home.chats_tab.click() self.home.contacts_tab.click() contacts_number = self.home.get_contact_rows_count() - if contacts_number != len(waku_user.contacts): - self.errors.append( - "Incorrect contacts number restored: %s instead of %s" % (contacts_number, len(waku_user.contacts))) - else: - for contact in waku_user.contacts: - if not self.home.element_by_text(contact).is_element_displayed(30): - self.errors.append('%s was not restored as a contact from waku backup!' % contact) + # Todo: enable when https://github.com/status-im/status-mobile/issues/18096 is fixed + # if contacts_number != len(waku_user.contacts): + # self.errors.append( + # "Incorrect contacts number restored: %s instead of %s" % (contacts_number, len(waku_user.contacts))) + for contact in waku_user.contacts: + if not self.home.element_by_text(contact).is_element_displayed(30): + self.errors.append('%s was not restored as a contact from waku backup!' % contact) # Disabled for simple check as sometimes from waku-backup users restored with 3-random names # self.home.click_system_back_button_until_element_is_shown() # contact_row = self.home.contact_details_row(index=i + 1) @@ -967,6 +967,8 @@ def test_community_leave(self): self.errors.verify_no_errors() @marks.testrail_id(702948) + @marks.xfail( + reason="Can't navigate to a channel by hashtag link, https://github.com/status-im/status-mobile/issues/18095") def test_community_hashtag_links_to_community_channels(self): for home in self.homes: home.navigate_back_to_home_view() From 2bc7b6232419de74eb278cce954e4a7b79db3f51 Mon Sep 17 00:00:00 2001 From: Flavio Fraschetti Date: Wed, 6 Dec 2023 13:21:17 -0300 Subject: [PATCH 05/12] Communities - Display community rules at request to join (#18082) This update introduces a feature that displays community rules to users as they join. --- src/status_im/communities/core.cljs | 1 + .../actions/accounts_selection/view.cljs | 8 ++++++++ .../actions/community_rules/style.cljs | 10 ++++++++++ .../actions/community_rules/view.cljs | 16 ++++++++++++++++ src/status_im2/subs/communities.cljs | 6 ++++++ 5 files changed, 41 insertions(+) create mode 100644 src/status_im2/contexts/communities/actions/community_rules/style.cljs create mode 100644 src/status_im2/contexts/communities/actions/community_rules/view.cljs diff --git a/src/status_im/communities/core.cljs b/src/status_im/communities/core.cljs index 8574a117508..4a47ffc3c07 100644 --- a/src/status_im/communities/core.cljs +++ b/src/status_im/communities/core.cljs @@ -74,6 +74,7 @@ :adminSettings :admin-settings :tokenPermissions :token-permissions :communityTokensMetadata :tokens-metadata + :introMessage :intro-message :muteTill :muted-till}) (update :admin-settings set/rename-keys diff --git a/src/status_im2/contexts/communities/actions/accounts_selection/view.cljs b/src/status_im2/contexts/communities/actions/accounts_selection/view.cljs index cc50dbb1ea6..b80d51363f8 100644 --- a/src/status_im2/contexts/communities/actions/accounts_selection/view.cljs +++ b/src/status_im2/contexts/communities/actions/accounts_selection/view.cljs @@ -4,6 +4,7 @@ [react-native.core :as rn] [react-native.gesture :as gesture] [status-im2.common.password-authentication.view :as password-authentication] + [status-im2.contexts.communities.actions.community-rules.view :as community-rules] [status-im2.contexts.communities.actions.request-to-join.style :as style] [utils.i18n :as i18n] [utils.re-frame :as rf])) @@ -26,6 +27,13 @@ [rn/view {:flex 1} [gesture/scroll-view {:style {:flex 1}} [rn/view style/page-container + [quo/text + {:style {:margin-top 24} + :accessibility-label :community-rules-title + :weight :semi-bold + :size :paragraph-1} + (i18n/label :t/community-rules)] + [community-rules/view id] [rn/view {:style (style/bottom-container)} [quo/button {:accessibility-label :cancel diff --git a/src/status_im2/contexts/communities/actions/community_rules/style.cljs b/src/status_im2/contexts/communities/actions/community_rules/style.cljs new file mode 100644 index 00000000000..37d85fb9475 --- /dev/null +++ b/src/status_im2/contexts/communities/actions/community_rules/style.cljs @@ -0,0 +1,10 @@ +(ns status-im2.contexts.communities.actions.community-rules.style) + +(def community-rule + {:flex 1 + :align-items :flex-start + :margin-top 16}) + +(def community-rule-text + {:margin-left 6 + :flex 1}) diff --git a/src/status_im2/contexts/communities/actions/community_rules/view.cljs b/src/status_im2/contexts/communities/actions/community_rules/view.cljs new file mode 100644 index 00000000000..f682d792037 --- /dev/null +++ b/src/status_im2/contexts/communities/actions/community_rules/view.cljs @@ -0,0 +1,16 @@ +(ns status-im2.contexts.communities.actions.community-rules.view + (:require + [quo.core :as quo] + [react-native.core :as rn] + [status-im2.contexts.communities.actions.community-rules.style :as style] + [utils.re-frame :as rf])) + +(defn view + [id] + (let [rules (rf/sub [:communities/rules id])] + [rn/view {:style style/community-rule} + [quo/text + {:style style/community-rule-text + :weight :regular + :size :paragraph-2} + rules]])) diff --git a/src/status_im2/subs/communities.cljs b/src/status_im2/subs/communities.cljs index d0f8a9c250a..0fc4ab22ce5 100644 --- a/src/status_im2/subs/communities.cljs +++ b/src/status_im2/subs/communities.cljs @@ -329,3 +329,9 @@ :<- [:communities] (fn [communities [_ id]] (get-in communities [id :images]))) + +(re-frame/reg-sub + :communities/rules + :<- [:communities] + (fn [communities [_ community-id]] + (get-in communities [community-id :intro-message]))) From 390bbdb6ec27473f1197ba842a8592674487f21a Mon Sep 17 00:00:00 2001 From: Icaro Motta Date: Wed, 6 Dec 2023 13:39:47 -0300 Subject: [PATCH 06/12] Add missing clj-kondo linter for nubank/matcher-combinators (#18091) --- .clj-kondo/config.edn | 10 +--------- .clj-kondo/nubank/matcher-combinators/config.edn | 4 ++++ 2 files changed, 5 insertions(+), 9 deletions(-) create mode 100644 .clj-kondo/nubank/matcher-combinators/config.edn diff --git a/.clj-kondo/config.edn b/.clj-kondo/config.edn index fa20942ef3e..498e1192046 100644 --- a/.clj-kondo/config.edn +++ b/.clj-kondo/config.edn @@ -62,15 +62,7 @@ ;; https://github.com/borkdude/clj-kondo/issues/867 :unresolved-symbol {:exclude [PersistentPriorityMap.EMPTY number - status-im.test-helpers/restore-app-db - - ;; When the namespace - ;; matcher-combinators.test is loaded, it - ;; extends cljs.test/is macro with - ;; directives `match?` and - ;; `thrown-match?`. - match? - thrown-match?]} + status-im.test-helpers/restore-app-db]} :unresolved-var {:level :error} :unsorted-required-namespaces {:level :error} :unused-alias {:level :warning} diff --git a/.clj-kondo/nubank/matcher-combinators/config.edn b/.clj-kondo/nubank/matcher-combinators/config.edn new file mode 100644 index 00000000000..ea4ded7232f --- /dev/null +++ b/.clj-kondo/nubank/matcher-combinators/config.edn @@ -0,0 +1,4 @@ +{:linters + {:unresolved-symbol + {:exclude [(cljs.test/is [match? thrown-match?]) + (clojure.test/is [match? thrown-match?])]}}} From 03444ae4ffd48eee53f519970bbbbd22d793f26e Mon Sep 17 00:00:00 2001 From: Icaro Motta Date: Wed, 6 Dec 2023 18:10:47 -0300 Subject: [PATCH 07/12] Request to join screen - show modal title and community context tag (#18077) --- .../actions/accounts_selection/style.cljs | 27 +++++++ .../actions/accounts_selection/view.cljs | 71 +++++++++++-------- .../contexts/communities/overview/view.cljs | 4 +- translations/en.json | 3 +- 4 files changed, 74 insertions(+), 31 deletions(-) create mode 100644 src/status_im2/contexts/communities/actions/accounts_selection/style.cljs diff --git a/src/status_im2/contexts/communities/actions/accounts_selection/style.cljs b/src/status_im2/contexts/communities/actions/accounts_selection/style.cljs new file mode 100644 index 00000000000..eb94b4cc4ed --- /dev/null +++ b/src/status_im2/contexts/communities/actions/accounts_selection/style.cljs @@ -0,0 +1,27 @@ +(ns status-im2.contexts.communities.actions.accounts-selection.style + (:require + [quo.foundations.colors :as colors])) + +(def screen-horizontal-padding 20) + +(def container + {:flex 1}) + +(def page-top + {:padding-vertical 12 + :padding-horizontal screen-horizontal-padding}) + +(def content + {:margin-bottom 20 + :padding-horizontal screen-horizontal-padding}) + +(defn bottom-actions + [] + {:position :absolute + :background-color (colors/theme-colors colors/white colors/neutral-95) + :bottom 0 + :left 0 + :right 0 + :padding-horizontal screen-horizontal-padding + :padding-vertical 12 + :flex 1}) diff --git a/src/status_im2/contexts/communities/actions/accounts_selection/view.cljs b/src/status_im2/contexts/communities/actions/accounts_selection/view.cljs index b80d51363f8..9aa83f297d0 100644 --- a/src/status_im2/contexts/communities/actions/accounts_selection/view.cljs +++ b/src/status_im2/contexts/communities/actions/accounts_selection/view.cljs @@ -4,12 +4,12 @@ [react-native.core :as rn] [react-native.gesture :as gesture] [status-im2.common.password-authentication.view :as password-authentication] + [status-im2.contexts.communities.actions.accounts-selection.style :as style] [status-im2.contexts.communities.actions.community-rules.view :as community-rules] - [status-im2.contexts.communities.actions.request-to-join.style :as style] [utils.i18n :as i18n] [utils.re-frame :as rf])) -(defn join-community-and-navigate-back +(defn- join-community-and-navigate-back [id] (rf/dispatch [:password-authentication/show {:content (fn [] [password-authentication/view])} @@ -18,31 +18,46 @@ {:community-id id :password %}])}]) (rf/dispatch [:navigate-back])) +(defn- page-top + [{:keys [community-name logo-uri]}] + [rn/view {:style style/page-top} + [quo/text + {:size :heading-1 + :weight :semi-bold} + (i18n/label :t/request-to-join)] + [quo/context-tag + {:type :community + :size 24 + :community-logo logo-uri + :community-name community-name + :container-style {:margin-top 8}}]]) + (defn view [] - (fn [] - (let [{:keys [_name - id - _images]} (rf/sub [:get-screen-params])] - [rn/view {:flex 1} - [gesture/scroll-view {:style {:flex 1}} - [rn/view style/page-container - [quo/text - {:style {:margin-top 24} - :accessibility-label :community-rules-title - :weight :semi-bold - :size :paragraph-1} - (i18n/label :t/community-rules)] - [community-rules/view id] - [rn/view {:style (style/bottom-container)} - [quo/button - {:accessibility-label :cancel - :on-press #(rf/dispatch [:navigate-back]) - :type :grey - :container-style style/cancel-button} - (i18n/label :t/cancel)] - [quo/button - {:accessibility-label :join-community-button - :on-press #(join-community-and-navigate-back id) - :container-style {:flex 1}} - (i18n/label :t/request-to-join)]]]]]))) + (let [{id :community-id} (rf/sub [:get-screen-params]) + {:keys [name color images]} (rf/sub [:communities/community id])] + [rn/view {:style style/container} + [quo/page-nav + {:text-align :left + :icon-name :i/close + :on-press #(rf/dispatch [:navigate-back]) + :accessibility-label :back-button}] + [page-top + {:community-name name + :logo-uri (get-in images [:thumbnail :uri])}] + [gesture/scroll-view + [rn/view {:style style/content} + [quo/text + {:style {:margin-top 24} + :accessibility-label :community-rules-title + :weight :semi-bold + :size :paragraph-1} + (i18n/label :t/community-rules)] + [community-rules/view id]]] + [rn/view {:style (style/bottom-actions)} + [quo/slide-button + {:size :size-48 + :track-text (i18n/label :t/slide-to-request-to-join) + :track-icon :i/face-id + :customization-color color + :on-complete #(join-community-and-navigate-back id)}]]])) diff --git a/src/status_im2/contexts/communities/overview/view.cljs b/src/status_im2/contexts/communities/overview/view.cljs index 0bc3c40eb5b..626c92ab15f 100644 --- a/src/status_im2/contexts/communities/overview/view.cljs +++ b/src/status_im2/contexts/communities/overview/view.cljs @@ -173,7 +173,7 @@ (i18n/label :t/join-open-community)]]))) (defn join-community - [{:keys [joined color permissions token-permissions] :as community} + [{:keys [joined color permissions token-permissions id] :as community} pending?] (let [access-type (get-access-type (:access permissions)) unknown-access? (= access-type :unknown-access) @@ -185,7 +185,7 @@ [quo/button {:on-press (if config/community-accounts-selection-enabled? - #(rf/dispatch [:open-modal :community-account-selection community]) + #(rf/dispatch [:open-modal :community-account-selection {:community-id id}]) #(rf/dispatch [:open-modal :community-requests-to-join community])) :accessibility-label :show-request-to-join-screen-button diff --git a/translations/en.json b/translations/en.json index 8dd205bff4c..d25d4e99083 100644 --- a/translations/en.json +++ b/translations/en.json @@ -1902,6 +1902,7 @@ "swap": "Swap", "select-token-to-swap": "Select token to Swap", "select-token-to-receive": "Select token to receive", + "slide-to-request-to-join": "Slide to request to join", "slide-to-reveal-code": "Slide to reveal code", "slide-to-create-account": "Slide to create account", "minimum-received": "Minimum received", @@ -2405,5 +2406,5 @@ "send-limit": "Max: {{limit}}", "searching-for-activity": "Searching for activity...", "this-address-has-no-activity": "This address has no activity", - "this-address-has-activity": "This address has activity" + "this-address-has-activity": "This address has activity" } From 3b5fe3671730939aa114b03f4f042131753ac90a Mon Sep 17 00:00:00 2001 From: Yevheniia Berdnyk Date: Wed, 6 Dec 2023 15:30:01 +0200 Subject: [PATCH 08/12] e2e: added test for edit/delete message when offline --- .../chats/test_public_chat_browsing.py | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/appium/tests/critical/chats/test_public_chat_browsing.py b/test/appium/tests/critical/chats/test_public_chat_browsing.py index 0eb18940c46..406bf7207b9 100644 --- a/test/appium/tests/critical/chats/test_public_chat_browsing.py +++ b/test/appium/tests/critical/chats/test_public_chat_browsing.py @@ -4,6 +4,7 @@ import emoji import pytest from _pytest.outcomes import Failed +from appium.webdriver.connectiontype import ConnectionType from selenium.common.exceptions import NoSuchElementException, TimeoutException from tests import marks, run_in_parallel, pytest_config_global, transl @@ -769,6 +770,36 @@ def test_community_mark_all_messages_as_read(self): "New messages badge is shown in community channel element while there are no unread messages") self.errors.verify_no_errors() + @marks.testrail_id(704615) + def test_community_edit_delete_message_when_offline(self): + self.channel_2.just_fyi("Sending messages for edit and delete") + message_to_edit, message_to_delete = "message to edit", "message to delete" + self.channel_2.send_message(message_to_edit) + self.channel_2.send_message(message_to_delete) + self.home_1.navigate_back_to_home_view() + self.home_1.communities_tab.click() + self.home_1.get_chat(self.community_name, community=True).click() + self.community_1.get_channel(self.channel_name).click() + self.channel_1.just_fyi("Receiver is checking if initial messages were delivered") + for message in message_to_edit, message_to_delete: + if not self.channel_2.chat_element_by_text(message).is_element_displayed(30): + self.channel_2.driver.fail("Message '%s' was not received") + + self.channel_2.just_fyi("Turning on airplane mode and editing/deleting messages") + self.channel_2.driver.set_network_connection(ConnectionType.AIRPLANE_MODE) + message_after_edit = "text after edit" + self.channel_2.edit_message_in_chat(message_to_edit, message_after_edit) + self.channel_2.delete_message_in_chat(message_to_delete) + self.channel_2.just_fyi("Turning on network connection") + self.channel_2.driver.set_network_connection(ConnectionType.ALL_NETWORK_ON) + + self.channel_1.just_fyi("Receiver is checking if messages were updated and deleted") + if not self.channel_1.chat_element_by_text(message_after_edit).is_element_displayed(30): + self.errors.append("Updated message '%s' is not delivered to the receiver" % message_after_edit) + if not self.channel_1.chat_element_by_text(message_to_delete).is_element_disappeared(): + self.errors.append("Message '%s' was not deleted for the receiver" % message_to_delete) + self.errors.verify_no_errors() + @pytest.mark.xdist_group(name="new_five_2") @marks.new_ui_critical From 198a4d74a535dff9af8d7a4f0e2e8188c0b3e6fc Mon Sep 17 00:00:00 2001 From: Brian Sztamfater Date: Wed, 6 Dec 2023 20:16:08 -0300 Subject: [PATCH 09/12] feat: transaction confirmation page ui (#17812) Signed-off-by: Brian Sztamfater --- .../components/wallet/summary_info/style.cljs | 2 +- .../send/transaction_confirmation/style.cljs | 41 ++++ .../send/transaction_confirmation/view.cljs | 196 ++++++++++++++++++ src/status_im2/navigation/screens.cljs | 5 + translations/en.json | 6 +- 5 files changed, 248 insertions(+), 2 deletions(-) create mode 100644 src/status_im2/contexts/wallet/send/transaction_confirmation/style.cljs create mode 100644 src/status_im2/contexts/wallet/send/transaction_confirmation/view.cljs diff --git a/src/quo/components/wallet/summary_info/style.cljs b/src/quo/components/wallet/summary_info/style.cljs index 204f0be21c5..9854d697341 100644 --- a/src/quo/components/wallet/summary_info/style.cljs +++ b/src/quo/components/wallet/summary_info/style.cljs @@ -4,7 +4,7 @@ (defn container [networks? theme] - {:width 335 + {:width "100%" :height (if networks? 90 56) :border-radius 16 :border-width 1 diff --git a/src/status_im2/contexts/wallet/send/transaction_confirmation/style.cljs b/src/status_im2/contexts/wallet/send/transaction_confirmation/style.cljs new file mode 100644 index 00000000000..be2bdf4f617 --- /dev/null +++ b/src/status_im2/contexts/wallet/send/transaction_confirmation/style.cljs @@ -0,0 +1,41 @@ +(ns status-im2.contexts.wallet.send.transaction-confirmation.style + (:require [quo.foundations.colors :as colors])) + +(defn container + [margin-top] + {:position :absolute + :top margin-top + :right 0 + :left 0 + :bottom 0}) + +(def content-container + {:padding-top 12 + :padding-horizontal 20 + :padding-bottom 32}) + +(def title-container + {:margin-right 4}) + +(defn details-container + [theme] + {:flex-direction :row + :justify-content :space-between + :height 52 + :padding-horizontal 12 + :padding-top 7 + :padding-bottom 8 + :border-radius 16 + :border-width 1 + :border-color (colors/theme-colors colors/neutral-10 colors/neutral-90 theme)}) + +(def slide-button-container + {:position :absolute + :right 20 + :left 20 + :bottom 20}) + +(defn section-label + [theme] + {:margin-bottom 8 + :color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}) diff --git a/src/status_im2/contexts/wallet/send/transaction_confirmation/view.cljs b/src/status_im2/contexts/wallet/send/transaction_confirmation/view.cljs new file mode 100644 index 00000000000..1168c6f4683 --- /dev/null +++ b/src/status_im2/contexts/wallet/send/transaction_confirmation/view.cljs @@ -0,0 +1,196 @@ +(ns status-im2.contexts.wallet.send.transaction-confirmation.view + (:require + [quo.core :as quo] + [quo.foundations.resources :as quo.resources] + [quo.theme :as quo.theme] + [react-native.core :as rn] + [react-native.safe-area :as safe-area] + [reagent.core :as reagent] + [status-im2.common.resources :as resources] + [status-im2.contexts.wallet.send.transaction-confirmation.style :as style] + [utils.i18n :as i18n] + [utils.re-frame :as rf])) + +(defn- transaction-title + [] + [rn/view {:style style/content-container} + [rn/view {:style {:flex-direction :row}} + [quo/text + {:size :heading-1 + :weight :semi-bold + :style style/title-container + :accessibility-label :send-label} + (i18n/label :t/send)] + [quo/summary-tag + {:label "150 ETH" + :type :token + :image-source (quo.resources/get-token :eth)}]] + [rn/view + {:style {:flex-direction :row + :margin-top 4}} + [quo/text + {:size :heading-1 + :weight :semi-bold + :style style/title-container + :accessibility-label :send-label} + (i18n/label :t/from)] + [quo/summary-tag + {:label "Collectibles vault" + :type :account + :emoji "πŸ‘" + :customization-color :purple}]] + [rn/view + {:style {:flex-direction :row + :margin-top 4}} + [quo/text + {:size :heading-1 + :weight :semi-bold + :style style/title-container + :accessibility-label :send-label} + (i18n/label :t/to)] + [quo/summary-tag + {:label "Mark Libot" + :type :user + :image-source (resources/get-mock-image :user-picture-male4) + :customization-color :magenta}]]]) + +(defn- transaction-from + [status-account-props theme] + [rn/view + {:style {:padding-horizontal 20 + :padding-bottom 16}} + [quo/text + {:size :paragraph-2 + :weight :medium + :style (style/section-label theme) + :accessibility-label :summary-from-label} + (i18n/label :t/from-capitalized)] + [quo/summary-info + {:type :status-account + :networks? true + :values {:ethereum 150 + :optimism 50 + :arbitrum 25} + :account-props status-account-props}]]) + +(defn- transaction-to + [user-props theme] + [rn/view + {:style {:padding-horizontal 20 + :padding-bottom 16}} + [quo/text + {:size :paragraph-2 + :weight :medium + :style (style/section-label theme) + :accessibility-label :summary-from-label} + (i18n/label :t/to-capitalized)] + [quo/summary-info + {:type :user + :networks? true + :values {:ethereum 150 + :optimism 50 + :arbitrum 25} + :account-props user-props}]]) + +(defn- transaction-details + [theme] + [rn/view + {:style {:padding-horizontal 20 + :padding-bottom 16}} + [quo/text + {:size :paragraph-2 + :weight :medium + :style (style/section-label theme) + :accessibility-label :summary-from-label} + (i18n/label :t/details)] + [rn/view + {:style (style/details-container theme)} + [quo/data-item + {:container-style {:flex 1 + :height 36} + :blur? false + :description :default + :icon-right? false + :card? false + :label :none + :status :default + :size :small + :title (i18n/label :t/est-time) + :subtitle "3-5 min"}] + [quo/data-item + {:container-style {:flex 1 + :height 36} + :blur? false + :description :default + :icon-right? false + :card? false + :label :none + :status :default + :size :small + :title (i18n/label :t/max-fees) + :subtitle "€188,70"}] + [quo/data-item + {:container-style {:flex 1 + :height 36} + :blur? false + :description :default + :icon-right? false + :card? false + :label :none + :status :default + :size :small + :title (i18n/label :t/user-gets {:name "Mark"}) + :subtitle "149.99 ETH"}]]]) + +(defn- f-view-internal + [_] + (let [reset-slider? (reagent/atom false) + margin-top (safe-area/get-top) + biometric-auth? true + on-close #(rf/dispatch [:navigate-back-within-stack :wallet-select-asset]) + status-account-props {:customization-color :purple + :size 32 + :emoji "πŸ‘" + :type :default + :name "Collectibles vault" + :address "0x0ah...78b"} + user-props {:full-name "M L" + :status-indicator? false + :size :small + :ring-background (resources/get-mock-image :ring) + :customization-color :blue + :name "Mark Libot" + :address "0x0ah...78b" + :status-account (merge status-account-props + {:size 16 + :name "New house" + :emoji "πŸ”"})}] + (fn [{:keys [theme]}] + [rn/view {:style {:flex 1}} + [quo/gradient-cover {:customization-color :purple}] + [rn/view {:style (style/container margin-top)} + [quo/page-nav + {:icon-name :i/arrow-left + :on-press on-close + :accessibility-label :top-bar + :right-side [{:icon-name :i/advanced + :on-press (fn callback [] nil) + :accessibility-label "Advanced"}]}] + [transaction-title] + [transaction-from status-account-props theme] + [transaction-to user-props theme] + [transaction-details theme] + [rn/view {:style style/slide-button-container} + [quo/slide-button + {:size :size/s-48 + :customization-color :purple + :on-reset (when @reset-slider? #(reset! reset-slider? false)) + :on-complete #(js/alert "Not implemented yet") + :track-icon (if biometric-auth? :i/face-id :password) + :track-text (i18n/label :t/slide-to-send)}]]]]))) + +(defn view-internal + [props] + [:f> f-view-internal props]) + +(def view (quo.theme/with-theme view-internal)) diff --git a/src/status_im2/navigation/screens.cljs b/src/status_im2/navigation/screens.cljs index 8f3ef893364..b7049751ff0 100644 --- a/src/status_im2/navigation/screens.cljs +++ b/src/status_im2/navigation/screens.cljs @@ -55,6 +55,7 @@ [status-im2.contexts.wallet.send.input-amount.view :as wallet-send-input-amount] [status-im2.contexts.wallet.send.select-address.view :as wallet-select-address] [status-im2.contexts.wallet.send.select-asset.view :as wallet-select-asset] + [status-im2.contexts.wallet.send.transaction-confirmation.view :as wallet-transaction-confirmation] [status-im2.navigation.options :as options] [status-im2.navigation.transitions :as transitions])) @@ -312,6 +313,10 @@ :options {:insets {:top? true}} :component wallet-select-asset/view} + {:name :wallet-transaction-confirmation + :options {:insets {:bottom? true}} + :component wallet-transaction-confirmation/view} + {:name :scan-address :options (merge options/dark-screen diff --git a/translations/en.json b/translations/en.json index d25d4e99083..439332f87e5 100644 --- a/translations/en.json +++ b/translations/en.json @@ -2406,5 +2406,9 @@ "send-limit": "Max: {{limit}}", "searching-for-activity": "Searching for activity...", "this-address-has-no-activity": "This address has no activity", - "this-address-has-activity": "This address has activity" + "this-address-has-activity": "This address has activity", + "details": "Details", + "est-time": "Est. time", + "user-gets": "{{name}} gets", + "slide-to-send": "Slide to send" } From aa89ebdb93fbe3d1e3b831976f1b50fad5ffd003 Mon Sep 17 00:00:00 2001 From: frank Date: Thu, 7 Dec 2023 10:16:25 +0800 Subject: [PATCH 10/12] fix: Marking AC notification as read does not affect correspondent message in chat (#18058) --- src/status_im/chat/models/loading.cljs | 1 + .../contexts/shell/activity_center/events.cljs | 11 +++++++---- .../shell/activity_center/events_test.cljs | 16 ++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/status_im/chat/models/loading.cljs b/src/status_im/chat/models/loading.cljs index 622671d9c21..b5b89761a5c 100644 --- a/src/status_im/chat/models/loading.cljs +++ b/src/status_im/chat/models/loading.cljs @@ -45,6 +45,7 @@ {:db (update-in db [:chats chat-id] merge chat)})) (rf/defn load-chat + {:events [:chats-list/load-chat]} [_ chat-id] {:json-rpc/call [{:method "wakuext_chat" :params [chat-id] diff --git a/src/status_im2/contexts/shell/activity_center/events.cljs b/src/status_im2/contexts/shell/activity_center/events.cljs index e0274d66485..4d368579ae5 100644 --- a/src/status_im2/contexts/shell/activity_center/events.cljs +++ b/src/status_im2/contexts/shell/activity_center/events.cljs @@ -122,10 +122,13 @@ :on-error [:activity-center/process-notification-failure notification-id :notification/mark-as-read]}]})) -(rf/defn mark-as-read-success - {:events [:activity-center.notifications/mark-as-read-success]} - [cofx notification] - (notifications-reconcile cofx [(assoc notification :read true)])) +(defn mark-as-read-success + [_ [{:keys [chat-id] :as notification}]] + {:fx [(when chat-id + [:dispatch [:chats-list/load-chat chat-id]]) + [:dispatch [:activity-center.notifications/reconcile [(assoc notification :read true)]]]]}) + +(rf/reg-event-fx :activity-center.notifications/mark-as-read-success mark-as-read-success) (rf/defn mark-as-unread {:events [:activity-center.notifications/mark-as-unread]} diff --git a/src/status_im2/contexts/shell/activity_center/events_test.cljs b/src/status_im2/contexts/shell/activity_center/events_test.cljs index 4fdc4ec1f46..8f0028e24a2 100644 --- a/src/status_im2/contexts/shell/activity_center/events_test.cljs +++ b/src/status_im2/contexts/shell/activity_center/events_test.cljs @@ -63,16 +63,12 @@ (events/mark-as-read cofx (:id notif))))))) (deftest mark-as-read-success-test - (let [f-args (atom []) - cofx {:db {}} - notif {:id "0x1" :read false :type types/one-to-one-chat}] - (with-redefs [events/notifications-reconcile - (fn [& args] - (reset! f-args args) - :result)] - (is (= :result (events/mark-as-read-success cofx notif))) - (is (match? [cofx [(assoc notif :read true)]] - @f-args))))) + (let [cofx {:db {}} + notif {:id "0x1" :read false :type types/one-to-one-chat :chat-id "chat-id"} + expected-fx {:fx [[:dispatch [:chats-list/load-chat "chat-id"]] + [:dispatch + [:activity-center.notifications/reconcile [(assoc notif :read true)]]]]}] + (is (match? expected-fx (events/mark-as-read-success cofx [notif]))))) (deftest mark-as-unread-test (testing "does nothing if the notification ID cannot be found in the app db" From f692ae2222034ee15c05b77421fc0d09da4ba5c5 Mon Sep 17 00:00:00 2001 From: Omar Basem Date: Thu, 7 Dec 2023 08:00:56 +0400 Subject: [PATCH 11/12] Wallet: ENS (#18000) * wallet: ens --- .../components/inputs/address_input/view.cljs | 12 ++-- src/status_im2/constants.cljs | 3 + src/status_im2/contexts/wallet/events.cljs | 41 +++++++++++++ .../wallet/send/select_address/style.cljs | 6 +- .../wallet/send/select_address/view.cljs | 59 ++++++++++--------- .../wallet/send/select_asset/view.cljs | 11 +--- src/status_im2/navigation/screens.cljs | 3 +- 7 files changed, 84 insertions(+), 51 deletions(-) diff --git a/src/quo/components/inputs/address_input/view.cljs b/src/quo/components/inputs/address_input/view.cljs index e56089c20b0..31ea5938531 100644 --- a/src/quo/components/inputs/address_input/view.cljs +++ b/src/quo/components/inputs/address_input/view.cljs @@ -61,14 +61,10 @@ value (reagent/atom "") focused? (atom false)] (fn [{:keys [scanned-value theme blur? on-change-text on-blur on-focus on-clear on-scan on-detect-ens - on-detect-address - ens-regex address-regex - valid-ens-or-address?]}] + on-detect-address address-regex valid-ens-or-address?]}] (let [on-change (fn [text] (when (not= @value text) - (let [ens? (when ens-regex - (boolean (re-matches ens-regex text))) - address? (when address-regex + (let [address? (when address-regex (boolean (re-matches address-regex text)))] (if (> (count text) 0) (reset! status :typing) @@ -76,9 +72,9 @@ (reset! value text) (when on-change-text (on-change-text text)) - (when (and ens? on-detect-ens) + (when (and on-detect-ens (> (count text) 0)) (reset! status :loading) - (on-detect-ens text)) + (on-detect-ens text #(reset! status :typing))) (when (and address? on-detect-address) (reset! status :loading) (on-detect-address text))))) diff --git a/src/status_im2/constants.cljs b/src/status_im2/constants.cljs index b0e20c11da5..73c730bda61 100644 --- a/src/status_im2/constants.cljs +++ b/src/status_im2/constants.cljs @@ -390,3 +390,6 @@ (def ^:const account-default-customization-color :blue) (def ^:const wallet-account-name-max-length 20) + +(def ^:const status-address-domain ".stateofus.eth") +(def ^:const eth-address-domain ".eth") diff --git a/src/status_im2/contexts/wallet/events.cljs b/src/status_im2/contexts/wallet/events.cljs index c397856d48c..8f2a4bbe6d9 100644 --- a/src/status_im2/contexts/wallet/events.cljs +++ b/src/status_im2/contexts/wallet/events.cljs @@ -7,9 +7,11 @@ [quo.foundations.colors :as colors] [react-native.background-timer :as background-timer] [status-im2.common.data-store.wallet :as data-store] + [status-im2.contexts.wallet.item-types :as item-types] [status-im2.contexts.wallet.temp :as temp] [taoensso.timbre :as log] [utils.ethereum.chain :as chain] + [utils.ethereum.eip.eip55 :as eip55] [utils.i18n :as i18n] [utils.number] [utils.re-frame :as rf] @@ -327,6 +329,45 @@ {:event :wallet/get-collectible-details-done :response response}))))) +(rf/reg-event-fx :wallet/find-ens + (fn [{:keys [db]} [input contacts chain-id cb]] + (let [result (if (empty? input) + [] + (filter #(string/starts-with? (or (:ens-name %) "") input) contacts))] + (if (and input (empty? result)) + (rf/dispatch [:wallet/search-ens input chain-id cb ".stateofus.eth"]) + {:db (assoc db + :wallet/local-suggestions + (map #(assoc % :type item-types/saved-address) result) + :wallet/valid-ens-or-address? (not-empty result))})))) + +(rf/reg-event-fx :wallet/search-ens + (fn [_ [input chain-id cb domain]] + (let [ens (if (string/includes? input ".") input (str input domain))] + {:fx [[:json-rpc/call + [{:method "ens_addressOf" + :params [chain-id ens] + :on-success #(rf/dispatch [:wallet/set-ens-address % ens]) + :on-error (fn [] + (if (= domain ".stateofus.eth") + (rf/dispatch [:wallet/search-ens input chain-id cb ".eth"]) + (do + (rf/dispatch [:wallet/set-ens-address nil ens]) + (cb))))}]]]}))) + +(rf/reg-event-fx :wallet/set-ens-address + (fn [{:keys [db]} [result ens]] + {:db (assoc db + :wallet/local-suggestions (if result + [{:type item-types/address + :ens ens + :address (eip55/address->checksum result) + :networks [:ethereum :optimism]}] + []) + :wallet/valid-ens-or-address? (boolean result))})) + + + (rf/reg-event-fx :wallet/fetch-address-suggestions (fn [{:keys [db]} [address]] {:db (assoc db diff --git a/src/status_im2/contexts/wallet/send/select_address/style.cljs b/src/status_im2/contexts/wallet/send/select_address/style.cljs index c663fc8f37c..05a473c694b 100644 --- a/src/status_im2/contexts/wallet/send/select_address/style.cljs +++ b/src/status_im2/contexts/wallet/send/select_address/style.cljs @@ -1,9 +1,7 @@ (ns status-im2.contexts.wallet.send.select-address.style) -(defn container - [margin-top] - {:flex 1 - :margin-top margin-top}) +(def container + {:flex 1}) (def title-container {:margin-horizontal 20 diff --git a/src/status_im2/contexts/wallet/send/select_address/view.cljs b/src/status_im2/contexts/wallet/send/select_address/view.cljs index 20d365c06bf..877f6a8ff55 100644 --- a/src/status_im2/contexts/wallet/send/select_address/view.cljs +++ b/src/status_im2/contexts/wallet/send/select_address/view.cljs @@ -4,7 +4,6 @@ [quo.foundations.colors :as colors] [quo.theme :as quo.theme] [react-native.core :as rn] - [react-native.safe-area :as safe-area] [reagent.core :as reagent] [status-im2.constants :as constants] [status-im2.contexts.wallet.common.account-switcher.view :as account-switcher] @@ -49,12 +48,11 @@ (fn [] (let [scanned-address (rf/sub [:wallet/scanned-address]) send-address (rf/sub [:wallet/send-address]) - valid-ens-or-address? (rf/sub [:wallet/valid-ens-or-address?])] + valid-ens-or-address? (rf/sub [:wallet/valid-ens-or-address?]) + chain-id (rf/sub [:chain-id]) + contacts (rf/sub [:contacts/active])] [quo/address-input - {:on-focus (fn [] - (when (empty? @input-value) - (rf/dispatch [:wallet/clean-local-suggestions])) - (reset! input-focused? true)) + {:on-focus #(reset! input-focused? true) :on-blur #(reset! input-focused? false) :on-scan (fn [] (rn/dismiss-keyboard!) @@ -62,22 +60,19 @@ :ens-regex constants/regx-ens :address-regex constants/regx-address :scanned-value (or send-address scanned-address) - :on-detect-ens #(debounce/debounce-and-dispatch - [:wallet/validate-ens %] - 300) :on-detect-address #(debounce/debounce-and-dispatch [:wallet/validate-address %] 300) + :on-detect-ens (fn [text cb] + (debounce/debounce-and-dispatch + [:wallet/find-ens text contacts chain-id cb] + 300)) :on-change-text (fn [text] - (let [starts-like-eth-address (re-matches - constants/regx-full-or-partial-address - text)] - (when-not (= scanned-address text) - (rf/dispatch [:wallet/clean-scanned-address])) - (if starts-like-eth-address - (rf/dispatch [:wallet/fetch-address-suggestions text]) - (rf/dispatch [:wallet/clean-local-suggestions])) - (reset! input-value text))) + (when-not (= scanned-address text) + (rf/dispatch [:wallet/clean-scanned-address])) + (when (empty? text) + (rf/dispatch [:wallet/clean-local-suggestions])) + (reset! input-value text)) :valid-ens-or-address? valid-ens-or-address?}]))) (defn- ens-linked-address @@ -90,8 +85,8 @@ ^{:key (str network)} [quo/text {:size :paragraph-2 - :style {:color (colors/resolve-color (:network-name network) theme)}} - (str (:short-name network) ":")]) + :style {:color (colors/resolve-color network theme)}} + (str (subs (name network) 0 3) ":")]) networks) [quo/text {:size :paragraph-2 @@ -101,14 +96,20 @@ (defn- suggestion-component [] - (fn [{:keys [type ens address accounts] :as local-suggestion} _ _ _] + (fn [{:keys [type ens address accounts primary-name public-key ens-name color] :as local-suggestion} _ + _ _] (let [props {:on-press (fn [] (let [address (if accounts (:address (first accounts)) address)] (when-not ens (rf/dispatch [:wallet/select-send-address address])))) :active-state? false}] (cond (= type types/saved-address) - [quo/saved-address (merge props {:user-props local-suggestion})] + [quo/saved-address + (merge props + {:user-props {:name primary-name + :address public-key + :ens ens-name + :customization-color color}})] (= type types/saved-contact-address) [quo/saved-contact-address (merge props local-suggestion)] (and (not ens) (= type types/address)) @@ -132,8 +133,7 @@ (defn- f-view-internal [] - (let [margin-top (safe-area/get-top) - selected-tab (reagent/atom (:id (first tabs-data))) + (let [selected-tab (reagent/atom (:id (first tabs-data))) on-close (fn [] (rf/dispatch [:wallet/clean-scanned-address]) (rf/dispatch [:wallet/clean-local-suggestions]) @@ -143,8 +143,12 @@ input-focused? (reagent/atom false)] (fn [] (let [valid-ens-or-address? (boolean (rf/sub [:wallet/valid-ens-or-address?]))] + (rn/use-effect (fn [] + (fn [] + (rf/dispatch [:wallet/clean-scanned-address]) + (rf/dispatch [:wallet/clean-local-suggestions])))) [rn/scroll-view - {:content-container-style (style/container margin-top) + {:content-container-style style/container :keyboard-should-persist-taps :handled :scroll-enabled false} [account-switcher/view {:on-press on-close}] @@ -168,10 +172,7 @@ :type :primary :disabled? (not valid-ens-or-address?) :container-style style/button - :on-press (fn [] - (rf/dispatch [:wallet/select-send-address @input-value]) - (rf/dispatch [:navigate-to-within-stack - [:wallet-select-asset :wallet-select-address]]))} + :on-press #(js/alert "Not implemented yet")} (i18n/label :t/continue)])] [:<> [quo/tabs diff --git a/src/status_im2/contexts/wallet/send/select_asset/view.cljs b/src/status_im2/contexts/wallet/send/select_asset/view.cljs index 984dda3338e..1add54fb44a 100644 --- a/src/status_im2/contexts/wallet/send/select_asset/view.cljs +++ b/src/status_im2/contexts/wallet/send/select_asset/view.cljs @@ -7,6 +7,7 @@ [react-native.core :as rn] [react-native.safe-area :as safe-area] [reagent.core :as reagent] + [status-im2.contexts.wallet.common.account-switcher.view :as account-switcher] [status-im2.contexts.wallet.send.select-asset.style :as style] [utils.i18n :as i18n] [utils.re-frame :as rf])) @@ -76,15 +77,7 @@ {:content-container-style {:flex 1} :keyboard-should-persist-taps :handled :scroll-enabled false} - [quo/page-nav - {:icon-name :i/arrow-left - :on-press on-close - :accessibility-label :top-bar - :right-side :account-switcher - :account-switcher {:customization-color :purple - :on-press #(js/alert "Not implemented yet") - :state :default - :emoji "πŸ‘"}}] + [account-switcher/view {:on-press on-close}] [quo/text-combinations {:title (i18n/label :t/select-asset) :container-style style/title-container diff --git a/src/status_im2/navigation/screens.cljs b/src/status_im2/navigation/screens.cljs index b7049751ff0..4cea065c2a8 100644 --- a/src/status_im2/navigation/screens.cljs +++ b/src/status_im2/navigation/screens.cljs @@ -306,7 +306,8 @@ :component wallet-send-input-amount/view} {:name :wallet-select-address - :options {:modalPresentationStyle :overCurrentContext} + :options {:modalPresentationStyle :overCurrentContext + :insets {:top? true}} :component wallet-select-address/view} {:name :wallet-select-asset From dc587e493f01ef702e96fe254db9099e9155f4d7 Mon Sep 17 00:00:00 2001 From: Omar Basem Date: Thu, 7 Dec 2023 09:43:36 +0400 Subject: [PATCH 12/12] Wallet: generate new keypair UI (#18045) * feat: new keypair flow ui --- .../contexts/wallet/common/temp.cljs | 4 + .../backup_recovery_phrase/style.cljs | 65 +++++++++++++ .../backup_recovery_phrase/view.cljs | 95 +++++++++++++++++++ .../create_account/select_keypair/view.cljs | 21 +++- src/status_im2/navigation/screens.cljs | 6 ++ translations/en.json | 19 +++- 6 files changed, 206 insertions(+), 4 deletions(-) create mode 100644 src/status_im2/contexts/wallet/create_account/backup_recovery_phrase/style.cljs create mode 100644 src/status_im2/contexts/wallet/create_account/backup_recovery_phrase/view.cljs diff --git a/src/status_im2/contexts/wallet/common/temp.cljs b/src/status_im2/contexts/wallet/common/temp.cljs index ad4f6c20828..691e159a164 100644 --- a/src/status_im2/contexts/wallet/common/temp.cljs +++ b/src/status_im2/contexts/wallet/common/temp.cljs @@ -107,3 +107,7 @@ :networks networks-list :state :default :customization-color :blue}]) + +(def secret-phrase + ["witch" "collapse" "practice" "feed" "shame" "open" "lion" + "collapse" "umbrella" "fabric" "sadness" "obligue"]) diff --git a/src/status_im2/contexts/wallet/create_account/backup_recovery_phrase/style.cljs b/src/status_im2/contexts/wallet/create_account/backup_recovery_phrase/style.cljs new file mode 100644 index 00000000000..5cda62a0598 --- /dev/null +++ b/src/status_im2/contexts/wallet/create_account/backup_recovery_phrase/style.cljs @@ -0,0 +1,65 @@ +(ns status-im2.contexts.wallet.create-account.backup-recovery-phrase.style + (:require + [quo.foundations.colors :as colors] + [quo.theme :as quo.theme] + [react-native.platform :as platform])) + +(def header-container + {:margin-horizontal 20 + :margin-vertical 12}) + +(defn seed-phrase-container + [theme] + {:margin-horizontal 20 + :padding-horizontal 12 + :border-width 1 + :border-color (colors/theme-colors colors/neutral-10 colors/neutral-80 theme) + :border-radius 16 + :background-color (colors/theme-colors colors/white colors/neutral-80-opa-40 theme) + :flex-direction :row}) + +(def word-item + {:align-items :center + :flex-direction :row}) + +(defn separator + [theme] + {:margin-vertical 12 + :margin-horizontal 12 + :border-width (when platform/ios? 1) + :border-right-width (when platform/android? 1) + :border-color (colors/theme-colors colors/neutral-10 colors/neutral-80 theme) + :border-style :dashed}) + +(def step-item + {:flex-direction :row + :margin-vertical 8 + :align-items :center}) + +(def blur-container + {:position :absolute + :left 0 + :right 0 + :top 0 + :bottom 0 + :border-radius 16 + :overflow :hidden}) + +(defn blur + [theme] + {:style {:flex 1} + :blur-radius 20 + :blur-type (quo.theme/theme-value :light :dark theme) + :blur-amount 20}) + +(def slide-button + {:position :absolute + :bottom 12 + :left 0 + :right 0}) + +(defn description-text + [theme] + {:margin-horizontal 40 + :text-align :center + :color (colors/theme-colors colors/neutral-80-opa-70 colors/white-opa-70 theme)}) diff --git a/src/status_im2/contexts/wallet/create_account/backup_recovery_phrase/view.cljs b/src/status_im2/contexts/wallet/create_account/backup_recovery_phrase/view.cljs new file mode 100644 index 00000000000..62da279257d --- /dev/null +++ b/src/status_im2/contexts/wallet/create_account/backup_recovery_phrase/view.cljs @@ -0,0 +1,95 @@ +(ns status-im2.contexts.wallet.create-account.backup-recovery-phrase.view + (:require + [quo.core :as quo] + [quo.theme :as quo.theme] + [react-native.blur :as blur] + [react-native.core :as rn] + [reagent.core :as reagent] + [status-im2.contexts.wallet.common.temp :as temp] + [status-im2.contexts.wallet.create-account.backup-recovery-phrase.style :as style] + [utils.i18n :as i18n] + [utils.re-frame :as rf])) + +(defn- word-item + [item index _ increment] + [rn/view {:style style/word-item} + [quo/counter {:type :grey} (+ index increment)] + [quo/text {:style {:margin-left 4}} item]]) + +(defn- words-column + [words first-half?] + [rn/flat-list + {:style {:padding-vertical 8} + :data (if first-half? (subvec words 0 6) (subvec words 6)) + :separator [rn/view {:style {:height 12}}] + :render-fn word-item + :render-data (if first-half? 1 7) + :scroll-enabled false}]) + +(defn- step-item + [item index _ checked?] + [rn/view {:style style/step-item} + [quo/selectors + {:type :checkbox + :on-change #(swap! checked? assoc (keyword (str index)) %)}] + [quo/text {:style {:margin-left 12}} (i18n/label item)]]) + +(defn- view-internal + [{:keys [theme]}] + (let [step-labels [:t/backup-step-1 :t/backup-step-2 :t/backup-step-3 + :t/backup-step-4] + checked? (reagent/atom + {:0 false + :1 false + :2 false + :3 false}) + revealed? (reagent/atom false) + {:keys [customization-color]} (rf/sub [:profile/profile])] + (fn [] + [rn/view {:style {:flex 1}} + [quo/page-nav + {:icon-name :i/close + :on-press #(rf/dispatch [:navigate-back]) + :accessibility-label :top-bar}] + [quo/text-combinations + {:container-style style/header-container + :title (i18n/label :t/backup-recovery-phrase) + :description (i18n/label :t/backup-recovery-phrase-description)}] + [rn/view {:style (style/seed-phrase-container theme)} + [words-column temp/secret-phrase true] + [rn/view {:style (style/separator theme)}] + [words-column temp/secret-phrase false] + (when-not @revealed? + [rn/view {:style style/blur-container} + [blur/view (style/blur theme)]])] + (when-not @revealed? + [rn/view + {:style {:padding-horizontal 20 + :padding-top 20}} + [quo/text + {:weight :semi-bold + :style {:margin-bottom 8}} (i18n/label :t/how-to-backup)] + [rn/flat-list + {:data step-labels + :render-fn step-item + :render-data checked? + :scroll-enabled false}]]) + (if @revealed? + [rn/view {:style style/slide-button} + [quo/bottom-actions + {:button-one-label (i18n/label :t/i-have-written) + :button-one-props {:disabled? (some false? (vals @checked?)) + :customization-color customization-color + :on-press #(js/alert "To be implemented")}}] + [quo/text + {:size :paragraph-2 + :style (style/description-text theme)} + (i18n/label :t/next-you-will)]] + [quo/bottom-actions + {:button-one-label (i18n/label :t/reveal-phrase) + :button-one-props {:disabled? (some false? (vals @checked?)) + :customization-color customization-color + :on-press #(reset! revealed? true)} + :container-style style/slide-button}])]))) + +(def view (quo.theme/with-theme view-internal)) diff --git a/src/status_im2/contexts/wallet/create_account/select_keypair/view.cljs b/src/status_im2/contexts/wallet/create_account/select_keypair/view.cljs index 346c52d0780..e7499085557 100644 --- a/src/status_im2/contexts/wallet/create_account/select_keypair/view.cljs +++ b/src/status_im2/contexts/wallet/create_account/select_keypair/view.cljs @@ -8,6 +8,24 @@ [utils.i18n :as i18n] [utils.re-frame :as rf])) +(defn keypair-options + [] + [quo/action-drawer + [[{:icon :i/add + :accessibility-label :generate-new-keypair + :label (i18n/label :t/generate-new-keypair) + :on-press #(rf/dispatch [:navigate-to :wallet-backup-recovery-phrase])} + {:icon :i/seed + :accessibility-label :import-using-phrase + :label (i18n/label :t/import-using-phrase) + :add-divider? true} + {:icon :i/keycard-card + :accessibility-label :import-from-keycard + :label (i18n/label :t/import-from-keycard)} + {:icon :i/key + :accessibility-label :import-private-key + :label (i18n/label :t/import-private-key)}]]]) + (def accounts [{:account-props {:customization-color :turquoise :size 32 @@ -38,7 +56,8 @@ :title (i18n/label :t/keypairs) :description (i18n/label :t/keypairs-description) :button-icon :i/add - :button-on-press #(js/alert "not implemented") + :button-on-press #(rf/dispatch [:show-bottom-sheet + {:content keypair-options}]) :customization-color customization-color}] [quo/keypair (merge diff --git a/src/status_im2/navigation/screens.cljs b/src/status_im2/navigation/screens.cljs index 4cea065c2a8..52c2a5e34c3 100644 --- a/src/status_im2/navigation/screens.cljs +++ b/src/status_im2/navigation/screens.cljs @@ -46,6 +46,8 @@ [status-im2.contexts.wallet.add-address-to-watch.confirm-address.view :as confirm-address-to-watch] [status-im2.contexts.wallet.add-address-to-watch.view :as add-address-to-watch] [status-im2.contexts.wallet.collectible.view :as wallet-collectible] + [status-im2.contexts.wallet.create-account.backup-recovery-phrase.view :as + wallet-backup-recovery-phrase] [status-im2.contexts.wallet.create-account.edit-derivation-path.view :as wallet-edit-derivation-path] [status-im2.contexts.wallet.create-account.select-keypair.view :as wallet-select-keypair] [status-im2.contexts.wallet.create-account.view :as wallet-create-account] @@ -297,6 +299,10 @@ :options {:insets {:top? true}} :component wallet-create-account/view} + {:name :wallet-backup-recovery-phrase + :options {:insets {:top? true :bottom? true}} + :component wallet-backup-recovery-phrase/view} + {:name :wallet-saved-addresses :component wallet-saved-addresses/view} diff --git a/translations/en.json b/translations/en.json index 439332f87e5..4b8705ccb1f 100644 --- a/translations/en.json +++ b/translations/en.json @@ -63,7 +63,6 @@ "back": "Back", "back-up-seed-phrase": "Back up seed phrase", "back-up-your-seed-phrase": "Back up your seed phrase", - "backup-recovery-phrase": "Back up seed phrase", "balance": "Balance", "begin-set-up": "Begin setup", "biometric-auth-android-sensor-desc": "Touch sensor", @@ -2406,9 +2405,23 @@ "send-limit": "Max: {{limit}}", "searching-for-activity": "Searching for activity...", "this-address-has-no-activity": "This address has no activity", - "this-address-has-activity": "This address has activity", "details": "Details", "est-time": "Est. time", "user-gets": "{{name}} gets", - "slide-to-send": "Slide to send" + "slide-to-send": "Slide to send", + "this-address-has-activity": "This address has activity", + "generate-new-keypair": "Generate new keypair", + "import-using-phrase": "Import using recovery phrase", + "import-from-keycard": "Import from Keycard", + "import-private-key": "Import private key", + "backup-recovery-phrase": "Backup recovery phrase", + "backup-recovery-phrase-description": "Save in a secure place that only you control, these 12 words give access to all of your funds.", + "how-to-backup": "How to backup your recovery phrase", + "backup-step-1": "Find pen and paper", + "backup-step-2": "Write down your recovery phrase", + "backup-step-3": "Find a place to store it", + "backup-step-4": "I know I can only see it once", + "reveal-phrase": "Reveal phrase", + "i-have-written": "I have written it down on paper", + "next-you-will": "Next, you will be asked to confirm the position of certain words in your recovery phrase" }