Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
984bc74b6d | ||
|
|
17cd163f25 | ||
|
|
f3c967f26b | ||
|
|
9f78eaa91d | ||
|
|
778b06abb2 | ||
|
|
68d7eddb4d | ||
|
|
c7165cf078 | ||
|
|
50dcf9d9b9 | ||
|
|
372bf83da5 | ||
|
|
710829d248 | ||
|
|
23fae29f9d | ||
|
|
daf3e52281 | ||
|
|
3338a4b1a1 | ||
|
|
9ead91c383 | ||
|
|
fb84885af0 | ||
|
|
4aac04e931 | ||
|
|
90166e8762 | ||
|
|
d68fdb18f4 | ||
|
|
e46f4d9081 | ||
|
|
dd2fd3410b | ||
|
|
085e2df34c | ||
|
|
51bfd3567c | ||
|
|
fb6d907cc5 | ||
|
|
a88c5b7bf7 | ||
|
|
f9f328107d | ||
|
|
04dee8be45 | ||
|
|
52f7fc59ee | ||
|
|
b5202b4d28 | ||
|
|
210cf64ce0 | ||
|
|
ed270b2162 | ||
|
|
d412fa3c63 | ||
|
|
b7f675aa5c | ||
|
|
bfa23c182f | ||
|
|
6b721265af | ||
|
|
589a581298 | ||
|
|
0546a87e9a | ||
|
|
e5ce7fed3a | ||
|
|
58d5c3d7a5 | ||
|
|
6ccea1ddb2 | ||
|
|
a9a17aaae8 | ||
|
|
6d69c278cd | ||
|
|
c7e230d070 | ||
|
|
d309aa366d | ||
|
|
f124ca4252 | ||
|
|
1385e27cf4 | ||
|
|
f82d28c6c9 | ||
|
|
a2856cf1c3 | ||
|
|
e6a7c420a2 | ||
|
|
671aa67002 | ||
|
|
dbc8df251a | ||
|
|
279993b658 | ||
|
|
0c1a18b444 |
@@ -77,7 +77,6 @@ pipeline {
|
||||
}
|
||||
}
|
||||
stage('Upload') {
|
||||
when { expression { !utils.isReleaseBuild() } }
|
||||
steps { script {
|
||||
env.DIAWI_URL = ios.uploadToDiawi()
|
||||
env.PKG_URL = env.DIAWI_URL
|
||||
|
||||
@@ -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
|
||||
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 17 KiB |
@@ -49,6 +49,7 @@
|
||||
:Text {}
|
||||
:StatusBar {}
|
||||
:ScrollView {}
|
||||
:SafeAreaView {}
|
||||
:KeyboardAvoidingView {}
|
||||
:TextInput {}
|
||||
:Image {}
|
||||
|
||||
@@ -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))))
|
||||
|
||||
@@ -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,10 +17,12 @@
|
||||
|
||||
(defn- view-internal
|
||||
[]
|
||||
(fn [{:keys [disabled? theme blur? left-action delete-key? on-press on-delete]
|
||||
(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}
|
||||
@@ -60,7 +62,7 @@
|
||||
:theme theme}]
|
||||
(if delete-key?
|
||||
[keyboard-item
|
||||
{:item :i/delete
|
||||
{:item :i/backspace
|
||||
:type :key
|
||||
:disabled? disabled?
|
||||
:on-press on-delete
|
||||
|
||||
@@ -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})
|
||||
@@ -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
|
||||
|
||||
@@ -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))})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
(ns quo.components.wallet.token-input.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[quo.components.buttons.button.view :as button]
|
||||
[quo.components.dividers.divider-line.view :as divider-line]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.tags.network-tags.view :as network-tag]
|
||||
[quo.components.wallet.token-input.style :as style]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.foundations.common :as common]
|
||||
[quo.foundations.resources :as resources]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
[clojure.string :as string]
|
||||
[quo.components.buttons.button.view :as button]
|
||||
[quo.components.dividers.divider-line.view :as divider-line]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.tags.network-tags.view :as network-tag]
|
||||
[quo.components.wallet.token-input.style :as style]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.foundations.common :as common]
|
||||
[quo.foundations.resources :as resources]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn calc-value
|
||||
[crypto? currency token value conversion]
|
||||
@@ -21,13 +21,14 @@
|
||||
(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 nil)
|
||||
crypto? (reagent/atom true)
|
||||
input-ref (atom nil)]
|
||||
[{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-swap container-style show-keyboard?]
|
||||
on-change-text on-swap container-style show-keyboard?]
|
||||
:or {show-keyboard? true}
|
||||
external-value :value}]
|
||||
[rn/view
|
||||
@@ -42,40 +43,44 @@
|
||||
: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 #(do (reset! input-ref %)
|
||||
(when %
|
||||
(.focus ^js %)))
|
||||
:placeholder "0"
|
||||
:placeholder-text-color (colors/theme-colors colors/neutral-40
|
||||
colors/neutral-50
|
||||
theme)
|
||||
:default-value (or external-value @value)
|
||||
:keyboard-type :numeric
|
||||
:max-length 12
|
||||
:on-change-text #(reset! value %)
|
||||
:style (style/text-input theme)
|
||||
:selection-color customization-color
|
||||
:show-soft-input-on-focus show-keyboard?}]]
|
||||
[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 (or (clj->js (if @crypto? token currency)) ""))]]
|
||||
[button/button
|
||||
{:icon true
|
||||
:icon-only? true
|
||||
:size 32
|
||||
:on-press (fn []
|
||||
(swap! crypto? not)
|
||||
(when on-swap
|
||||
(on-swap @crypto?)))
|
||||
:type :outline
|
||||
:accessibility-label :reorder}
|
||||
:i/reorder]
|
||||
(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 (or (clj->js (if @crypto? token currency)) ""))]]
|
||||
[button/button
|
||||
{:icon true
|
||||
:icon-only? true
|
||||
:size 32
|
||||
:on-press (fn []
|
||||
(swap! crypto? not)
|
||||
(when on-swap
|
||||
(on-swap @crypto?)))
|
||||
:type :outline
|
||||
:accessibility-label :reorder}
|
||||
:i/reorder]]
|
||||
[divider-line/view {:container-style {:margin-vertical 8}}]
|
||||
[rn/view {:style style/data-container}
|
||||
[network-tag/view {:networks networks :title title}]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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}]))
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
(vector
|
||||
action-button
|
||||
dismiss-button)
|
||||
dismiss-button)
|
||||
(vector dismiss-button))
|
||||
(when on-dismiss
|
||||
{:cancelable false})))))
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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]]))
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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]])]))
|
||||
@@ -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,30 +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"]
|
||||
[quo/button {:on-press #(rf/dispatch [:navigate-to :wallet-send-input-amount])}
|
||||
"Send: input amount"]])
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn wallet-overview-state
|
||||
[networks]
|
||||
@@ -65,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
|
||||
|
||||
@@ -29,17 +29,29 @@
|
||||
(/ n (Math/pow 10 (utils.number/parse-int decimals)))
|
||||
0))
|
||||
|
||||
(defn- total-token-value-in-all-chains
|
||||
(defn total-token-value-in-all-chains
|
||||
[{:keys [balances-per-chain decimals]}]
|
||||
(->> balances-per-chain
|
||||
(vals)
|
||||
(map #(calculate-raw-balance (:raw-balance %) decimals))
|
||||
(reduce +)))
|
||||
|
||||
(defn calculate-balance-for-token
|
||||
[token]
|
||||
(* (total-token-value-in-all-chains token)
|
||||
(-> token :market-values-per-currency :usd :price)))
|
||||
|
||||
(defn calculate-balance
|
||||
[tokens-in-account]
|
||||
(->> tokens-in-account
|
||||
(map (fn [token]
|
||||
(* (total-token-value-in-all-chains token)
|
||||
(-> token :market-values-per-currency :usd :price))))
|
||||
(map #(calculate-balance-for-token %))
|
||||
(reduce +)))
|
||||
|
||||
(defn network-list
|
||||
[{:keys [balances-per-chain]} networks]
|
||||
(into #{}
|
||||
(mapv (fn [chain-id]
|
||||
(first (filter #(or (= (:chain-id %) chain-id)
|
||||
(= (:related-chain-id %) chain-id))
|
||||
networks)))
|
||||
(keys balances-per-chain))))
|
||||
|
||||