Wallet: Derivation Path screen (#19268)

Wallet: Derivation Path screen (#19268)
This commit is contained in:
Omar Basem 2024-03-18 20:44:16 +04:00 committed by GitHub
parent 7948582e46
commit e5cee4b640
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 205 additions and 100 deletions

View File

@ -1,5 +1,5 @@
import { useAnimatedReaction, withTiming, runOnJS } from 'react-native-reanimated'; import { useAnimatedReaction, withTiming, runOnJS } from 'react-native-reanimated';
import { useState } from "react" import { useState } from 'react';
export function messagesListOnScroll(distanceFromListTop, chatListScrollY, callback) { export function messagesListOnScroll(distanceFromListTop, chatListScrollY, callback) {
return function (event) { return function (event) {
@ -15,15 +15,19 @@ export function messagesListOnScroll(distanceFromListTop, chatListScrollY, callb
} }
export function useMessagesScrolledToThreshold(distanceFromListTop, threshold) { export function useMessagesScrolledToThreshold(distanceFromListTop, threshold) {
const [scrolledToThreshold, setScrolledToThreshold] = useState(false) const [scrolledToThreshold, setScrolledToThreshold] = useState(false);
useAnimatedReaction(function () { useAnimatedReaction(
function () {
return distanceFromListTop.value <= threshold; return distanceFromListTop.value <= threshold;
}, function (current) { },
function (current) {
if (current !== scrolledToThreshold) { if (current !== scrolledToThreshold) {
runOnJS(setScrolledToThreshold)(current) runOnJS(setScrolledToThreshold)(current);
} }
}, [scrolledToThreshold]) },
[scrolledToThreshold],
);
return scrolledToThreshold return scrolledToThreshold;
} }

View File

@ -21,9 +21,9 @@ export function navigationHeaderPosition(distanceFromListTop, isAllLoaded, topBa
export function navigationButtonsCompleteOpacity(isCalculationComplete) { export function navigationButtonsCompleteOpacity(isCalculationComplete) {
return useDerivedValue(function () { return useDerivedValue(function () {
'worklet' 'worklet';
return isCalculationComplete.value ? withTiming(1) : 0 return isCalculationComplete.value ? withTiming(1) : 0;
}) });
} }
export function interpolateNavigationViewOpacity(props) { export function interpolateNavigationViewOpacity(props) {

View File

@ -58,6 +58,7 @@
:on-press on-press} :on-press on-press}
[rn/view [rn/view
{:style (style/row-container sub-label)} {:style (style/row-container sub-label)}
(when icon
[rn/view [rn/view
{:accessibility-label :left-icon-for-action {:accessibility-label :left-icon-for-action
:accessible true :accessible true
@ -65,7 +66,7 @@
[icon/icon icon [icon/icon icon
{:color (or icon-color (get-icon-color danger? theme)) {:color (or icon-color (get-icon-color danger? theme))
:no-color no-icon-color? :no-color no-icon-color?
:size 20}]] :size 20}]])
[rn/view [rn/view
{:style style/text-container} {:style style/text-container}
[text/text [text/text

View File

@ -187,6 +187,11 @@
; EIP1581 Chat Key 0, the default whisper key ; EIP1581 Chat Key 0, the default whisper key
(def ^:const path-whisper (str path-eip1581 "/0'/0")) (def ^:const path-whisper (str path-eip1581 "/0'/0"))
(def ^:const path-ropsten-testnet "m/44'/1'/0")
(def ^:const path-ledger "m/44'/60'/0'")
(def ^:const path-ledger-live "m/44'/60'")
(def ^:const path-keepkey "m/44'/60'")
(def ^:const path-default-wallet-keyword (keyword path-default-wallet)) (def ^:const path-default-wallet-keyword (keyword path-default-wallet))
(def ^:const path-whisper-keyword (keyword path-whisper)) (def ^:const path-whisper-keyword (keyword path-whisper))
(def ^:const path-wallet-root-keyword (keyword path-wallet-root)) (def ^:const path-wallet-root-keyword (keyword path-wallet-root))

View File

@ -3,8 +3,14 @@
[status-im.contexts.wallet.create-account.edit-derivation-path.view :as edit-derivation-path] [status-im.contexts.wallet.create-account.edit-derivation-path.view :as edit-derivation-path]
[test-helpers.component :as h])) [test-helpers.component :as h]))
(def sub-mocks
{:profile/profile {:public-key "123"}
:contacts/contact-two-names-by-identity ["a"]
:profile/image "image"})
(h/describe "Edit derivation path page" (h/describe "Edit derivation path page"
(h/test "Default render" (h/test "Default render"
(h/setup-subs sub-mocks)
(h/render-with-theme-provider [edit-derivation-path/view {}]) (h/render-with-theme-provider [edit-derivation-path/view {}])
(h/is-truthy (h/get-by-translation-text :t/edit-derivation-path)) (h/is-truthy (h/get-by-translation-text :t/edit-derivation-path))
(h/is-truthy (h/get-by-translation-text :t/path-format)) (h/is-truthy (h/get-by-translation-text :t/path-format))
@ -14,6 +20,7 @@
(h/test "Reveal address pressed" (h/test "Reveal address pressed"
(h/setup-subs sub-mocks)
(let [on-reveal (h/mock-fn)] (let [on-reveal (h/mock-fn)]
(h/render-with-theme-provider [edit-derivation-path/view {:on-reveal on-reveal}]) (h/render-with-theme-provider [edit-derivation-path/view {:on-reveal on-reveal}])
(h/fire-event :press (h/get-by-translation-text :t/reveal-address)) (h/fire-event :press (h/get-by-translation-text :t/reveal-address))
@ -21,6 +28,7 @@
(h/wait-for #(h/is-truthy (h/get-by-translation-text :t/address-activity))))) (h/wait-for #(h/is-truthy (h/get-by-translation-text :t/address-activity)))))
(h/test "Reset button pressed" (h/test "Reset button pressed"
(h/setup-subs sub-mocks)
(let [on-reset (h/mock-fn)] (let [on-reset (h/mock-fn)]
(h/render-with-theme-provider [edit-derivation-path/view {:on-reset on-reset}]) (h/render-with-theme-provider [edit-derivation-path/view {:on-reset on-reset}])
(h/fire-event :press (h/get-by-translation-text :t/reset)) (h/fire-event :press (h/get-by-translation-text :t/reset))

View File

@ -0,0 +1,39 @@
(ns status-im.contexts.wallet.create-account.edit-derivation-path.path-format-sheet.view
(:require
[quo.core :as quo]
[status-im.constants :as constants]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[]
(let [{:keys [customization-color]} (rf/sub [:get-screen-params])]
[:<>
[quo/drawer-top {:title (i18n/label :t/path-format)}]
[quo/action-drawer
[[{:accessibility-label :default-ethereum-format
:label (i18n/label :t/default-ethereum-format)
:state :selected
:customization-color customization-color
:sub-label constants/path-wallet-root}
{:accessibility-label :ropsten-testnet
:label (i18n/label :t/ropsten-testnet)
:sub-label constants/path-ropsten-testnet
:customization-color customization-color}
{:accessibility-label :ledger
:label (i18n/label :t/ledger)
:sub-label constants/path-ledger
:customization-color customization-color}
{:accessibility-label :ledger-live
:label (i18n/label :t/ledger-live)
:sub-label constants/path-ledger-live
:customization-color customization-color}
{:accessibility-label :keepkey
:label (i18n/label :t/keep-key)
:sub-label constants/path-keepkey
:customization-color customization-color}
{:icon :i/customize
:accessibility-label :custom
:label (i18n/label :t/custom)
:sub-label (i18n/label :t/type-your-path)
:add-divider? true}]]]]))

View File

@ -17,7 +17,7 @@
(def input-container (def input-container
{:padding-horizontal 20 {:padding-horizontal 20
:padding-top 12}) :padding-top 20})
(defn save-button-container (defn save-button-container
[bottom] [bottom]

View File

@ -1,12 +1,15 @@
(ns status-im.contexts.wallet.create-account.edit-derivation-path.view (ns status-im.contexts.wallet.create-account.edit-derivation-path.view
(:require (:require
[quo.core :as quo] [quo.core :as quo]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme] [quo.theme :as quo.theme]
[react-native.core :as rn] [react-native.core :as rn]
[react-native.safe-area :as safe-area] [react-native.safe-area :as safe-area]
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im.contexts.wallet.common.temp :as temp] [status-im.contexts.wallet.common.temp :as temp]
[status-im.contexts.wallet.common.utils :as utils] [status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.create-account.edit-derivation-path.path-format-sheet.view :as
path-format-sheet]
[status-im.contexts.wallet.create-account.edit-derivation-path.style :as style] [status-im.contexts.wallet.create-account.edit-derivation-path.style :as style]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
@ -25,7 +28,7 @@
(when on-reveal (when on-reveal
(on-reveal))) (on-reveal)))
clear-action #(reset! state :empty) clear-action #(reset! state :empty)
derive-action #(reset! state :choose) derive-action #(js/alert "To be implemented")
choose-action #(reset! state :show) choose-action #(reset! state :show)
path-value (reagent/atom (utils/get-formatted-derivation-path 3)) path-value (reagent/atom (utils/get-formatted-derivation-path 3))
handle-path-change (fn [v] handle-path-change (fn [v]
@ -38,12 +41,18 @@
(when on-reset (when on-reset
(on-reset)))] (on-reset)))]
(fn [{:keys [theme]}] (fn [{:keys [theme]}]
(let [{:keys [public-key]} (rf/sub [:profile/profile])
primary-name (first (rf/sub [:contacts/contact-two-names-by-identity
public-key]))
profile-picture (rf/sub [:profile/image])
show-path-format-sheet #(rf/dispatch [:show-bottom-sheet {:content path-format-sheet/view}])]
[rn/view [rn/view
{:style (style/screen top)} {:style (style/screen top)}
[quo/page-nav [quo/page-nav
{:background :blur {:background :blur
:icon-name :i/close :icon-name :i/close
:on-press #(rf/dispatch [:navigate-back])}] :on-press #(rf/dispatch [:navigate-back])}]
[rn/view {:style {:padding-bottom 20}}
[quo/text [quo/text
{:size :heading-1 {:size :heading-1
:weight :semi-bold :weight :semi-bold
@ -51,17 +60,31 @@
(i18n/label :t/edit-derivation-path)] (i18n/label :t/edit-derivation-path)]
[rn/view {:style style/tag} [rn/view {:style style/tag}
[quo/context-tag [quo/context-tag
{:type :icon {:size 24
:size 24 :profile-picture profile-picture
:icon :i/placeholder
:style style/tag :style style/tag
:context "Alisher Card"}]] :full-name primary-name}]]]
[rn/view {:style style/temporal-placeholder} [rn/pressable {:on-press show-path-format-sheet}
[quo/text "Dropdown input will be here"] [quo/input
[quo/text (i18n/label :t/path-format)]] {:small? true
:editable false
:placeholder (i18n/label :t/search-assets)
:right-icon {:on-press show-path-format-sheet
:icon-name :i/dropdown
:style-fn (fn []
{:color (colors/theme-colors colors/neutral-20
colors/neutral-80
theme)
:color-2 (colors/theme-colors colors/neutral-100
colors/white
theme)})}
:label (i18n/label :t/path-format)
:value (i18n/label :t/default-format)
:container-style {:margin-horizontal 20}}]]
[quo/input [quo/input
{:container-style style/input-container {:container-style style/input-container
:value @path-value :value @path-value
:editable false
:label (i18n/label :t/derivation-path) :label (i18n/label :t/derivation-path)
:placeholder (utils/get-formatted-derivation-path 3) :placeholder (utils/get-formatted-derivation-path 3)
:button {:on-press reset-path-value :button {:on-press reset-path-value
@ -71,8 +94,7 @@
(case @state (case @state
:default :default
[quo/bottom-actions [quo/bottom-actions
{:theme theme {:actions :one-action
:actions :one-action
:button-one-label (i18n/label :t/reveal-address) :button-one-label (i18n/label :t/reveal-address)
:button-one-props {:type :outline :button-one-props {:type :outline
:icon-left :i/keycard-card :icon-left :i/keycard-card
@ -80,8 +102,7 @@
:empty :empty
[quo/bottom-actions [quo/bottom-actions
{:theme theme {:actions :one-action
:actions :one-action
:button-one-label (i18n/label :t/derive-addresses) :button-one-label (i18n/label :t/derive-addresses)
:button-one-props {:type :outline :button-one-props {:type :outline
:icon-left :i/keycard-card :icon-left :i/keycard-card
@ -105,16 +126,21 @@
[quo/button [quo/button
{:on-press (fn [_] {:on-press (fn [_]
(reset! path-value (utils/get-formatted-derivation-path 1)) (reset! path-value (utils/get-formatted-derivation-path 1))
(choose-action))} "Choose"]] (choose-action))}
"Choose"]]
nil) nil)
[rn/view {:style (style/save-button-container bottom)} [rn/view {:style (style/save-button-container bottom)}
[quo/bottom-actions [quo/bottom-actions
{:theme theme {:actions :one-action
:actions :one-action
:button-one-label (i18n/label :t/save) :button-one-label (i18n/label :t/save)
:button-one-props {:type :primary :button-one-props {:type :primary
:on-press #(js/alert "Save!") :on-press #(js/alert "Save!")
:disabled? true}}]]]))) :disabled? true}}]]
(when-not (= @state :show)
[quo/numbered-keyboard
{:left-action :dot
:delete-key? true}])]))))
(def view (quo.theme/with-theme view-internal)) (def view (quo.theme/with-theme view-internal))

View File

@ -14,6 +14,7 @@
[status-im.contexts.wallet.create-account.style :as style] [status-im.contexts.wallet.create-account.style :as style]
[status-im.contexts.wallet.create-account.utils :as create-account.utils] [status-im.contexts.wallet.create-account.utils :as create-account.utils]
[status-im.contexts.wallet.sheets.account-origin.view :as account-origin] [status-im.contexts.wallet.sheets.account-origin.view :as account-origin]
[status-im.feature-flags :as ff]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf] [utils.re-frame :as rf]
[utils.responsiveness :refer [iphone-11-Pro-20-pixel-from-width]] [utils.responsiveness :refer [iphone-11-Pro-20-pixel-from-width]]
@ -32,7 +33,7 @@
:customization-color account-color}) :customization-color account-color})
:action (when-not keypair-name :button) :action (when-not keypair-name :button)
:action-props {:on-press (fn [] :action-props {:on-press (fn []
(rf/dispatch [:navigate-to :scrren/wallet.select-keypair])) (rf/dispatch [:navigate-to :screen/wallet.select-keypair]))
:button-text (i18n/label :t/edit) :button-text (i18n/label :t/edit)
:alignment :flex-start} :alignment :flex-start}
:description :text :description :text
@ -41,7 +42,13 @@
:image :icon :image :icon
:image-props :i/derivated-path :image-props :i/derivated-path
:action :button :action :button
:action-props {:on-press #(js/alert "Coming soon!") :action-props {:on-press (fn []
(ff/alert ::ff/wallet.network-filter
#(rf/dispatch [:navigate-to
:screen/wallet.edit-derivation-path
{:customization-color account-color}])))
:button-text (i18n/label :t/edit) :button-text (i18n/label :t/edit)
:icon-left :i/placeholder :icon-left :i/placeholder
:alignment :flex-start} :alignment :flex-start}

View File

@ -12,6 +12,7 @@
(reagent/atom (reagent/atom
{::wallet.edit-default-keypair true {::wallet.edit-default-keypair true
::wallet.bridge-token (enabled-in-env? :FLAG_BRIDGE_TOKEN_ENABLED) ::wallet.bridge-token (enabled-in-env? :FLAG_BRIDGE_TOKEN_ENABLED)
::wallet.edit-derivation-path (enabled-in-env? :FLAG_EDIT_DERIVATION_PATH)
::wallet.remove-account (enabled-in-env? :FLAG_REMOVE_ACCOUNT_ENABLED) ::wallet.remove-account (enabled-in-env? :FLAG_REMOVE_ACCOUNT_ENABLED)
::wallet.network-filter (enabled-in-env? :FLAG_NETWORK_FILTER_ENABLED) ::wallet.network-filter (enabled-in-env? :FLAG_NETWORK_FILTER_ENABLED)
::profile.new-contact-ui (enabled-in-env? :FLAG_NEW_CONTACT_UI_ENABLED) ::profile.new-contact-ui (enabled-in-env? :FLAG_NEW_CONTACT_UI_ENABLED)

View File

@ -9,6 +9,7 @@
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[status-im.common.pixel-ratio :as pixel-ratio] [status-im.common.pixel-ratio :as pixel-ratio]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.contexts.profile.utils :as profile.utils]
[utils.address :as address] [utils.address :as address]
[utils.image-server :as image-server] [utils.image-server :as image-server]
[utils.security.core :as security])) [utils.security.core :as security]))
@ -129,6 +130,12 @@
(fn [{:keys [preferred-name]}] (fn [{:keys [preferred-name]}]
preferred-name)) preferred-name))
(re-frame/reg-sub
:profile/image
:<- [:profile/profile-with-image]
(fn [profile]
(profile.utils/photo profile)))
(re-frame/reg-sub (re-frame/reg-sub
:multiaccount/default-account :multiaccount/default-account
:<- [:wallet/accounts] :<- [:wallet/accounts]

View File

@ -2547,5 +2547,12 @@
"provider-is-down": "The provider for the following chain(s) is down: {{chains}}", "provider-is-down": "The provider for the following chain(s) is down: {{chains}}",
"unknown": "Unknown", "unknown": "Unknown",
"unsupported-file": "Unsupported file", "unsupported-file": "Unsupported file",
"cant-fetch-info": "Can't fetch info" "cant-fetch-info": "Can't fetch info",
"default-ethereum-format": "Default Ethereum format",
"ropsten-testnet": "Ropsten Testnet",
"ledger": "Ledger",
"ledger-live": "Ledger live",
"keep-key": "KeepKey",
"type-your-path": "Type your own derivation path",
"default-format": "Default format"
} }