Compare commits

...
Author SHA1 Message Date
Brian Sztamfater 984bc74b6d lint fixes 2023-12-05 02:31:24 -03:00
Brian Sztamfater 17cd163f25 some cleanup 2023-12-05 02:23:06 -03:00
Brian Sztamfater f3c967f26b improve flow 2023-12-05 01:13:05 -03:00
Brian Sztamfater 9f78eaa91d integrate select input screen to the flow, also calculate routes prior showing transaction confirmation screen 2023-12-04 21:46:33 -03:00
Brian Sztamfater 778b06abb2 some refactor 2023-12-04 20:48:48 -03:00
Brian Sztamfater 68d7eddb4d only allow ETH transfers for now 2023-12-04 20:48:48 -03:00
Brian Sztamfater c7165cf078 calculate fiat balances correctly and some other fixes 2023-12-04 20:48:46 -03:00
Brian Sztamfater 50dcf9d9b9 goerli as default suggested routes network 2023-12-04 20:48:22 -03:00
Brian Sztamfater 372bf83da5 some polishing 2023-12-04 20:48:21 -03:00
Brian Sztamfater 710829d248 fix endpoints integration 2023-12-04 20:47:45 -03:00
Brian Sztamfater 23fae29f9d try basic integration 2023-12-04 20:47:42 -03:00
Brian Sztamfater daf3e52281 some cleanup 2023-12-04 20:46:45 -03:00
Jamie Caprani 3338a4b1a1 chore 2023-12-04 20:03:28 -03:00
Jamie Caprani 9ead91c383 progress 2023-12-04 20:02:09 -03:00
Ajay Sivan fb84885af0 Add Test Networks Enabled option in settings 2023-12-04 19:59:06 -03:00
Ulises M 4aac04e931 Add utils.money/add version able to work with nils 2023-12-04 19:59:05 -03:00
Brian Sztamfater 90166e8762 some refactor 2023-12-01 13:38:57 -03:00
Brian Sztamfater d68fdb18f4 adjustment to summary info component 2023-12-01 13:38:57 -03:00
Brian Sztamfater e46f4d9081 adjust text color 2023-12-01 13:38:56 -03:00
Brian Sztamfater dd2fd3410b some refactor 2023-12-01 13:38:56 -03:00
Brian Sztamfater 085e2df34c localize strings 2023-12-01 13:38:55 -03:00
Brian Sztamfater 51bfd3567c most of the ui in place, polishing pending 2023-12-01 13:38:54 -03:00
Brian Sztamfater fb6d907cc5 some progress 2023-12-01 13:38:54 -03:00
Brian Sztamfater a88c5b7bf7 feat: transaction confirmation page ui 2023-12-01 13:38:52 -03:00
Jamie Caprani f9f328107d chore: add ability to create watch address & some related ui changes on account page (#17868) 2023-12-01 04:29:01 -08:00
Yevheniia Berdnyk 04dee8be45 e2e: updated data for waku backup test 2023-12-01 12:28:26 +02:00
Alexander 52f7fc59ee Updated data-item, monospaced & aligned address (#18008)
* Upd

* Fix
2023-12-01 10:03:08 +01:00
Mohamed Javid b5202b4d28 [Feature] Added activity check on entered watch address (#17970)
This commit 
 - implements the activity check for the entered watch address.
 - added warning colors
 - fixes bottom inset in add address to watch screen

---------

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2023-12-01 00:28:09 +05:30
Andrea Maria Piana 210cf64ce0 Fix panic syncing community token gated
https://github.com/status-im/status-go/compare/8a4c2d8d...8206ffc7
2023-11-30 13:49:47 +00:00
Lungu Cristian ed270b2162 Enabling biometry without password during sync (#17960)
* feat: added migration for the keychain hashed password

* feat: added sync biometry without password entry

* fix: biometry typo from develop

* ref: moved migration side-effects outside the event

* ref: some renaming for keychain migration

* ref: addressed @cammellos' review comments

* ref: removed unnecessary anon fn

* fix: addressed @ilmotta's review comments

* ref: removed theme from enable-biometrics

* ref: addressed J-Son89's review comments

* test: added tests for mask-data and hash-masked-password

* test: added schema to hash-masked-password and fixed test

* fix: forgot the threading

* ref: improved the masked data schema

* fix: no biometry error when canceled by user

* fix: biometry error wasn't propagated during login

* fix: alert dismiss button not passed properly

* fix: show biometrics NOT_ENROLLED error only once

* lint: removed unused require
2023-11-30 13:40:29 +02:00
Andrea Maria Piana d412fa3c63 Set up skeleton for communities request to join 2023-11-30 09:49:43 +00:00
Yevheniia Berdnyk b7f675aa5c e2e: fix for deep links test 2023-11-30 01:09:42 +02:00
Volodymyr Kozieiev bfa23c182f Add requirement for component tests (#18015) 2023-11-29 18:50:49 +00:00
Mohsen 6b721265af [#17986] feat: implement new settings ui, header section (#17991) 2023-11-29 20:54:11 +03:00
Jamie CapraniandRende11 589a581298 chore(wallet): add ui for send page (#17786) - merged in (#18017)
---------
Co-authored-by: Rende11 <artamonovn@gmail.com>
2023-11-29 05:12:21 -08:00
Yevheniia Berdnyk 0546a87e9a e2e: deep links tests added 2023-11-29 14:09:31 +02:00
Parvesh Monu e5ce7fed3a fix position of the last item in the community chat list and the position of the jump-to button (#17999) 2023-11-29 16:45:30 +05:30
Siddarth Kumar 58d5c3d7a5 don't restrict diawi upload for iOS release builds (#18016)
This commit removes the restriction of uploading iOS release builds to Diawi

Its helpful to have the status app uploaded to Diawi to test release builds on our iPhones.

The installer is very straightforward and makes life easier when we want to try out release builds.
2023-11-28 22:46:58 +05:30
Ibrahem Khalil 6ccea1ddb2 Continue button is invisible behind keyboard in Add Address To Watch … (#17940) 2023-11-28 18:38:06 +02:00
Alex Tumanov a9a17aaae8 Implement dropdown-input based on the original dropdown component (#17927) 2023-11-28 15:21:15 +00:00
Andrea Maria Piana 6d69c278cd Update key in tests 2023-11-28 10:57:10 +00:00
Yevheniia Berdnyk c7e230d070 e2e: changed test order 2023-11-28 12:05:47 +02:00
frank d309aa366d chore: specify light client mode for wakuv2 (#18002) 2023-11-28 14:48:58 +08:00
Jamie Caprani f124ca4252 chore(wallet): add common page-nav component for account switcher (#17946) 2023-11-27 09:16:31 -08:00
Brian Sztamfater 1385e27cf4 feat: select asset screen ui (#17780)
feat: select asset screen ui

Signed-off-by: Brian Sztamfater <brian@status.im>
2023-11-27 11:03:02 -03:00
Volodymyr Kozieiev f82d28c6c9 Show network info on collectible info page (#17980) 2023-11-27 12:29:12 +00:00
Omar Basem a2856cf1c3 Wallet: Emoji picker performance (#17891)
Wallet: Emoji picker navigation perf
2023-11-27 09:57:29 +04:00
Yevheniia Berdnyk e6a7c420a2 e2e: APK upload time limit increased 2023-11-23 12:34:30 +02:00
alwx 671aa67002 Detect image dimensions correctly 2023-11-23 09:28:38 +00:00
Omar Basem dbc8df251a Wallet: Keypair follow up (#17953)
* Wallet: Keypair follow up
2023-11-23 10:00:22 +04:00
Ulises Manuel 279993b658 Add channel-name component (#17903) 2023-11-22 15:54:52 -06:00
Volodymyr Kozieiev 0c1a18b444 Connect collectible overview page to backend (#17884) 2023-11-22 19:40:26 +00:00
136 changed files with 3305 additions and 710 deletions
-1
View File
@@ -77,7 +77,6 @@ pipeline {
}
}
stage('Upload') {
when { expression { !utils.isReleaseBuild() } }
steps { script {
env.DIAWI_URL = ios.uploadToDiawi()
env.PKG_URL = env.DIAWI_URL
+1 -1
View File
@@ -716,7 +716,7 @@ src
- `src/js`: Raw Javascript files, e.g. React Native Reanimated worklets.
- `src/mocks`: Plumbing configuration to be able to run tests.
- `src/quo/`: The component library for Status Mobile.
- `src/quo/`: The component library for Status Mobile. [Read more...](../src/quo/README.md)
- `src/react_native/`: Contains only low-level constructs to help React Native
work in tandem with Clojure(Script).
- `src/status_im2/`: Directory where we try to be as strict as possible about
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

+1
View File
@@ -49,6 +49,7 @@
:Text {}
:StatusBar {}
:ScrollView {}
:SafeAreaView {}
:KeyboardAvoidingView {}
:TextInput {}
:Image {}
+11
View File
@@ -116,6 +116,17 @@ rendered. We use [React Native Testing Library](https://callstack.github.io/reac
There are dozens of examples in the repository, so use them as a reference. A
good and complete example is [quo.components.avatars.user-avatar.component-spec](/src/quo/components/avatars/user_avatar/component_spec.cljs)
### No-props test
When writing tests for the component that has props, please add one test that covers situation when props aren't passed. Because even if component not showing anything meaningful without props, it shouldn't crash.
```clojure
(h/describe "Transaction Progress"
(h/test "component renders without props"
(h/render [quo/transaction-progress {}])
(h/is-truthy (h/get-by-label-text :transaction-progress)))
```
## Do not couple the library with re-frame
Don't use re-frame inside this library (e.g. dispatch & subscribe). If a
@@ -30,6 +30,6 @@
{:accessibility-label :account-emoji
:adjusts-font-size-to-fit true
:style {:font-size emoji-size}}
(string/trim emoji)]]))
(when emoji (string/trim emoji))]]))
(def view (quo.theme/with-theme view-internal))
@@ -67,7 +67,7 @@
[rn/text
{:style (style/emoji-size size)
:accessibility-label :emoji}
(string/trim emoji)])
(when emoji (string/trim emoji))])
[lock locked? size theme]])
(def view (quo.theme/with-theme view-internal))
@@ -2,26 +2,30 @@
(:require [quo.foundations.colors :as colors]))
(defn- circle-color
[customization-color]
(colors/custom-color customization-color 50 20))
[customization-color neutral? theme]
(if neutral?
(colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5 theme)
(colors/custom-color customization-color 50 20)))
(defn- text-color
[customization-color theme]
(colors/theme-colors
(colors/custom-color customization-color 50)
(colors/custom-color customization-color 60)
theme))
[customization-color neutral? theme]
(if neutral?
(colors/theme-colors colors/neutral-80-opa-70 colors/white-opa-70 theme)
(colors/theme-colors
(colors/custom-color customization-color 50)
(colors/custom-color customization-color 60)
theme)))
(defn container
[circle-size customization-color]
[circle-size customization-color neutral? theme]
{:width circle-size
:height circle-size
:border-radius circle-size
:text-align :center
:justify-content :center
:align-items :center
:background-color (circle-color customization-color)})
:background-color (circle-color customization-color neutral? theme)})
(defn text
[customization-color theme]
{:color (text-color customization-color theme)})
[customization-color neutral? theme]
{:color (text-color customization-color neutral? theme)})
@@ -1,5 +1,6 @@
(ns quo.components.avatars.wallet-user-avatar.view
(:require [quo.components.avatars.wallet-user-avatar.style :as style]
(:require [clojure.string :as string]
[quo.components.avatars.wallet-user-avatar.style :as style]
[quo.components.markdown.text :as text]
[quo.theme :as quo.theme]
[react-native.core :as rn]
@@ -40,18 +41,21 @@
:customization-color - keyword (default: nil) - color of the avatar
:size - keyword (default: last element of properties object) - size of the
avatar
:monospace? - boolean (default: false) - use monospace font"
[{:keys [full-name customization-color size theme monospace?]
:monospace? - boolean (default: false) - use monospace font
:lowercase? - boolean (default: false) - lowercase text
:neutral? - boolean (default: false) - use neutral colors variant"
[{:keys [full-name customization-color size theme monospace? lowercase? neutral?]
:or {size biggest-possible}}]
(let [circle-size (:size (size properties))
small? (check-if-size-small size)]
small? (check-if-size-small size)
initials (utils.string/get-initials full-name (if small? 1 2))]
[rn/view
{:style (style/container circle-size customization-color)}
{:style (style/container circle-size customization-color neutral? theme)}
[text/text
{:accessibility-label :wallet-user-avatar
:size (:font-size (size properties))
:weight (if monospace? :monospace (:font-weight (size properties)))
:style (style/text customization-color theme)}
(utils.string/get-initials full-name (if small? 1 2))]]))
:style (style/text customization-color neutral? theme)}
(if (and initials lowercase?) (string/lower-case initials) initials)]]))
(def wallet-user-avatar (quo.theme/with-theme view-internal))
@@ -0,0 +1,56 @@
(ns quo.components.dropdowns.dropdown-input.component-spec
(:require
[quo.components.dropdowns.dropdown-input.view :as dropdown-input]
[test-helpers.component :as h]))
(h/describe "Dropdown Input"
(h/test "default render"
(let [header-label "Label"
label "Dropdown"]
(h/render [dropdown-input/view
{:label? true
:header-label
header-label} label])
(h/is-truthy (h/get-by-label-text :dropdown))
(h/is-truthy (h/get-by-text header-label))
(h/is-truthy (h/get-by-text label))))
(h/test "render with icon"
(let [label "Dropdown"]
(h/render [dropdown-input/view
{:icon? true
:icon-name
:i/wallet
:label? true}
label])
(h/is-truthy (h/get-by-label-text :dropdown))
(h/is-truthy (h/get-by-label-text :left-icon))
(h/is-truthy (h/get-by-text label))))
(h/test "render in active state"
(let [label "Dropdown"]
(h/render [dropdown-input/view
{:state :active
:label?
true} label])
(h/is-truthy (h/get-by-label-text :dropdown))
(h/is-truthy (h/get-by-label-text :right-icon "Expecting active state icon"))))
(h/test "render in disabled state"
(let [label "Dropdown"]
(h/render [dropdown-input/view
{:state :disabled
:label? true} label])
(h/is-truthy (h/get-by-label-text :dropdown))
(h/is-disabled (h/get-by-text label "Dropdown should be disabled in disabled state"))))
(h/test "on-press"
(let [event (h/mock-fn)
label "Dropdown"]
(h/render [dropdown-input/view
{:on-press event
:label?
true} label])
(h/fire-event :press (h/get-by-text label))
(h/was-called event))))
@@ -0,0 +1,49 @@
(ns quo.components.dropdowns.dropdown-input.properties
(:require
[quo.foundations.colors :as colors]))
(def icon-size 20)
(defn- grey-blur
[theme active?]
{:left-icon-color (colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-70 theme)
:right-icon-color (colors/theme-colors colors/neutral-80-opa-10 colors/white-opa-10 theme)
:right-icon-color-2 (colors/theme-colors colors/neutral-100 colors/white theme)
:label-color (colors/theme-colors colors/neutral-100 colors/white theme)
:border-color (if active?
(colors/theme-colors colors/neutral-80-opa-20
colors/white-opa-40
theme)
(colors/theme-colors colors/neutral-80-opa-10
colors/white-opa-10
theme))})
(defn- outline
[theme active?]
{:left-icon-color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
:right-icon-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
:right-icon-color-2 (colors/theme-colors colors/neutral-100 colors/white theme)
:label-color (colors/theme-colors colors/neutral-100 colors/white theme)
:border-color (if active?
(colors/theme-colors colors/neutral-40 colors/neutral-60 theme)
(colors/theme-colors colors/neutral-30 colors/neutral-70 theme))})
(defn- grey
[theme active?]
{:left-icon-color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
:right-icon-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
:right-icon-color-2 (colors/theme-colors colors/neutral-100 colors/white theme)
:label-color (colors/theme-colors colors/neutral-100 colors/white theme)
:border-color (if active?
(colors/theme-colors colors/neutral-40 colors/neutral-60 theme)
(colors/theme-colors colors/neutral-20
colors/neutral-60
theme))})
(defn get-colors
[{:keys [theme state blur?]}]
(let [active? (= state :active)]
(cond
blur? (grey-blur theme active?)
(= theme :dark) (outline theme active?)
(= theme :light) (grey theme active?))))
@@ -0,0 +1,62 @@
(ns quo.components.dropdowns.dropdown-input.style
(:require
[quo.foundations.colors :as colors]))
(def gap 8)
(def blur-view
{:position :absolute
:top 0
:left 0
:right 0
:bottom 0})
(def left-icon
{:margin-right gap})
(defn right-icon
[theme]
{:color (colors/theme-colors colors/neutral-100 colors/white theme)
:margin-right gap})
(defn header-label
[theme blur?]
{:color (if blur?
(colors/theme-colors colors/neutral-80-opa-40
colors/white-opa-70
theme)
(colors/theme-colors colors/neutral-50
colors/neutral-40
theme))
:margin-bottom gap})
(def root-container
{:width "100%"
:height 40})
(defn container
[{:keys [background-color border-color]}
{:keys [icon? state]}]
(cond-> {:align-items :center
:justify-content :space-between
:flex-direction :row
:padding-vertical 9
:padding-left 16
:padding-right 12
:overflow :hidden
:background-color background-color
:border-radius 12}
icon?
(assoc :padding-left 12)
border-color
(assoc :border-color border-color
:border-width 1)
(= state :disabled)
(assoc :opacity 0.3)))
(def right-half-container
{:flex-direction :row
:align-items :center})
@@ -0,0 +1,68 @@
(ns quo.components.dropdowns.dropdown-input.view
(:require
[quo.components.dropdowns.dropdown-input.properties :as properties]
[quo.components.dropdowns.dropdown-input.style :as style]
[quo.components.icon :as icon]
[quo.components.markdown.text :as text]
[quo.theme :as theme]
[react-native.core :as rn]))
(defn- view-internal
[{:keys [state theme on-press icon?
label? blur?
accessibility-label header-label]
:or {state :default
icon? true
label? true
blur? false
header-label "Label"}
:as props}
label]
(let [{:keys [left-icon-color right-icon-color right-icon-color-2]
:as colors} (properties/get-colors props)
right-icon (if (= state :active) :i/pullup :i/dropdown)]
[rn/view
{:style style/root-container}
(when label?
[text/text
{:size :paragraph-2
:weight :medium
:align :left
:style (style/header-label theme blur?)} header-label])
[rn/pressable
{:accessibility-label (or accessibility-label :dropdown)
:disabled (= state :disabled)
:on-press on-press
:style (style/container colors props)}
[rn/view
{:style style/right-half-container}
(when icon?
[icon/icon
:i/placeholder
{:accessibility-label :left-icon
:color left-icon-color
:size properties/icon-size
:container-style style/left-icon}])
[text/text
{:size :paragraph-1
:weight :regular
:number-of-lines 1
:style (style/right-icon theme)}
label]]
[icon/icon
right-icon
{:size properties/icon-size
:accessibility-label :right-icon
:color right-icon-color
:color-2 right-icon-color-2}]]]))
(def view
"Props:
- state: :default (default) | :active | :disabled
- label: string
- header-label: string
- icon?: boolean
- label?: boolean
- blur?: boolean
- on-press: function"
(theme/with-theme view-internal))
@@ -11,6 +11,7 @@
(case k
:success (colors/resolve-color :success theme)
:error (colors/resolve-color :danger theme)
:warning (colors/resolve-color :warning theme)
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
(defn view-internal
@@ -13,11 +13,11 @@
[{:keys [theme address networks blur?]}]
[rn/view {:style style/left-container}
[wallet-user-avatar/wallet-user-avatar
{:size :medium
:f-name "0"
:l-name "x"
{:size :size-32
:full-name "0 x"
:monospace? true
:uppercase? false}]
:lowercase? true
:neutral? true}]
[rn/view {:style style/account-container}
[text/text {:size :paragraph-1}
(map (fn [network]
@@ -25,8 +25,8 @@
[text/text
{:size :paragraph-1
:weight :semi-bold
:style {:color (colors/resolve-color network theme)}}
(str (subs (name network) 0 3) ":")])
:style {:color (colors/resolve-color (:network-name network) theme)}}
(str (:short-name network) ":")])
networks)
[text/text
{:size :paragraph-1
@@ -1,6 +1,5 @@
(ns quo.components.list-items.saved-address.view
(:require
[clojure.string :as string]
[quo.components.avatars.wallet-user-avatar.view :as wallet-user-avatar]
[quo.components.icon :as icon]
[quo.components.list-items.saved-address.style :as style]
@@ -13,27 +12,23 @@
(defn- left-container
[{:keys [blur? theme name ens address customization-color]}]
(let [names (remove string/blank? (string/split name " "))
first-name (if (> (count names) 0) (first names) "")
last-name (if (> (count names) 1) (last names) "")]
[rn/view {:style style/left-container}
[wallet-user-avatar/wallet-user-avatar
{:size :medium
:f-name first-name
:l-name last-name
:customization-color customization-color}]
[rn/view {:style style/account-container}
[text/text
{:weight :semi-bold
:size :paragraph-1
:style style/name-text}
name]
[text/text {:size :paragraph-2}
[text/text
{:size :paragraph-2
:weight :monospace
:style (style/account-address blur? theme)}
(or ens (address/get-shortened-key address))]]]]))
[rn/view {:style style/left-container}
[wallet-user-avatar/wallet-user-avatar
{:size :size-32
:full-name name
:customization-color customization-color}]
[rn/view {:style style/account-container}
[text/text
{:weight :semi-bold
:size :paragraph-1
:style style/name-text}
name]
[text/text {:size :paragraph-2}
[text/text
{:size :paragraph-2
:weight :monospace
:style (style/account-address blur? theme)}
(or ens (address/get-shortened-key address))]]]])
(defn- internal-view
[]
@@ -26,21 +26,25 @@
(def info
{:flex-direction :row
:align-items :center})
:align-items :center
:width "70%"})
(def token-info
{:height 40})
{:height 40
:flex 1})
(def token-image
{:width 32
:height 32
:border-width 1
:border-radius 16
:border-color colors/neutral-80-opa-5
:margin-right 8})
{:width 32
:height 32
:border-width 1
:border-radius 16
:border-color colors/neutral-80-opa-5
:margin-right 8
:background-color colors/neutral-80-opa-5})
(def values-container
{:align-items :flex-end})
{:align-items :flex-end
:max-width "30%"})
(defn fiat-value
[theme]
@@ -15,11 +15,14 @@
{:source (or (:source token) token)
:style style/token-image}]
[rn/view {:style style/token-info}
[text/text {:weight :semi-bold} label]
[text/text
{:weight :semi-bold
:number-of-lines 1}
(if-not (empty? label) label "-")]
[preview-list/view
{:type :network
:size :size-14
:number 3}
:number (count networks)}
networks]]])
(defn- values
@@ -30,12 +33,14 @@
:accessibility-label :check-icon}]
[rn/view {:style style/values-container}
[text/text
{:weight :medium
:size :paragraph-2}
{:weight :medium
:size :paragraph-2
:number-of-lines 1}
token-value]
[text/text
{:style (style/fiat-value theme)
:size :paragraph-2}
{:style (style/fiat-value theme)
:size :paragraph-2
:number-of-lines 1}
fiat-value]]))
(defn- view-internal
@@ -36,7 +36,7 @@
:blur? false
:type :digit} 1])
(h/is-truthy (h/query-by-label-text :text-label))
(h/fire-event :press (h/query-by-label-text :keyboard-key))
(h/fire-event :press (h/query-by-label-text :keyboard-key-1))
(h/was-called on-press)))
(h/test "Is not pressable when disabled is true"
@@ -47,5 +47,5 @@
:blur? false
:type :digit} 1])
(h/is-truthy (h/query-by-label-text :text-label))
(h/fire-event :press (h/query-by-label-text :keyboard-key))
(h/fire-event :press (h/query-by-label-text :keyboard-key-1))
(h/was-not-called on-press))))
@@ -7,6 +7,11 @@
[react-native.core :as rn]
[reagent.core :as reagent]))
(defn- label->accessibility-label
[label]
(let [label-name (if (keyword? label) (name label) label)]
(keyword (str "keyboard-key-" label-name))))
(defn- view-internal
[]
(let [pressed? (reagent/atom false)]
@@ -14,9 +19,11 @@
(let [label-color (style/get-label-color disabled? theme blur?)
background-color (style/toggle-background-color @pressed? blur? theme)]
[rn/pressable
{:accessibility-label :keyboard-key
{:accessibility-label (label->accessibility-label label)
:disabled (or disabled? (not label))
:on-press (fn [] (on-press label))
:on-press (fn []
(when on-press
(on-press label)))
:on-press-in #(reset! pressed? true)
:on-press-out #(reset! pressed? false)
:style (style/container background-color)}
@@ -1,7 +1,7 @@
(ns quo.components.numbered-keyboard.numbered-keyboard.style)
(def container
{:flex 1
{:display :flex
:padding-top 8
:padding-horizontal 48})
@@ -17,13 +17,17 @@
(defn- view-internal
[]
(fn [{:keys [disabled? theme blur? left-action delete-key? on-press]}]
(fn [{:keys [disabled? theme blur? left-action delete-key? on-press on-delete
container-style]
:or {left-action :none}}]
[rn/view
{:style style/container}
{:style (merge style/container
container-style)}
(for [row-index (range 1 4)]
^{:key row-index}
[rn/view {:style style/row-container}
(for [column-index (range 1 4)]
^{:key (str row-index column-index)}
[keyboard-item
{:item (+ (* (dec row-index) 3) column-index)
:type :digit
@@ -58,10 +62,10 @@
:theme theme}]
(if delete-key?
[keyboard-item
{:item :i/delete
{:item :i/backspace
:type :key
:disabled? disabled?
:on-press on-press
:on-press on-delete
:blur? blur?
:theme theme}]
[keyboard-item])]]))
+22
View File
@@ -0,0 +1,22 @@
(ns quo.components.overlay.style
(:require [quo.foundations.colors :as colors]))
(defn overlay-background
[type]
(let [background-color (case type
:shell colors/neutral-80-opa-80-blur
:drawer colors/neutral-100-opa-70-blur
nil)]
{:position :absolute
:top 0
:left 0
:right 0
:bottom 0
:background-color background-color}))
(def container
{:flex 1})
(def blur-container
{:flex 1
:background-color :transparent})
+20
View File
@@ -0,0 +1,20 @@
(ns quo.components.overlay.view
(:require
[quo.components.overlay.style :as style]
[react-native.blur :as blur]
[react-native.core :as rn]))
(defn view
[{:keys [type]} & children]
[rn/view {:style (style/overlay-background type)}
(if (= type :shell)
[blur/view
{:blur-amount 20
:blur-radius 25
:blur-type :transparent
:overlay-color :transparent
:style style/container}
[rn/view {:style style/blur-container}
children]]
[rn/view {:style style/container}
children])])
@@ -1,6 +1,7 @@
(ns quo.components.settings.data-item.component-spec
(:require
[quo.core :as quo]
[quo.foundations.resources :as quo.resources]
[test-helpers.component :as h]))
(h/describe
@@ -9,14 +10,14 @@
(h/render [quo/data-item
{:on-press (h/mock-fn)
:blur? false
:description :account
:icon-right? false
:card? true
:label :none
:status :default
:size :default
:title "Label"
:subtitle "Description"
:subtitle "Subtitle"
:subtitle-type :account
:icon :i/placeholder
:emoji "🎮"
:customization-color :yellow}])
@@ -26,14 +27,14 @@
(h/render [quo/data-item
{:on-press (h/mock-fn)
:blur? false
:description :account
:icon-right? false
:card? false
:label :none
:status :default
:size :default
:title "Label"
:subtitle "Description"
:subtitle "Subtitle"
:subtitle-type :account
:icon :i/placeholder
:emoji "🎮"
:customization-color :yellow}])
@@ -44,14 +45,14 @@
(h/render [quo/data-item
{:on-press (h/mock-fn)
:blur? false
:description :account
:icon-right? false
:card? true
:label :none
:status :default
:size :small
:title "Label"
:subtitle "Description"
:subtitle "Subtitle"
:subtitle-type :account
:icon :i/placeholder
:emoji "🎮"
:customization-color :yellow}])
@@ -62,14 +63,14 @@
(h/render [quo/data-item
{:on-press (h/mock-fn)
:blur? false
:description :account
:icon-right? false
:card? true
:label :none
:status :default
:size :default
:title "Label"
:subtitle "Description"
:subtitle "Subtitle"
:subtitle-type :account
:icon :i/placeholder
:emoji "🎮"
:customization-color :yellow}])
@@ -80,31 +81,31 @@
(h/render [quo/data-item
{:on-press (h/mock-fn)
:blur? false
:description :account
:icon-right? false
:card? true
:label :none
:status :default
:size :default
:title "Label"
:subtitle "Description"
:subtitle "Subtitle"
:subtitle-type :account
:icon :i/placeholder
:emoji "🎮"
:customization-color :yellow}])
(h/is-truthy (h/get-by-text "Description")))
(h/is-truthy (h/get-by-text "Subtitle")))
(h/test "right icon is not visible when icon-right? is false"
(h/render [quo/data-item
{:on-press (h/mock-fn)
:blur? false
:description :account
:icon-right? false
:card? true
:label :none
:status :default
:size :default
:title "Label"
:subtitle "Description"
:subtitle "Subtitle"
:subtitle-type :account
:icon :i/placeholder
:emoji "🎮"
:customization-color :yellow}])
@@ -114,7 +115,6 @@
(h/render [quo/data-item
{:on-press (h/mock-fn)
:blur? false
:description :account
:icon-right? true
:right-icon :i/chevron-right
:card? true
@@ -122,17 +122,17 @@
:status :default
:size :default
:title "Label"
:subtitle "Description"
:subtitle "Subtitle"
:subtitle-type :account
:icon :i/placeholder
:emoji "🎮"
:customization-color :yellow}])
(h/is-truthy (h/query-by-label-text :icon-right)))
(h/test "description icon is visible when description is icon"
(h/test "icon is visible when subtitle type is icon"
(h/render [quo/data-item
{:on-press (h/mock-fn)
:blur? false
:description :icon
:icon-right? true
:right-icon :i/chevron-right
:card? true
@@ -140,17 +140,17 @@
:status :default
:size :default
:title "Label"
:subtitle "Description"
:subtitle "Subtitle"
:subtitle-type :icon
:icon :i/placeholder
:emoji "🎮"
:customization-color :yellow}])
(h/is-truthy (h/query-by-label-text :description-icon)))
(h/is-truthy (h/query-by-label-text :subtitle-type-icon)))
(h/test "description image is visible when description is network"
(h/test "image is visible when subtitle type is network"
(h/render [quo/data-item
{:on-press (h/mock-fn)
:blur? false
:description :network
:icon-right? true
:right-icon :i/chevron-right
:card? true
@@ -158,17 +158,18 @@
:status :default
:size :default
:title "Label"
:subtitle "Description"
:subtitle "Subtitle"
:subtitle-type :network
:icon :i/placeholder
:emoji "🎮"
:customization-color :yellow}])
(h/is-truthy (h/query-by-label-text :description-image)))
:customization-color :yellow
:network-image (quo.resources/get-network :ethereum)}])
(h/is-truthy (h/query-by-label-text :subtitle-type-image)))
(h/test "description emoji is visible when description is account"
(h/test "emoji is visible when subtitle type is account"
(h/render [quo/data-item
{:on-press (h/mock-fn)
:blur? false
:description :account
:icon-right? true
:right-icon :i/chevron-right
:card? true
@@ -176,7 +177,8 @@
:status :default
:size :default
:title "Label"
:subtitle "Description"
:subtitle "Subtitle"
:subtitle-type :account
:icon :i/placeholder
:emoji "🎮"
:customization-color :yellow}])
@@ -37,8 +37,8 @@
:align-items :center})
(defn subtitle-icon-container
[description]
{:margin-right (when (not= :default description) 4)
[subtitle-type]
{:margin-right (when (not= :default subtitle-type) 4)
:justify-content :center})
(defn title
+14 -13
View File
@@ -7,7 +7,6 @@
[quo.components.markdown.text :as text]
[quo.components.settings.data-item.style :as style]
[quo.foundations.colors :as colors]
[quo.foundations.resources :as quo.resources]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[utils.i18n :as i18n]))
@@ -17,13 +16,15 @@
[rn/view {:style (style/loading-container size blur? theme)}])
(defn- left-subtitle
[{:keys [theme size description icon icon-color blur? subtitle customization-color emoji]}]
[{:keys [theme size subtitle-type icon icon-color blur? subtitle customization-color emoji
network-image]
:or {subtitle-type :default}}]
[rn/view {:style style/subtitle-container}
(when (not= :small size)
[rn/view {:style (style/subtitle-icon-container description)}
(case description
[rn/view {:style (style/subtitle-icon-container subtitle-type)}
(case subtitle-type
:icon [icons/icon icon
{:accessibility-label :description-icon
{:accessibility-label :subtitle-type-icon
:size 16
:color icon-color}]
:account [account-avatar/view
@@ -32,8 +33,8 @@
:emoji emoji
:type :default}]
:network [rn/image
{:accessibility-label :description-image
:source (quo.resources/tokens :eth)
{:accessibility-label :subtitle-type-image
:source network-image
:style style/image}]
nil)])
[text/text
@@ -58,10 +59,9 @@
(i18n/label :t/days)])])
(defn- left-side
"The description can either be given as a string `description` or a component `custom-subtitle`"
[{:keys [theme title status size blur? description custom-subtitle icon subtitle label icon-color
customization-color
emoji]
"The description can either be given as a string `subtitle-type` or a component `custom-subtitle`"
[{:keys [theme title status size blur? custom-subtitle icon subtitle subtitle-type label icon-color
customization-color network-image emoji]
:as props}]
[rn/view {:style style/left-side}
[left-title
@@ -79,13 +79,14 @@
[left-subtitle
{:theme theme
:size size
:description description
:subtitle-type subtitle-type
:icon icon
:icon-color icon-color
:blur? blur?
:subtitle subtitle
:customization-color customization-color
:emoji emoji}]))])
:emoji emoji
:network-image network-image}]))])
(defn- right-side
[{:keys [label icon-right? right-icon icon-color communities-list]}]
@@ -0,0 +1,28 @@
(ns quo.components.text-combinations.channel-name.component-spec
(:require [quo.components.text-combinations.channel-name.view :as channel-name]
[test-helpers.component :as h]))
(h/describe "Channel name"
(h/test "Renders Default"
(h/render [channel-name/view {:channel-name "Test channel"}])
(h/is-truthy (h/get-by-text "# Test channel")))
(h/test "Renders unlocked icon"
(h/render [channel-name/view
{:channel-name "Test channel"
:unlocked? true}])
(h/is-truthy (h/get-by-label-text :channel-name-unlocked-icon)))
(h/test "Renders muted icon"
(h/render [channel-name/view
{:channel-name "Test channel"
:muted? true}])
(h/is-truthy (h/get-by-label-text :channel-name-muted-icon)))
(h/test "Renders muted and unlocked icon"
(h/render [channel-name/view
{:channel-name "Test channel"
:muted? true
:unlocked? true}])
(h/is-truthy (h/get-by-label-text :channel-name-unlocked-icon))
(h/is-truthy (h/get-by-label-text :channel-name-muted-icon))))
@@ -0,0 +1,30 @@
(ns quo.components.text-combinations.channel-name.style
(:require [quo.foundations.colors :as colors]))
(def container {:flex-direction :row})
(def icons-container
{:flex-direction :row
:padding-top 8
:padding-bottom 4
:margin-left 6})
(def icon {:width 20 :height 20})
(def icons-gap {:width 4})
(defn- blur-icon-color
[theme]
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-40 theme))
(defn unlocked-icon-color
[theme blur?]
(if blur?
(blur-icon-color theme)
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
(defn muted-icon-color
[theme blur?]
(if blur?
(blur-icon-color theme)
(colors/theme-colors colors/neutral-40 colors/neutral-60 theme)))
@@ -0,0 +1,40 @@
(ns quo.components.text-combinations.channel-name.view
(:require [quo.components.icon :as icon]
[quo.components.markdown.text :as text]
[quo.components.text-combinations.channel-name.style :as style]
[quo.theme]
[react-native.core :as rn]))
(defn icons
[{:keys [theme unlocked? muted? blur?]}]
[rn/view {:style style/icons-container}
(when unlocked?
[rn/view
{:style style/icon
:accessibility-label :channel-name-unlocked-icon}
[icon/icon :i/unlocked
{:color (style/unlocked-icon-color theme blur?)
:size 20}]])
(when (and unlocked? muted?)
[rn/view {:style style/icons-gap}])
(when muted?
[rn/view
{:style style/icon
:accessibility-label :channel-name-muted-icon}
[icon/icon :i/muted
{:color (style/muted-icon-color theme blur?)
:size 20}]])])
(defn- view-internal
[{:keys [unlocked? muted? channel-name] :as props}]
[rn/view {:style style/container}
[text/text
{:size :heading-1
:weight :semi-bold}
(str "# " channel-name)]
(when (or unlocked? muted?)
[icons props])])
(def view (quo.theme/with-theme view-internal))
@@ -9,3 +9,8 @@
(def description-description-text
{:margin-top 8})
(def emoji-hash
{:margin-top 8
:letter-spacing 0.5
:line-height 20.5})
@@ -27,7 +27,8 @@
description-accessibility-label
button-icon
button-on-press
customization-color]}]
customization-color
emoji-hash]}]
[rn/view {:style container-style}
[rn/view
{:style {:flex-direction :row
@@ -55,6 +56,11 @@
:weight :regular
:size :paragraph-1
:style style/description-description-text}
description])])
description])
(when emoji-hash
[text/text
{:number-of-lines 1
:style style/emoji-hash}
emoji-hash])])
(def view (theme/with-theme view-internal))
@@ -133,7 +133,7 @@
| key | description |
| -------------|-------------|
| `:account-name` | A value representing the account name (default `nil`)
| `:account` | A value that represents if the account is a `:watched-account` or a `:default` account. (default `nil`)
| `:account` | A value that represents if the account is a `:watched-address` or a `:default` account. (default `nil`)
| `:time-frame` | A value that represents the type of the timeframe, Can be from a preset of time frames. `[:1-week :1-month :3-months :1-year :custom]` (default `nil`) if custom is set, We expect a start time and if there's a space between two times that are in `time-frame-string` we'll split them with an arrow to the right icon
| `:loading?` | A value that indicates that component is loading data. (default `nil`)
| `:metrics` | A value that indicates if the account value have increased can be `:positive` or `:negative` (default `nil`)
@@ -28,3 +28,9 @@
{:flex-direction :row
:align-items :center
:justify-content :space-between})
(defn subtitle
[blur? theme]
{:color (if blur?
colors/white-opa-40
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))})
+15 -13
View File
@@ -11,6 +11,7 @@
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[react-native.platform :as platform]
[reagent.core :as reagent]
[utils.i18n :as i18n]))
@@ -19,11 +20,6 @@
(let [first-name (first (string/split full-name #" "))]
(i18n/label :t/keypair-title {:name first-name})))
(defn details-string
[address stored]
(str (when address (str address " ∙ "))
(if (= stored :on-device) (i18n/label :t/on-device) (i18n/label :t/on-keycard))))
(defn avatar
[{{:keys [full-name]} :details
avatar-type :type
@@ -67,15 +63,21 @@
[{:keys [details stored blur? theme]}]
(let [{:keys [address]} details]
[rn/view
{:style {:flex-direction :row
:align-items :center}}
{:style {:flex-direction :row
:align-items :center}
:accessibility-label :details}
[text/text
{:size :paragraph-2
:accessibility-label :details
:style {:color (if blur?
colors/white-opa-40
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))}}
(details-string address stored)]
{:size :paragraph-2
:style (style/subtitle blur? theme)}
address]
[text/text
{:size :paragraph-2
:style (merge (style/subtitle blur? theme) {:bottom (if platform/ios? 2 -2)})}
" ∙ "]
[text/text
{:size :paragraph-2
:style (style/subtitle blur? theme)}
(if (= stored :on-device) (i18n/label :t/on-device) (i18n/label :t/on-keycard))]
(when (= stored :on-keycard)
[rn/view {:style {:margin-left 4}}
[icon/icon :i/keycard-card
@@ -4,7 +4,7 @@
(defn container
[networks? theme]
{:width 335
{:width "100%"
:height (if networks? 90 56)
:border-radius 16
:border-width 1
+43 -23
View File
@@ -15,18 +15,26 @@
(defn calc-value
[crypto? currency token value conversion]
(if crypto?
(str (get common/currency-label currency) (.toFixed (* value conversion) 2))
(str (.toFixed (/ value conversion) 2) " " (string/upper-case (clj->js token)))))
(let [num-value (if (string? value) (parse-double (or value "0")) value)]
(if crypto?
(str (get common/currency-label currency) (.toFixed (* num-value conversion) 2))
(str (.toFixed (/ num-value conversion) 2) " " (string/upper-case (or (clj->js token) ""))))))
(defn- view-internal
[]
(let [width (:width (rn/get-window))
value (reagent/atom 0)
crypto? (reagent/atom true)
input-ref (atom nil)]
(fn [{:keys [theme token currency conversion networks title customization-color]}]
[rn/view {:style (style/main-container width)}
[{external-value :value}]
(let [width (:width (rn/get-window))
value (reagent/atom nil)
crypto? (reagent/atom true)
input-ref (atom nil)
controlled-input? (some? external-value)]
(fn [{:keys [theme token currency conversion networks title customization-color
on-change-text on-swap container-style show-keyboard?]
:or {show-keyboard? true}
external-value :value}]
[rn/view
{:style (merge
(style/main-container width)
container-style)}
[rn/view {:style style/amount-container}
[rn/pressable
{:on-press #(when @input-ref (.focus ^js @input-ref))
@@ -35,29 +43,41 @@
:align-items :flex-end}}
[rn/image
{:style style/token
:source (resources/get-token token)}]
:source (resources/get-token (keyword (string/lower-case token)))}]
[rn/text-input
{:ref #(reset! input-ref %)
:placeholder "0"
:placeholder-text-color (colors/theme-colors colors/neutral-40 colors/neutral-50 theme)
:keyboard-type :numeric
:max-length 12
:default-value @value
:on-change-text #(reset! value %)
:style (style/text-input theme)
:selection-color customization-color}]
(cond-> {:auto-focus true
:ref #(reset! input-ref %)
:placeholder "0"
:placeholder-text-color (colors/theme-colors colors/neutral-40
colors/neutral-50
theme)
:keyboard-type :numeric
:max-length 12
:on-change-text (fn [v]
(when-not controlled-input?
(reset! value v))
(when on-change-text
(on-change-text v)))
:style (style/text-input theme)
:selection-color customization-color
:show-soft-input-on-focus show-keyboard?}
controlled-input? (assoc :value external-value)
(not controlled-input?) (assoc :default-value @value))]
[text/text
{:size :paragraph-2
:weight :semi-bold
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
:margin-right 8
:padding-bottom 2}}
(string/upper-case (clj->js (if @crypto? token currency)))]]
(string/upper-case (or (clj->js (if @crypto? token currency)) ""))]]
[button/button
{:icon true
:icon-only? true
:size 32
:on-press #(swap! crypto? not)
:on-press (fn []
(swap! crypto? not)
(when on-swap
(on-swap @crypto?)))
:type :outline
:accessibility-label :reorder}
:i/reorder]]
@@ -68,6 +88,6 @@
{:size :paragraph-2
:weight :medium
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
(calc-value @crypto? currency token @value conversion)]]])))
(calc-value @crypto? currency token (or external-value @value) conversion)]]])))
(def view (quo.theme/with-theme view-internal))
+8
View File
@@ -48,6 +48,7 @@
quo.components.drawers.drawer-buttons.view
quo.components.drawers.drawer-top.view
quo.components.drawers.permission-context.view
quo.components.dropdowns.dropdown-input.view
quo.components.dropdowns.dropdown.view
quo.components.dropdowns.network-dropdown.view
quo.components.empty-state.empty-state.view
@@ -100,6 +101,7 @@
quo.components.numbered-keyboard.keyboard-key.view
quo.components.numbered-keyboard.numbered-keyboard.view
quo.components.onboarding.small-option-card.view
quo.components.overlay.view
quo.components.password.tips.view
quo.components.profile.collectible.view
quo.components.profile.profile-card.view
@@ -136,6 +138,7 @@
quo.components.tags.tags
quo.components.tags.tiny-tag.view
quo.components.tags.token-tag.view
quo.components.text-combinations.channel-name.view
quo.components.text-combinations.view
quo.components.wallet.account-card.view
quo.components.wallet.account-origin.view
@@ -231,6 +234,7 @@
;;;; Dropdowns
(def dropdown quo.components.dropdowns.dropdown.view/view)
(def dropdown-input quo.components.dropdowns.dropdown-input.view/view)
(def network-dropdown quo.components.dropdowns.network-dropdown.view/view)
;;;; Empty State
@@ -313,6 +317,9 @@
(def notification quo.components.notifications.notification.view/notification)
(def toast quo.components.notifications.toast.view/toast)
;;;; Overlay
(def overlay quo.components.overlay.view/view)
;;;; Password
(def tips quo.components.password.tips.view/view)
@@ -369,6 +376,7 @@
;;;; Text combinations
(def text-combinations quo.components.text-combinations.view/view)
(def channel-name quo.components.text-combinations.channel-name.view/view)
;;;; Wallet
(def account-card quo.components.wallet.account-card.view/view)
+2
View File
@@ -26,6 +26,7 @@
[quo.components.drawers.drawer-buttons.component-spec]
[quo.components.drawers.drawer-top.component-spec]
[quo.components.drawers.permission-context.component-spec]
[quo.components.dropdowns.dropdown-input.component-spec]
[quo.components.dropdowns.dropdown.component-spec]
[quo.components.dropdowns.network-dropdown.component-spec]
[quo.components.gradient.gradient-cover.component-spec]
@@ -75,6 +76,7 @@
[quo.components.tags.status-tags-component-spec]
[quo.components.tags.summary-tag.component-spec]
[quo.components.tags.tiny-tag.component-spec]
[quo.components.text-combinations.channel-name.component-spec]
[quo.components.wallet.account-card.component-spec]
[quo.components.wallet.account-origin.component-spec]
[quo.components.wallet.account-overview.component-spec]
+16 -2
View File
@@ -148,7 +148,9 @@
(def black-opa-30 (alpha black 0.3))
(def black-opa-60 (alpha black 0.6))
(def onboarding-header-black "#000716")
(def border-avatar-light
"Simulates a blurred, transparent border for avatars in light mode"
"#475060")
;;;;Primary
;;Solid
@@ -201,6 +203,16 @@
(def danger-50-opa-30 (alpha danger-50 0.3))
(def danger-50-opa-40 (alpha danger-50 0.4))
;;;;Warning
(def warning-50 "#FF7D46")
(def warning-60 "#CC6438")
;;50 with transparency
(def warning-50-opa-5 (alpha warning-50 0.05))
(def warning-50-opa-10 (alpha warning-50 0.1))
(def warning-50-opa-20 (alpha warning-50 0.2))
(def warning-50-opa-30 (alpha warning-50 0.3))
(def warning-50-opa-40 (alpha warning-50 0.4))
;; Colors for customizing users account
(def customization
@@ -254,7 +266,9 @@
:danger {50 danger-50
60 danger-60}
:success {50 success-50
60 success-60}}
60 success-60}
:warning {50 warning-50
60 warning-60}}
customization
networks))
+185 -8
View File
@@ -33,14 +33,191 @@
(get dapps k))
(def tokens
{:eth (js/require "../resources/images/tokens/mainnet/ETH-token.png")
:knc (js/require "../resources/images/tokens/mainnet/KNC.png")
:mana (js/require "../resources/images/tokens/mainnet/MANA.png")
:rare (js/require "../resources/images/tokens/mainnet/RARE.png")
:dai (js/require "../resources/images/tokens/mainnet/DAI.png")
:fxc (js/require "../resources/images/tokens/mainnet/FXC.png")
:usdt (js/require "../resources/images/tokens/mainnet/USDT.png")
:snt (js/require "../resources/images/tokens/mainnet/SNT.png")})
{:0-native (js/require "../resources/images/tokens/mainnet/0-native.png")
:0xbtc (js/require "../resources/images/tokens/mainnet/0XBTC.png")
:1st (js/require "../resources/images/tokens/mainnet/1ST.png")
:abt (js/require "../resources/images/tokens/mainnet/ABT.png")
:abyss (js/require "../resources/images/tokens/mainnet/ABYSS.png")
:ae (js/require "../resources/images/tokens/mainnet/AE.png")
:agld (js/require "../resources/images/tokens/mainnet/AGLD.png")
:akro (js/require "../resources/images/tokens/mainnet/AKRO.png")
:amb (js/require "../resources/images/tokens/mainnet/AMB.png")
:ampl (js/require "../resources/images/tokens/mainnet/AMPL.png")
:ant (js/require "../resources/images/tokens/mainnet/ANT.png")
:appc (js/require "../resources/images/tokens/mainnet/APPC.png")
:ast (js/require "../resources/images/tokens/mainnet/AST.png")
:atmchain (js/require "../resources/images/tokens/mainnet/ATMChain.png")
:ausdc (js/require "../resources/images/tokens/mainnet/aUSDC.png")
:bal (js/require "../resources/images/tokens/mainnet/BAL.png")
:bam (js/require "../resources/images/tokens/mainnet/BAM.png")
:band (js/require "../resources/images/tokens/mainnet/BAND.png")
:bat (js/require "../resources/images/tokens/mainnet/BAT.png")
:blt (js/require "../resources/images/tokens/mainnet/BLT.png")
:blz (js/require "../resources/images/tokens/mainnet/BLZ.png")
:bnb (js/require "../resources/images/tokens/mainnet/BNB.png")
:bnt (js/require "../resources/images/tokens/mainnet/BNT.png")
:brln (js/require "../resources/images/tokens/mainnet/BRLN.png")
:btm (js/require "../resources/images/tokens/mainnet/BTM.png")
:btu (js/require "../resources/images/tokens/mainnet/BTU.png")
:cdai (js/require "../resources/images/tokens/mainnet/cDAI.png")
:cdt (js/require "../resources/images/tokens/mainnet/CDT.png")
:centra (js/require "../resources/images/tokens/mainnet/Centra.png")
:cfi (js/require "../resources/images/tokens/mainnet/CFI.png")
:ck (js/require "../resources/images/tokens/mainnet/CK.png")
:cnd (js/require "../resources/images/tokens/mainnet/CND.png")
:cob (js/require "../resources/images/tokens/mainnet/COB.png")
:comp (js/require "../resources/images/tokens/mainnet/COMP.png")
:crv (js/require "../resources/images/tokens/mainnet/CRV.png")
:cvc (js/require "../resources/images/tokens/mainnet/CVC.png")
:dai (js/require "../resources/images/tokens/mainnet/DAI.png")
:dat (js/require "../resources/images/tokens/mainnet/DAT.png")
:data (js/require "../resources/images/tokens/mainnet/DATA.png")
:dcn (js/require "../resources/images/tokens/mainnet/DCN.png")
:dgd (js/require "../resources/images/tokens/mainnet/DGD.png")
:dgx (js/require "../resources/images/tokens/mainnet/DGX.png")
:dlt (js/require "../resources/images/tokens/mainnet/DLT.png")
:dnt (js/require "../resources/images/tokens/mainnet/DNT.png")
:dpy (js/require "../resources/images/tokens/mainnet/DPY.png")
:drt (js/require "../resources/images/tokens/mainnet/DRT.png")
:dta (js/require "../resources/images/tokens/mainnet/DTA.png")
:edg (js/require "../resources/images/tokens/mainnet/EDG.png")
:edo (js/require "../resources/images/tokens/mainnet/EDO.png")
:ekg (js/require "../resources/images/tokens/mainnet/EKG.png")
:eko (js/require "../resources/images/tokens/mainnet/EKO.png")
:elf (js/require "../resources/images/tokens/mainnet/ELF.png")
:emona (js/require "../resources/images/tokens/mainnet/EMONA.png")
:eng (js/require "../resources/images/tokens/mainnet/ENG.png")
:enj (js/require "../resources/images/tokens/mainnet/ENJ.png")
:ens (js/require "../resources/images/tokens/mainnet/ENS.png")
:eos (js/require "../resources/images/tokens/mainnet/EOS.png")
:equad (js/require "../resources/images/tokens/mainnet/EQUAD.png")
:eth (js/require "../resources/images/tokens/mainnet/ETH-token.png")
:eth2x-fli (js/require "../resources/images/tokens/mainnet/ETH2x-FLI.png")
:ethos (js/require "../resources/images/tokens/mainnet/ETHOS.png")
:evx (js/require "../resources/images/tokens/mainnet/EVX.png")
:fuel (js/require "../resources/images/tokens/mainnet/FUEL.png")
:fun (js/require "../resources/images/tokens/mainnet/FUN.png")
:fxc (js/require "../resources/images/tokens/mainnet/FXC.png")
:gdc (js/require "../resources/images/tokens/mainnet/GDC.png")
:gen (js/require "../resources/images/tokens/mainnet/GEN.png")
:glm (js/require "../resources/images/tokens/mainnet/GLM.png")
:gno (js/require "../resources/images/tokens/mainnet/GNO.png")
:gnt (js/require "../resources/images/tokens/mainnet/GNT.png")
:grid (js/require "../resources/images/tokens/mainnet/GRID.png")
:grt (js/require "../resources/images/tokens/mainnet/GRT.png")
:hez (js/require "../resources/images/tokens/mainnet/HEZ.png")
:hst (js/require "../resources/images/tokens/mainnet/HST.png")
:ht (js/require "../resources/images/tokens/mainnet/HT.png")
:icn (js/require "../resources/images/tokens/mainnet/ICN.png")
:icos (js/require "../resources/images/tokens/mainnet/ICOS.png")
:iost (js/require "../resources/images/tokens/mainnet/IOST.png")
:kdo (js/require "../resources/images/tokens/mainnet/KDO.png")
:kin (js/require "../resources/images/tokens/mainnet/KIN.png")
:knc (js/require "../resources/images/tokens/mainnet/KNC.png")
:kudos (js/require "../resources/images/tokens/mainnet/Kudos.png")
:lend (js/require "../resources/images/tokens/mainnet/LEND.png")
:link (js/require "../resources/images/tokens/mainnet/LINK.png")
:lisk (js/require "../resources/images/tokens/mainnet/LISK.png")
:loom (js/require "../resources/images/tokens/mainnet/LOOM.png")
:lpt (js/require "../resources/images/tokens/mainnet/LPT.png")
:lrc (js/require "../resources/images/tokens/mainnet/LRC.png")
:mana (js/require "../resources/images/tokens/mainnet/MANA.png")
:mco (js/require "../resources/images/tokens/mainnet/MCO.png")
:mda (js/require "../resources/images/tokens/mainnet/MDA.png")
:met (js/require "../resources/images/tokens/mainnet/MET.png")
:mfg (js/require "../resources/images/tokens/mainnet/MFG.png")
:mgo (js/require "../resources/images/tokens/mainnet/MGO.png")
:mkr (js/require "../resources/images/tokens/mainnet/MKR.png")
:mln (js/require "../resources/images/tokens/mainnet/MLN.png")
:moc (js/require "../resources/images/tokens/mainnet/MOC.png")
:mod (js/require "../resources/images/tokens/mainnet/MOD.png")
:mth (js/require "../resources/images/tokens/mainnet/MTH.png")
:mtl (js/require "../resources/images/tokens/mainnet/MTL.png")
:myb (js/require "../resources/images/tokens/mainnet/MYB.png")
:nexo (js/require "../resources/images/tokens/mainnet/NEXO.png")
:nexxo (js/require "../resources/images/tokens/mainnet/NEXXO.png")
:nmr (js/require "../resources/images/tokens/mainnet/NMR.png")
:npxs (js/require "../resources/images/tokens/mainnet/NPXS.png")
:ogn (js/require "../resources/images/tokens/mainnet/OGN.png")
:omg (js/require "../resources/images/tokens/mainnet/OMG.png")
:otn (js/require "../resources/images/tokens/mainnet/OTN.png")
:oxt (js/require "../resources/images/tokens/mainnet/OXT.png")
:pax (js/require "../resources/images/tokens/mainnet/PAX.png")
:paxg (js/require "../resources/images/tokens/mainnet/PAXG.png")
:pay (js/require "../resources/images/tokens/mainnet/PAY.png")
:pbtc (js/require "../resources/images/tokens/mainnet/PBTC.png")
:plr (js/require "../resources/images/tokens/mainnet/PLR.png")
:poe (js/require "../resources/images/tokens/mainnet/POE.png")
:poly (js/require "../resources/images/tokens/mainnet/POLY.png")
:powr (js/require "../resources/images/tokens/mainnet/POWR.png")
:ppp (js/require "../resources/images/tokens/mainnet/PPP.png")
:ppt (js/require "../resources/images/tokens/mainnet/PPT.png")
:pt (js/require "../resources/images/tokens/mainnet/PT.png")
:qkc (js/require "../resources/images/tokens/mainnet/QKC.png")
:qrl (js/require "../resources/images/tokens/mainnet/QRL.png")
:qsp (js/require "../resources/images/tokens/mainnet/QSP.png")
:r (js/require "../resources/images/tokens/mainnet/R.png")
:rae (js/require "../resources/images/tokens/mainnet/RAE.png")
:rare (js/require "../resources/images/tokens/mainnet/RARE.png")
:rcn (js/require "../resources/images/tokens/mainnet/RCN.png")
:rdn (js/require "../resources/images/tokens/mainnet/RDN.png")
:ren (js/require "../resources/images/tokens/mainnet/REN.png")
:rep (js/require "../resources/images/tokens/mainnet/REP.png")
:req (js/require "../resources/images/tokens/mainnet/REQ.png")
:rhoc (js/require "../resources/images/tokens/mainnet/RHOC.png")
:rlc (js/require "../resources/images/tokens/mainnet/RLC.png")
:rol (js/require "../resources/images/tokens/mainnet/ROL.png")
:sai (js/require "../resources/images/tokens/mainnet/SAI.png")
:salt (js/require "../resources/images/tokens/mainnet/SALT.png")
:san (js/require "../resources/images/tokens/mainnet/SAN.png")
:sngls (js/require "../resources/images/tokens/mainnet/SNGLS.png")
:snm (js/require "../resources/images/tokens/mainnet/SNM.png")
:snt (js/require "../resources/images/tokens/mainnet/SNT.png")
:snx (js/require "../resources/images/tokens/mainnet/SNX.png")
:socks (js/require "../resources/images/tokens/mainnet/SOCKS.png")
:spank (js/require "../resources/images/tokens/mainnet/SPANK.png")
:spike (js/require "../resources/images/tokens/mainnet/SPIKE.png")
:spn (js/require "../resources/images/tokens/mainnet/SPN.png")
:st (js/require "../resources/images/tokens/mainnet/ST.png")
:storj (js/require "../resources/images/tokens/mainnet/STORJ.png")
:storm (js/require "../resources/images/tokens/mainnet/STORM.png")
:strk (js/require "../resources/images/tokens/mainnet/STRK.png")
:stx (js/require "../resources/images/tokens/mainnet/STX.png")
:sub (js/require "../resources/images/tokens/mainnet/SUB.png")
:supr (js/require "../resources/images/tokens/mainnet/SUPR.png")
:susd (js/require "../resources/images/tokens/mainnet/sUSD.png")
:taas (js/require "../resources/images/tokens/mainnet/TAAS.png")
:taud (js/require "../resources/images/tokens/mainnet/TAUD.png")
:tcad (js/require "../resources/images/tokens/mainnet/TCAD.png")
:tgbp (js/require "../resources/images/tokens/mainnet/TGBP.png")
:tkn (js/require "../resources/images/tokens/mainnet/TKN.png")
:tkx (js/require "../resources/images/tokens/mainnet/TKX.png")
:tnt (js/require "../resources/images/tokens/mainnet/TNT.png")
:trst (js/require "../resources/images/tokens/mainnet/TRST.png")
:trx (js/require "../resources/images/tokens/mainnet/TRX.png")
:tusd (js/require "../resources/images/tokens/mainnet/TUSD.png")
:ubi (js/require "../resources/images/tokens/mainnet/UBI.png")
:ubt (js/require "../resources/images/tokens/mainnet/UBT.png")
:ukg (js/require "../resources/images/tokens/mainnet/UKG.png")
:uni (js/require "../resources/images/tokens/mainnet/UNI.png")
:upp (js/require "../resources/images/tokens/mainnet/UPP.png")
:usdc (js/require "../resources/images/tokens/mainnet/USDC.png")
:usds (js/require "../resources/images/tokens/mainnet/USDS.png")
:usdt (js/require "../resources/images/tokens/mainnet/USDT.png")
:veri (js/require "../resources/images/tokens/mainnet/VERI.png")
:vgx (js/require "../resources/images/tokens/mainnet/VGX.png")
:vib (js/require "../resources/images/tokens/mainnet/VIB.png")
:wabi (js/require "../resources/images/tokens/mainnet/WaBi.png")
:wbtc (js/require "../resources/images/tokens/mainnet/WBTC.png")
:weth (js/require "../resources/images/tokens/mainnet/WETH.png")
:wings (js/require "../resources/images/tokens/mainnet/WINGS.png")
:wtc (js/require "../resources/images/tokens/mainnet/WTC.png")
:xaur (js/require "../resources/images/tokens/mainnet/XAUR.png")
:xpa (js/require "../resources/images/tokens/mainnet/XPA.png")
:xrl (js/require "../resources/images/tokens/mainnet/XRL.png")
:xuc (js/require "../resources/images/tokens/mainnet/XUC.png")
:zrx (js/require "../resources/images/tokens/mainnet/ZRX.png")
:zsc (js/require "../resources/images/tokens/mainnet/ZSC.png")})
(defn get-token
[k]
+1
View File
@@ -17,6 +17,7 @@
(def view (reagent/adapt-react-class (.-View ^js react-native)))
(def scroll-view (reagent/adapt-react-class (.-ScrollView ^js react-native)))
(def safe-area-view (reagent/adapt-react-class (.-SafeAreaView ^js react-native)))
(def ^:private image-native
(reagent/adapt-react-class (.-Image ^js react-native)))
+10 -8
View File
@@ -58,14 +58,16 @@
(defn save-credentials
"Stores the credentials for the address to the Keychain"
[server username password callback]
(-> (.setInternetCredentials ^js react-native-keychain
(string/lower-case server)
username
password
keychain-secure-hardware
keychain-restricted-availability)
(.then callback)))
([server username password]
(save-credentials server username password identity))
([server username password callback]
(-> (.setInternetCredentials ^js react-native-keychain
(string/lower-case server)
username
password
keychain-secure-hardware
keychain-restricted-availability)
(.then callback))))
(defn get-credentials
"Gets the credentials for a specified server from the Keychain"
+1 -1
View File
@@ -14,6 +14,6 @@
(rf/merge cofx
(multiaccounts.update/multiaccount-update
:currency
currency
"USD"
{})
(prices/update-prices)))
@@ -82,4 +82,7 @@
"wallet-owned-collectibles-filtering-done" {:fx [[:dispatch
[:wallet/owned-collectibles-filtering-done
event]]]}
"wallet-get-collectibles-details-done" {:fx [[:dispatch
[:wallet/get-collectible-details-done
event]]]}
(log/warn ::unknown-wallet-event :type type :event event)))
+1 -2
View File
@@ -172,8 +172,7 @@
:use-mailservers? true
:recovered recovered}
config/default-multiaccount)
;; The address from which we derive any chat
;; account/encryption keys
;; The address from which we derive any chat account/encryption keys
eip1581-address
(assoc :eip1581-address eip1581-address)
save-mnemonic?
+2 -1
View File
@@ -74,7 +74,8 @@
:Nameserver "8.8.8.8"
:PeerExchange true
:Port 0
:UDPPort 0})
:UDPPort 0
:LightClient true})
(def login-node-config
{:WalletConfig (cond-> {:Enabled true}
@@ -14,7 +14,8 @@
transactions-management-enabled?
wakuv2-flag
current-fleet
webview-debug]}]
webview-debug
test-networks-enabled?]}]
(keep
identity
[{:size :small
@@ -95,6 +96,15 @@
[:profile.settings/change-webview-debug (not webview-debug)])
:accessory :switch
:active webview-debug}
{:size :small
:title "Test Networks Enabled"
:accessibility-label :test-networks-enabled
:container-margin-bottom 8
:on-press
#(re-frame/dispatch
[:profile.settings/change-test-networks-enabled (not test-networks-enabled?)])
:accessory :switch
:active test-networks-enabled?}
{:size :small
:title (i18n/label :t/waku-bloom-filter-mode)
:accessibility-label :waku-bloom-filter-mode-settings-switch
@@ -117,7 +127,8 @@
(views/defview advanced-settings
[]
(views/letsubs [{:keys [webview-debug]} [:profile/profile]
(views/letsubs [{:keys [webview-debug
test-networks-enabled?]} [:profile/profile]
network-name [:network-name]
waku-bloom-filter-mode [:waku/bloom-filter-mode]
wakuv2-flag [:waku/v2-flag]
@@ -133,6 +144,7 @@
:dev-mode? false
:wakuv2-flag wakuv2-flag
:waku-bloom-filter-mode waku-bloom-filter-mode
:webview-debug webview-debug})
:webview-debug webview-debug
:test-networks-enabled? test-networks-enabled?})
:key-fn (fn [_ i] (str i))
:render-fn render-item}]))
+3 -21
View File
@@ -246,8 +246,8 @@
assets (get visible-tokens chain)
tokens (->> (vals all-tokens)
(remove #(or (:hidden? %)
;;if not scan-all-tokens? remove not
;;visible tokens
;;if not scan-all-tokens? remove
;;not visible tokens
(and (not scan-all-tokens?)
(not (get assets (:symbol %))))))
(reduce (fn [acc {:keys [address symbol]}]
@@ -1075,7 +1075,7 @@
(re-frame/reg-fx
;;TODO: this could be replaced by a single API call on status-go side
:wallet-legacy/initialize-wallet
(fn [[network-id network callback]]
(fn [[network-id callback]]
(-> (js/Promise.all
(clj->js
[(js/Promise.
@@ -1083,24 +1083,6 @@
(json-rpc/call {:method "accounts_getAccounts"
:on-success resolve-fn
:on-error reject})))
(js/Promise.
(fn [resolve-fn _]
(json-rpc/call
{:method "wallet_addEthereumChain"
:params
[{:isTest false
:tokenOverrides []
:rpcUrl (get-in network [:config :UpstreamConfig :URL])
:chainColor "green"
:chainName (:name network)
:nativeCurrencyDecimals 10
:shortName "erc20"
:layer 1
:chainId (int network-id)
:enabled false
:fallbackURL (get-in network [:config :UpstreamConfig :URL])}]
:on-success resolve-fn
:on-error (fn [_] (resolve-fn nil))})))
(js/Promise.
(fn [resolve-fn _]
(json-rpc/call {:method "wallet_getTokens"
+1 -1
View File
@@ -22,7 +22,7 @@
(vector
action-button
dismiss-button)
dismiss-button)
(vector dismiss-button))
(when on-dismiss
{:cancelable false})))))
+51 -5
View File
@@ -2,9 +2,11 @@
(:require
[native-module.core :as native-module]
[re-frame.core :as re-frame]
[react-native.async-storage :as async-storage]
[react-native.platform :as platform]
[react-native.touch-id :as touch-id]
[status-im2.common.keychain.events :as keychain]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -41,16 +43,60 @@
{:db (assoc db :biometric/supported-type supported-type)})
(rf/defn show-message
{:events [:biometric/show-message]}
[_ code]
(let [content (if (#{"NOT_AVAILABLE" "NOT_ENROLLED"} code)
(i18n/label :t/grant-face-id-permissions)
(when-not (or (= code "USER_CANCELED") (= code "USER_FALLBACK"))
(i18n/label :t/biometric-auth-error {:code code})))]
(when content
(let [handle-error? (and code
(not (contains? #{"USER_CANCELED" "USER_FALLBACK"} code)))
content (if (#{"NOT_AVAILABLE" "NOT_ENROLLED"} code)
(i18n/label :t/grant-face-id-permissions)
(i18n/label :t/biometric-auth-error {:code code}))]
(when handle-error?
{:utils/show-popup
{:title (i18n/label :t/biometric-auth-login-error-title)
:content content}})))
(defn- supress-biometry-error-key
[key-uid]
(keyword (str "biometric/supress-not-enrolled-error-" key-uid)))
;; NOTE: if the account had biometrics registered, but it's not enrolled at the moment,
;; we should show the error message only once and supress further "NOT_ENROLLED" errors
;; until biometry is enrolled again. Note that we can only know that when :biometric/authenticate
;; is dispatched and fails with "NOT_ENROLLED", since :biometric/get-supported-biometric-type
;; only tells us what kind of biometric is available on the device, but it doesn't know of its
;; enrollment status.
(re-frame/reg-fx
:biometric/supress-not-enrolled-error
(fn [[key-uid dispatch-event]]
(let [storage-key (supress-biometry-error-key key-uid)]
(-> (async-storage/get-item storage-key identity)
(.then (fn [item]
(when (not item)
(rf/dispatch dispatch-event)
(async-storage/set-item! storage-key true))))
(.catch (fn [err]
(log/error "Couldn't supress biometry NOT_ENROLLED error"
{:key-uid key-uid
:event :biometric/supress-not-enrolled-error
:error err})))))))
;; NOTE: when biometrics is re-enrolled, we erase the flag in async-storage to assure
;; the "NOT_ENROLLED" error message will be shown again if biometrics is un-enrolled
;; in the future.
(re-frame/reg-fx
:biometric/reset-not-enrolled-error
(fn [key-uid]
(let [storage-key (supress-biometry-error-key key-uid)]
(-> (async-storage/get-item storage-key identity)
(.then (fn [supress?]
(when supress?
(async-storage/set-item! storage-key nil))))
(.catch (fn [err]
(log/error "Couldn't reset supressing biometry NOT_ENROLLED error"
{:key-uid key-uid
:event :biometric/reset-not-enrolled-error
:error err})))))))
(re-frame/reg-fx
:biometric/authenticate
(fn [options]
+1 -1
View File
@@ -117,7 +117,7 @@
[rn/view
{:style (style/sheet-content theme padding-bottom-override insets shell? bottom-margin)
:on-layout #(reset! sheet-height (.-nativeEvent.layout.height ^js %))}
(when gradient-cover?
(when (and gradient-cover? customization-color)
[rn/view {:style style/gradient-bg}
[quo/gradient-cover
{:customization-color customization-color
+68 -14
View File
@@ -49,16 +49,15 @@
(defn save-auth-method!
[key-uid method]
(keychain/save-credentials
(str key-uid "-auth")
key-uid
method
#(when-not %
(log/error
(str "Error while saving auth method."
" "
"The app will continue to work normally, "
"but you will have to login again next time you launch it.")))))
(-> (keychain/save-credentials
(str key-uid "-auth")
key-uid
method)
(.catch (fn [err]
(log/error "Failed to save auth method in the keychain"
{:error err
:key-uid key-uid
:auth-method method})))))
(re-frame/reg-fx
:keychain/save-auth-method
@@ -79,27 +78,59 @@
(if can-save?
(keychain/get-credentials
(str key-uid "-auth")
#(callback (if % (oops/oget % "password") auth-method-none)))
(fn [value]
(callback (if value (oops/oget value "password") auth-method-none))))
(callback nil))))))
(defn save-user-password!
[key-uid password]
(keychain/save-credentials key-uid key-uid (security/safe-unmask-data password) #()))
(defn get-user-password!
[key-uid callback]
(keychain/get-credentials key-uid
(fn [value]
(callback (when value
(-> value
(oops/oget "password")
(security/mask-data)))))))
(re-frame/reg-fx
:keychain/get-user-password
(fn [[key-uid callback]]
(keychain/get-credentials
key-uid
#(if % (callback (security/mask-data (oops/oget % "password"))) (callback nil)))))
(get-user-password! key-uid callback)))
(rf/defn get-user-password
[_ key-uid callback]
{:keychain/get-user-password [key-uid callback]})
(defn- password-migration-key-name
[key-uid]
(str key-uid "-password-migration"))
(defn save-password-migration!
[key-uid]
(-> (keychain/save-credentials
(password-migration-key-name key-uid)
key-uid
;; NOTE: using the key-uid as the password, but we don't really care about the
;; value, we only care that it's there
key-uid)
(.catch (fn [error]
(log/error "Failed to get the keychain password migration flag"
{:error error
:key-uid key-uid})))))
(defn get-password-migration!
[key-uid callback]
(keychain/get-credentials
(password-migration-key-name key-uid)
(comp callback boolean)))
(re-frame/reg-fx
:keychain/clear-user-password
(fn [key-uid]
(keychain/reset-credentials (password-migration-key-name key-uid))
(keychain/reset-credentials key-uid)))
(re-frame/reg-fx
@@ -107,5 +138,28 @@
(fn [{:keys [key-uid masked-password on-success on-error]}]
(-> (save-user-password! key-uid masked-password)
(.then #(save-auth-method! key-uid auth-method-biometric))
(.then #(save-password-migration! key-uid))
(.then #(when on-success (on-success)))
(.catch #(when on-error (on-error %))))))
;; NOTE: migrating the plaintext password in the keychain
;; with the hashed one. Added due to the sync onboarding
;; flow, where the password arrives already hashed.
(re-frame/reg-fx
:keychain/password-hash-migration
(fn [{:keys [key-uid callback]
:or {callback identity}}]
(-> (get-password-migration! key-uid identity)
(.then (fn [migrated?]
(if migrated?
(callback)
(-> (get-user-password! key-uid identity)
(.then security/hash-masked-password)
(.then #(save-user-password! key-uid %))
(.then #(save-password-migration! key-uid))
(.then callback)))))
(.catch (fn [err]
(log/error "Failed to migrate the keychain password"
{:error err
:key-uid key-uid
:event :keychain/password-hash-migration}))))))
@@ -14,8 +14,11 @@
(defn authorize
[{:keys [on-enter-password biometric-auth? on-auth-success on-auth-fail on-close
auth-button-label theme blur? auth-button-icon-left]}]
(println auth-button-label "dasasdasdadsdas")
(biometric/get-supported-type
(fn [biometric-type]
(println biometric-type "biometric-type")
(if (and biometric-auth? biometric-type)
(biometric/authenticate
{:reason (i18n/label :t/biometric-auth-confirm-message)
@@ -30,8 +33,10 @@
:shell? blur?
:content (fn []
[enter-password/view
{:on-enter-password on-enter-password}])}]))})
{:button-label auth-button-label
:on-enter-password on-enter-password}])}]))})
(do
(println "222222")
(reset-password)
(rf/dispatch [:show-bottom-sheet
{:on-close on-close
+3 -1
View File
@@ -74,7 +74,7 @@
(def default-multiaccount
{:preview-privacy? blank-preview?
:wallet-legacy/visible-tokens {:mainnet #{:SNT}}
:wallet-legacy/visible-tokens {:mainnet #{:SNT :ETH :DAI}}
:currency :usd
:appearance 0
:profile-pictures-show-to 2
@@ -170,3 +170,5 @@
(def default-kdf-iterations 3200)
(def shell-navigation-disabled? false)
(def community-accounts-selection-enabled? false)
+1 -1
View File
@@ -193,7 +193,7 @@
(def regx-address #"^0x[a-fA-F0-9]{40}$")
(def regx-address-contains #"(?i)0x[a-fA-F0-9]{40}")
(def regx-starts-with-uuid #"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")
(def regx-address-fragment #"^0x[a-fA-F0-9]{1,40}$")
(def regx-full-or-partial-address #"^0x[a-fA-F0-9]{1,40}$")
(def ^:const dapp-permission-contact-code "contact-code")
(def ^:const dapp-permission-web3 "web3")
@@ -8,6 +8,10 @@
[utils.re-frame :as rf]
[utils.url :as url]))
;; these constants are used when there is no width or height defined for a specific image
(def ^:const fallback-image-width 1000)
(def ^:const fallback-image-height 1000)
(defn calculate-dimensions
[width height max-container-width max-container-height]
(let [max-width (if (> width height) max-container-width (* 1.5 constants/image-size))
@@ -15,7 +19,12 @@
{:width (min width max-width) :height (min height max-height)}))
(defn image-message
[index {:keys [content image-width image-height message-id] :as message} {:keys [on-long-press]}
[index
{:keys [content image-width image-height message-id]
:as message
:or {image-width fallback-image-width
image-height fallback-image-height}}
{:keys [on-long-press]}
message-container-data]
(let [insets (safe-area/get-insets)
{:keys [window-width padding-left padding-right avatar-container-width
@@ -0,0 +1,40 @@
(ns status-im2.contexts.communities.actions.accounts-selection.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[react-native.gesture :as gesture]
[status-im2.common.password-authentication.view :as password-authentication]
[status-im2.contexts.communities.actions.request-to-join.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn join-community-and-navigate-back
[id]
(rf/dispatch [:password-authentication/show
{:content (fn [] [password-authentication/view])}
{:label (i18n/label :t/join-open-community)
:on-press #(rf/dispatch [:communities/request-to-join
{:community-id id :password %}])}])
(rf/dispatch [:navigate-back]))
(defn view
[]
(fn []
(let [{:keys [_name
id
_images]} (rf/sub [:get-screen-params])]
[rn/view {:flex 1}
[gesture/scroll-view {:style {:flex 1}}
[rn/view style/page-container
[rn/view {:style (style/bottom-container)}
[quo/button
{:accessibility-label :cancel
:on-press #(rf/dispatch [:navigate-back])
:type :grey
:container-style style/cancel-button}
(i18n/label :t/cancel)]
[quo/button
{:accessibility-label :join-community-button
:on-press #(join-community-and-navigate-back id)
:container-style {:flex 1}}
(i18n/label :t/request-to-join)]]]]])))
@@ -242,6 +242,7 @@
(defn- internal-discover-view
[params]
(rf/dispatch [:fetch-contract-communities])
[:f> f-view-internal params])
(def view (quo.theme/with-theme internal-discover-view))
@@ -1,6 +1,7 @@
(ns status-im2.contexts.communities.overview.style
(:require
[quo.foundations.colors :as colors]))
[quo.foundations.colors :as colors]
[status-im2.contexts.shell.jump-to.constants :as jump-to.constants]))
(def screen-horizontal-padding 20)
@@ -41,6 +42,16 @@
:right 0
:bottom 0})
(def floating-shell-button
{:position :absolute
:bottom 21})
(defn channel-list-component
[]
{:margin-top 8
:margin-bottom (+ 21 jump-to.constants/floating-shell-button-height)
:flex 1})
(defn token-gated-container
[]
{:border-radius 16
@@ -10,6 +10,7 @@
[status-im2.common.password-authentication.view :as password-authentication]
[status-im2.common.scroll-page.style :as scroll-page.style]
[status-im2.common.scroll-page.view :as scroll-page]
[status-im2.config :as config]
[status-im2.constants :as constants]
[status-im2.contexts.communities.actions.chat.view :as chat-actions]
[status-im2.contexts.communities.actions.community-options.view :as options]
@@ -82,7 +83,7 @@
{:on-layout #(on-first-channel-height-changed
(+ 38 (int (Math/ceil (layout-y %))))
(into #{} (map (comp :name second) channels-list)))
:style {:margin-top 8 :flex 1}}
:style (style/channel-list-component)}
(for [[category-id {:keys [chats name collapsed?]}] channels-list]
[rn/view
{:key category-id
@@ -91,12 +92,13 @@
:on-layout #(on-category-layout name (int (layout-y %)))}
(when-not (= constants/empty-category-id category-id)
[quo/divider-label
{:on-press #(collapse-category community-id category-id collapsed?)
:chevron-icon (if collapsed? :i/chevron-right :i/chevron-down)
:chevron :left}
{:on-press #(collapse-category community-id category-id collapsed?)
:chevron-icon (if collapsed? :i/chevron-right :i/chevron-down)
:container-style {:margin-top 8}
:chevron :left}
name])
(when-not collapsed?
[rn/view {:style {:padding-horizontal 8 :padding-bottom 8}}
[rn/view {:style {:padding-horizontal 8}}
(for [chat chats]
^{:key (:id chat)}
[channel-chat-item community-id community-color chat])])])])
@@ -181,10 +183,14 @@
(if (seq token-permissions)
[token-gates community]
[quo/button
{:on-press #(rf/dispatch [:open-modal :community-requests-to-join community])
{:on-press
(if config/community-accounts-selection-enabled?
#(rf/dispatch [:open-modal :community-account-selection community])
#(rf/dispatch [:open-modal :community-requests-to-join community]))
:accessibility-label :show-request-to-join-screen-button
:customization-color color
:icon-left :i/communities}
:icon-left :i/communities}
(i18n/label :t/request-to-join-community)]))
(when (not (or joined pending? token-permissions))
@@ -375,5 +381,4 @@
{:jump-to {:on-press #(rf/dispatch [:shell/navigate-to-jump-to])
:customization-color customization-color
:label (i18n/label :t/jump-to)}}
{:position :absolute
:bottom 34}]]))
style/floating-shell-button]]))
+43 -26
View File
@@ -151,6 +151,34 @@
(reset! filtered-data nil)
(reset! search-text ""))
(defn f-view
[{:keys [render-emojis? search-text on-change-text clear-states active-category scroll-ref theme]
:as sheet-opts}]
(let [search-active? (pos? (count @search-text))]
;; rendering emojis is heavy on the UI thread, we need to delay rendering until the navigation
;; animation completes. 250 is based on the default 300ms navigation duration.
(rn/use-effect #(js/setTimeout (fn [] (reset! render-emojis? true)) 250))
[rn/keyboard-avoiding-view
{:style style/flex-spacer
:keyboard-vertical-offset 8}
[rn/view {:style style/flex-spacer}
[rn/view {:style style/search-input-container}
[quo/input
{:small? true
:placeholder (i18n/label :t/emoji-search-placeholder)
:icon-name :i/search
:value @search-text
:on-change-text on-change-text
:clearable? search-active?
:on-clear clear-states}]]
(when @render-emojis?
[render-list sheet-opts])
(when-not search-active?
[footer
{:theme theme
:active-category active-category
:scroll-ref scroll-ref}])]]))
(defn- view-internal
[_]
(let [{:keys [on-select]} (rf/sub [:get-screen-params])
@@ -158,6 +186,7 @@
set-scroll-ref #(reset! scroll-ref %)
search-text (reagent/atom "")
filtered-data (reagent/atom nil)
render-emojis? (reagent/atom false)
active-category (reagent/atom constants/default-category)
clear-states #(clear {:active-category active-category
:filtered-data filtered-data
@@ -179,31 +208,19 @@
{:event event
:active-category active-category
:should-update-active-category? (nil? @filtered-data)}))]
(fn [{:keys [theme] :as sheet-opts}]
(let [search-active? (pos? (count @search-text))]
[rn/keyboard-avoiding-view
{:style style/flex-spacer
:keyboard-vertical-offset 8}
[rn/view {:style style/flex-spacer}
[rn/view {:style style/search-input-container}
[quo/input
{:small? true
:placeholder (i18n/label :t/emoji-search-placeholder)
:icon-name :i/search
:value @search-text
:on-change-text on-change-text
:clearable? search-active?
:on-clear clear-states}]]
[render-list
(merge {:filtered-data @filtered-data
:set-scroll-ref set-scroll-ref
:on-select on-select
:on-viewable-items-changed on-viewable-items-changed}
sheet-opts)]
(when-not search-active?
[footer
{:theme theme
:active-category active-category
:scroll-ref scroll-ref}])]]))))
(fn [sheet-opts]
[:f> f-view
(merge sheet-opts
{:render-emojis? render-emojis?
:search-text search-text
:on-change-text on-change-text
:clear-states clear-states
:filtered-data @filtered-data
:set-scroll-ref set-scroll-ref
:on-select on-select
:on-viewable-items-changed on-viewable-items-changed
:active-category active-category
:scroll-ref scroll-ref})])))
(def view (quo.theme/with-theme view-internal))
@@ -1,7 +1,6 @@
(ns status-im2.contexts.onboarding.enable-biometrics.view
(:require
[quo.core :as quo]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[status-im2.common.biometric.events :as biometric]
@@ -12,8 +11,7 @@
[status-im2.contexts.onboarding.enable-biometrics.style :as style]
[status-im2.navigation.state :as state]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[utils.security.core :as security]))
[utils.re-frame :as rf]))
(defn page-title
@@ -26,7 +24,7 @@
:description-accessibility-label :enable-biometrics-sub-title}])
(defn enable-biometrics-buttons
[insets theme]
[insets]
(let [supported-biometric-type (rf/sub [:biometric/supported-type])
bio-type-label (biometric/get-label-by-type supported-biometric-type)
profile-color (or (:color (rf/sub [:onboarding-2/profile]))
@@ -34,23 +32,12 @@
syncing-results? (= :syncing-results @state/root-id)]
[rn/view {:style (style/buttons insets)}
[standard-auth/button
(merge
{:size 40
:accessibility-label :enable-biometrics-button
:icon-left :i/face-id
:customization-color profile-color
:button-label (i18n/label :t/biometric-enable-button {:bio-type-label bio-type-label})}
(if syncing-results?
{:theme theme
:blur? true
:on-enter-password (fn [entered-password]
(rf/dispatch
[:onboarding-2/authenticate-enable-biometrics
(security/safe-unmask-data
entered-password)])
(rf/dispatch [:hide-bottom-sheet]))
:auth-button-label (i18n/label :t/confirm)}
{:on-press #(rf/dispatch [:onboarding-2/enable-biometrics])}))]
{:size 40
:accessibility-label :enable-biometrics-button
:icon-left :i/face-id
:customization-color profile-color
:on-press #(rf/dispatch [:onboarding-2/enable-biometrics])
:button-label (i18n/label :t/biometric-enable-button {:bio-type-label bio-type-label})}]
[quo/button
{:accessibility-label :maybe-later-button
:background :blur
@@ -78,18 +65,16 @@
:source (resources/get-image :biometrics)}]))
(defn f-enable-biometrics
[{:keys [theme]}]
[]
(let [insets (safe-area/get-insets)]
[rn/view {:style (style/page-container insets)}
[page-title]
(if whitelist/whitelisted?
[enable-biometrics-parallax]
[enable-biometrics-simple])
[enable-biometrics-buttons insets theme]]))
[enable-biometrics-buttons insets]]))
(defn view
[]
[:f> f-enable-biometrics])
(defn- internale-enable-biometrics
[params]
[:f> f-enable-biometrics params])
(def view (quo.theme/with-theme internale-enable-biometrics))
+3 -10
View File
@@ -35,15 +35,6 @@
{:biometric/authenticate {:on-success #(rf/dispatch [:onboarding-2/biometrics-done])
:on-fail #(rf/dispatch [:onboarding-2/biometrics-fail %])}})
(rf/defn authenticate-enable-biometrics
{:events [:onboarding-2/authenticate-enable-biometrics]}
[{:keys [db]} password]
{:db (-> db
(assoc-in [:onboarding-2/profile :password] password)
(assoc-in [:onboarding-2/profile :syncing?] true))
:biometric/authenticate {:on-success #(rf/dispatch [:onboarding-2/biometrics-done])
:on-fail #(rf/dispatch [:onboarding-2/biometrics-fail %])}})
(rf/defn navigate-to-enable-notifications
{:events [:onboarding-2/navigate-to-enable-notifications]}
[{:keys [db]}]
@@ -154,7 +145,9 @@
biometric-enabled?
(assoc :keychain/save-password-and-auth-method
{:key-uid key-uid
:masked-password masked-password
:masked-password (if syncing?
masked-password
(security/hash-masked-password masked-password))
:on-success (fn []
(if syncing?
(rf/dispatch [:onboarding-2/navigate-to-enable-notifications])
+1 -2
View File
@@ -8,8 +8,7 @@
(defn login
[]
{;; Temporary fix until https://github.com/status-im/status-go/issues/3024 is
;; resolved
{;; Temporary fix until https://github.com/status-im/status-go/issues/3024 is resolved
:wakuV2Nameserver "8.8.8.8"
:openseaAPIKey config/opensea-api-key
:poktToken config/POKT_TOKEN
@@ -11,7 +11,6 @@
[status-im.group-chats.core :as group-chats]
[status-im.mobile-sync-settings.core :as mobile-network]
[status-im.transport.core :as transport]
[status-im2.common.biometric.events :as biometric]
[status-im2.common.keychain.events :as keychain]
[status-im2.common.log :as logging]
[status-im2.config :as config]
@@ -42,11 +41,22 @@
{:db (assoc-in db [:profile/login :processing] true)
::login [key-uid (native-module/sha3 (security/safe-unmask-data password))]}))
(rf/defn biometrics-login
{:events [:profile.login/biometrics-login]}
[{:keys [db]}]
(let [{:keys [key-uid password]} (:profile/login db)]
{:db (assoc-in db [:profile/login :processing] true)
::login [key-uid (security/safe-unmask-data password)]}))
(rf/defn login-local-paired-user
{:events [:profile.login/local-paired-user]}
[{:keys [db]}]
(let [{:keys [key-uid password]} (get-in db [:syncing :profile])]
{::login [key-uid password]}))
(let [{:keys [key-uid password]} (get-in db [:syncing :profile])
masked-password (security/mask-data password)]
{:db (-> db
(assoc-in [:onboarding-2/profile :password] masked-password)
(assoc-in [:onboarding-2/profile :syncing?] true))
::login [key-uid password]}))
(rf/defn redirect-to-root
[{:keys [db] :as cofx}]
@@ -109,7 +119,6 @@
(cond-> {:wallet-legacy/initialize-transactions-management-enabled nil
:wallet-legacy/initialize-wallet
[network-id
current-network-config
(fn [accounts tokens custom-tokens favourites]
(re-frame/dispatch [:wallet-legacy/initialize-wallet
accounts tokens custom-tokens favourites]))]
@@ -151,20 +160,16 @@
(rf/defn get-auth-method-success
{:events [:profile.login/get-auth-method-success]}
[{:keys [db]} auth-method]
[{:keys [db]} auth-method key-uid]
(merge {:db (assoc db :auth-method auth-method)}
(when (= auth-method keychain/auth-method-biometric)
{:biometric/authenticate
{:on-success #(rf/dispatch [:profile.login/biometric-success])
:on-faile #(rf/dispatch [:profile.login/biometric-auth-fail])}})))
(rf/defn biometric-auth-success
{:events [:profile.login/biometric-success]}
[{:keys [db] :as cofx}]
(let [key-uid (get-in db [:profile/login :key-uid])]
(keychain/get-user-password cofx
key-uid
#(rf/dispatch [:profile.login/get-user-password-success %]))))
{:keychain/password-hash-migration
{:key-uid key-uid
:callback (fn []
(rf/dispatch [:biometric/authenticate
{:on-success #(rf/dispatch [:profile.login/biometric-success])
:on-fail #(rf/dispatch
[:profile.login/biometric-auth-fail %])}]))}})))
;; result of :keychain/get-auth-method above
(rf/defn get-user-password-success
@@ -175,14 +180,29 @@
cofx
{:db (assoc-in db [:profile/login :password] password)}
(navigation/init-root :progress)
(login))))
(biometrics-login))))
(rf/reg-event-fx
:profile.login/biometric-success
(fn [{:keys [db]}]
(let [key-uid (get-in db [:profile/login :key-uid])]
{:db db
:fx [[:biometric/reset-not-enrolled-error key-uid]
[:keychain/get-user-password
[key-uid #(rf/dispatch [:profile.login/get-user-password-success %])]]]})))
(rf/reg-event-fx
:profile.login/biometric-auth-fail
(fn [{:keys [db]} [code]]
(let [key-uid (get-in db [:profile/login :key-uid])]
{:db db
:fx [[:dispatch [:init-root :profiles]]
(if (= code "NOT_ENROLLED")
[:biometric/supress-not-enrolled-error
[key-uid
[:biometric/show-message code]]]
[:dispatch [:biometric/show-message code]])]})))
(rf/defn biometric-auth-fail
{:events [:profile.login/biometric-auth-fail]}
[{:keys [db] :as cofx} code]
(rf/merge cofx
(navigation/init-root :profiles)
(biometric/show-message code)))
(rf/defn verify-database-password
{:events [:profile.login/verify-database-password]}
@@ -197,7 +217,7 @@
(rf/defn verify-database-password-success
{:events [:profile.login/verified-database-password]}
[{:keys [db] :as cofx} valid? callback]
[{:keys [db]} valid? callback]
(if valid?
(do
(when (fn? callback)
@@ -14,6 +14,7 @@
:on-success #(log/debug "sent contact update")}]}))
(rf/defn profile-update
{:events [:profile.settings/profile-update]}
[{:keys [db] :as cofx}
setting setting-value
{:keys [dont-sync? on-success] :or {on-success #()}}]
@@ -56,6 +57,10 @@
{:profile.settings/webview-debug-changed value}
(profile-update :webview-debug (boolean value) {})))
(rf/reg-event-fx :profile.settings/change-test-networks-enabled
(fn [_ [value]]
{:fx [[:dispatch [:profile.settings/profile-update :test-networks-enabled? (boolean value) {}]]]}))
(rf/defn change-preview-privacy-flag
{:events [:profile.settings/change-preview-privacy]}
[{:keys [db] :as cofx} private?]
@@ -0,0 +1,43 @@
(ns status-im2.contexts.profile.settings.header.avatar
(:require [quo.core :as quo]
[quo.theme :as quo.theme]
[react-native.reanimated :as reanimated]
[status-im2.contexts.profile.settings.header.style :as style]))
(def scroll-animation-input-range [0 50])
(def header-extrapolation-option
{:extrapolateLeft "clamp"
:extrapolateRight "clamp"})
(defn f-avatar
[{:keys [scroll-y full-name online? profile-picture customization-color]}]
(let [image-scale-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[1 0.5]
header-extrapolation-option)
image-top-margin-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[0 20]
header-extrapolation-option)
image-side-margin-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[0 -20]
header-extrapolation-option)
theme (quo.theme/get-theme)]
[reanimated/view
{:style (style/avatar-container theme
image-scale-animation
image-top-margin-animation
image-side-margin-animation)}
[quo/user-avatar
{:full-name full-name
:online? online?
:profile-picture profile-picture
:status-indicator? true
:ring? true
:customization-color customization-color
:size :big}]]))
(defn view
[props]
[:f> f-avatar props])
@@ -0,0 +1,36 @@
(ns status-im2.contexts.profile.settings.header.header-shape
(:require [quo.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[react-native.svg :as svg]
[status-im2.contexts.profile.settings.header.style :as style]))
(defn left-radius
[background-color]
[svg/svg {:width "20" :height "20" :viewBox "0 0 20 20" :fill "none"}
[svg/path
{:d "M20 0C7 2 0 10 0 20V0H15Z"
:fill background-color}]])
(defn right-radius
[background-color]
[svg/svg {:width "20" :height "21" :viewBox "0 0 20 21" :fill "none"}
[svg/path
{:d "M20 20V0H0C11 0 20 9 20 20Z"
:fill background-color}]])
(defn f-view
[{:keys [scroll-y customization-color theme]}]
(let [background-color (colors/resolve-color customization-color theme 40)
opacity-animation (reanimated/interpolate scroll-y
[0 45 50]
[1 1 0])]
[:<>
[rn/view {:style (style/header-middle-shape background-color)}]
[reanimated/view {:style (style/radius-container opacity-animation)}
[left-radius background-color]
[right-radius background-color]]]))
(defn view
[props]
[:f> f-view props])
@@ -0,0 +1,48 @@
(ns status-im2.contexts.profile.settings.header.style
(:require [quo.foundations.colors :as colors]
[react-native.reanimated :as reanimated]))
(defn header-view
[customization-color theme]
{:background-color (colors/resolve-color customization-color theme 40)
:min-height 100
:flex 1})
(def avatar-row-wrapper
{:display :flex
:padding-left 16
:padding-right 12
:margin-top -60
:margin-bottom -4
:align-items :flex-end
:justify-content :space-between
:flex-direction :row})
(def title-container
{:padding-horizontal 20
:padding-vertical 12})
(defn header-middle-shape
[background-color]
{:background-color background-color
:height 48
:flex-grow 1})
(defn radius-container
[opacity-animation]
(reanimated/apply-animations-to-style
{:opacity opacity-animation}
{:flex-direction :row
:justify-content :space-between}))
(defn avatar-container
[theme scale-animation top-margin-animation side-margin-animation]
(reanimated/apply-animations-to-style
{:transform [{:scale scale-animation}]
:margin-top top-margin-animation
:margin-left side-margin-animation
:margin-bottom side-margin-animation}
{:align-items :flex-start
:border-width 4
:border-color (colors/theme-colors colors/border-avatar-light colors/neutral-80-opa-80 theme)
:border-radius 100}))
@@ -0,0 +1,49 @@
(ns status-im2.contexts.profile.settings.header.view
(:require [clojure.string :as string]
[quo.core :as quo]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[status-im2.common.not-implemented :as not-implemented]
[status-im2.contexts.profile.settings.header.avatar :as header.avatar]
[status-im2.contexts.profile.settings.header.header-shape :as header.shape]
[status-im2.contexts.profile.settings.header.style :as style]
[status-im2.contexts.profile.utils :as profile.utils]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- f-view
[{:keys [theme scroll-y]}]
(let [{:keys [public-key emoji-hash] :as profile} (rf/sub [:profile/profile-with-image])
online? (rf/sub [:visibility-status-updates/online?
public-key])
customization-color (rf/sub [:profile/customization-color])
full-name (profile.utils/displayed-name profile)
profile-picture (profile.utils/photo profile)
emoji-string (string/join emoji-hash)]
[:<>
[header.shape/view
{:scroll-y scroll-y
:customization-color customization-color
:theme theme}]
[rn/view {:style style/avatar-row-wrapper}
[header.avatar/view
{:scroll-y scroll-y
:display-name full-name
:online? online?
:customization-color customization-color
:profile-picture profile-picture}]
[rn/view {:style {:margin-bottom 4}}
[quo/dropdown
{:background :blur
:size :size-32
:type :outline
:icon? true
:icon-name :i/online
:on-press not-implemented/alert}
(i18n/label :t/online)]]]
[quo/text-combinations
{:container-style style/title-container
:emoji-hash emoji-string
:title full-name}]]))
(def view (quo.theme/with-theme f-view))
@@ -0,0 +1,83 @@
(ns status-im2.contexts.profile.settings.list-items
(:require [status-im2.common.not-implemented :as not-implemented]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(def items
[[{:title (i18n/label :t/edit-profile)
:on-press not-implemented/alert
:image-props :i/edit
:image :icon
:action :arrow}
{:title (i18n/label :t/password)
:on-press not-implemented/alert
:image-props :i/password
:image :icon
:action :arrow}]
[{:title (i18n/label :t/messages)
:on-press not-implemented/alert
:image-props :i/messages
:image :icon
:action :arrow}
{:title (i18n/label :t/wallet)
:on-press not-implemented/alert
:image-props :i/wallet
:image :icon
:action :arrow}
{:title (i18n/label :t/dapps)
:on-press not-implemented/alert
:image-props :i/placeholder
:image :icon
:action :arrow}
{:title "Browser"
:on-press not-implemented/alert
:image-props :i/browser
:image :icon
:action :arrow}
{:title (i18n/label :t/keycard)
:on-press not-implemented/alert
:image-props :i/keycard
:image :icon
:action :arrow}]
[{:title (i18n/label :t/syncing)
:on-press not-implemented/alert
:image-props :i/syncing
:image :icon
:action :arrow}
{:title (i18n/label :t/notifications)
:on-press not-implemented/alert
:image-props :i/notifications
:image :icon
:action :arrow}
{:title (i18n/label :t/appearance)
:on-press not-implemented/alert
:image-props :i/light
:image :icon
:action :arrow}
{:title (i18n/label :t/language-and-currency)
:on-press not-implemented/alert
:image-props :i/globe
:image :icon
:action :arrow}]
[{:title (i18n/label :t/data-usage)
:on-press not-implemented/alert
:image-props :i/mobile
:image :icon
:action :arrow}
{:title (i18n/label :t/advanced)
:on-press not-implemented/alert
:image-props :i/settings
:image :icon
:action :arrow}]
;; temporary link to legacy settings
[{:title "Legacy settings"
:on-press #(rf/dispatch [:navigate-to :my-profile])
:action :arrow
:image :icon
:image-props :i/toggle}]
[{:title (i18n/label :t/about)
:on-press not-implemented/alert
:action :arrow}
{:title (i18n/label :t/status-help)
:on-press not-implemented/alert
:action :arrow}]])
@@ -0,0 +1,11 @@
(ns status-im2.contexts.profile.settings.style
(:require [quo.foundations.colors :as colors]))
(defn navigation-wrapper
[{:keys [customization-color inset theme]}]
{:padding-top inset
:background-color (colors/resolve-color customization-color theme 40)})
(def footer-container
{:padding-horizontal 20
:padding-vertical 12})
@@ -0,0 +1,71 @@
(ns status-im2.contexts.profile.settings.view
(:require [oops.core :as oops]
[quo.core :as quo]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[react-native.safe-area :as safe-area]
[status-im2.common.not-implemented :as not-implemented]
[status-im2.contexts.profile.settings.header.view :as settings.header]
[status-im2.contexts.profile.settings.list-items :as settings.items]
[status-im2.contexts.profile.settings.style :as style]
[utils.debounce :as debounce]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- settings-item-view
[data]
[quo/category
{:list-type :settings
:blur? true
:data data}])
(defn scroll-handler
[event scroll-y]
(let [current-y (oops/oget event "nativeEvent.contentOffset.y")]
(reanimated/set-shared-value scroll-y current-y)))
(defn- footer
[logout-press]
[rn/view {:style style/footer-container}
[quo/button
{:on-press logout-press
:type :danger
:icon-left :i/log-out}
(i18n/label :t/logout)]])
(defn- settings-view
[theme]
(let [insets (safe-area/get-insets)
customization-color (rf/sub [:profile/customization-color])
scroll-y (reanimated/use-shared-value 0)
logout-press #(rf/dispatch [:multiaccounts.logout.ui/logout-pressed])]
[quo/overlay {:type :shell}
[rn/view
{:style (style/navigation-wrapper {:customization-color customization-color
:inset (:top insets)
:theme theme})}
[quo/page-nav
{:background :blur
:icon-name :i/close
:on-press #(rf/dispatch [:navigate-back])
:right-side [{:icon-name :i/multi-profile :on-press #(rf/dispatch [:open-modal :sign-in])}
{:icon-name :i/qr-code :on-press not-implemented/alert}
{:icon-name :i/share
:on-press #(debounce/dispatch-and-chill [:open-modal :share-shell] 1000)}]}]]
[rn/flat-list
{:header [settings.header/view {:scroll-y scroll-y}]
:data settings.items/items
:key-fn :title
:shows-vertical-scroll-indicator false
:render-fn settings-item-view
:footer [footer logout-press]
:scroll-event-throttle 16
:on-scroll #(scroll-handler % scroll-y)
:bounces false}]]))
(defn- internal-view
[props]
[:f> settings-view props])
(def view (quo.theme/with-theme internal-view))
@@ -0,0 +1,47 @@
(ns status-im2.contexts.quo-preview.dropdowns.dropdown-input
(:require
[quo.core :as quo]
[reagent.core :as reagent]
[status-im2.contexts.quo-preview.preview :as preview]))
(def descriptor
[{:key :state
:type :select
:options [{:key :default}
{:key :active}
{:key :disabled}]}
{:key :icon?
:type :boolean}
{:key :label?
:type :boolean}
{:key :blur?
:type :boolean}
{:key :header-label
:type :text}
{:key :label
:type :text}])
(defn view
[]
(let [state (reagent/atom {:state :default
:label "Dropdown"
:header-label "Label"
:icon? true
:label? true
:blur? false})
label (reagent/cursor state [:label])
blur? (reagent/cursor state [:blur?])]
[:f>
(fn []
[preview/preview-container
{:state state
:descriptor descriptor
:component-container-style (when-not @blur?
{:align-items :center
:margin-horizontal 30})
:blur-container-style {:align-items :center}
:blur? @blur?
:show-blur-background? true}
[quo/dropdown-input
(assoc @state :on-press #(js/alert "Pressed dropdown"))
@label]])]))
+10 -2
View File
@@ -58,6 +58,8 @@
[status-im2.contexts.quo-preview.drawers.permission-drawers :as
permission-drawers]
[status-im2.contexts.quo-preview.dropdowns.dropdown :as dropdown]
[status-im2.contexts.quo-preview.dropdowns.dropdown-input :as
dropdown-input]
[status-im2.contexts.quo-preview.dropdowns.network-dropdown :as
network-dropdown]
[status-im2.contexts.quo-preview.empty-state.empty-state :as empty-state]
@@ -158,6 +160,8 @@
[status-im2.contexts.quo-preview.tags.tags :as tags]
[status-im2.contexts.quo-preview.tags.tiny-tag :as tiny-tag]
[status-im2.contexts.quo-preview.tags.token-tag :as token-tag]
[status-im2.contexts.quo-preview.text-combinations.channel-name :as
channel-name]
[status-im2.contexts.quo-preview.text-combinations.preview :as
text-combinations]
[status-im2.contexts.quo-preview.wallet.account-card :as account-card]
@@ -273,7 +277,9 @@
:dropdowns [{:name :dropdown
:component dropdown/view}
{:name :network-dropdown
:component network-dropdown/view}]
:component network-dropdown/view}
{:name :dropdown-input
:component dropdown-input/view}]
:empty-state [{:name :empty-state
:component empty-state/view}]
:gradient [{:name :gradient-cover
@@ -445,7 +451,9 @@
{:name :token-tag
:component token-tag/view}]
:text-combinations [{:name :text-combinations
:component text-combinations/view}]
:component text-combinations/view}
{:name :channel-name
:component channel-name/view}]
:wallet [{:name :account-card :component account-card/view}
{:name :account-origin :component account-origin/view}
{:name :account-overview
@@ -1,6 +1,7 @@
(ns status-im2.contexts.quo-preview.settings.data-item
(:require
[quo.core :as quo]
[quo.foundations.resources :as quo.resources]
[reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im2.contexts.quo-preview.preview :as preview]))
@@ -15,7 +16,7 @@
{:key :graph}
{:key :preview}]}
{:type :select
:key :description
:key :subtitle-type
:options [{:key :default}
{:key :icon}
{:key :network}
@@ -38,18 +39,19 @@
[]
(let [state (reagent/atom {:on-press #(js/alert (str "pressed"))
:blur? false
:description :account
:subtitle-type :account
:icon-right? false
:card? true
:label :none
:status :default
:size :default
:title "Label"
:subtitle "Description"
:subtitle "Subtitle"
:icon :i/placeholder
:right-icon :i/chevron-right
:emoji "🎮"
:customization-color :yellow
:network-image (quo.resources/get-network :ethereum)
:communities-list communities-list})]
(fn []
[preview/preview-container
@@ -0,0 +1,29 @@
(ns status-im2.contexts.quo-preview.text-combinations.channel-name
(:require [quo.core :as quo]
[reagent.core :as reagent]
[status-im2.contexts.quo-preview.preview :as preview]))
(def descriptor
[{:key :channel-name
:type :text}
{:key :unlocked?
:type :boolean}
{:key :muted?
:type :boolean}
{:key :blur?
:type :boolean}])
(defn view
[]
(let [state (reagent/atom {:channel-name "random"
:unlocked? true
:muted? true
:blur? false})]
(fn []
[preview/preview-container
{:state state
:descriptor descriptor
:show-blur-background? true
:blur? (:blur? @state)}
[quo/channel-name @state]])))
@@ -8,8 +8,8 @@
(def descriptor
[{:key :title :type :text}
{:key :avatar :type :boolean}
{:key :description
:type :text}])
{:key :description :type :text}
{:key :emoji-hash :type :text}])
(defn state->text-combinations-props
[state]
@@ -22,7 +22,8 @@
(let [state (reagent/atom {:title "Title"
:title-accessibility-label :title
:description ""
:description-accessibility-label :subtitle})]
:description-accessibility-label :subtitle
:emoji-hash "🐲🍀🎭🌟🚀🐠🌈🏰🔮🦉🐼🍉🎨🚲🌙🍔🌵"})]
(fn []
[preview/preview-container
{:state state
@@ -4,7 +4,7 @@
[quo.foundations.resources :as quo.resources]
[react-native.core :as rn]
[status-im2.contexts.wallet.account.bridge.style :as style]
[status-im2.contexts.wallet.common.sheets.account-options.view :as account-options]
[status-im2.contexts.wallet.common.account-switcher.view :as account-switcher]
[status-im2.contexts.wallet.common.temp :as temp]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -18,17 +18,9 @@
(let [networks (rf/sub [:wallet/network-details])
networks-logos (map network-logo networks)]
[rn/view {:style {:flex 1}}
[quo/page-nav
{:icon-name :i/close
:on-press #(rf/dispatch [:navigate-back])
:accessibility-label :top-bar
:right-side :account-switcher
:account-switcher {:customization-color :purple
:on-press #(rf/dispatch [:show-bottom-sheet
{:content account-options/view
:gradient-cover? true
:customization-color :purple}])
:emoji "🍑"}}]
[account-switcher/view
{:on-press #(rf/dispatch [:navigate-back])
:accessibility-label :top-bar}]
[quo/text-combinations
{:container-style style/header-container
:title (i18n/label :t/bridge)}]
@@ -1,31 +1,12 @@
(ns status-im2.contexts.wallet.account.tabs.about.view
(:require
[quo.core :as quo]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[status-im2.contexts.wallet.account.tabs.about.style :as style]
[status-im2.contexts.wallet.common.temp :as temp]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn description
[{:keys [address theme]}]
(let [networks-list (rf/sub [:wallet/network-details])]
[quo/text {:size :paragraph-2}
(map (fn [{:keys [chain-id short-name network-name]}]
^{:key (str chain-id short-name)}
[quo/text
{:size :paragraph-2
:weight :medium
:style {:color (colors/resolve-color network-name theme)}}
(str short-name ":")])
networks-list)
[quo/text
{:size :paragraph-2
:weight :monospace}
address]]))
(defn about-options
[]
[quo/action-drawer
@@ -51,19 +32,25 @@
:accessibility-label :share-address
:label (i18n/label :t/share-address)}]]])
(defn- view-internal
(defn view
[]
[rn/view {:style style/about-tab}
[quo/data-item
(merge temp/data-item-state
{:custom-subtitle (fn [] [quo/address-text
{:networks [{:network-name :ethereum :short-name "eth"}
{:network-name :optimism :short-name "opt"}
{:network-name :arbitrum :short-name "arb1"}]
:address temp/address
:format :long}])
:container-style {:margin-bottom 12}
:on-press #(rf/dispatch [:show-bottom-sheet {:content about-options}])})]
[quo/account-origin temp/account-origin-state]])
(def view (quo.theme/with-theme view-internal))
(let [{:keys [type address]} (rf/sub [:wallet/current-viewing-account])
networks (rf/sub [:wallet/network-details])
watch-only? (= type :watch)]
[rn/view {:style style/about-tab}
[quo/data-item
{:description :default
:icon-right? true
:right-icon :i/options
:card? true
:label :none
:status :default
:size :default
:title (if watch-only? (i18n/label :t/watched-address) (i18n/label :t/address))
:custom-subtitle (fn [] [quo/address-text
{:networks networks
:address address
:format :long}])
:container-style {:margin-bottom 12}
:on-press #(rf/dispatch [:show-bottom-sheet {:content about-options}])}]
(when (not watch-only?) [quo/account-origin temp/account-origin-state])]))
@@ -5,7 +5,7 @@
[reagent.core :as reagent]
[status-im2.contexts.wallet.account.style :as style]
[status-im2.contexts.wallet.account.tabs.view :as tabs]
[status-im2.contexts.wallet.common.sheets.account-options.view :as account-options]
[status-im2.contexts.wallet.common.account-switcher.view :as account-switcher]
[status-im2.contexts.wallet.common.temp :as temp]
[status-im2.contexts.wallet.common.utils :as utils]
[utils.i18n :as i18n]
@@ -21,50 +21,41 @@
:padding-bottom 8}
:render-fn quo/settings-item}]])
(def tabs-data
[{:id :assets :label (i18n/label :t/assets) :accessibility-label :assets-tab}
{:id :collectibles :label (i18n/label :t/collectibles) :accessibility-label :collectibles-tab}
{:id :activity :label (i18n/label :t/activity) :accessibility-label :activity-tab}
{:id :dapps :label (i18n/label :t/dapps) :accessibility-label :dapps}
{:id :about :label (i18n/label :t/about) :accessibility-label :about}])
(def first-tab-id :assets)
(defn tabs-data
[watch-only?]
(cond-> [{:id :assets :label (i18n/label :t/assets) :accessibility-label :assets-tab}
{:id :collectibles :label (i18n/label :t/collectibles) :accessibility-label :collectibles-tab}
{:id :activity :label (i18n/label :t/activity) :accessibility-label :activity-tab}]
(not watch-only?) (conj {:id :dapps :label (i18n/label :t/dapps) :accessibility-label :dapps})
true (conj {:id :about :label (i18n/label :t/about) :accessibility-label :about})))
(defn view
[]
(let [selected-tab (reagent/atom (:id (first tabs-data)))]
(let [selected-tab (reagent/atom first-tab-id)]
(fn []
(let [{:keys [name color emoji balance]} (rf/sub [:wallet/current-viewing-account])
networks (rf/sub [:wallet/network-details])]
(let [{:keys [name color balance type]} (rf/sub [:wallet/current-viewing-account])
watch-only? (= type :watch)]
[rn/view {:style {:flex 1}}
[quo/page-nav
{:type :wallet-networks
:background :blur
:icon-name :i/close
:on-press #(rf/dispatch [:wallet/close-account-page])
:networks networks
:networks-on-press #(js/alert "Pressed Networks")
:right-side :account-switcher
:account-switcher {:customization-color color
:on-press #(rf/dispatch [:show-bottom-sheet
{:content account-options/view
:gradient-cover? true
:customization-color color}])
:emoji emoji}}]
[account-switcher/view {:on-press #(rf/dispatch [:wallet/close-account-page])}]
[quo/account-overview
{:current-value (utils/prettify-balance balance)
:account-name name
:account :default
:account (if watch-only? :watched-address :default)
:customization-color color}]
[quo/wallet-graph {:time-frame :empty}]
[quo/wallet-ctas
{:send-action #(rf/dispatch [:open-modal :wallet-select-address])
:buy-action #(rf/dispatch [:show-bottom-sheet
{:content buy-drawer}])
:bridge-action #(rf/dispatch [:open-modal :wallet-bridge])}]
(when (not watch-only?)
[quo/wallet-ctas
{:send-action #(rf/dispatch [:open-modal :wallet-select-address])
:buy-action #(rf/dispatch [:show-bottom-sheet
{:content buy-drawer}])
:bridge-action #(rf/dispatch [:open-modal :wallet-bridge])}])
[quo/tabs
{:style style/tabs
:size 32
:default-active @selected-tab
:data tabs-data
:data (tabs-data watch-only?)
:on-change #(reset! selected-tab %)
:scrollable? true
:scroll-on-press? true}]
@@ -13,11 +13,11 @@
(h/describe "select address for watch only account"
(h/test "validation messages show for already used addressed"
(setup-subs {:wallet/scanned-address nil
:wallet/addresses (set
["0x12E838Ae1f769147b12956485dc56e57138f3AC8"
"0x22E838Ae1f769147b12956485dc56e57138f3AC8"])
:profile/customization-color :blue})
(setup-subs {:wallet/scanned-address nil
:wallet/addresses #{"0x12E838Ae1f769147b12956485dc56e57138f3AC8"
"0x22E838Ae1f769147b12956485dc56e57138f3AC8"}
:wallet/watch-address-activity-state nil
:profile/customization-color :blue})
(h/render [add-address-to-watch/view])
(h/is-falsy (h/query-by-label-text :error-message))
(h/fire-event :change-text
@@ -26,11 +26,11 @@
(h/is-truthy (h/get-by-translation-text :address-already-in-use))))
(h/test "validation messages show for invalid address"
(setup-subs {:wallet/scanned-address nil
:wallet/addresses (set
["0x12E838Ae1f769147b12956485dc56e57138f3AC8"
"0x22E838Ae1f769147b12956485dc56e57138f3AC8"])
:profile/customization-color :blue})
(setup-subs {:wallet/scanned-address nil
:wallet/addresses #{"0x12E838Ae1f769147b12956485dc56e57138f3AC8"
"0x22E838Ae1f769147b12956485dc56e57138f3AC8"}
:wallet/watch-address-activity-state nil
:profile/customization-color :blue})
(h/render [add-address-to-watch/view])
(h/is-falsy (h/query-by-label-text :error-message))
(h/fire-event :change-text (h/get-by-label-text :add-address-to-watch) "0x12E838Ae1f769147b")
@@ -0,0 +1,26 @@
(ns status-im2.contexts.wallet.add-address-to-watch.confirm-address.component-spec
(:require
[re-frame.core :as re-frame]
[status-im2.contexts.wallet.add-address-to-watch.confirm-address.view :as confirm-address]
[test-helpers.component :as h]
[utils.re-frame :as rf]))
(defn setup-subs
[subscriptions]
(doseq [keyval subscriptions]
(re-frame/reg-sub
(key keyval)
(fn [_] (val keyval)))))
(h/describe "Add Watch Only Account Page"
(h/test "Create Account button is disabled while no account name exists"
(let [callback (h/mock-fn)]
(with-redefs [rf/dispatch #(callback)]
(setup-subs {:profile/wallet-accounts []
:get-screen-params {:address "0xmock-address"}})
(h/render [confirm-address/view {}])
(h/is-truthy (h/get-by-text "0xmock-address"))
(h/was-not-called callback)
(h/fire-event :change-text (h/get-by-label-text :profile-title-input) "NAME")
(h/fire-event :press (h/get-by-translation-text :t/add-watched-address))
(h/was-called callback)))))
@@ -3,7 +3,6 @@
[clojure.string :as string]
[quo.core :as quo]
[quo.foundations.colors :as colors]
[re-frame.core :as re-frame]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.contexts.emoji-picker.utils :as emoji-picker.utils]
@@ -43,8 +42,14 @@
:bottom-action-label :t/add-watched-address
:bottom-action-props {:customization-color @account-color
:disabled? (string/blank? @account-name)
:on-press #(re-frame/dispatch [:navigate-to
:wallet-account])}}
:on-press #(rf/dispatch [:wallet/add-account
nil
{:type :watch
:account-name @account-name
:emoji @account-emoji
:color @account-color}
{:address address
:public-key ""}])}}
[quo/data-item
{:card? true
:right-icon :i/advanced
@@ -54,5 +59,12 @@
:subtitle address
:status :default
:size :default
:subtitle-type :default
:custom-subtitle (fn [] [quo/text
{:size :paragraph-2
;; TODO: monospace font
;; https://github.com/status-im/status-mobile/issues/17009
:weight :monospace}
address])
:container-style style/data-item
:on-press #(js/alert "To be implemented")}]]])))
@@ -5,15 +5,8 @@
:margin-top 12
:margin-bottom 20})
(def button-container
{:position :absolute
:bottom 22
:left 20
:right 20})
(def scan
{:align-self
:flex-end})
{:margin-top 26})
(def input
{:flex 1
@@ -5,6 +5,7 @@
[react-native.clipboard :as clipboard]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.common.floating-button-page.view :as floating-button-page]
[status-im2.contexts.wallet.add-address-to-watch.style :as style]
[status-im2.contexts.wallet.common.validation :as validation]
[utils.i18n :as i18n]
@@ -26,11 +27,14 @@
(let [scanned-address (rf/sub [:wallet/scanned-address])
empty-input? (and (string/blank? @input-value)
(string/blank? scanned-address))
on-change-text (fn [new-text]
(reset! validation-msg (validate new-text))
(reset! input-value new-text)
(if (and (not-empty new-text) (nil? (validate new-text)))
(rf/dispatch [:wallet/get-address-details new-text])
(rf/dispatch [:wallet/clear-address-activity-check]))
(when (and scanned-address (not= scanned-address new-text))
(rf/dispatch [:wallet/clear-address-activity-check])
(rf/dispatch [:wallet/clean-scanned-address])))
paste-on-input #(clipboard/get-string
(fn [clipboard-text]
@@ -66,6 +70,32 @@
:icon-only? true}
:i/scan]]))
(defn activity-indicator
[]
(let [activity-state (rf/sub [:wallet/watch-address-activity-state])
{:keys [accessibility-label icon type message]}
(case activity-state
:has-activity {:accessibility-label :account-has-activity
:icon :i/done
:type :success
:message :t/this-address-has-activity}
:no-activity {:accessibility-label :account-has-no-activity
:icon :i/info
:type :warning
:message :t/this-address-has-no-activity}
{:accessibility-label :searching-for-activity
:icon :i/pending-state
:type :default
:message :t/searching-for-activity})]
(when activity-state
[quo/info-message
{:accessibility-label accessibility-label
:size :default
:icon icon
:type type
:style style/info-message}
(i18n/label message)])))
(defn view
[]
(let [addresses (rf/sub [:wallet/addresses])
@@ -76,40 +106,46 @@
clear-input (fn []
(reset! input-value nil)
(reset! validation-msg nil)
(rf/dispatch [:wallet/clear-address-activity-check])
(rf/dispatch [:wallet/clean-scanned-address]))
customization-color (rf/sub [:profile/customization-color])]
(rf/dispatch [:wallet/clean-scanned-address])
(rf/dispatch [:wallet/clear-address-activity-check])
(fn []
[rn/view
{:style {:flex 1}}
[quo/page-nav
{:type :no-title
:icon-name :i/close
:on-press (fn []
(rf/dispatch [:wallet/clean-scanned-address])
(rf/dispatch [:navigate-back]))}]
[quo/text-combinations
{:container-style style/header-container
:title (i18n/label :t/add-address)
:description (i18n/label :t/enter-eth)}]
[:f> address-input
{:input-value input-value
:validate validate
:validation-msg validation-msg
:clear-input clear-input}]
(when @validation-msg
[quo/info-message
{:accessibility-label :error-message
:size :default
:icon :i/info
:type :error
:style style/info-message}
@validation-msg])
[quo/button
{:customization-color customization-color
:disabled? (string/blank? @input-value)
:on-press #(rf/dispatch [:navigate-to
:confirm-address-to-watch
{:address @input-value}])
:container-style style/button-container}
(i18n/label :t/continue)]])))
[floating-button-page/view
{:header [quo/page-nav
{:type :no-title
:icon-name :i/close
:on-press (fn []
(rf/dispatch [:wallet/clean-scanned-address])
(rf/dispatch [:wallet/clear-address-activity-check])
(rf/dispatch [:navigate-back]))}]
:footer
[quo/button
{:customization-color customization-color
:disabled? (or (string/blank? @input-value) (some? (validate @input-value)))
:on-press #(rf/dispatch [:navigate-to
:confirm-address-to-watch
{:address @input-value}])
:container-style {:z-index 2}}
(i18n/label :t/continue)]}
[quo/text-combinations
{:container-style style/header-container
:title (i18n/label :t/add-address)
:description (i18n/label :t/enter-eth)}]
[:f> address-input
{:input-value input-value
:validate validate
:validation-msg validation-msg
:clear-input clear-input}]
(when @validation-msg
[quo/info-message
{:accessibility-label :error-message
:size :default
:icon :i/info
:type :error
:style style/info-message}
@validation-msg])
[activity-indicator]]])))
@@ -4,10 +4,15 @@
{:margin-top 100
:margin-bottom 34})
(def preview
(def preview-container
{:margin-horizontal 8
:margin-top 12})
(def preview
{:width "100%"
:aspect-ratio 1
:border-radius 16})
(def header
{:margin-horizontal 20
:margin-top 16
@@ -17,6 +22,9 @@
{:flex-direction :row
:margin-top 6})
(def collection-avatar-container
{:margin-right 8})
(def buttons-container
{:flex-direction :row
:align-items :stretch
@@ -50,13 +58,13 @@
{:margin-left 6
:flex 1})
(def traits-section
{:margin-horizontal 20
:margin-top 8})
(def traits-title-container
{:margin-left 20
:margin-top 8})
(def traits-item
{:margin-horizontal 6
:flex 1})
{:margin 6
:flex 1})
(def traits-container
{:margin-horizontal 14
@@ -1,20 +1,23 @@
(ns status-im2.contexts.wallet.collectible.view
(:require
[clojure.string :as string]
[quo.core :as quo]
[quo.foundations.resources :as quo.resources]
[react-native.core :as rn]
[status-im2.common.scroll-page.view :as scroll-page]
[status-im2.contexts.wallet.collectible.style :as style]
[status-im2.contexts.wallet.common.temp :as temp]
[utils.i18n :as i18n]))
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn header
[{:keys [name description collection-image]}]
[{:keys [name description collection-image-url]}]
[rn/view {:style style/header}
[quo/text
{:weight :semi-bold
:size :heading-1} name]
[rn/view style/collection-container
[quo/collection-avatar {:image collection-image}]
[rn/view {:style style/collection-container}
[rn/view {:style style/collection-avatar-container}
[quo/collection-avatar {:image collection-image-url}]]
[quo/text
{:weight :semi-bold
:size :paragraph-1}
@@ -57,53 +60,61 @@
(defn traits-section
[traits]
[rn/view {:style style/traits-section}
[quo/section-label
{:section (i18n/label :t/traits)}]]
[rn/flat-list
{:render-fn (fn [{:keys [title subtitle]}]
[rn/view {:style style/traits-item}
[quo/data-item
{:description :default
:card? true
:status :default
:size :default
:title title
:subtitle subtitle}]])
:data traits
:key :collectibles-list
:key-fn :id
:num-columns 2
:content-container-style style/traits-container}])
(when (pos? (count traits))
[rn/view
[quo/section-label
{:section (i18n/label :t/traits)
:container-style style/traits-title-container}]
[rn/flat-list
{:render-fn (fn [{:keys [trait-type value]}]
[quo/data-item
{:card? true
:status :default
:size :default
:title trait-type
:subtitle value
:subtitle-type :default
:container-style style/traits-item}])
:data traits
:key :collectibles-list
:key-fn :id
:num-columns 2
:content-container-style style/traits-container}]]))
(defn info
[]
[rn/view
{:style style/info-container}
[rn/view {:style style/account}
[quo/data-item
{:description :account
:card? true
:status :default
:size :default
:title (i18n/label :t/account-title)
:subtitle "Collectibles vault"
:emoji "🎮"
:customization-color :yellow}]]
[chain-id]
(let [network (rf/sub [:wallet/network-details-by-chain-id
chain-id])
network-keyword (get network :network-name)
network-name (string/capitalize (name network-keyword))]
[rn/view
{:style style/info-container}
[rn/view {:style style/account}
[quo/data-item
{:card? true
:status :default
:size :default
:title (i18n/label :t/account-title)
:subtitle "Collectibles vault"
:subtitle-type :account
:emoji "🎮"
:customization-color :yellow}]]
[rn/view {:style style/network}
[quo/data-item
{:description :network
:card? true
:status :default
:size :default
:title (i18n/label :t/network)
:subtitle (i18n/label :t/mainnet)}]]])
[rn/view {:style style/network}
[quo/data-item
{:card? true
:status :default
:size :default
:title (i18n/label :t/network)
:network-image (quo.resources/get-network network-keyword)
:subtitle network-name
:subtitle-type :network}]]]))
(defn view
[]
(let [{:keys [name description image traits] :as props} temp/collectible-details]
(let [collectible-details (rf/sub [:wallet/last-collectible-details])
{:keys [name description preview-url traits id]} collectible-details
chain-id (get-in id [:contract-id :chain-id])]
[scroll-page/scroll-page
{:navigate-back? true
:height 148
@@ -112,13 +123,14 @@
:description description
:right-side [{:icon-name :i/options
:on-press #(js/alert "pressed")}]
:picture image}}
:picture preview-url}}
[rn/view {:style style/container}
[rn/image
{:source image
:style style/preview}]
[header props]
[rn/view {:style style/preview-container}
[rn/image
{:source preview-url
:style style/preview}]]
[header collectible-details]
[cta-buttons]
[tabs]
[info]
[info chain-id]
[traits-section traits]]]))
@@ -0,0 +1,22 @@
(ns status-im2.contexts.wallet.common.account-switcher.view
(:require [quo.core :as quo]
[status-im2.contexts.wallet.common.sheets.account-options.view :as account-options]
[utils.re-frame :as rf]))
(defn view
[{:keys [on-press accessibility-label] :or {accessibility-label :top-bar}}]
(let [{:keys [color emoji]} (rf/sub [:wallet/current-viewing-account])
networks (rf/sub [:wallet/network-details])]
[quo/page-nav
{:icon-name :i/close
:on-press on-press
:accessibility-label accessibility-label
:networks networks
:networks-on-press #(js/alert "Pressed Networks")
:right-side :account-switcher
:account-switcher {:customization-color color
:on-press #(rf/dispatch [:show-bottom-sheet
{:content account-options/view
:gradient-cover? true
:customization-color color}])
:emoji emoji}}]))
@@ -21,11 +21,13 @@
:style {:flex 1}
:content-container-style {:align-items :center}
:num-columns 2
:render-fn (fn [{:keys [preview-url]}]
:render-fn (fn [{:keys [preview-url id]}]
[quo/collectible
{:images [preview-url]
:on-press #(rf/dispatch
[:navigate-to
:wallet-collectible])}])}])))
:on-press (fn []
(rf/dispatch [:wallet/get-collectible-details id])
(rf/dispatch
[:navigate-to
:wallet-collectible]))}])}])))
(def view (quo.theme/with-theme view-internal))
@@ -44,12 +44,12 @@
[quo/data-item
{:status :default
:size :default
:description :default
:label :none
:blur? false
:card? true
:title (i18n/label :t/address)
:subtitle address
:subtitle-type :default
:container-style (merge style/data-item
{:background-color (colors/theme-colors colors/neutral-2_5
colors/neutral-90
@@ -1,28 +1,11 @@
(ns status-im2.contexts.wallet.common.temp
(:require
[clojure.string :as string]
[quo.core :as quo]
[quo.foundations.resources :as quo.resources]
[react-native.core :as rn]
[status-im2.common.resources :as status.resources]
[status-im2.constants :as constants]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn wallet-temporary-navigation
[]
[rn/view
{:style {:flex 1
:align-items :center
:justify-content :center}}
[quo/text {} "TEMPORARY NAVIGATION"]
[quo/button {:on-press #(rf/dispatch [:navigate-to :wallet-accounts])}
"Navigate to Account"]
[quo/button {:on-press #(rf/dispatch [:navigate-to :wallet-create-account])}
"Create Account"]
[quo/button {:on-press #(rf/dispatch [:navigate-to :wallet-saved-addresses])}
"Saved Addresses"]])
[utils.i18n :as i18n]))
(defn wallet-overview-state
[networks]
@@ -63,56 +46,6 @@
:percentage-change "0.00"
:fiat-change "€0.00"}}])
(def collectibles
[{:image (status.resources/get-mock-image :collectible1)
:id 1}
{:image (status.resources/get-mock-image :collectible2)
:id 2}
{:image (status.resources/get-mock-image :collectible3)
:id 3}
{:image (status.resources/get-mock-image :collectible4)
:id 4}
{:image (status.resources/get-mock-image :collectible5)
:id 5}
{:image (status.resources/get-mock-image :collectible6)
:id 6}])
(def collectible-details
nil
#_{:name "#5946"
:description "Bored Ape Yacht Club"
:image (status.resources/get-mock-image :collectible-monkey)
:collection-image (status.resources/get-mock-image :bored-ape)
:traits [{:title "Background"
:subtitle "Blue"
:id 1}
{:title "Clothes"
:subtitle "Bayc T Black"
:id 2}
{:title "Eyes"
:subtitle "Sleepy"
:id 3}
{:title "Fur"
:subtitle "Black"
:id 4}
{:title "Hat"
:subtitle "Beanie"
:id 5}
{:title "Mouth"
:subtitle "Bored Pipe"
:id 6}]})
(def account-overview-state
{:current-value "€0.00"
:account-name "Account 1"
:account :default
:customization-color :blue})
(def network-names
[{:network-name :ethereum :short-name "eth"}
{:network-name :optimism :short-name "opt"}
{:network-name :arbitrum :short-name "arb1"}])
(def address "0x39cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd4")
(def data-item-state

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