Compare commits

..
Author SHA1 Message Date
Ulises M 56962fde77 WIP 2 2025-01-30 10:16:29 -06:00
Ulises M 248bd853a8 WIP: Testing alias from status-go 2025-01-29 21:17:14 -06:00
185 changed files with 1842 additions and 3493 deletions
-4
View File
@@ -143,10 +143,6 @@ android {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17
}
// Disable default lint checks to remove redundant lintVitalReportRelease task
lintOptions {
checkReleaseBuilds false
}
// https://developer.android.com/studio/projects/install-ndk#vanilla_cmake
externalNativeBuild {
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.17'
library 'status-jenkins-lib@v1.9.13'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.17'
library 'status-jenkins-lib@v1.9.13'
import groovy.json.JsonBuilder
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.17'
library 'status-jenkins-lib@v1.9.13'
pipeline {
agent { label 'linux' }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.17'
library 'status-jenkins-lib@v1.9.13'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.17'
library 'status-jenkins-lib@v1.9.13'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
-39
View File
@@ -1,39 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Fallback versions for each dependency
readonly FOOJAY_FALLBACK="0.5.0"
readonly KOTLIN_FALLBACK="1.8.0"
readonly TOOLS_FALLBACK="3.5.4"
readonly HERMES_FALLBACK="0.73.5"
GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel)
cd "${GIT_ROOT}"
get_version() {
local file="$1"
local pattern="$2"
local fallback="$3"
local version
if [[ ! -f "$file" ]]; then
echo "$fallback"
return 0
fi
version=$(grep "$pattern" "$file" 2>/dev/null | grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.*[0-9]*" | tail -n1 || echo "$fallback")
echo "$version"
}
foojay_version=$(get_version "./node_modules/@react-native/gradle-plugin/settings.gradle.kts" "foojay.*version" "$FOOJAY_FALLBACK")
kotlin_version=$(get_version "./node_modules/@react-native/gradle-plugin/gradle/libs.versions.toml" "kotlin =" "$KOTLIN_FALLBACK")
tools_version=$(get_version "./patches/BlurView-build.gradle.patch" "gradle:" "$TOOLS_FALLBACK")
hermes_version=$(get_version "./node_modules/react-native/ReactAndroid/gradle.properties" "VERSION_NAME" "$HERMES_FALLBACK")
cat << EOF
org.gradle.toolchains.foojay-resolver-convention:org.gradle.toolchains.foojay-resolver-convention.gradle.plugin:$foojay_version
org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:$kotlin_version
com.android.tools.build:gradle:$tools_version
com.facebook.react:hermes-android:$hermes_version
EOF
+8 -2
View File
@@ -38,10 +38,16 @@ function gen_deps_list() {
echo -e "${CLR}Found ${GRN}$(wc -l < "${DEPS_LIST}")${RST} direct dependencies..."
}
# FIXME: Fix for missing packages.
# FIXME: Temporary fix for missing packages.
# https://github.com/status-im/status-mobile/issues/15447
function add_deps_hack() {
"${CUR_DIR}/deps_versions.sh" >> "${DEPS_LIST}"
echo -n \
'org.gradle.toolchains.foojay-resolver-convention:org.gradle.toolchains.foojay-resolver-convention.gradle.plugin:0.5.0
org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.8.0
com.android.tools.build:gradle:3.5.4
com.android.tools.lint:lint-gradle:31.1.1
com.facebook.react:hermes-android:0.73.5' \
>> "${DEPS_LIST}"
}
# Find download URLs for each dependency.
+2 -2
View File
@@ -1,8 +1,8 @@
#!/usr/bin/env bash
# This script generates a list of dependencies for the main project and its
# sub-projects defined using Gradle config files. It uses github-dependency-graph-gradle-plugin:
# https://github.com/gradle/github-dependency-graph-gradle-plugin?tab=readme-ov-file#using-the-plugin-to-generate-dependency-reports
# sub-projects defined using Gradle config files. It parses Gradle output of
# 'dependencies' and 'buildEnvironment` tasks using AWK.
set -Eeuo pipefail
+3 -2
View File
@@ -13,8 +13,8 @@ let
repo = "status-go";
rev = "unknown";
shortRev = rev;
version = "unknown";
cleanVersion = version;
rawVersion = "develop";
cleanVersion = rawVersion;
goPackagePath = "github.com/${owner}/${repo}";
# We use builtins.path so that we can name the resulting derivation,
# Normally the name would not be deterministic, taken from the checkout directory.
@@ -43,6 +43,7 @@ let
inherit (versionJSON) owner repo version;
rev = versionJSON.commit-sha1;
shortRev = strings.substring 0 7 rev;
rawVersion = versionJSON.version;
cleanVersion = lib.sanitizeVersion versionJSON.version;
# Need to pretend this is from status-im to let Go build it.
goPackagePath = "github.com/status-im/${repo}";
Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

+5 -4
View File
@@ -10,10 +10,11 @@
([{:keys [style]} child]
(let [theme (quo.theme/use-theme)]
[rn/view
{:style [style
{:pointer-events :box-none
:background-color (or (:background-color style)
(colors/theme-colors colors/white colors/neutral-80 theme))}]}
{:style (assoc style
:pointer-events :box-none
:background-color
(or (:background-color style)
(colors/theme-colors colors/white colors/neutral-80 theme)))}
child])))
(def view (if platform/ios? blur/view view-android))
+58 -59
View File
@@ -56,63 +56,62 @@
24 8
12))})
(defn container-styles
(defn style-container
[{:keys [size disabled? border-radius background-color border-color icon-only? icon-top
icon-left icon-right inner-style]}]
[{:height size
:align-items :center
:justify-content :center
:flex-direction (if icon-top :column :row)
:padding-horizontal (when-not (or icon-only? icon-left icon-right)
(case size
56 (if border-color 10 11)
40 16
32 12
24 7
16))
:padding-left (when-not (or icon-only? icon-left)
(case size
56 nil
40 16
32 12
24 8
16))
:padding-right (when-not (or icon-only? icon-right)
(case size
56 nil
40 16
32 12
24 8
16))
:padding-top (when-not (or icon-only? icon-left icon-right)
(case size
56 0
40 (if border-color 8 9)
32 (if border-color 4 5)
24 0
(if border-color 8 9)))
:padding-bottom (when-not (or icon-only? icon-left icon-right)
(case size
56 0
40 9
32 5
24 0
9))
:overflow :hidden
:background-color (if disabled? (colors/alpha background-color 0.3) background-color)
:border-radius (if border-radius
border-radius
(case size
56 12
40 12
32 10
24 8
12))
:border-color border-color
:border-width (when border-color 1)}
(when icon-only?
{:width size})
(when border-color
{:border-color border-color
:border-width 1})
inner-style])
icon-left icon-right]}]
(merge {:height size
:align-items :center
:justify-content :center
:flex-direction (if icon-top :column :row)
:padding-horizontal (when-not (or icon-only? icon-left icon-right)
(case size
56 (if border-color 10 11)
40 16
32 12
24 7
16))
:padding-left (when-not (or icon-only? icon-left)
(case size
56 nil
40 16
32 12
24 8
16))
:padding-right (when-not (or icon-only? icon-right)
(case size
56 nil
40 16
32 12
24 8
16))
:padding-top (when-not (or icon-only? icon-left icon-right)
(case size
56 0
40 (if border-color 8 9)
32 (if border-color 4 5)
24 0
(if border-color 8 9)))
:padding-bottom (when-not (or icon-only? icon-left icon-right)
(case size
56 0
40 9
32 5
24 0
9))
:overflow :hidden
:background-color (if disabled? (colors/alpha background-color 0.3) background-color)
:border-radius (if border-radius
border-radius
(case size
56 12
40 12
32 10
24 8
12))
:border-color border-color
:border-width (when border-color 1)}
(when icon-only?
{:width size})
(when border-color
{:border-color border-color
:border-width 1})))
+7 -4
View File
@@ -62,9 +62,12 @@
:on-press on-press
:allow-multiple-presses? allow-multiple-presses?
:on-long-press on-long-press
:style [(style/shape-style-container size border-radius) container-style]}
:style (merge
(style/shape-style-container size border-radius)
container-style)}
[rn/view
{:style (style/container-styles {:size size
{:style (merge
(style/style-container {:size size
:disabled? disabled?
:border-radius border-radius
:background-color background-color
@@ -72,8 +75,8 @@
:icon-only? icon-only?
:icon-top icon-top
:icon-left icon-left
:icon-right icon-right
:inner-style inner-style})}
:icon-right icon-right})
inner-style)}
(when overlay-customization-color
[customization-colors/overlay
{:customization-color overlay-customization-color
@@ -58,7 +58,7 @@
:error
[info-message/view
{:icon :i/alert
{:icon :i/info
:size :default
:status :error}
text]
+1 -2
View File
@@ -30,8 +30,7 @@
selected? (assoc :border-top-color (colors/alpha color 0.4)
:border-end-color (colors/alpha color 0.4)
:border-bottom-color (colors/alpha color 0.2)
:border-start-color (colors/alpha color 0.2)
:border-color nil)
:border-start-color (colors/alpha color 0.2))
(zero? idx) (assoc :margin-left -4))))
(defn color-circle
@@ -31,8 +31,7 @@
[:scroll? {:optional true} [:maybe :boolean]]
[:blur? {:optional true} [:maybe :boolean]]
[:container-style {:optional true} [:maybe :map]]
[:buttons-container-style {:optional true} [:maybe :map]]
[:buttons-style {:optional true} [:maybe :map]]]]]
[:buttons-container-style {:optional true} [:maybe :map]]]]]
:any])
(def ^:private role-icon
@@ -44,9 +43,10 @@
(defn- view-internal
[{:keys [actions description description-text description-top-text error-message role button-one-label
button-two-label blur? button-one-props button-two-props scroll? container-style
buttons-container-style buttons-style context-tag-props]}]
buttons-container-style context-tag-props]}]
(let [theme (quo.theme/use-theme)]
[rn/view {:style (merge (style/container scroll? blur? theme) container-style)}
[rn/view
{:style (merge (style/container scroll? blur? theme) container-style)}
(when (= description :top-error)
[rn/view {:style style/error-message}
[icon/icon
@@ -82,7 +82,7 @@
[button/button
(merge
{:size 40
:container-style (merge style/button-container buttons-style)
:container-style style/button-container
:background (when (or blur? scroll?) :blur)
:theme theme
:accessibility-label :button-two}
@@ -91,7 +91,7 @@
[button/button
(merge
{:size 40
:container-style (merge style/button-container buttons-style)
:container-style style/button-container
:background (when (or blur? scroll?) :blur)
:theme theme
:accessibility-label :button-one}
@@ -13,11 +13,11 @@
(def content
{:align-items :flex-start
:margin-top 8
:margin-bottom (+ (safe-area/get-bottom) 12)})
(defn title
[theme]
{:color (colors/theme-colors colors/neutral-100
colors/white
theme)
:margin-bottom 8})
{:color (colors/theme-colors colors/neutral-100
colors/white
theme)})
@@ -24,13 +24,12 @@
:always-bounce-vertical false
:content-inset-adjustment-behavior :never}
[rn/view {:style style/container}
(when title
[text/text
{:size :heading-2
:accessibility-label :documentation-drawer-title
:style (style/title theme)
:weight :semi-bold}
title])
[text/text
{:size :heading-2
:accessibility-label :documentation-drawer-title
:style (style/title theme)
:weight :semi-bold}
title]
[rn/view {:style style/content :accessibility-label :documentation-drawer-content}
content
(when show-button?
@@ -57,10 +57,17 @@
:container-style style/keycard-icon}])])
(defn- account-subtitle
[{:keys [description]}]
[address-text/view
{:address description
:format :short}])
[{:keys [networks theme blur? description]}]
(if networks
[address-text/view
{:networks networks
:address description
:format :short}]
[text/text
{:size :paragraph-2
:weight :regular
:style (style/description theme blur?)}
description]))
(defn- default-keypair-subtitle
[{:keys [description theme blur?]}]
@@ -102,7 +109,7 @@
description])
(defn- subtitle
[{:keys [type theme blur? stored description community-name community-logo
[{:keys [type theme blur? stored networks description community-name community-logo
context-tag-type account-name emoji customization-color full-name profile-picture context
icon]}]
(cond
@@ -114,7 +121,8 @@
(= :account type)
[account-subtitle
{:theme theme
{:networks networks
:theme theme
:blur? blur?
:description description}]
@@ -197,11 +205,11 @@
(defn view
[{:keys [title title-icon type description blur? community-name community-logo button-icon
account-name emoji context-tag-type button-type container-style
on-button-press on-button-long-press profile-picture stored label full-name
on-button-press on-button-long-press profile-picture stored networks label full-name
button-disabled? account-avatar-emoji account-avatar-type customization-color icon-avatar
context icon]}]
(let [theme (quo.theme/use-theme)]
[rn/view {:style [style/container container-style]}
[rn/view {:style (merge style/container container-style)}
(when (left-image-supported-types type)
[rn/view {:style style/left-container}
[left-image
@@ -225,6 +233,7 @@
:theme theme
:blur? blur?
:stored stored
:networks networks
:description description
:community-name community-name
:community-logo community-logo
@@ -35,4 +35,4 @@
(def image-placeholder
{:width 80
:height 80
:background-color colors/danger-50})
:background-color colors/danger})
@@ -18,5 +18,5 @@
:colors [color-top color-bottom]
:start {:x 0 :y 0}
:end {:x 0 :y 1}
:style [(style/root-container opacity height)
container-style]}])))
:style (merge (style/root-container opacity height)
container-style)}])))
@@ -53,7 +53,7 @@
(colors/theme-colors colors/neutral-30 colors/neutral-60 theme)))
(defn address-input
[{:keys [default-value blur? on-change-text on-blur on-focus on-clear on-scan on-paste
[{:keys [default-value blur? on-change-text on-blur on-focus on-clear on-scan
on-detect-ens on-detect-address on-detect-unclassified address-regex ens-regex
valid-ens-or-address? container-style]}]
(let [theme (quo.theme/use-theme)
@@ -82,13 +82,12 @@
(not ens?)
on-detect-unclassified)
(on-detect-unclassified text)))))
on-paste (rn/use-callback #(if (fn? on-paste)
(on-paste on-change)
(clipboard/get-string
(fn [clipboard]
(when-not (empty? clipboard)
(on-change clipboard)))))
[on-paste])
on-paste (rn/use-callback
(fn []
(clipboard/get-string
(fn [clipboard]
(when-not (empty? clipboard)
(on-change clipboard))))))
on-clear (rn/use-callback
(fn []
(on-change "")
+2 -2
View File
@@ -31,7 +31,7 @@
:placeholder (colors/theme-colors colors/neutral-80-opa-20 colors/white-opa-20 theme)
:text (colors/theme-colors colors/neutral-100 colors/white theme)}
:error
{:border-color colors/danger-50-opa-40
{:border-color (colors/theme-colors colors/danger-opa-40 colors/danger-opa-40 theme)
:placeholder (colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-40 theme)
:text (colors/theme-colors colors/neutral-100 colors/white theme)}
:disabled
@@ -48,7 +48,7 @@
:placeholder (colors/theme-colors colors/neutral-30 colors/neutral-60 theme)
:text (colors/theme-colors colors/neutral-100 colors/white theme)}
:error
{:border-color colors/danger-50-opa-40
{:border-color (colors/theme-colors colors/danger-opa-40 colors/danger-opa-40 theme)
:placeholder (colors/theme-colors colors/neutral-40 colors/white-opa-40 theme)
:text (colors/theme-colors colors/neutral-100 colors/white theme)}
:disabled
+1 -1
View File
@@ -131,7 +131,7 @@
:char-limit char-limit
:theme theme}])
[rn/view
{:style [(style/input-container colors-by-status small? disabled?) input-container-style]}
{:style (merge (style/input-container colors-by-status small? disabled?) input-container-style)}
(when-let [{:keys [icon-name]} left-icon]
[left-accessory
{:variant-colors variant-colors
@@ -4,7 +4,11 @@
[test-helpers.component :as h]))
(h/describe "keycard component"
(let [holder-name "Alisha"]
(h/test "Render of keycard component when: holder-name prop is set"
(h/test "Render of keycard component when: holder-name prop is not set"
(h/render [keycard/keycard])
(h/is-truthy (h/get-by-translation-text :t/empty-keycard)))
(h/test "Render of keycard component when: holder-name prop is set"
(let [holder-name "Alisha"]
(h/render [keycard/keycard {:holder-name holder-name}])
(h/is-truthy (h/get-by-translation-text :t/user-keycard {:name holder-name})))))
+16 -4
View File
@@ -6,21 +6,21 @@
(def keycard-chip-height 28)
(defn card-container
[locked? theme blur?]
[locked? theme]
{:overflow :hidden
:height keycard-height
:align-items :flex-start
:justify-content :space-between
:border-width 1
:border-color (if (or locked? blur?)
:border-color (if locked?
colors/white-opa-5
(colors/theme-colors colors/neutral-20 colors/neutral-80 theme))
:border-style :solid
:border-radius 16
:padding 16
:background-color (if locked?
(colors/theme-colors colors/danger-50 colors/danger-50-opa-40 theme)
colors/keycard-color)})
(colors/theme-colors colors/danger colors/danger-opa-40 theme)
(colors/theme-colors colors/neutral-5 colors/neutral-90 theme))})
(defn keycard-logo
[locked? theme]
@@ -28,6 +28,18 @@
colors/white
(colors/theme-colors colors/neutral-100 colors/white theme))})
(defn keycard-watermark
[locked? theme]
{:position :absolute
:tint-color (if locked?
colors/white-opa-5
(colors/theme-colors colors/neutral-100 colors/white theme))
:align-self :center
:height 280.48
:transform [{:rotate "-30deg"} {:translateY -30}]
:opacity (when-not locked? 0.02)
:z-index 1})
(def keycard-chip
{:height keycard-chip-height
:position :absolute
+19 -15
View File
@@ -1,6 +1,5 @@
(ns quo.components.keycard.view
(:require
[clojure.string :as string]
[quo.components.keycard.style :as style]
[quo.components.tags.tag :as tag]
[quo.foundations.colors :as colors]
@@ -15,9 +14,12 @@
- :locked? - Boolean to specify whether the keycard is locked or not
- :theme :light/:dark
"
[{:keys [holder-name locked? blur?]}]
(let [theme (quo.theme/use-theme)]
[rn/view {:style (style/card-container locked? theme blur?)}
[{:keys [holder-name locked?]}]
(let [theme (quo.theme/use-theme)
label (if holder-name
(i18n/label :t/user-keycard {:name holder-name})
(i18n/label :t/empty-keycard))]
[rn/view {:style (style/card-container locked? theme)}
[rn/image
{:source (resources/get-image :keycard-logo)
:style (style/keycard-logo locked? theme)}]
@@ -25,14 +27,16 @@
{:source (resources/get-image
(if (or locked? (= :dark theme)) :keycard-chip-dark :keycard-chip-light))
:style style/keycard-chip}]
(when-not (string/blank? holder-name)
[tag/tag
{:size 32
:type (when locked? :icon)
:label (i18n/label :t/user-keycard {:name holder-name})
:labelled? true
:blurred? true
:resource (when locked? :i/locked)
:accessibility-label :holder-name
:icon-color colors/white-70-blur
:override-theme (when locked? :dark)}])]))
[rn/image
{:source (resources/get-image :keycard-watermark)
:style (style/keycard-watermark locked? theme)}]
[tag/tag
{:size 32
:type (when locked? :icon)
:label label
:labelled? true
:blurred? true
:resource (when locked? :i/locked)
:accessibility-label :holder-name
:icon-color colors/white-70-blur
:override-theme (when locked? :dark)}]]))
@@ -15,6 +15,7 @@
(h/test "Test icon renders for ':action :icon'"
(h/render-with-theme-provider [account-list-card/view
{:account-props account-props
:network :ethereum
:action :icon
:on-options-press (fn [])}])
(h/is-truthy (h/get-by-label-text :icon))))
@@ -12,7 +12,7 @@
[schema.core :as schema]))
(defn- internal-view
[{:keys [action blur? account-props on-press on-options-press]}]
[{:keys [action blur? account-props networks on-press on-options-press]}]
(let [theme (quo.theme/use-theme)
[state set-state] (rn/use-state :default)
on-press-in (rn/use-callback #(set-state :pressed))
@@ -31,9 +31,10 @@
:size :paragraph-2}
(:name account-props)]
[address-text/view
{:blur? blur?
:address (:address account-props)
:format :short}]]]
{:blur? blur?
:networks networks
:address (:address account-props)
:format :short}]]]
(when (= action :icon)
[rn/pressable {:on-press on-options-press}
[icon/icon :i/options
+1 -1
View File
@@ -48,7 +48,7 @@
:margin-left -4}
(if (= type :top)
{:top 0}
{:transform [{:rotate-z "180deg"}]
{:transform [{:rotateZ "180deg"}]
:bottom 0})
style)}]))
@@ -35,7 +35,7 @@
subtitle]]])
(defn- main-variant
[{:keys [title subtitle button-label image max-height accessibility-label on-press button-props]}]
[{:keys [title subtitle button-label image max-height accessibility-label on-press button-type]}]
[rn/view {:style style/main-variant}
[rn/view {:style style/main-variant-text-container}
[text/text
@@ -56,20 +56,18 @@
:resize-mode :contain
:source image}]
[button/button
(merge
{:on-press on-press
:accessibility-label accessibility-label
:type :grey
:size 40
:container-style style/main-button
:theme :dark
:background :blur}
button-props)
{:on-press on-press
:accessibility-label accessibility-label
:type (or button-type :grey)
:size 40
:container-style style/main-button
:theme :dark
:background :blur}
button-label]])
(defn small-option-card
[{:keys [variant title subtitle button-label image max-height on-press accessibility-label
button-props container-style]
button-type container-style]
:or {variant :main accessibility-label :small-option-card}}]
(let [main-variant? (= variant :main)
card-component (if main-variant? main-variant icon-variant)
@@ -86,4 +84,4 @@
:accessibility-label accessibility-label
:image image
:max-height max-height
:button-props button-props}]]))
:button-type button-type}]]))
@@ -10,7 +10,7 @@
[{:keys [label data container-style blur?]}]
(let [theme (quo.theme/use-theme)
last-item (rn/use-memo #(last data) [data])]
[rn/view {:style [(style/container label) container-style]}
[rn/view {:style (merge (style/container label) container-style)}
(when label
[text/text
{:weight :medium
@@ -29,3 +29,4 @@
[data-item/view data-item-props]
(when-not (= item last-item)
[rn/view {:style (style/settings-separator blur? theme)}])])]]))
@@ -24,7 +24,7 @@
separator (rn/use-memo (fn [] [rn/view
{:style (style/reorder-separator blur? theme)}])
[blur? theme])]
[rn/view {:style [(style/container label) container-style]}
[rn/view {:style (merge (style/container label) container-style)}
[text/text
{:weight :medium
:size :paragraph-2
@@ -11,7 +11,7 @@
(let [theme (quo.theme/use-theme)
settings-items (remove nil? data)
last-index (dec (count settings-items))]
[rn/view {:style [(style/container label) container-style]}
[rn/view {:style (merge (style/container label) container-style)}
(when label
[text/text
{:weight :medium
+6 -1
View File
@@ -10,7 +10,12 @@
{:flex 1}))
(def avatar-overlay
{:justify-content :center
{:position :absolute
:top 0
:right 0
:left 0
:bottom 0
:justify-content :center
:align-items :center})
(defn qr-image
+1 -1
View File
@@ -11,7 +11,7 @@
(defn- avatar-image
[{avatar-type :avatar
:as props}]
[rn/view {:style [rn/stylesheet-absolute-fill style/avatar-overlay]}
[rn/view {:style style/avatar-overlay}
[rn/view
{:style (case avatar-type
:wallet-account style/avatar-container-rounded
@@ -13,6 +13,8 @@
{:type :profile
:profile-picture 123})
(def wallet-props {:networks '(:ethereum)})
(def text-press-event
{:test-name "Text pressed"
:accessibility-label :share-qr-code-info-text
@@ -31,6 +33,24 @@
:event-name :press
:callback-prop-key :on-share-press})
(def multichain-press-event
{:test-name "Multichain tab pressed"
:accessibility-label :share-qr-code-multichain-tab
:event-name :press
:callback-prop-key :on-multichain-press})
(def legacy-press-event
{:test-name "Legacy tab pressed"
:accessibility-label :share-qr-code-legacy-tab
:event-name :press
:callback-prop-key :on-legacy-press})
(def settings-press-event
{:test-name "Settings pressed"
:accessibility-label :share-qr-code-settings
:event-name :press
:callback-prop-key :on-settings-press})
(defn render-share-qr-code
[props]
;; NOTE: rendering the profile type first, so that the re-render is triggered.
@@ -54,22 +74,45 @@
(h/is-truthy (h/get-by-text qr-label)))
(h/test "Wallet Legacy"
(render-share-qr-code (assoc default-props
:type
:wallet))
(render-share-qr-code (merge default-props
wallet-props
{:type :wallet
:address :legacy}))
(h/is-truthy (h/get-by-text qr-label)))
(h/test "Saved address"
(render-share-qr-code (assoc default-props
:type
:saved-address))
(h/test "Wallet multichain"
(render-share-qr-code (merge default-props
wallet-props
{:type :wallet
:address :multichain}))
(h/is-truthy (h/get-by-text qr-label)))
(h/test "Saved address legacy"
(render-share-qr-code (merge default-props
wallet-props
{:type :saved-address
:address :legacy}))
(h/is-truthy (h/get-by-text qr-label)))
(h/test "Watched address"
(render-share-qr-code (assoc default-props
:type
:watched-address))
(h/test "Saved address multichain"
(render-share-qr-code (merge default-props
wallet-props
{:type :saved-address
:address :multichain}))
(h/is-truthy (h/get-by-text qr-label)))
(h/test "Watched address legacy"
(render-share-qr-code (merge default-props
wallet-props
{:type :watched-address
:address :legacy}))
(h/is-truthy (h/get-by-text qr-label)))
(h/test "Watched address multichain"
(render-share-qr-code (merge default-props
wallet-props
{:type :watched-address
:address :multichain}))
(h/is-truthy (h/get-by-text qr-label))))
(h/describe "Fires all events for all types"
@@ -93,27 +136,78 @@
(h/describe "Wallet Legacy"
(test-fire-events
(assoc default-props
:type :wallet
:emoji "👻")
(merge default-props
wallet-props
{:type :wallet
:address :legacy
:emoji "👻"})
[text-press-event
text-long-press-event
share-press-event]))
share-press-event
multichain-press-event
legacy-press-event]))
(h/describe "Saved Address"
(h/describe "Wallet Multichain"
(test-fire-events
(assoc default-props
:type
:saved-address)
(merge default-props
wallet-props
{:type :wallet
:address :multichain
:emoji "👻"})
[text-press-event
text-long-press-event
share-press-event]))
share-press-event
legacy-press-event
multichain-press-event
settings-press-event]))
(h/describe "Watched Address"
(h/describe "Saved Address Legacy"
(test-fire-events
(assoc default-props
:type :watched-address
:emoji "👽")
(merge default-props
wallet-props
{:type :saved-address
:address :legacy})
[text-press-event
text-long-press-event
share-press-event])))))
share-press-event
legacy-press-event
multichain-press-event]))
(h/describe "Saved Address Multichain"
(test-fire-events
(merge default-props
wallet-props
{:type :saved-address :address :multichain})
[text-press-event
text-long-press-event
share-press-event
legacy-press-event
multichain-press-event
settings-press-event]))
(h/describe "Watched Address Legacy"
(test-fire-events
(merge default-props
wallet-props
{:type :watched-address
:address :legacy
:emoji "👽"})
[text-press-event
text-long-press-event
share-press-event
legacy-press-event
multichain-press-event]))
(h/describe "Watched Address Multichain"
(test-fire-events
(merge default-props
wallet-props
{:type :watched-address
:address :multichain
:emoji "👽"})
[text-press-event
text-long-press-event
share-press-event
legacy-press-event
multichain-press-event
settings-press-event])))))
@@ -1,4 +1,10 @@
(ns quo.components.share.share-qr-code.schema)
(ns quo.components.share.share-qr-code.schema
(:require
[quo.foundations.resources :as resources]))
(defn- valid-network?
[network]
(-> network resources/get-network boolean))
(def ?base
[:map
@@ -29,9 +35,25 @@
[:type [:= :wallet]]
[:emoji {:optional true} [:maybe ?emoji]]])
(def ?address-multichain
[:map
[:address [:= :multichain]]
[:on-settings-press {:optional true} fn?]])
(def ?address-base
[:merge
[:map
[:networks [:sequential [:fn valid-network?]]]
[:on-legacy-press {:optional true} [:maybe fn?]]
[:on-multichain-press {:optional true} [:maybe fn?]]
[:address [:enum :legacy :multichain]]]
[:multi {:dispatch :address}
[:multichain ?address-multichain]]])
(def ?saved-address
[:map
[:type [:= :saved-address]]])
[:type [:= :saved-address]]
[:on-settings-press {:optional true} fn?]])
(def ?watched-address
[:map
@@ -45,8 +67,8 @@
[:multi {:dispatch :type}
[:channel [:merge ?base ?channel]]
[:profile [:merge ?base ?profile]]
[:wallet [:merge ?base ?wallet]]
[:saved-address [:merge ?base ?saved-address]]
[:watched-address [:merge ?base ?watched-address]]]]]
[:wallet [:merge ?base ?address-base ?wallet]]
[:saved-address [:merge ?base ?address-base ?saved-address]]
[:watched-address [:merge ?base ?address-base ?watched-address]]]]]
:any])
@@ -12,12 +12,37 @@
[quo.components.share.qr-code.view :as qr-code]
[quo.components.share.share-qr-code.schema :as component-schema]
[quo.components.share.share-qr-code.style :as style]
[quo.components.tabs.tab.view :as tab]
[quo.components.wallet.address-text.view :as address-text]
[quo.foundations.colors :as colors]
[quo.theme]
[react-native.core :as rn]
[schema.core :as schema]
[utils.i18n :as i18n]))
(defn- header
[{:keys [on-legacy-press on-multichain-press address]}]
[rn/view {:style style/header-container}
[tab/view
{:accessibility-label :share-qr-code-multichain-tab
:id :wallet-multichain-tab
:active-item-container-style style/header-tab-active
:item-container-style style/header-tab-inactive
:size 24
:active (= :multichain address)
:on-press on-multichain-press}
(i18n/label :t/multichain)]
[rn/view {:style style/space-between-tabs}]
[tab/view
{:accessibility-label :share-qr-code-legacy-tab
:id :wallet-legacy-tab
:active-item-container-style style/header-tab-active
:item-container-style style/header-tab-inactive
:size 24
:active (= :legacy address)
:on-press on-legacy-press}
(i18n/label :t/legacy)]])
(defn- info-label
[share-qr-code-type]
[text/text {:size :paragraph-2 :weight :medium :style style/title}
@@ -61,7 +86,7 @@
:on-long-press on-text-long-press}
qr-data]])
(defn- wallet-bottom
(defn- wallet-legacy-bottom
[{:keys [component-width qr-data on-text-press on-text-long-press]}]
[info-text
{:width component-width
@@ -69,6 +94,28 @@
:on-long-press on-text-long-press}
qr-data])
(defn wallet-multichain-bottom
[{:keys [component-width qr-data on-text-press on-text-long-press on-settings-press]}]
[rn/view
{:style style/wallet-multichain-container}
[info-text
{:width component-width
:on-press on-text-press
:on-long-press on-text-long-press}
[address-text/view
{:address qr-data
:full-address? true
:weight :regular
:size :paragraph-1}]]
[button/button
{:icon-only? true
:type :grey
:background :blur
:size 32
:accessibility-label :share-qr-code-settings
:on-press on-settings-press}
:i/advanced]])
(defn- header-icon
[{:keys [share-qr-type customization-color emoji profile-picture full-name]}]
(case share-qr-type
@@ -93,9 +140,17 @@
:full-name full-name}]
nil))
(defn- has-header?
[share-qr-type]
(case share-qr-type
(:wallet
:watched-address
:saved-address) true
false))
(defn- share-qr-code
[{:keys [share-qr-type qr-image-uri component-width customization-color full-name
profile-picture emoji on-share-press]
profile-picture emoji on-share-press address]
:as props}]
[:<>
[gradient-cover/view {:customization-color customization-color :height 463}]
@@ -113,6 +168,8 @@
{:color colors/white-opa-40
:container-style style/watched-account-icon}])]
[share-button {:on-press on-share-press}]]
(when (has-header? share-qr-type)
[header props])
[quo.theme/provider :light
[qr-code/view
{:qr-image-uri qr-image-uri
@@ -128,12 +185,12 @@
:profile-picture profile-picture
:emoji emoji}]]
[rn/view {:style style/bottom-container}
(case share-qr-type
:profile
(if (= share-qr-type :profile)
[profile-bottom props]
(:wallet :watched-address :saved-address)
[wallet-bottom props]
nil)]]])
(case address
:legacy [wallet-legacy-bottom props]
:multichain [wallet-multichain-bottom props]
nil))]]])
(defn- view-internal
[{provided-width :width :as props}]
@@ -97,7 +97,7 @@
theme (quo.theme/use-theme)}
:as props}]
(let [[image-error? set-image-error] (rn/use-state false)]
[rn/view {:style [{:align-items :flex-start} container-style]}
[rn/view {:style (merge {:align-items :flex-start} container-style)}
[rn/view
{:style (style/container {:theme theme
:type type
@@ -6,28 +6,17 @@
[{:keys [status theme blur?]}]
{:flex-direction :row
:align-self :flex-start
:background-color (cond (= status :error)
(colors/theme-colors
(colors/override-color :danger 10 50)
(colors/override-color :danger 10 60)
theme)
(= status :warning)
(colors/theme-colors
(colors/override-color :warning 10 50)
(colors/override-color :warning 10 60)
theme))
:background-color (when (= status :error)
(colors/theme-colors
(colors/override-color :danger 10 50)
(colors/override-color :danger 10 60)
theme))
:border-width 1
:border-color (cond (= status :error)
(colors/theme-colors
(colors/override-color :danger 20 50)
(colors/override-color :danger 20 60)
theme)
(= status :warning)
(colors/theme-colors
(colors/override-color :warning 20 50)
(colors/override-color :warning 20 60)
theme)
(and blur? (= status :default)) (colors/theme-colors
colors/neutral-80-opa-5
colors/white-opa-5
@@ -46,7 +35,5 @@
[{:keys [status theme networks-shown?]}]
{:padding-left (if networks-shown? 4 0)
:margin-top -1
:color (cond (= status :error)
(colors/resolve-color :danger theme)
(= status :warning)
(colors/resolve-color :warning theme))})
:color (when (= status :error)
(colors/resolve-color :danger theme))})
@@ -14,9 +14,9 @@
(defn network-bridge-add
[{:keys [network state theme container-style on-press]}]
[rn/pressable
{:style [(style/container network state theme)
(style/add-container theme)
container-style]
{:style (merge (style/container network state theme)
(style/add-container theme)
container-style)
:on-press on-press}
[icon/icon :i/edit
{:size 12
@@ -36,7 +36,7 @@
(if (= status :edit)
[network-bridge-add (assoc args :theme theme)]
[rn/pressable
{:style [(style/container network status theme) container-style]
{:style (merge (style/container network status theme) container-style)
:accessible true
:accessibility-label :container
:on-press on-press
+6 -1
View File
@@ -195,12 +195,17 @@
(def success-60-opa-30 (alpha success-60 0.3))
(def success-60-opa-40 (alpha success-60 0.4))
;;;;Danger
(def danger "#E95460")
;; Danger with transparency
(def danger-opa-40 (alpha danger 0.4))
;;Solid
(def danger-50 "#E95460")
(def danger-60 "#BA434D")
(def system-yellow "#FFD60A")
(def keycard-color "#FF6400")
;;50 with transparency
(def danger-50-opa-0 (alpha danger-50 0))
+1
View File
@@ -4,6 +4,7 @@
{:keycard-logo (js/require "../resources/images/ui2/keycard-logo.png")
:keycard-chip-light (js/require "../resources/images/ui2/keycard-chip-light.png")
:keycard-chip-dark (js/require "../resources/images/ui2/keycard-chip-dark.png")
:keycard-watermark (js/require "../resources/images/ui2/keycard-watermark.png")
:bored-ape (js/require "../resources/images/mock2/bored-ape.png")})
(def ui-themed
-2
View File
@@ -211,5 +211,3 @@
(def linking (.-Linking react-native))
(defn open-url [link] (.openURL ^js linking link))
(def stylesheet-absolute-fill ^js (.. react-native -StyleSheet -absoluteFill))
+10 -1
View File
@@ -21,7 +21,9 @@
["react-native-redash" :refer (withPause)]
[react-native.flat-list :as rn-flat-list]
[react-native.platform :as platform]
[react-native.utils :as rn.utils]
[reagent.core :as reagent]
[utils.transforms :as transforms]
[utils.worklets.core :as worklets.core]))
(def ^:const default-duration 300)
@@ -34,7 +36,13 @@
;; Animated Components
(def create-animated-component (comp reagent/adapt-react-class (.-createAnimatedComponent reanimated)))
(def view (reagent/adapt-react-class (.-View reanimated)))
(def ^:private view* (reagent/adapt-react-class (.-View reanimated)))
(defn view
[& argv]
(let [[reagent-props children] (rn.utils/get-props-and-children argv)
updated-props (update reagent-props :style transforms/styles-with-vectors)]
(into [view* updated-props] children)))
(def scroll-view (reagent/adapt-react-class (.-ScrollView reanimated)))
(def image (reagent/adapt-react-class (.-Image reanimated)))
@@ -178,3 +186,4 @@
(with-timing value
(clj->js {:duration duration
:easing (default-easing)})))))
-54
View File
@@ -1,54 +0,0 @@
(ns react-native.utils-test
(:require
[cljs.test :refer [deftest is testing]]
[utils.reagent :as sut]))
(sut/set-convert-props-in-vectors!)
(deftest convert-prop-value-test
;; `test-fn` transforms the result to be easily compared during testing
(let [test-fn (comp js->clj sut/convert-prop-value)]
(testing "camelCase keys are kept as is"
(let [props {:foo nil
:bar nil}]
(is (= (update-keys props name)
(test-fn props)))))
(testing "kebab-case keys are transformed"
(let [props {:foo nil
:bar nil}]
(is (= {"foo" nil
"bar" nil}
(test-fn props)))))
(testing "kebab-case keys are transformed when passed inside a vector"
(let [props-in-vector [{:foo nil
:bar nil}]]
(is (= [{"foo" nil
"bar" nil}]
(test-fn props-in-vector)))))
(testing "kebab-case keys are transformed recursively when the structure has vectors"
(let [props-with-vectors {:foo [{:foo-bar nil
:foo-baz nil}]
:bar [{:bar-baz nil}
{:bar-qux nil}]}]
(is (= {"foo" [{"fooBar" nil
"fooBaz" nil}]
"bar" [{"barBaz" nil} {"barQux" nil}]}
(test-fn props-with-vectors))))
(testing "Complex example"
(let [complex-props {:foo [{:foo-bar nil :foo-baz nil}]
:bar [{:bar-baz nil} {:bar-qux nil}]
:qux {:foo-qux :bar-qux}
:foo-bar-qux {:foo [{:bar :qux}
{:bar-qux nil}]
:foo-bar :qux
:foo-bar-qux [:foo :bar :qux {:foo-bar :foo-bar}]}}]
(is (= {"foo" [{"fooBar" nil "fooBaz" nil}]
"bar" [{"barBaz" nil} {"barQux" nil}]
"qux" {"fooQux" "bar-qux"}
"fooBarQux" {"foo" [{"bar" "qux"} {"barQux" nil}]
"fooBar" "qux"
"fooBarQux" ["foo" "bar" "qux" {"fooBar" "foo-bar"}]}}
(test-fn complex-props))))))))
+3 -3
View File
@@ -73,10 +73,10 @@
[{:keys [scroll-ref tabs selected-tab on-tab-change scroll-shared-value content customization-color]}]
(let [theme (quo.theme/use-theme)]
[:<>
[banner-card-blur-layer scroll-shared-value
[banner-card-hiding-layer
[:f> banner-card-blur-layer scroll-shared-value
[:f> banner-card-hiding-layer
(assoc content :scroll-shared-value scroll-shared-value :theme theme)]]
[banner-card-tabs-layer
[:f> banner-card-tabs-layer
{:scroll-shared-value scroll-shared-value
:selected-tab selected-tab
:tabs tabs
+1 -1
View File
@@ -18,13 +18,13 @@
:podcasts (js/require "../resources/images/ui2/podcasts.png")
:generate-keys (js/require "../resources/images/ui2/generate-keys.png")
:add-key-to-keycard (js/require "../resources/images/ui2/add-key-to-keycard.png")
:import-key-to-keycard (js/require "../resources/images/ui2/import-key-to-keycard.png")
:ethereum-address (js/require "../resources/images/ui2/ethereum-address.png")
:use-keycard (js/require "../resources/images/ui2/keycard.png")
:use-recovery-phrase (js/require "../resources/images/ui2/recovery-phrase.png")
:check-your-keycard (js/require "../resources/images/ui2/check-your-keycard.png")
:qr-code (js/require "../resources/images/ui2/qr-code.png")
:keycard-logo (js/require "../resources/images/ui2/keycard-logo.png")
:keycard-watermark (js/require "../resources/images/ui2/keycard-watermark.png")
:keycard-buy (js/require "../resources/images/ui2/keycard-buy.png")
:keycard-migration (js/require "../resources/images/ui2/keycard-migration.png")
:keycard-migration-failed (js/require "../resources/images/ui2/keycard-migration-failed.png")
+10 -1
View File
@@ -15,7 +15,16 @@
(def flex-spacer {:flex 1})
(def hole {:z-index 2 :opacity 0.95})
(def absolute-fill
{:position :absolute
:top 0
:bottom 0
:left 0
:right 0})
(def hole
(merge absolute-fill
{:z-index 2 :opacity 0.95}))
(defn root-container
[padding-top]
+3 -3
View File
@@ -174,10 +174,10 @@
:on-success-scan set-qr-code-succeeded
:on-failed-scan set-rescan-timeout}))}]]
[hole-view/hole-view
{:style [rn/stylesheet-absolute-fill style/hole]
:holes [(assoc qr-view-finder :border-radius 16)]}
{:style style/hole
:holes [(assoc qr-view-finder :borderRadius 16)]}
[quo/blur
{:style rn/stylesheet-absolute-fill
{:style style/absolute-fill
:blur-amount 10
:blur-type :transparent
:overlay-color colors/neutral-80-opa-80-blur
-2
View File
@@ -34,8 +34,6 @@
(def mainnet-chain-explorer-link "https://etherscan.io/address/")
(def optimism-mainnet-chain-explorer-link "https://optimistic.etherscan.io/address/")
(def arbitrum-mainnet-chain-explorer-link "https://arbiscan.io/address/")
(def base-mainnet-chain-explorer-link "https://basescan.org/address/")
(def base-sepolia-chain-explorer-link "https://sepolia.basescan.org/address/")
(def sepolia-chain-explorer-link "https://sepolia.etherscan.io/address/")
(def optimism-sepolia-chain-explorer-link "https://sepolia-optimistic.etherscan.io/address/")
(def arbitrum-sepolia-chain-explorer-link "https://sepolia.arbiscan.io/address/")
-3
View File
@@ -443,10 +443,7 @@
(def ^:const wallet-account-name-max-length 20)
(def ^:const gas-rate-low 0)
(def ^:const gas-rate-medium 1)
(def ^:const gas-rate-high 2)
(def ^:const gas-rate-custom 3)
(def ^:const send-type-transfer 0)
(def ^:const send-type-bridge 5)
(def ^:const send-type-erc-721-transfer 6)
+2 -6
View File
@@ -114,17 +114,13 @@
{:scroll-input (oops/oget % "nativeEvent.contentOffset.y")
:shared-value scroll-shared-value})}])))
(defn- on-new-message-press
[]
(let [main-event [:show-bottom-sheet {:content chat.actions.view/new-chat}]]
(rf/dispatch [:profile/check-profile-update-prompt main-event])))
(defn- banner-data
[profile-link]
{:title-props
{:beta? true
:label (i18n/label :t/messages)
:handler on-new-message-press
:handler #(rf/dispatch
[:show-bottom-sheet {:content chat.actions.view/new-chat}])
:accessibility-label :new-chat-button}
:card-props
{:on-press #(rf/dispatch [:open-share {:options {:url profile-link}}])
@@ -95,10 +95,10 @@
(defn get-actions
[{:keys [outgoing content pinned-by outgoing-status deleted? deleted-for-me? content-type
bridge-message message-id]
bridge-message]
:as message-data}
{:keys [able-to-send-message? community? community-member? can-delete-message-for-everyone?
message-pin-enabled group-chat group-admin? debug-log-level?]}]
message-pin-enabled group-chat group-admin?]}]
(let [edit-message? (and (or community-member? (not community?))
outgoing
(not (or deleted? deleted-for-me?))
@@ -153,14 +153,6 @@
:icon :i/copy
:id :copy})
debug-log-level?
(conj {:type :main
:on-press #(clipboard/set-string message-id)
:label (i18n/label :t/copy-message-id)
:accessibility-label :copy-message-id
:icon :i/copy
:id :copy-message-id})
pin-message?
(conj {:type :main
:on-press #(pin-message message-data)
@@ -1,137 +0,0 @@
(ns status-im.contexts.keycard.backup.events
(:require [utils.re-frame :as rf]
[utils.security.core :as security]))
(rf/reg-event-fx :keycard/backup.generate-and-load-key
(fn [{:keys [db]}]
(let [{:keys [masked-phrase pin]} (get-in db [:keycard :backup])]
{:fx [[:effects.keycard/generate-and-load-key
{:mnemonic (security/safe-unmask-data masked-phrase)
:pin pin
:on-success (fn []
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:navigate-back])
(rf/dispatch [:open-modal :screen/keycard.backup.success]))
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error %])}]]})))
(defn- ready-to-add-not-empty
[error]
(rf/dispatch [:navigate-back])
(if (= error :keycard/error.not-keycard)
(rf/dispatch [:keycard/on-application-info-error error])
(do
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:open-modal :screen/keycard.backup.not-empty
{:on-press #(rf/dispatch [:keycard/backup.ready-to-add-connect])}]))))
(rf/reg-event-fx :keycard/backup.ready-to-add-connect
(fn [_]
{:fx [[:dispatch
[:keycard/connect
{:theme :dark
:on-error
(fn [error]
(if (= error :keycard/error.keycard-empty)
(rf/dispatch [:keycard/backup.generate-and-load-key])
(ready-to-add-not-empty error)))}]]]}))
(defn- scan-empty-card-not-empty
[error]
(rf/dispatch [:navigate-back])
(if (= error :keycard/error.not-keycard)
(rf/dispatch [:keycard/on-application-info-error error])
(do
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:open-modal :screen/keycard.backup.not-empty
{:on-press #(rf/dispatch [:keycard/backup.scan-empty-card])}]))))
(rf/reg-event-fx :keycard/backup.scan-empty-card
(fn [_]
{:fx [[:dispatch
[:keycard/connect
{:theme :dark
:on-error
(fn [error]
(if (= error :keycard/error.keycard-empty)
(do
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:keycard/backup.create-or-enter-pin]))
(scan-empty-card-not-empty error)))}]]]}))
(rf/reg-event-fx :keycard/backup.save-pin
(fn [{:keys [db]} [pin]]
{:db (assoc-in db [:keycard :backup :pin] pin)}))
(defn- save-pin-and-navigate-to-phrase
[pin]
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:navigate-back])
(rf/dispatch [:keycard/backup.save-pin pin])
(rf/dispatch
[:open-modal :screen/use-recovery-phrase-dark
{:on-success #(rf/dispatch [:keycard/backup.phrase-entered %])}]))
(defn- verify-entered-pin-and-continue
[pin]
(rf/dispatch
[:keycard/connect
{:theme :dark
:on-error
(fn [error]
(if (= error :keycard/error.keycard-empty)
(rf/dispatch
[:keycard/verify-pin
{:pin pin
:on-success #(save-pin-and-navigate-to-phrase pin)
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error %])}])
(rf/dispatch [:keycard/on-application-info-error error])))}]))
(declare init-card-not-empty)
(defn- init-card-with-pin-and-continue
[pin]
(rf/dispatch
[:keycard/connect
{:theme :dark
:on-error
(fn [error]
(if (= error :keycard/error.keycard-empty)
(rf/dispatch
[:keycard/init-card
{:pin pin
:on-success #(rf/dispatch
[:keycard/get-application-info
{:on-error
(fn [error]
(if (= error :keycard/error.keycard-empty)
(save-pin-and-navigate-to-phrase pin)
(init-card-not-empty pin error)))}])}])
(init-card-not-empty pin error)))}]))
(defn- init-card-not-empty
[pin error]
(rf/dispatch [:navigate-back])
(if (= error :keycard/error.not-keycard)
(rf/dispatch [:keycard/on-application-info-error error])
(do
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:open-modal :screen/keycard.backup.not-empty
{:on-press #(init-card-with-pin-and-continue pin)}]))))
(rf/reg-event-fx :keycard/backup.create-or-enter-pin
(fn [{:keys [db]}]
(let [{:keys [initialized?]} (get-in db [:keycard :application-info])]
{:fx [[:dispatch [:navigate-back]]
(if initialized?
[:dispatch
[:open-modal :screen/keycard.pin.enter
{:on-complete verify-entered-pin-and-continue}]]
[:dispatch
[:open-modal :screen/keycard.pin.create
{:on-complete init-card-with-pin-and-continue}]])]})))
(rf/reg-event-fx :keycard/backup.phrase-entered
(fn [{:keys [db]} [{:keys [phrase]}]]
{:db (assoc-in db [:keycard :backup :masked-phrase] phrase)
:fx [[:dispatch [:navigate-back]]
[:dispatch [:open-modal :screen/keycard.backup.ready-to-add]]]}))
@@ -1,96 +0,0 @@
(ns status-im.contexts.keycard.backup.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.common.events-helper :as events-helper]
[status-im.common.resources :as resources]
[status-im.contexts.keycard.common.view :as common.view]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn ready-to-add
[]
[:<>
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/ready-add-keypair-keycard)}]
[rn/view {:style {:flex 1 :align-items :center :justify-content :center}}
[rn/image
{:resize-mode :contain
:source (resources/get-image :keycard-migration)}]]
[common.view/tips]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/scan-keycard)
:button-one-props {:on-press #(rf/dispatch [:keycard/backup.ready-to-add-connect])}}]])
(defn success-view
[]
[:<>
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/backup-keycard-created)}]
[rn/view {:style {:flex 1}}]
[rn/view {:style {:padding-horizontal 20}}
[quo/button {:on-press events-helper/navigate-back}
(i18n/label :t/done)]]])
(defn not-empty-view
[]
(let [{:keys [on-press]} (rf/sub [:get-screen-params])]
[:<>
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/keycard-not-empty)
:description :text
:description-text (i18n/label :t/scan-empty-keycard)}]
[rn/view {:style {:flex 1}}]
[common.view/tips]
[rn/view {:style {:padding-horizontal 20}}
[quo/button {:on-press on-press}
(i18n/label :t/try-again)]]]))
(defn scan-empty
[]
[:<>
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/scan-empty-keycard)
:description :text
:description-text (i18n/label :t/backup-empty-keycard-only)}]
[rn/view {:style {:flex 1 :align-items :center :justify-content :center}}
[rn/image
{:resize-mode :contain
:source (resources/get-image :check-your-keycard)}]]
[common.view/tips]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/ready-to-scan)
:button-one-props {:on-press #(rf/dispatch [:keycard/backup.scan-empty-card])}}]])
(defn sheet
[{:keys [on-continue]}]
(let [customization-color (rf/sub [:profile/customization-color])]
[:<>
[quo/drawer-top {:title (i18n/label :t/create-backup-keycard)}]
[quo/text
{:style {:padding-horizontal 20
:padding-vertical 8}}
(i18n/label :t/backup-keycard-instructions)]
[quo/bottom-actions
{:actions :two-actions
:button-one-label (i18n/label :t/continue)
:button-one-props {:customization-color customization-color
:on-press (fn []
(rf/dispatch [:hide-bottom-sheet])
(on-continue))}
:button-two-label (i18n/label :t/cancel)
:button-two-props {:type :grey
:on-press #(rf/dispatch [:hide-bottom-sheet])}}]]))
@@ -1,73 +0,0 @@
(ns status-im.contexts.keycard.change-pin.events
(:require [status-im.contexts.keycard.utils :as utils]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[utils.security.core :as security]))
(rf/reg-event-fx :keycard/change-pin.enter-current-pin
(fn [{:keys [db]}]
{:db (update db :keycard dissoc :change-pin)
:fx [[:dispatch [:navigate-back]]
[:dispatch
[:open-modal :screen/keycard.pin.enter
{:title (i18n/label :t/enter-current-keycard-pin)
:on-complete (fn [current-pin]
(rf/dispatch [:navigate-back])
(rf/dispatch [:keycard/change-pin.save-current-pin current-pin])
(rf/dispatch [:keycard/change-pin.enter-new-pin]))}]]]}))
(rf/reg-event-fx :keycard/change-pin.save-current-pin
(fn [{:keys [db]} [pin]]
{:db (assoc-in db [:keycard :change-pin :current-pin] (security/mask-data pin))}))
(rf/reg-event-fx :keycard/change-pin.enter-new-pin
(fn [_]
{:fx [[:dispatch
[:open-modal :screen/keycard.pin.create
{:title (i18n/label :t/create-new-keycard-pin)
:repeat-stage-title (i18n/label :t/repeat-new-keycard-pin)
:on-complete (fn [new-pin]
(rf/dispatch [:navigate-back])
(rf/dispatch [:keycard/change-pin.save-new-pin new-pin])
(rf/dispatch [:open-modal :screen/keycard.ready-to-change-pin]))}]]]}))
(rf/reg-event-fx :keycard/change-pin.save-new-pin
(fn [{:keys [db]} [pin]]
{:db (assoc-in db [:keycard :change-pin :new-pin] (security/mask-data pin))}))
(defn- change-pin-and-continue
[current-pin new-pin]
(rf/dispatch [:keycard/change-pin
{:on-success (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:open-modal :screen/keycard.pin-change-success]))
:on-failure (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:open-modal :screen/keycard.pin-change-failed]))
:current-pin current-pin
:new-pin new-pin}]))
(defn- verify-pin-and-continue
[current-pin new-pin]
(rf/dispatch
[:keycard/verify-pin
{:pin current-pin
:on-success #(change-pin-and-continue current-pin new-pin)
:on-failure (fn [error]
(when-not (utils/tag-lost? (:error error))
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:keycard/on-action-with-pin-error error])
(rf/dispatch [:keycard/change-pin.enter-current-pin])))}]))
(rf/reg-event-fx :keycard/change-pin.verify-current-pin-and-continue
(fn [{:keys [db]}]
(let [{:keys [current-pin new-pin]} (get-in db [:keycard :change-pin])
unmasked-current-pin (security/safe-unmask-data current-pin)
unmasked-new-pin (security/safe-unmask-data new-pin)]
{:fx [[:dispatch
[:keycard/connect
{:theme :dark
:key-uid (get-in db [:profile/profile :key-uid])
:on-success #(verify-pin-and-continue unmasked-current-pin unmasked-new-pin)}]]]})))
@@ -1,82 +0,0 @@
(ns status-im.contexts.keycard.change-pin.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.common.events-helper :as events-helper]
[status-im.contexts.keycard.common.view :as common.view]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn change-pin-confirmation-sheet
[]
[quo/documentation-drawers
{:title (i18n/label :t/change-pin-keycard)
:shell? true}
[rn/view
[quo/text {:size :paragraph-2}
(i18n/label :t/change-pin-keycard-message)]
[quo/bottom-actions
{:actions :two-actions
:container-style {:margin-horizontal -20}
:blur? true
:button-one-label (i18n/label :t/continue)
:button-one-props {:on-press #(rf/dispatch [:keycard/change-pin.enter-current-pin])}
:button-two-label (i18n/label :t/cancel)
:button-two-props {:on-press events-helper/hide-bottom-sheet
:type :grey}}]]])
(defn ready-to-change-pin
[]
[:<>
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/ready-to-change-pin)}]
[rn/view {:style {:flex 1 :align-items :center :justify-content :center}}
[rn/image
{:resize-mode :contain}]]
[common.view/tips]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/scan-keycard)
:button-one-props {:on-press #(rf/dispatch
[:keycard/change-pin.verify-current-pin-and-continue])}}]])
(defn pin-change-success
[]
[:<>
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/keycard-pin-changed)
:description :text
:description-text (i18n/label :t/keycard-pin-changed-description)}]
[rn/view {:style {:flex 1 :align-items :center :justify-content :center}}
[rn/image
{:resize-mode :contain}]]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/done)
:button-one-props {:on-press events-helper/navigate-back}}]])
(defn pin-change-failed
[]
[:<>
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/keycard-pin-change-failed)
:description :text
:description-text (i18n/label :t/keycard-pin-change-failed-description)}]
[rn/view {:style {:flex 1 :align-items :center :justify-content :center}}
[rn/image
{:resize-mode :contain}]]
[common.view/tips]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/try-again)
:button-one-props {:on-press (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:open-modal :screen/keycard.ready-to-change-pin]))}}]])
@@ -1,26 +0,0 @@
(ns status-im.contexts.keycard.check.events
(:require [utils.re-frame :as rf]))
(rf/reg-event-fx :keycard/check-empty-card
(fn [{:keys [db]}]
(let [keycard-profile? (not (nil? (get-in db [:profile/profile :keycard-pairing])))]
{:fx [[:dispatch
[:keycard/connect
{:key-uid (get-in db [:profile/profile :key-uid])
:theme :dark
:on-success
(fn []
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:navigate-back])
(if keycard-profile?
(rf/dispatch [:open-modal :screen/keycard.manage.profile-keys])
(rf/dispatch [:open-modal :screen/keycard.migrate.profile-keys])))
:on-error
(fn [error]
(rf/dispatch [:navigate-back])
(if (and (= error :keycard/error.keycard-empty)
(not keycard-profile?))
(do
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:open-modal :screen/keycard.empty]))
(rf/dispatch [:keycard/on-application-info-error error])))}]]]})))
@@ -4,7 +4,6 @@
[status-im.common.events-helper :as events-helper]
[status-im.common.resources :as resources]
[status-im.constants :as constants]
[status-im.contexts.keycard.common.view :as common.view]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -36,7 +35,6 @@
:right-side [{:icon-name :i/info
:on-press #(rf/dispatch [:show-bottom-sheet
{:content keycard-documentation
:theme :dark
:shell? true}])}]}]
[quo/page-top
{:title (i18n/label :t/check-keycard)
@@ -46,7 +44,9 @@
[rn/image
{:resize-mode :contain
:source (resources/get-image :check-your-keycard)}]]
[common.view/tips]
[quo/divider-label (i18n/label :t/tips-scan-keycard)]
[quo/markdown-list {:description (i18n/label :t/remove-phone-case)}]
[quo/markdown-list {:description (i18n/label :t/keep-card-steady)}]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/ready-to-scan)
@@ -1,10 +0,0 @@
(ns status-im.contexts.keycard.common.view
(:require [quo.core :as quo]
[utils.i18n :as i18n]))
(defn tips
[]
[:<>
[quo/divider-label (i18n/label :t/tips-scan-keycard)]
[quo/markdown-list {:description (i18n/label :t/remove-phone-case)}]
[quo/markdown-list {:description (i18n/label :t/keep-card-steady)}]])
@@ -1,7 +1,5 @@
(ns status-im.contexts.keycard.create.events
(:require [clojure.string :as string]
[status-im.common.resources :as resources]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[utils.security.core :as security]))
@@ -9,10 +7,9 @@
(fn [_]
{:fx [[:dispatch
[:keycard/connect
{:theme :dark
:on-error
{:on-error
(fn [error]
(if (= error :keycard/error.keycard-empty)
(if (= error :keycard/error.keycard-blank)
(do
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:open-modal :screen/keycard.empty-create]))
@@ -21,17 +18,8 @@
(defn- backup-recovery-phrase-success
[masked-seed-phrase]
(rf/dispatch [:navigate-back])
(rf/dispatch [:open-modal :screen/confirm-backup-dark
(rf/dispatch [:open-modal :screen/confirm-backup
{:masked-seed-phrase masked-seed-phrase
:theme :dark
:shell? true
:on-try-again #(rf/dispatch [:open-modal :screen/backup-recovery-phrase-dark
{:on-success backup-recovery-phrase-success
:masked-seed-phrase (->> masked-seed-phrase
security/safe-unmask-data
(string/join " ")
security/mask-data)
:revealed? true}])
:on-success #(rf/dispatch [:keycard/create.phrase-backed-up
masked-seed-phrase])}]))
@@ -51,13 +39,10 @@
security/safe-unmask-data
(string/join " ")
security/mask-data))
:fx [[:dispatch
[:keycard/create.create-or-enter-pin
{:ready-to-add-screen-title (i18n/label :t/ready-add-keypair-keycard)
:ready-to-add-screen-image (resources/get-image :add-key-to-keycard)}]]]}))
:fx [[:dispatch [:keycard/create.create-or-enter-pin]]]}))
(rf/reg-event-fx :keycard/create.create-or-enter-pin
(fn [{:keys [db]} [{:keys [ready-to-add-screen-title ready-to-add-screen-image]}]]
(fn [{:keys [db]}]
(let [{:keys [initialized?]} (get-in db [:keycard :application-info])]
{:fx [[:dispatch [:navigate-back]]
(if initialized?
@@ -71,9 +56,7 @@
{:on-complete (fn [new-pin]
(rf/dispatch [:navigate-back])
(rf/dispatch [:keycard/create.save-pin new-pin])
(rf/dispatch [:open-modal :screen/keycard.create.ready-to-add
{:title ready-to-add-screen-title
:image ready-to-add-screen-image}]))}]])]})))
(rf/dispatch [:open-modal :screen/keycard.create.ready-to-add]))}]])]})))
(rf/reg-event-fx :keycard/create.save-pin
(fn [{:keys [db]} [pin]]
@@ -81,7 +64,7 @@
(rf/reg-event-fx :keycard/create.on-application-info-error
(fn [{:keys [db]} [error]]
(if (or (= error :keycard/error.keycard-empty)
(if (or (= error :keycard/error.keycard-blank)
(and (get-in db [:keycard :application-info :initialized?])
(= error :keycard/error.keycard-wrong-profile)))
(rf/dispatch [:keycard/create.continue])
@@ -91,8 +74,7 @@
(fn [_]
{:fx [[:dispatch
[:keycard/connect
{:theme :dark
:on-error #(rf/dispatch [:keycard/create.on-application-info-error %])}]]]}))
{:on-error #(rf/dispatch [:keycard/create.on-application-info-error %])}]]]}))
(defn get-application-info-and-continue
[]
@@ -108,7 +90,7 @@
(cond
(not initialized?)
{:fx [[:effects.keycard/init-card
{:fx [[:keycard/init-card
{:pin pin
:on-success get-application-info-and-continue}]]}
@@ -130,7 +112,4 @@
(if (contains? (:profile/profiles-overview db) key-uid)
{:fx [[:dispatch [:onboarding/multiaccount-already-exists key-uid]]]}
{:db (assoc-in db [:keycard :create :masked-phrase] masked-seed-phrase)
:fx [[:dispatch
[:keycard/create.create-or-enter-pin
{:ready-to-add-screen-title (i18n/label :t/ready-to-import-keypair-keycard)
:ready-to-add-screen-image (resources/get-image :import-key-to-keycard)}]]]})))
:fx [[:dispatch [:keycard/create.create-or-enter-pin]]]})))
+27 -31
View File
@@ -2,9 +2,10 @@
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.common.events-helper :as events-helper]
[status-im.common.not-implemented :as not-implemented]
[status-im.common.resources :as resources]
[status-im.config :as config]
[status-im.constants :as constants]
[status-im.contexts.keycard.common.view :as common.view]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -24,7 +25,6 @@
:title (i18n/label :t/check-keycard)
:subtitle (i18n/label :t/see-keycard-ready)
:button-label (i18n/label :t/scan-keycard)
:button-props {:type :primary :icon-left :i/keycard}
:accessibility-label :get-keycard
:image (resources/get-image :check-your-keycard)
:on-press #(rf/dispatch [:keycard/create.check-empty-card])}]
@@ -37,35 +37,31 @@
:image (resources/get-image :use-keycard)
:on-press #(rf/dispatch [:browser.ui/open-url constants/get-keycard-url])}]]
[rn/view {:style {:flex 1}}]
[common.view/tips]])
(defn- ready-to-add-documentation
[]
[quo/documentation-drawers
{:shell? true}
[quo/text {:size :paragraph-2}
(i18n/label :t/ready-add-keypair-keycard-documentation)]])
[quo/divider-label (i18n/label :t/tips-scan-keycard)]
[quo/markdown-list {:description (i18n/label :t/remove-phone-case)}]
[quo/markdown-list {:description (i18n/label :t/keep-card-steady)}]])
(defn ready-to-add
[]
(let [{:keys [title image]} (rf/sub [:get-screen-params])]
[:<>
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back
:right-side [{:icon-name :i/info
:on-press #(rf/dispatch [:show-bottom-sheet
{:content ready-to-add-documentation
:theme :dark
:shell? true}])}]}]
[quo/page-top
{:title title}]
[rn/image
{:resize-mode :contain
:style {:flex 1 :align-self :center :margin-vertical 37}
:source image}]
[common.view/tips]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/scan-keycard)
:button-one-props {:on-press #(rf/dispatch [:keycard/create.start])}}]]))
[:<>
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back
:right-side [(when config/show-not-implemented-features?
{:icon-name :i/info
:on-press not-implemented/alert})]}]
[quo/page-top
{:title (i18n/label :t/ready-add-keypair-keycard)
:description :text
:description-text ""}]
[rn/image
{:resize-mode :contain
:style {:flex 1 :align-self :center :margin-vertical 37}
:source (resources/get-image :add-key-to-keycard)}]
[quo/divider-label (i18n/label :t/tips-scan-keycard)]
[quo/markdown-list {:description (i18n/label :t/remove-phone-case)}]
[quo/markdown-list {:description (i18n/label :t/keep-card-steady)}]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/scan-keycard)
:button-one-props {:on-press #(rf/dispatch [:keycard/create.start])}}]])
+1 -9
View File
@@ -56,14 +56,6 @@
(fn [args]
(keycard/factory-reset (keycard.utils/wrap-handlers args))))
(rf/reg-fx :effects.keycard/verify-pin
(fn [args]
(keycard/verify-pin (keycard.utils/wrap-handlers args))))
(rf/reg-fx :effects.keycard/change-pin
(fn [args]
(keycard/change-pin (keycard.utils/wrap-handlers args))))
(rf/reg-fx :effects.keycard/sign
(fn [args]
(-> (keycard/sign args)
@@ -83,7 +75,7 @@
(promesa/then on-success)
(promesa/catch (keycard.utils/get-on-failure args)))))
(rf/reg-fx :effects.keycard/init-card
(rf/reg-fx :keycard/init-card
(fn [args]
(keycard/init-card (keycard.utils/wrap-handlers args))))
@@ -25,7 +25,7 @@
:accessibility-label :create-new-profile-keycard
:container-style {:margin-horizontal 20 :margin-top 8}
:image (resources/get-image :keycard-buy)
:button-props {:type :primary}
:button-type :primary
:on-press #(rf/dispatch [:keycard/create.get-phrase])}]
[quo/small-option-card
{:variant :icon
+8 -39
View File
@@ -2,22 +2,20 @@
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.common.events-helper :as events-helper]
[status-im.contexts.keycard.backup.view :as backup.view]
[status-im.contexts.keycard.factory-reset.view :as factory-reset]
[status-im.contexts.keycard.unblock.view :as keycard.unblock]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(def titles
{:keycard/error.keycard-empty {:title (i18n/label :t/keycard-empty)
{:keycard/error.keycard-blank {:title (i18n/label :t/keycard-empty)
:description (i18n/label :t/no-key-pair-keycard)}
:keycard/error.keycard-wrong-profile {:title (i18n/label :t/keycard-not-empty)
:description (i18n/label :t/cant-store-new-keys)}
:keycard/error.keycard-unpaired {:title (i18n/label :t/keycard-full)
:description (i18n/label :t/pairing-slots-occupied)}
:keycard/error.keycard-frozen {:title (i18n/label :t/keycard-blocked)
:keycard/error.keycard-frozen {:title (i18n/label :t/keycard-locked)
:description (i18n/label :t/cant-use-right-now)}
:keycard/error.keycard-locked {:title (i18n/label :t/keycard-blocked)
:keycard/error.keycard-locked {:title (i18n/label :t/keycard-locked)
:description (i18n/label :t/cant-use-right-now)}})
(defn view
@@ -33,38 +31,11 @@
:description :text
:description-text description}]
[rn/view {:style {:margin-horizontal 20}}
[quo/keycard {:blur? true}]
[quo/section-label
{:section (i18n/label :t/what-you-can-do) :container-style {:padding-vertical 8}}]
(if (= error :keycard/error.keycard-empty)
[quo/settings-item
{:title (i18n/label :t/use-backup-keycard)
:image :icon
:image-props :i/placeholder
:action :arrow
:description :text
:description-props {:text (i18n/label :t/create-backup-profile-keycard)}
:on-press (fn []
(rf/dispatch [:show-bottom-sheet
{:content
(fn []
[backup.view/sheet
{:on-continue
(rf/dispatch
[:keycard/backup.create-or-enter-pin])}])}]))}]
[quo/keycard {:holder-name ""}]
(when (not= :keycard/error.keycard-blank error)
[:<>
(when (or (= error :keycard/error.keycard-frozen)
(= error :keycard/error.keycard-locked))
[quo/settings-item
{:title (i18n/label :t/unblock-keycard)
:image :icon
:image-props :i/placeholder
:action :arrow
:description :text
:description-props {:text (i18n/label :t/with-recovery-phrase)}
:on-press (fn []
(rf/dispatch [:show-bottom-sheet
{:content keycard.unblock/sheet}]))}])
[quo/section-label
{:section (i18n/label :t/what-you-can-do) :container-style {:padding-vertical 8}}]
[quo/settings-item
{:title (i18n/label :t/factory-reset)
:image :icon
@@ -74,6 +45,4 @@
:description-props {:text (i18n/label :t/remove-keycard-content)}
:on-press (fn []
(rf/dispatch [:show-bottom-sheet
{:theme :dark
:shell? true
:content factory-reset/sheet}]))}]])]]))
{:content factory-reset/sheet}]))}]])]]))
+9 -34
View File
@@ -1,7 +1,5 @@
(ns status-im.contexts.keycard.events
(:require [re-frame.core :as rf]
status-im.contexts.keycard.backup.events
status-im.contexts.keycard.check.events
status-im.contexts.keycard.create.events
status-im.contexts.keycard.login.events
status-im.contexts.keycard.migrate.events
@@ -10,7 +8,6 @@
status-im.contexts.keycard.nfc.sheets.events
status-im.contexts.keycard.pin.events
status-im.contexts.keycard.sign.events
status-im.contexts.keycard.unblock.events
[status-im.contexts.keycard.utils :as keycard.utils]
[utils.address :as address]
utils.datetime
@@ -59,10 +56,6 @@
[:keycard/on-application-info-error
:keycard/error.keycard-locked]])]}))))
(rf/reg-event-fx :keycard/init-card
(fn [_ [data]]
{:effects.keycard/init-card data}))
(rf/reg-event-fx :keycard/get-keys
(fn [_ [data]]
{:effects.keycard/get-keys data}))
@@ -79,20 +72,11 @@
(fn [_ [data]]
{:effects.keycard/factory-reset data}))
(rf/reg-event-fx :keycard/verify-pin
(fn [_ [data]]
{:effects.keycard/verify-pin data}))
(rf/reg-event-fx :keycard/change-pin
(fn [_ [data]]
{:effects.keycard/change-pin data}))
(rf/reg-event-fx :keycard/connect-derive-address-and-add-account
(fn [_ [{:keys [pin derivation-path key-uid account-preferences]}]]
{:fx [[:dispatch
[:keycard/connect
{:theme :dark
:key-uid key-uid
{:key-uid key-uid
:on-success
(fn []
(rf/dispatch
@@ -161,26 +145,17 @@
(rf/dispatch [:keycard/on-application-info-error
:keycard/error.not-keycard]))))}}))
(rf/reg-event-fx :keycard/connect.next-stage
(fn [{:keys [db]} [{:keys [key-uid on-success on-error]}]]
(let [event-vector [:keycard/get-application-info
{:key-uid key-uid
:on-success on-success
:on-error on-error}]]
{:db (assoc-in db [:keycard :on-card-connected-event-vector] event-vector)
:fx [(when (get-in db [:keycard :card-connected?])
[:dispatch event-vector])]})))
(rf/reg-event-fx :keycard/connect
(fn [{:keys [db]} [{:keys [key-uid on-success on-error theme]}]]
(let [event-vector [:keycard/get-application-info
{:key-uid key-uid
:on-success on-success
:on-error on-error}]]
(fn [{:keys [db]} [{:keys [key-uid on-success on-error on-connect-event-vector]}]]
(let [event-vector
(or on-connect-event-vector
[:keycard/get-application-info
{:key-uid key-uid
:on-success on-success
:on-error on-error}])]
{:db (assoc-in db [:keycard :on-card-connected-event-vector] event-vector)
:fx [[:dispatch
[:keycard/show-connection-sheet
{:on-cancel-event-vector [:keycard/cancel-connection]
:theme theme}]]
{:on-cancel-event-vector [:keycard/cancel-connection]}]]
(when (get-in db [:keycard :card-connected?])
[:dispatch event-vector])]})))
@@ -22,8 +22,7 @@
[key-uid]
(rf/dispatch
[:keycard/connect
{:theme :dark
:key-uid key-uid
{:key-uid key-uid
:on-success reset-card
:on-error (fn [error]
(if (or (= error :keycard/error.keycard-frozen)
@@ -43,8 +43,7 @@
(fn []
{:fx [[:dispatch
[:keycard/connect
{:theme :dark
:on-error
{:on-error
(fn [error]
(if (= error :keycard/error.keycard-wrong-profile)
(do
@@ -58,8 +57,7 @@
(fn [{:keys [db]} [pin]]
{:fx [[:dispatch
[:keycard/connect
{:theme :dark
:key-uid (get-in db [:keycard :application-info :key-uid])
{:key-uid (get-in db [:keycard :application-info :key-uid])
:on-success (fn []
(rf/dispatch
[:keycard/get-more-keys
@@ -1,58 +0,0 @@
(ns status-im.contexts.keycard.manage.profile-keys.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.common.events-helper :as events-helper]
[status-im.contexts.keycard.backup.view :as backup.view]
[status-im.contexts.keycard.change-pin.view :as change-pin.view]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- backup-sheet
[]
[backup.view/sheet
{:on-continue
(fn []
(rf/dispatch [:navigate-back])
(rf/dispatch
[:open-modal :screen/keycard.backup.scan-empty]))}])
(defn view
[]
(let [profile-name (rf/sub [:profile/name])]
[:<>
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title profile-name}]
[rn/view {:style {:margin-horizontal 20}}
[rn/view {:style {:padding-top 8 :padding-bottom 20}}
[quo/keycard {:blur? true}]]
[quo/section-label
{:section (i18n/label :t/what-you-can-do) :container-style {:padding-vertical 8}}]
[quo/settings-item
{:title (i18n/label :t/change-pin-keycard)
:image :icon
:blur? true
:image-props :i/keycard
:action :arrow
:description :text
:description-props {:text (i18n/label :t/change-pin-keycard-description)}
:on-press (fn []
(rf/dispatch [:show-bottom-sheet
{:theme :dark
:shell? true
:content change-pin.view/change-pin-confirmation-sheet}]))}]
[quo/settings-item
{:title (i18n/label :t/backup-keycard)
:image :icon
:blur? true
:image-props :i/keycard
:action :arrow
:description :text
:description-props {:text (i18n/label :t/create-backup-profile-keycard)}
:on-press (fn []
(rf/dispatch [:show-bottom-sheet
{:theme :dark
:shell? true
:content backup-sheet}]))}]]]))
@@ -3,6 +3,23 @@
[utils.re-frame :as rf]
[utils.security.core :as security]))
(rf/reg-event-fx :keycard/migration.check-empty-card
(fn [{:keys [db]}]
{:fx [[:dispatch
[:keycard/connect
{:key-uid (get-in db [:profile/profile :key-uid])
:on-success
(fn []
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:open-modal :screen/keycard.profile-keys]))
:on-error
(fn [error]
(if (= error :keycard/error.keycard-blank)
(do
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:open-modal :screen/keycard.empty]))
(rf/dispatch [:keycard/on-application-info-error error])))}]]]}))
(defn get-application-info-and-continue
[key-uid]
(rf/dispatch [:keycard/get-application-info
@@ -10,7 +27,7 @@
:on-success #(rf/dispatch [:keycard/migration.continue])
:on-error
(fn [error]
(if (= error :keycard/error.keycard-empty)
(if (= error :keycard/error.keycard-blank)
(rf/dispatch [:keycard/migration.continue])
(rf/dispatch [:keycard/on-application-info-error error])))}]))
@@ -23,7 +40,7 @@
(cond
(not initialized?)
{:fx [[:effects.keycard/init-card
{:fx [[:keycard/init-card
{:pin pin
:on-success #(get-application-info-and-continue key-uid)}]]}
@@ -46,27 +63,17 @@
[:keycard/connect
{:key-uid (get-in db [:profile/profile :key-uid])
:on-success #(rf/dispatch [:keycard/migration.continue])
:theme :dark
:on-error
(fn [error]
(if (= error :keycard/error.keycard-empty)
(if (= error :keycard/error.keycard-blank)
(rf/dispatch [:keycard/migration.continue])
(rf/dispatch [:keycard/on-application-info-error error])))}]]]}))
(defn- backup-recovery-phrase-success
[masked-seed-phrase]
(rf/dispatch [:navigate-back])
(rf/dispatch [:open-modal :screen/confirm-backup-dark
(rf/dispatch [:open-modal :screen/confirm-backup
{:masked-seed-phrase masked-seed-phrase
:theme :dark
:shell? true
:on-try-again #(rf/dispatch [:open-modal :screen/backup-recovery-phrase-dark
{:on-success backup-recovery-phrase-success
:masked-seed-phrase (->> masked-seed-phrase
security/safe-unmask-data
(string/join " ")
security/mask-data)
:revealed? true}])
:on-success #(rf/dispatch [:keycard/migration.phrase-backed-up])}]))
(rf/reg-event-fx :keycard/migration.get-phrase
@@ -17,7 +17,7 @@
:description-text (i18n/label :t/finalise-migration-instructions)}]
[rn/view {:style {:margin-horizontal 20}}
[rn/view {:style {:padding-top 8 :padding-bottom 20}}
[quo/keycard {:blur? true}]]
[quo/keycard {:holder-name ""}]]
[quo/section-label {:section (i18n/label :t/what-you-can-do) :container-style {:padding-vertical 8}}]
[quo/settings-item
{:title (i18n/label :t/finalise-migration)
@@ -3,7 +3,6 @@
[react-native.core :as rn]
[status-im.common.events-helper :as events-helper]
[status-im.common.resources :as resources]
[status-im.contexts.keycard.common.view :as common.view]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -27,7 +26,9 @@
[rn/image
{:resize-mode :contain
:source (resources/get-image :keycard-migration)}]]
[common.view/tips]
[quo/divider-label (i18n/label :t/tips-scan-keycard)]
[quo/markdown-list {:description (i18n/label :t/remove-phone-case)}]
[quo/markdown-list {:description (i18n/label :t/keep-card-steady)}]
[quo/bottom-actions
{:actions :one-action
:button-one-label (if initialized? (i18n/label :t/enter-keycard-pin) (i18n/label :t/scan-keycard))
@@ -3,12 +3,11 @@
[react-native.platform :as platform]))
(rf/reg-event-fx :keycard/show-connection-sheet
(fn [{:keys [db]} [{:keys [on-cancel-event-vector theme]} :as args]]
(fn [{:keys [db]} [{:keys [on-cancel-event-vector]} :as args]]
(if platform/android?
{:db (assoc-in db
[:keycard :connection-sheet-opts]
{:on-close #(rf/dispatch on-cancel-event-vector)
:theme theme})
{:on-close #(rf/dispatch on-cancel-event-vector)})
:fx [[:effects.keycard.ios/start-nfc nil]
[:dismiss-keyboard true]
[:show-nfc-sheet nil]]}
@@ -8,9 +8,9 @@
(defn connect-keycard
[]
(let [connected? (rf/sub [:keycard/connected?])
{:keys [on-close theme]} (rf/sub [:keycard/connection-sheet-opts])
theme (or theme (quo.theme/use-theme))]
(let [connected? (rf/sub [:keycard/connected?])
{:keys [on-close]} (rf/sub [:keycard/connection-sheet-opts])
theme (quo.theme/use-theme)]
[rn/view {:flex 1}
[rn/view {:flex 1}]
[rn/view
@@ -9,47 +9,45 @@
(defn view
[]
(let [{:keys [on-complete title repeat-stage-title]} (rf/sub [:get-screen-params])
[pin set-pin] (rn/use-state "")
[first-pin set-first-pin] (rn/use-state "")
[error? set-error] (rn/use-state false)
[stage set-stage] (rn/use-state :create)
pin-empty? (string/blank? pin)
on-delete (rn/use-callback
(fn []
(set-error false)
(if (= (count pin) 1)
(do
(set-pin "")
(set-stage :create))
(when (and pin (pos? (count pin)))
(set-pin (.slice pin 0 -1)))))
[pin])
on-press (rn/use-callback
(fn [new-symbol]
(let [new-pin (str pin new-symbol)]
(when (<= (count new-pin)
constants/pincode-length)
(set-pin new-pin)
(when (= constants/pincode-length
(count new-pin))
(if (= :repeat stage)
(if (= first-pin new-pin)
(on-complete new-pin)
(set-error true))
(do
(set-pin "")
(set-first-pin new-pin)
(set-stage :repeat)))))))
[pin stage first-pin])]
(let [{:keys [on-complete]} (rf/sub [:get-screen-params])
[pin set-pin] (rn/use-state "")
[first-pin set-first-pin] (rn/use-state "")
[error? set-error] (rn/use-state false)
[stage set-stage] (rn/use-state :create)
pin-empty? (string/blank? pin)
on-delete (rn/use-callback
(fn []
(set-error false)
(if (= (count pin) 1)
(do
(set-pin "")
(set-stage :create))
(when (and pin (pos? (count pin)))
(set-pin (.slice pin 0 -1)))))
[pin])
on-press (rn/use-callback
(fn [new-symbol]
(let [new-pin (str pin new-symbol)]
(when (<= (count new-pin) constants/pincode-length)
(set-pin new-pin)
(when (= constants/pincode-length (count new-pin))
(if (= :repeat stage)
(if (= first-pin new-pin)
(on-complete new-pin)
(set-error true))
(do
(set-pin "")
(set-first-pin new-pin)
(set-stage :repeat)))))))
[pin stage first-pin])]
[rn/view {:style {:padding-bottom 12 :flex 1}}
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (if (= :create stage)
(or title (i18n/label :t/create-keycard-pin))
(or repeat-stage-title (i18n/label :t/repeat-keycard-pin)))
(i18n/label :t/create-keycard-pin)
(i18n/label :t/repeat-keycard-pin))
:description :text
:description-text (i18n/label :t/pin-needed-login-sign)}]
[rn/view {:style {:flex 1 :justify-content :center :align-items :center :padding-vertical 34}}
@@ -8,10 +8,10 @@
(defn view
[]
(let [{:keys [on-complete title]} (rf/sub [:get-screen-params])]
(let [{:keys [on-complete]} (rf/sub [:get-screen-params])]
[rn/view {:style {:padding-bottom 12 :flex 1}}
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top {:title (or title (i18n/label :t/enter-keycard-pin))}]
[quo/page-top {:title (i18n/label :t/enter-keycard-pin)}]
[keycard.pin/auth {:on-complete on-complete}]]))
@@ -1,87 +0,0 @@
(ns status-im.contexts.keycard.unblock.events
(:require [utils.re-frame :as rf]
[utils.security.core :as security]))
(rf/reg-event-fx :keycard/unblock.pin-created
(fn [{:keys [db]} [pin]]
{:db (assoc-in db [:keycard :unblock :pin] pin)
:fx [[:dispatch [:navigate-back]]
[:dispatch [:open-modal :screen/keycard.unblock.ready-to-unblock]]]}))
(rf/reg-event-fx :keycard/unblock.phrase-entered
(fn [{:keys [db]} [{:keys [phrase]}]]
{:db (assoc-in db [:keycard :unblock :masked-phrase] phrase)
:fx [[:dispatch [:navigate-back]]
[:dispatch
[:open-modal :screen/keycard.pin.create
{:on-complete #(rf/dispatch [:keycard/unblock.pin-created %])}]]]}))
(rf/reg-event-fx :keycard/unblock.generate-and-load-key
(fn [{:keys [db]}]
(let [{:keys [masked-phrase pin]} (get-in db [:keycard :unblock])]
{:fx [[:effects.keycard/generate-and-load-key
{:mnemonic (security/safe-unmask-data masked-phrase)
:pin pin
:on-success (fn []
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:navigate-back])
(rf/dispatch [:open-modal :screen/keycard.unblock.success]))}]]})))
;; third stage, import keys
(rf/reg-event-fx :keycard/unblock.import-keys
(fn []
{:fx [[:dispatch
[:keycard/connect.next-stage
{:on-error (fn [error]
(if (= error :keycard/error.keycard-empty)
(rf/dispatch [:keycard/unblock.generate-and-load-key])
(do
(rf/dispatch [:navigate-back])
(rf/dispatch [:keycard/on-application-info-error error]))))}]]]}))
;; second stage, check if card initialized
(rf/reg-event-fx :keycard/unblock.init-card-or-import-keys
(fn [{:keys [db]}]
(let [pin (get-in db [:keycard :unblock :pin])
{:keys [initialized?]} (get-in db [:keycard :application-info])]
{:fx [(if initialized?
[:dispatch [:keycard/unblock.import-keys]]
[:effects.keycard/init-card
{:pin pin
:on-success #(rf/dispatch [:keycard/unblock.import-keys])}])]})))
;; second stage, init card with pin
(defn init-with-pin
[]
(rf/dispatch
[:keycard/connect.next-stage
{:on-error (fn [error]
(if (= error :keycard/error.keycard-empty)
(rf/dispatch [:keycard/unblock.init-card-or-import-keys])
(do
(rf/dispatch [:navigate-back])
(rf/dispatch [:keycard/on-application-info-error error]))))}]))
;; first stage, reset card
(rf/reg-event-fx :keycard/unblock
(fn [{:keys [db]}]
{:fx [[:dispatch
[:keycard/connect
{:key-uid (get-in db [:keycard :application-info :key-uid])
:on-error (fn [error]
(cond
(or (= error :keycard/error.keycard-frozen)
(= error :keycard/error.keycard-locked))
(rf/dispatch [:keycard/factory-reset {:on-success init-with-pin}])
(= error :keycard/error.keycard-empty)
(init-with-pin)
:else
(do
(rf/dispatch [:navigate-back])
(if (= error :keycard/error.keycard-wrong-profile)
(do
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:open-modal :screen/keycard.different-card]))
(rf/dispatch [:keycard/on-application-info-error error])))))}]]]}))
@@ -1,60 +0,0 @@
(ns status-im.contexts.keycard.unblock.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.common.events-helper :as events-helper]
[status-im.contexts.keycard.common.view :as common.view]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn success-view
[]
[:<>
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/keycard-unblocked)}]
[rn/view {:style {:flex 1}}]
[rn/view {:style {:padding-horizontal 20}}
[quo/button {:on-press events-helper/navigate-back}
(i18n/label :t/done)]]])
(defn ready-to-unblock
[]
[:<>
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/ready-to-unblock-keycard)}]
[rn/view {:style {:flex 1}}]
[common.view/tips]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/scan-keycard)
:button-one-props {:on-press #(rf/dispatch [:keycard/unblock])}}]])
(defn sheet
[]
(let [customization-color (rf/sub [:profile/customization-color])]
[:<>
[quo/drawer-top {:title (i18n/label :t/unblock-keycard-recovery)}]
[quo/text
{:style {:padding-horizontal 20
:padding-vertical 8}}
(i18n/label :t/unblock-keycard-instructions)]
[quo/bottom-actions
{:actions :two-actions
:button-one-label (i18n/label :t/continue)
:button-one-props {:customization-color
customization-color
:on-press
(fn []
(rf/dispatch [:hide-bottom-sheet])
(rf/dispatch [:navigate-back])
(rf/dispatch
[:open-modal :screen/use-recovery-phrase-dark
{:on-success #(rf/dispatch [:keycard/unblock.phrase-entered %])}]))}
:button-two-label (i18n/label :t/cancel)
:button-two-props {:type :grey
:on-press #(rf/dispatch [:hide-bottom-sheet])}}]]))
+6 -7
View File
@@ -28,7 +28,7 @@
:keycard/error.not-keycard
(not has-master-key?)
:keycard/error.keycard-empty
:keycard/error.keycard-blank
(and (zero? pin-retry-counter)
(or (nil? puk-retry-counter)
@@ -84,9 +84,8 @@
(->> (:accounts kp)
(map :address)
set))]
(when-not (nil? address)
(-> keypairs
vals
find-keycard-keypair
keypair-addresses
(contains? (string/lower-case address))))))
(-> keypairs
vals
find-keycard-keypair
keypair-addresses
(contains? (string/lower-case address)))))
@@ -20,6 +20,8 @@
:type :default
:name "Trip to Vegas"
:address "0x0ah...78b"}
:networks [{:network-name :ethereum :short-name "eth"}
{:network-name :optimism :short-name "oeth"}]
:action :none
:on-press (fn [] (js/alert "Item pressed"))
:on-options-press (fn [] (js/alert "Options pressed"))
@@ -18,7 +18,6 @@
[{:type :select
:key :status
:options [{:key :error}
{:key :warning}
{:key :default}]}
{:type :text
:key :title}
@@ -44,23 +44,22 @@
(defn view
[]
(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})
{:keys [on-success masked-seed-phrase
revealed?]} (rf/sub [:get-screen-params])
revealed? (reagent/atom revealed?)
customization-color (rf/sub [:profile/customization-color])
seed-phrase (reagent/atom (if masked-seed-phrase
(->
(security/safe-unmask-data
masked-seed-phrase)
(string/split #"\s"))
[]))]
(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)
customization-color (rf/sub [:profile/customization-color])
{:keys [on-success masked-seed-phrase]} (rf/sub [:get-screen-params])
seed-phrase (reagent/atom (if masked-seed-phrase
(->
(security/safe-unmask-data
masked-seed-phrase)
(string/split #"\s"))
[]))]
(fn []
(let [theme (quo.theme/use-theme)]
(rn/use-mount
@@ -109,7 +108,8 @@
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/i-have-written)
:button-one-props {:customization-color customization-color
:button-one-props {:disabled? (some false? (vals @checked?))
:customization-color customization-color
:on-press #(on-success (security/mask-data @seed-phrase))}}]
[quo/text
{:size :paragraph-2
@@ -10,7 +10,6 @@
[]
{;; Temporary fix until https://github.com/status-im/status-go/issues/3024 is resolved
:wakuV2Nameserver "8.8.8.8"
:kdfIterations 3200
:statusProxyEnabled config/status-proxy-enabled?
:statusProxyStageName config/status-proxy-stage-name
:statusProxyMarketUser config/STATUS_BUILD_PROXY_USER
@@ -14,14 +14,15 @@
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn on-send-contact-request
(defn on-contact-request
[]
(let [main-event [:show-bottom-sheet {:content contact-request/view}]]
(rf/dispatch [:profile/check-profile-update-prompt main-event])))
(rf/dispatch [:show-bottom-sheet
{:content (fn [] [contact-request/view])}]))
(defn on-contact-review
[]
(rf/dispatch [:show-bottom-sheet {:content contact-review/view}]))
(rf/dispatch [:show-bottom-sheet
{:content (fn [] [contact-review/view])}]))
(defn view
[{:keys [scroll-y]}]
@@ -33,27 +34,27 @@
profile-picture (profile.utils/photo contact)
online? (rf/sub [:visibility-status-updates/online? public-key])
theme (quo.theme/use-theme)
contact-status (rn/use-memo
(fn []
(cond
(= contact-request-state
constants/contact-request-state-mutual) :contact
blocked? :blocked
:else nil))
[blocked? contact-request-state])
on-start-chat (rn/use-callback
#(rf/dispatch [:chat.ui/start-chat public-key ens-name])
[ens-name public-key])
on-unblock-press (rn/use-callback
(fn []
(rf/dispatch [:contact/unblock-contact
public-key])
(rf/dispatch [:toasts/upsert
{:id :user-unblocked
:type :positive
:text (i18n/label :t/user-unblocked
{:username full-name})}]))
[public-key full-name])]
contact-status (rn/use-memo (fn []
(cond
(= contact-request-state
constants/contact-request-state-mutual) :contact
blocked? :blocked
:else nil))
[blocked? contact-request-state])
on-start-chat (rn/use-callback #(rf/dispatch [:chat.ui/start-chat
public-key
ens-name])
[ens-name public-key])
on-unblock-press (rn/use-callback (fn []
(rf/dispatch [:contact/unblock-contact
public-key])
(rf/dispatch [:toasts/upsert
{:id :user-unblocked
:type :positive
:text (i18n/label :t/user-unblocked
{:username
full-name})}]))
[public-key full-name])]
[rn/view {:style style/header-container}
[rn/view {:style style/header-top-wrapper}
[rn/view {:style style/avatar-wrapper}
@@ -92,12 +93,14 @@
(cond
(and (not blocked?)
(or (not contact-request-state)
(= contact-request-state constants/contact-request-state-none)
(= contact-request-state constants/contact-request-state-dismissed)))
(or
(not contact-request-state)
(= contact-request-state constants/contact-request-state-none)
(= contact-request-state constants/contact-request-state-dismissed)))
[quo/button
{:container-style style/button-wrapper
:on-press on-send-contact-request
:on-press on-contact-request
:customization-color customization-color
:icon-left :i/add-user}
(i18n/label :t/send-contact-request)]
@@ -4,35 +4,27 @@
[utils.re-frame :as rf]))
(rf/reg-event-fx :profile/edit-accent-colour-success
(fn [_ [{:keys [customization-color navigate-back? show-toast?]}]]
(fn [_ [customization-color]]
{:fx [[:dispatch [:profile/save-local-accent-color customization-color]]
(when navigate-back?
[:dispatch [:navigate-back]])
(when show-toast?
[:dispatch
[:toasts/upsert
{:type :positive
:theme :dark
:text (i18n/label :t/accent-colour-updated)}]])]}))
[:dispatch [:navigate-back]]
[:dispatch
[:toasts/upsert
{:type :positive
:theme :dark
:text (i18n/label :t/accent-colour-updated)}]]]}))
(rf/reg-event-fx :profile/save-local-accent-color
(fn [{:keys [db]} [customization-color]]
{:db (assoc-in db [:profile/profile :customization-color] customization-color)}))
(defn edit-accent-colour
[{:keys [db]}
[{:keys [color navigate-back? show-toast?]
:or {navigate-back? true
show-toast? true}}]]
[{:keys [db]} [customization-color]]
(let [key-uid (get-in db [:profile/profile :key-uid])]
{:fx [[:json-rpc/call
[{:method "wakuext_setCustomizationColor"
:params [{:customizationColor color
:params [{:customizationColor customization-color
:keyUid key-uid}]
:on-success [:profile/edit-accent-colour-success
{:customization-color color
:navigate-back? navigate-back?
:show-toast? show-toast?}]
:on-success [:profile/edit-accent-colour-success customization-color]
:on-error #(log/error "failed to edit accent color." {:error %})}]]]}))
(rf/reg-event-fx :profile/edit-accent-colour edit-accent-colour)
@@ -11,10 +11,7 @@
[{:method "wakuext_setCustomizationColor"
:params [{:customizationColor new-color
:keyUid key-uid}]
:on-success [:profile/edit-accent-colour-success
{:customization-color new-color
:navigate-back? true
:show-toast? true}]
:on-success [:profile/edit-accent-colour-success new-color]
:on-error fn?}]]]}]
(is (match? expected
(sut/edit-accent-colour cofx [{:color new-color}])))))
(sut/edit-accent-colour cofx [new-color])))))
@@ -58,8 +58,7 @@
{:type :primary
:customization-color @unsaved-custom-color
:on-press (fn []
(rf/dispatch [:profile/edit-accent-colour
{:color @unsaved-custom-color}]))}
(rf/dispatch [:profile/edit-accent-colour @unsaved-custom-color]))}
(i18n/label :t/save-colour)]]]]))))
(defn view
@@ -11,22 +11,19 @@
(update db :profile/profile dissoc :images))}))
(rf/reg-event-fx :profile/edit-profile-picture-success
(fn [{db :db} [{:keys [show-toast?]} images]]
(let [has-picture? (-> db :profile/profile :images count pos?)]
(fn [_ [images]]
(let [has-picture? (rf/sub [:profile/has-picture])]
{:fx [[:dispatch [:profile/update-local-picture (reverse images)]]
(when show-toast?
[:dispatch
[:toasts/upsert
{:type :positive
:theme :dark
:text (i18n/label (if has-picture?
:t/profile-picture-updated
:t/profile-picture-added))}]])]})))
[:dispatch
[:toasts/upsert
{:type :positive
:theme :dark
:text (i18n/label (if has-picture?
:t/profile-picture-updated
:t/profile-picture-added))}]]]})))
(defn edit-profile-picture
[{:keys [db]}
[{:keys [picture crop-width crop-height show-toast?]
:or {show-toast? true}}]]
[{:keys [db]} [picture crop-width crop-height]]
(let [key-uid (get-in db [:profile/profile :key-uid])
crop-width (or crop-width profile-picture-picker/crop-size)
crop-height (or crop-height profile-picture-picker/crop-size)
@@ -34,28 +31,25 @@
{:fx [[:json-rpc/call
[{:method "multiaccounts_storeIdentityImage"
:params [key-uid path 0 0 crop-width crop-height]
:on-success [:profile/edit-profile-picture-success {:show-toast? show-toast?}]}]]]}))
:on-success [:profile/edit-profile-picture-success]}]]]}))
(rf/reg-event-fx :profile/edit-picture edit-profile-picture)
(rf/reg-event-fx :profile/delete-profile-picture-success
(fn [_ [{:keys [show-toast?]}]]
(fn [_]
{:fx [[:dispatch [:profile/update-local-picture nil]]
(when show-toast?
[:dispatch
[:toasts/upsert
{:type :positive
:theme :dark
:text (i18n/label :t/profile-picture-removed)}]])]}))
[:dispatch
[:toasts/upsert
{:type :positive
:theme :dark
:text (i18n/label :t/profile-picture-removed)}]]]}))
(defn delete-profile-picture
[{:keys [db]}
[{:keys [show-toast?]
:or {show-toast? true}}]]
[{:keys [db]}]
(let [key-uid (get-in db [:profile/profile :key-uid])]
{:fx [[:json-rpc/call
[{:method "multiaccounts_deleteIdentityImage"
:params [key-uid]
:on-success [:profile/delete-profile-picture-success {:show-toast? show-toast?}]}]]]}))
:on-success [:profile/delete-profile-picture-success]}]]]}))
(rf/reg-event-fx :profile/delete-picture delete-profile-picture)
@@ -12,9 +12,9 @@
[{:method "multiaccounts_storeIdentityImage"
:params [key-uid picture 0 0 profile-picture-picker/crop-size
profile-picture-picker/crop-size]
:on-success [:profile/edit-profile-picture-success {:show-toast? true}]}]]]}]
:on-success [:profile/edit-profile-picture-success]}]]]}]
(is (match? expected
(sut/edit-profile-picture cofx [{:picture picture}])))))
(sut/edit-profile-picture cofx [picture])))))
(deftest delete-picture-test
(let [key-uid "key-uid"
@@ -22,6 +22,6 @@
expected {:fx [[:json-rpc/call
[{:method "multiaccounts_deleteIdentityImage"
:params [key-uid]
:on-success [:profile/delete-profile-picture-success {:show-toast? true}]}]]]}]
:on-success [:profile/delete-profile-picture-success]}]]]}]
(is (match? expected
(sut/delete-profile-picture cofx [{}])))))
(sut/delete-profile-picture cofx)))))
@@ -16,7 +16,7 @@
has-picture? (rf/sub [:profile/has-picture])
on-change-profile-pic (fn [picture]
(if picture
(rf/dispatch [:profile/edit-picture {:picture picture}])
(rf/dispatch [:profile/edit-picture picture])
(rf/dispatch [:profile/delete-picture])))]
[rn/view
{:key :edit-profile
@@ -1,33 +0,0 @@
(ns status-im.contexts.profile.edit.introduce-yourself.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn sheet
[{:keys [pending-event]}]
(let [on-accept (fn []
(rf/dispatch [:open-modal :screen/profile.edit-profile-modal
{:pending-event pending-event}]))
on-reject #(rf/dispatch pending-event)]
[:<>
[rn/view {:style {:padding-horizontal 20}}
[quo/text
{:style {:padding-bottom 4}
:size :heading-2
:weight :semi-bold}
(i18n/label :t/just-introduce-yourself)]
[quo/text
{:style {:padding-top 4 :padding-bottom 12}
:size :paragraph-1
:weight :regular}
(i18n/label :t/add-display-name-and-picture)]]
[quo/bottom-actions
{:actions :two-actions
:buttons-style {:flex-shrink 1 :flex-basis 0}
:button-one-label (i18n/label :t/edit-profile)
:button-one-props {:type :primary
:on-press on-accept}
:button-two-label (i18n/label :t/skip)
:button-two-props {:type :grey
:on-press on-reject}}]]))
@@ -1,62 +0,0 @@
(ns status-im.contexts.profile.edit.modal.events
(:require [status-im.contexts.profile.edit.introduce-yourself.view :as introduce-yourself]
[utils.re-frame :as rf]))
(rf/reg-event-fx
:profile/edit-profile
(fn [_ [{:keys [display-name picture color on-success]}]]
{:fx (cond-> []
display-name
(conj [:dispatch
[:profile/edit-name
{:display-name display-name
:navigate-back? false
:show-toast? false}]])
color
(conj [:dispatch
[:profile/edit-accent-colour
{:color color
:navigate-back? false
:show-toast? false}]])
picture
(conj [:dispatch
[:profile/edit-picture
{:picture picture
:show-toast? false}]])
(nil? picture)
(conj [:dispatch [:profile/delete-picture {:show-toast? false}]])
:always
(conj [:dispatch [:navigate-back]]
[:dispatch on-success]))}))
(defn- profile-update-asked-storage-key
[key-uid]
(keyword :update-profile-asked key-uid))
(rf/reg-event-fx
:profile/set-profile-update-as-asked
(fn [{db :db}]
(let [storage-key (-> db :profile/profile :key-uid profile-update-asked-storage-key)]
{:fx [[:effects.async-storage/set {storage-key true}]]})))
(rf/reg-event-fx
:profile/ask-profile-update
(fn [_ [pending-event]]
{:fx [[:dispatch [:profile/set-profile-update-as-asked]]
[:dispatch
[:show-bottom-sheet
{:content (fn []
[introduce-yourself/sheet {:pending-event pending-event}])}]]]}))
(rf/reg-event-fx
:profile/check-profile-update-prompt
(fn [{db :db} [pending-event]]
(let [storage-key (-> db :profile/profile :key-uid profile-update-asked-storage-key)]
{:fx [[:effects.async-storage/get
{:keys [storage-key]
:cb (fn [profile-updated-data]
(rf/dispatch (if (storage-key profile-updated-data)
pending-event
[:profile/ask-profile-update pending-event])))}]]})))
@@ -1,55 +0,0 @@
(ns status-im.contexts.profile.edit.modal.style
(:require
[quo.foundations.colors :as colors]
[react-native.platform :as platform]))
(def continue-button
{:width "100%"
:margin-left :auto
:margin-top (if platform/android? :auto 0)
:margin-right :auto})
(def button-container
{:width "100%"
:padding-left 20
:padding-right 20
:padding-top 12
:align-self :flex-end
:height 64})
(defn view-button-container
[keyboard-shown?]
(merge button-container
(if platform/ios?
{:margin-bottom (if keyboard-shown? 0 34)}
{:margin-bottom (if keyboard-shown? 12 34)})))
(def blur-button-container
(merge button-container
(when platform/android? {:padding-bottom 12})))
(def page-container
{:flex 1})
(def info-message
{:margin-top 8})
(def title
{:color colors/white
:margin-top 12
:margin-bottom 18})
(def color-title
{:color colors/white-70-blur
:margin-top 20
:margin-bottom 16})
(def content-container
{:padding-horizontal 20})
(def input-container
{:align-items :flex-start})
(def profile-input-container
{:flex-direction :row
:justify-content :center})
@@ -1,266 +0,0 @@
(ns status-im.contexts.profile.edit.modal.view
(:require
[clojure.string :as string]
[oops.core :as oops]
[quo.core :as quo]
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.hooks :as hooks]
[react-native.platform :as platform]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im.common.avatar-picture-picker.view :as profile-picture-picker]
[status-im.common.events-helper :as events-helper]
[status-im.common.validation.profile :as profile-validator]
[status-im.constants :as c]
[status-im.contexts.profile.edit.modal.events]
[status-im.contexts.profile.edit.modal.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[utils.responsiveness :as responsiveness]))
(def scroll-view-height (reagent/atom 0))
(def content-container-height (reagent/atom 0))
(def set-scroll-view-height #(reset! scroll-view-height %))
(defn set-content-container-height
[e]
(reset! content-container-height (oops/oget e "nativeEvent.layout.height")))
(defn show-button-background?
[keyboard-height keyboard-shown content-scroll-y]
(let [button-container-height 64
keyboard-view-height (+ keyboard-height button-container-height)]
(when keyboard-shown
(cond
platform/android?
(< (- @scroll-view-height button-container-height) @content-container-height)
platform/ios?
(< (- @scroll-view-height keyboard-view-height) (- @content-container-height content-scroll-y))
:else
false))))
(defn button-container
[show-keyboard? keyboard-shown show-background? keyboard-height children]
(let [height (reagent/atom 0)]
(reset! height (if show-keyboard? (if keyboard-shown keyboard-height 0) 0))
[rn/view {:style {:margin-top :auto}}
(cond
(and (> @height 0) show-background?)
[quo/blur
(when keyboard-shown
{:blur-amount 34
:blur-type :transparent
:overlay-color :transparent
:background-color (if platform/android?
colors/neutral-100
colors/neutral-80-opa-1-blur)
:style style/blur-button-container})
children]
(and (> @height 0) (not show-background?))
[rn/view {:style (style/view-button-container true)}
children]
(not show-keyboard?)
[rn/view {:style (style/view-button-container false)}
children])]))
(defn- add-keyboard-listener
[e callback]
(oops/ocall rn/keyboard "addListener" e callback))
(defn- on-keyboard-show
[f]
(add-keyboard-listener (if platform/android? "keyboardDidShow" "keyboardWillShow") f))
(defn- on-keyboard-hide
[f]
(add-keyboard-listener (if platform/android? "keyboardDidHide" "keyboardWillHide") f))
(defn floating-button
[{:keys [custom-color scroll-y on-submit disabled?]}]
(reagent/with-let [show-keyboard? (reagent/atom false)
show-listener (on-keyboard-show #(reset! show-keyboard? true))
hide-listener (on-keyboard-hide #(reset! show-keyboard? false))]
(let [{:keys [keyboard-shown keyboard-height]} (hooks/use-keyboard)
show-background? (show-button-background? keyboard-height
keyboard-shown
scroll-y)]
[rn/keyboard-avoiding-view
{:style {:position :absolute
:top 0
:bottom 0
:left 0
:right 0}
:pointer-events :box-none}
[button-container @show-keyboard? keyboard-shown show-background? keyboard-height
[quo/button
{:accessibility-label :submit-create-profile-button
:type :primary
:customization-color custom-color
:on-press on-submit
:container-style style/continue-button
:disabled? disabled?}
(i18n/label :t/continue)]]])
(finally
(oops/ocall show-listener "remove")
(oops/ocall hide-listener "remove"))))
(defn- content
[{:keys [set-display-name set-validation-msg picture-picker]}]
(let [open-picture-picker (fn []
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:show-bottom-sheet
{:content picture-picker
:shell? true
:theme :dark}]))
on-change-text (fn [s]
(set-validation-msg s)
(set-display-name s))]
(fn [{:keys [profile-image custom-color display-name validation-msg valid-name?
name-too-short? initial-display-name set-scroll set-scroll-height
set-custom-color]}]
(let [{window-width :width} (rn/get-window)
info-type (cond
validation-msg :error
name-too-short? :default
:else :success)
info-message (or validation-msg
(i18n/label :t/minimum-characters
{:min-chars profile-validator/min-length}))
full-name (if (seq display-name)
display-name
initial-display-name)]
[rn/scroll-view
{:on-layout set-scroll-height
:on-scroll set-scroll
:scroll-event-throttle 64
:content-container-style {:flex-grow 1}}
[rn/view {:on-layout set-content-container-height}
[rn/view {:style style/content-container}
[quo/text
{:style style/title
:size :heading-1
:weight :semi-bold}
(i18n/label :t/edit-profile)]
[rn/view {:style style/input-container}
[rn/view {:style style/profile-input-container}
[quo/profile-input
{:customization-color custom-color
:placeholder initial-display-name
:on-press open-picture-picker
:image-picker-props {:profile-picture profile-image
:full-name full-name
:customization-color custom-color}
:title-input-props {:default-value ""
:auto-focus true
:max-length c/profile-name-max-length
:on-change-text on-change-text}}]]
[quo/info-message
{:status info-type
:size :default
:icon (if valid-name? :i/positive-state :i/info)
:color (when (= :default info-type) colors/white-70-blur)
:container-style style/info-message}
info-message]
[quo/text
{:size :paragraph-2
:weight :medium
:style style/color-title}
(i18n/label :t/colour)]]]
[quo/color-picker
{:blur? true
:default-selected custom-color
:on-change set-custom-color
:window-width window-width
:container-style {:padding-left (responsiveness/iphone-11-Pro-20-pixel-from-width
window-width)}}]]]))))
(defn- submittable-state?
[{:keys [new-color? new-picture? new-name? valid-name?]}]
(let [acceptable-name? (or (not new-name?) valid-name?)]
(or (and new-color? acceptable-name?)
(and new-picture? acceptable-name?)
(and new-name? valid-name?))))
(defn view
[]
(let [{:keys [pending-event]} (rf/sub [:get-screen-params])
{initial-display-name :display-name
initial-color :customization-color
[initial-image] :images} (rf/sub [:profile/profile])
top (safe-area/get-top)
scroll-y (reagent/atom 0)
display-name (reagent/atom "")
validation-msg (reagent/atom (profile-validator/validation-name @display-name))
custom-color (reagent/atom (or initial-color c/profile-default-color))
profile-image (reagent/atom initial-image)
set-display-name #(reset! validation-msg (profile-validator/validation-name %))
set-validation-msg #(reset! display-name (string/trim %))
set-custom-color #(reset! custom-color %)
set-scroll (fn [e]
(reset! scroll-y (oops/oget e "nativeEvent.contentOffset.y")))
set-scroll-height (fn [e]
(reset! scroll-y 0)
(-> e
(oops/oget "nativeEvent.layout.height")
set-scroll-view-height))
picture-picker (fn []
[profile-picture-picker/view
{:on-result #(reset! profile-image %)
:has-picture? (some? @profile-image)}])
update-profile (fn []
(rf/dispatch
[:profile/edit-profile
(cond-> {:on-success pending-event}
(and (seq @display-name)
(not= initial-display-name @display-name))
(assoc :display-name @display-name)
(and (not= initial-image @profile-image))
(assoc :picture @profile-image)
(not= initial-color @custom-color)
(assoc :color @custom-color))]))
on-close (fn []
(events-helper/navigate-back)
(rf/dispatch pending-event))]
(fn []
(let [name-too-short? (profile-validator/name-too-short? @display-name)
valid-name? (and (not @validation-msg) (not name-too-short?))
disabled? (not
(submittable-state?
{:new-color? (not= initial-color @custom-color)
:new-picture? (not= @profile-image initial-image)
:new-name? (and (not= initial-display-name @display-name)
(seq @display-name))
:valid-name? valid-name?}))]
[quo/overlay {:type :shell}
[rn/view {:style style/page-container}
[quo/page-nav
{:margin-top top
:background :blur
:icon-name :i/close
:on-press on-close}]
[content
{:profile-image @profile-image
:custom-color @custom-color
:display-name @display-name
:validation-msg @validation-msg
:valid-name? valid-name?
:name-too-short? name-too-short?
:picture-picker picture-picker
:initial-display-name initial-display-name
:set-scroll set-scroll
:set-scroll-height set-scroll-height
:set-custom-color set-custom-color
:set-display-name set-display-name
:set-validation-msg set-validation-msg}]
[floating-button
{:custom-color @custom-color
:scroll-y @scroll-y
:on-submit update-profile
:disabled? disabled?}]]]))))

Some files were not shown because too many files have changed in this diff Show More