Compare commits
21
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7376ae1509 | ||
|
|
ee85d6d596 | ||
|
|
d8d8a6c7a0 | ||
|
|
f5f1e6302d | ||
|
|
9c26a54006 | ||
|
|
ab868a6ae5 | ||
|
|
695bbcbe81 | ||
|
|
bf76ca167a | ||
|
|
af1942dff3 | ||
|
|
1c31127a6f | ||
|
|
fe404ab005 | ||
|
|
8869271054 | ||
|
|
5ea78084d1 | ||
|
|
ba57ab9ae4 | ||
|
|
0522120c66 | ||
|
|
6b9b5fa300 | ||
|
|
77733b3a65 | ||
|
|
79f7b6c6ba | ||
|
|
db787f9d4b | ||
|
|
a847f508f9 | ||
|
|
4152b9318b |
@@ -136,11 +136,6 @@ quo.animated/re-timing
|
||||
quo.design-system.colors/white
|
||||
quo.design-system.colors/black
|
||||
status-im.transport.core-test/messages
|
||||
status-im.ethereum.core/sidechain?
|
||||
status-im.ethereum.core/network-with-upstream-rpc?
|
||||
status-im.ethereum.core/current-address
|
||||
status-im.ethereum.core/network->network-name
|
||||
status-im.ethereum.core/estimate-gas
|
||||
quo.core/animated-header
|
||||
quo.core/safe-area-provider
|
||||
quo.core/safe-area-consumer
|
||||
|
||||
@@ -311,6 +311,7 @@ endef
|
||||
lint: export TARGET := clojure
|
||||
lint: ##@test Run code style checks
|
||||
@sh scripts/lint-re-frame-in-quo-components.sh && \
|
||||
sh scripts/lint-old-quo-usage.sh \
|
||||
clj-kondo --config .clj-kondo/config.edn --cache false --fail-level error --lint src && \
|
||||
ALL_CLOJURE_FILES=$(call find_all_clojure_files) && \
|
||||
zprint '{:search-config? true}' -sfc $$ALL_CLOJURE_FILES && \
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.15'
|
||||
|
||||
/* Options section can't access functions in objects. */
|
||||
def isPRBuild = utils.isPRBuild()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.15'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.15'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@set_ios_status_go_targets'
|
||||
library 'status-jenkins-lib@v1.7.15'
|
||||
|
||||
/* Options section can't access functions in objects. */
|
||||
def isPRBuild = utils.isPRBuild()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.15'
|
||||
|
||||
/* Options section can't access functions in objects. */
|
||||
def isPRBuild = utils.isPRBuild()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.15'
|
||||
|
||||
pipeline {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.15'
|
||||
|
||||
pipeline {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.15'
|
||||
|
||||
pipeline {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.15'
|
||||
|
||||
pipeline {
|
||||
agent { label 'macos' }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.15'
|
||||
|
||||
pipeline {
|
||||
agent { label params.AGENT_LABEL }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.15'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.7.14'
|
||||
library 'status-jenkins-lib@v1.7.15'
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
|
||||
+1
-1
@@ -707,7 +707,7 @@ SPEC CHECKSUMS:
|
||||
FBLazyVector: a8af91c2b5a0029d12ff6b32e428863d63c48991
|
||||
FBReactNativeSpec: 1b2309b096448a1dc9d0c43999216f8fda809ae8
|
||||
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
|
||||
glog: d93527a855523adb8c113837db4be68fb00e230d
|
||||
glog: 166d178815c300e8126de9a7900101814eb16253
|
||||
HMSegmentedControl: 34c1f54d822d8308e7b24f5d901ec674dfa31352
|
||||
Keycard: ac6df4d91525c3c82635ac24d4ddd9a80aca5fc8
|
||||
libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 725 B After Width: | Height: | Size: 673 B |
Binary file not shown.
|
Before Width: | Height: | Size: 1007 B After Width: | Height: | Size: 1001 B |
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
QUO_USAGES=$(grep -r -E '\[quo\.[^ ]* :(?:as|refer)|\[quo\.[^ ]*\]' --include '*.cljs' --include '*.clj' './src/status_im2' --exclude='./src/status_im2/common/theme/core.cljs' || true)
|
||||
|
||||
echo -e "\nChecking 'status_im2' namespace for 'quo' namespace usage."
|
||||
|
||||
if [ -n "$QUO_USAGES" ]; then
|
||||
echo -e "\033[0;31mERROR: Usage of the old 'quo' namespace detected in 'status_im2' code. Please update to 'quo2'. \n"
|
||||
echo -e "$QUO_USAGES \033[0m"
|
||||
exit 1
|
||||
fi
|
||||
@@ -470,7 +470,8 @@
|
||||
(defn sha3
|
||||
[s]
|
||||
(log/debug "[native-module] sha3")
|
||||
(.sha3 ^js (status) s))
|
||||
(when s
|
||||
(.sha3 ^js (status) (str s))))
|
||||
|
||||
(defn utf8-to-hex
|
||||
[s]
|
||||
@@ -491,8 +492,9 @@
|
||||
(defn address?
|
||||
[address]
|
||||
(log/debug "[native-module] address?")
|
||||
(let [result (.isAddress ^js (status) address)]
|
||||
(types/json->clj result)))
|
||||
(when address
|
||||
(let [result (.isAddress ^js (status) address)]
|
||||
(types/json->clj result))))
|
||||
|
||||
(defn to-checksum-address
|
||||
[address]
|
||||
|
||||
@@ -6,16 +6,20 @@
|
||||
(def default-padding 16)
|
||||
(def default-emoji-size 36)
|
||||
|
||||
(def ^:private container-size
|
||||
{:size-64 64})
|
||||
|
||||
(defn get-border-radius
|
||||
[size]
|
||||
(case size
|
||||
80 16
|
||||
48 12
|
||||
32 10
|
||||
28 8
|
||||
24 8
|
||||
20 6
|
||||
16 4
|
||||
80 16
|
||||
:size-64 16
|
||||
48 12
|
||||
32 10
|
||||
28 8
|
||||
24 8
|
||||
20 6
|
||||
16 4
|
||||
default-border-radius))
|
||||
|
||||
(defn get-padding
|
||||
@@ -33,29 +37,32 @@
|
||||
(defn get-emoji-size
|
||||
[size]
|
||||
(case size
|
||||
80 36
|
||||
48 24
|
||||
32 15
|
||||
28 12
|
||||
24 11
|
||||
20 11
|
||||
16 11
|
||||
80 36
|
||||
:size-64 30
|
||||
48 24
|
||||
32 15
|
||||
28 12
|
||||
24 11
|
||||
20 11
|
||||
16 11
|
||||
default-emoji-size))
|
||||
|
||||
(defn get-border-width
|
||||
[size]
|
||||
(case size
|
||||
16 0.8 ;; 0.8 px is for only size 16
|
||||
;; Rest of the size will have 1 px
|
||||
1))
|
||||
(if (= size 16)
|
||||
0.8 ;; 0.8 px is for only size 16
|
||||
1)) ;; Rest of the size will have 1 px
|
||||
|
||||
|
||||
(defn root-container
|
||||
[{:keys [type size theme customization-color]
|
||||
:or {size default-size
|
||||
customization-color :blue}}]
|
||||
(let [watch-only? (= type :watch-only)]
|
||||
(cond-> {:width size
|
||||
:height size
|
||||
(let [watch-only? (= type :watch-only)
|
||||
width (cond-> size
|
||||
(keyword? size) (container-size size))]
|
||||
(cond-> {:width width
|
||||
:height width
|
||||
:background-color (colors/custom-color-by-theme customization-color 50 60 nil nil theme)
|
||||
:border-radius (get-border-radius size)
|
||||
:border-color (if (= theme :light) colors/neutral-80-opa-5 colors/white-opa-5)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
(h/test "with emoji, no lock set, large size"
|
||||
(let [emoji "🍓"]
|
||||
(h/render [component/view {:emoji emoji :size :size/l}])
|
||||
(h/render [component/view {:emoji emoji :size :size-32}])
|
||||
(h/is-null (h/query-by-label-text :initials))
|
||||
(h/is-truthy (h/query-by-text emoji))
|
||||
(h/is-null (h/query-by-label-text :lock))))
|
||||
@@ -31,5 +31,5 @@
|
||||
(h/test "no emoji, large size"
|
||||
(h/render [component/view
|
||||
{:full-name "Status Mobile"
|
||||
:size :size/l}])
|
||||
:size :size-32}])
|
||||
(h/is-truthy (h/query-by-text "SM"))))
|
||||
|
||||
@@ -5,17 +5,27 @@
|
||||
|
||||
(defn outer-container
|
||||
[{:keys [size color]}]
|
||||
(let [size (if (= size :size/l) 32 24)]
|
||||
{:width size
|
||||
:height size
|
||||
:border-radius size
|
||||
(let [container-size (case size
|
||||
:size-64 64
|
||||
:size-32 32
|
||||
24)]
|
||||
{:width container-size
|
||||
:height container-size
|
||||
:border-radius container-size
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color (colors/theme-alpha color 0.1 0.1)}))
|
||||
|
||||
(defn emoji-size
|
||||
[size]
|
||||
{:font-size (case size
|
||||
:size-64 24
|
||||
:size-32 15
|
||||
11)})
|
||||
|
||||
(defn lock-container
|
||||
[size]
|
||||
(let [distance (if (= size :size/l) 20 12)]
|
||||
(let [distance (if (= size :size-32) 20 12)]
|
||||
{:position :absolute
|
||||
:left distance
|
||||
:top distance
|
||||
|
||||
@@ -5,17 +5,19 @@
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
utils.string))
|
||||
[utils.string]))
|
||||
|
||||
(defn- initials
|
||||
[full-name size color]
|
||||
(let [amount-initials (if (= size :size/l) 2 1)
|
||||
(let [amount-initials (if (#{:size-32 :size-64} size) 2 1)
|
||||
channel-name (string/replace full-name "#" "")]
|
||||
[text/text
|
||||
{:accessibility-label :initials
|
||||
:size :paragraph-2
|
||||
:weight :semi-bold
|
||||
:style {:color color}}
|
||||
(cond-> {:accessibility-label :initials
|
||||
:style {:color color}
|
||||
:size :paragraph-2
|
||||
:weight :semi-bold}
|
||||
(= size :size-64) (assoc :size :heading-1
|
||||
:weight :medium))
|
||||
(utils.string/get-initials channel-name amount-initials)]))
|
||||
|
||||
(defn- lock
|
||||
@@ -54,8 +56,8 @@
|
||||
:style (style/outer-container {:size size :color customization-color})}
|
||||
(if (string/blank? emoji)
|
||||
[initials full-name size customization-color]
|
||||
[text/text
|
||||
{:accessibility-label :emoji
|
||||
:size (if (= size :size/l) :paragraph-1 :label)}
|
||||
[rn/text
|
||||
{:style (style/emoji-size size)
|
||||
:accessibility-label :emoji}
|
||||
(string/trim emoji)])
|
||||
[lock locked? size]])
|
||||
|
||||
@@ -28,9 +28,10 @@
|
||||
(let [container-size (get-in sizes [size :container])
|
||||
icon-size (get-in sizes [size :icon])]
|
||||
[rn/view
|
||||
{:style (style/container {:container-size container-size
|
||||
:customization-color customization-color
|
||||
:theme theme})}
|
||||
{:accessibility-label :group-avatar
|
||||
:style (style/container {:container-size container-size
|
||||
:customization-color customization-color
|
||||
:theme theme})}
|
||||
(if picture
|
||||
[fast-image/fast-image
|
||||
{:source picture
|
||||
|
||||
@@ -2,48 +2,54 @@
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def sizes
|
||||
{:big {:dimensions 80
|
||||
:status-indicator 12
|
||||
:status-indicator-border 4
|
||||
:status-indicator-center-to-edge 12
|
||||
:font-size :heading-1
|
||||
:ring-width 4}
|
||||
:medium {:dimensions 48
|
||||
:status-indicator 8
|
||||
:status-indicator-border 2
|
||||
:status-indicator-center-to-edge 6
|
||||
:font-size :heading-2
|
||||
:ring-width 2}
|
||||
:small {:dimensions 32
|
||||
:status-indicator 8
|
||||
:status-indicator-border 2
|
||||
:status-indicator-center-to-edge 4
|
||||
:font-size :paragraph-2
|
||||
:ring-width 2}
|
||||
28 {:dimensions 28
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:status-indicator-center-to-edge 0
|
||||
:font-size :paragraph-2
|
||||
:ring-width 0}
|
||||
:xs {:dimensions 24
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:status-indicator-center-to-edge 0
|
||||
:font-size :paragraph-2
|
||||
:ring-width 2}
|
||||
:xxs {:dimensions 20
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:status-indicator-center-to-edge 0
|
||||
:font-size :label
|
||||
:ring-width 2}
|
||||
:xxxs {:dimensions 16
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:status-indicator-center-to-edge 0
|
||||
:font-size :label
|
||||
:ring-width 2}})
|
||||
{:big {:dimensions 80
|
||||
:status-indicator 12
|
||||
:status-indicator-border 4
|
||||
:status-indicator-center-to-edge 12
|
||||
:font-size :heading-1
|
||||
:ring-width 4}
|
||||
:size-64 {:dimensions 64
|
||||
:status-indicator 8
|
||||
:status-indicator-border 2
|
||||
:status-indicator-center-to-edge 6
|
||||
:font-size :heading-1
|
||||
:ring-width 2}
|
||||
:medium {:dimensions 48
|
||||
:status-indicator 8
|
||||
:status-indicator-border 2
|
||||
:status-indicator-center-to-edge 6
|
||||
:font-size :heading-2
|
||||
:ring-width 2}
|
||||
:small {:dimensions 32
|
||||
:status-indicator 8
|
||||
:status-indicator-border 2
|
||||
:status-indicator-center-to-edge 4
|
||||
:font-size :paragraph-2
|
||||
:ring-width 2}
|
||||
28 {:dimensions 28
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:status-indicator-center-to-edge 0
|
||||
:font-size :paragraph-2
|
||||
:ring-width 0}
|
||||
:xs {:dimensions 24
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:status-indicator-center-to-edge 0
|
||||
:font-size :paragraph-2
|
||||
:ring-width 2}
|
||||
:xxs {:dimensions 20
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:status-indicator-center-to-edge 0
|
||||
:font-size :label
|
||||
:ring-width 2}
|
||||
:xxxs {:dimensions 16
|
||||
:status-indicator 0
|
||||
:status-indicator-border 0
|
||||
:status-indicator-center-to-edge 0
|
||||
:font-size :label
|
||||
:ring-width 2}})
|
||||
|
||||
(defn initials-avatar
|
||||
[size customization-color theme]
|
||||
|
||||
@@ -8,18 +8,21 @@
|
||||
{:small 20
|
||||
:medium 32
|
||||
:large 48
|
||||
:size-64 64
|
||||
:x-large 80})
|
||||
|
||||
(def font-sizes
|
||||
{:small :label
|
||||
:medium :paragraph-2
|
||||
:large :paragraph-1
|
||||
:size-64 :heading-1
|
||||
:x-large :heading-1})
|
||||
|
||||
(def font-weights
|
||||
{:small :medium
|
||||
:medium :semi-bold
|
||||
:large :semi-bold
|
||||
:size-64 :medium
|
||||
:x-large :medium})
|
||||
|
||||
(defn wallet-user-avatar
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
(ns quo2.components.buttons.button.properties
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def backgrounds #{:photo :blur})
|
||||
|
||||
(defn custom-color-type
|
||||
[customization-color icon-only?]
|
||||
{:icon-color colors/white-opa-70
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
[sliding-complete?]
|
||||
(reset! sliding-complete? true))
|
||||
|
||||
(defn- reset-track-position
|
||||
(defn reset-track-position
|
||||
[x-pos]
|
||||
(animate-spring x-pos 0))
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
(ns quo2.components.buttons.slide-button.component-spec
|
||||
(:require [quo2.components.buttons.slide-button.view :as slide-button]
|
||||
[quo2.components.buttons.slide-button.constants :as constants]
|
||||
[quo2.components.buttons.slide-button.utils :as utils]
|
||||
["@testing-library/react-native" :as rtl]
|
||||
["react-native-gesture-handler/jest-utils" :as gestures-jest]
|
||||
[reagent.core :as r]
|
||||
@@ -82,17 +81,11 @@
|
||||
(h/has-style track-mock {:opacity constants/disable-opacity})))
|
||||
|
||||
(h/test "render the small button"
|
||||
(h/render [slide-button/view (assoc default-props :size :small)])
|
||||
(h/render [slide-button/view (assoc default-props :size :size/s-40)])
|
||||
(let [mock (h/get-by-test-id :slide-button-track)
|
||||
small-height (:track-height constants/small-dimensions)]
|
||||
(h/has-style mock {:height small-height})))
|
||||
|
||||
(h/test "render with the correct customization-color"
|
||||
(h/render [slide-button/view (assoc default-props :customization-color :purple)])
|
||||
(let [track-mock (h/get-by-test-id :slide-button-track)
|
||||
purple-color (utils/slider-color :track :purple)]
|
||||
(h/has-style track-mock {:backgroundColor purple-color})))
|
||||
|
||||
(h/test
|
||||
"calls on-complete when dragged"
|
||||
(let [props (merge default-props {:on-complete (h/mock-fn)})
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
:right 0})
|
||||
|
||||
(defn thumb-container
|
||||
[interpolate-track thumb-size customization-color]
|
||||
[{:keys [interpolate-track thumb-size customization-color theme]}]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:transform [{:translate-x (interpolate-track :track-clamp)}]}
|
||||
{:background-color (utils/slider-color :main customization-color)
|
||||
{:background-color (utils/slider-color :main customization-color theme)
|
||||
:border-radius 12
|
||||
:height thumb-size
|
||||
:width thumb-size
|
||||
@@ -46,7 +46,7 @@
|
||||
:justify-content :space-around}))
|
||||
|
||||
(defn track
|
||||
[disabled? customization-color height]
|
||||
[{:keys [disabled? customization-color height theme]}]
|
||||
{:align-items :flex-start
|
||||
:justify-content :center
|
||||
:border-radius 14
|
||||
@@ -54,7 +54,7 @@
|
||||
:align-self :stretch
|
||||
:padding constants/track-padding
|
||||
:opacity (if disabled? 0.3 1)
|
||||
:background-color (utils/slider-color :track customization-color)})
|
||||
:background-color (utils/slider-color :track customization-color theme)})
|
||||
|
||||
(defn track-cover
|
||||
[interpolate-track]
|
||||
@@ -74,7 +74,7 @@
|
||||
:width track-width})
|
||||
|
||||
(defn track-text
|
||||
[customization-color]
|
||||
[customization-color theme]
|
||||
(-> typography/paragraph-1
|
||||
(merge typography/font-medium)
|
||||
(assoc :color (utils/slider-color :main customization-color))))
|
||||
(assoc :color (utils/slider-color :main customization-color theme))))
|
||||
|
||||
@@ -6,9 +6,15 @@
|
||||
(defn slider-color
|
||||
"- `color-key` `:main`/`:track`
|
||||
- `customization-color` Customization color"
|
||||
[color-key customization-color]
|
||||
(let [colors-by-key {:main (colors/custom-color-by-theme customization-color 50 60)
|
||||
:track (colors/custom-color-by-theme customization-color 50 60 10 10)}]
|
||||
[color-key customization-color theme]
|
||||
(let [colors-by-key {:main (colors/theme-colors
|
||||
(colors/custom-color customization-color 50)
|
||||
(colors/custom-color customization-color 60)
|
||||
theme)
|
||||
:track (colors/theme-colors
|
||||
(colors/custom-color customization-color 50 10)
|
||||
(colors/custom-color customization-color 60 10)
|
||||
theme)}]
|
||||
(color-key colors-by-key)))
|
||||
|
||||
(defn clamp-value
|
||||
@@ -28,8 +34,8 @@
|
||||
(defn get-dimensions
|
||||
[track-width size dimension-key]
|
||||
(let [default-dimensions (case size
|
||||
:small constants/small-dimensions
|
||||
:large constants/large-dimensions
|
||||
:size/s-40 constants/small-dimensions
|
||||
:size/s-48 constants/large-dimensions
|
||||
constants/large-dimensions)]
|
||||
(-> default-dimensions
|
||||
(merge {:usable-track (calc-usable-track
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
[reagent.core :as reagent]
|
||||
[oops.core :as oops]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[quo2.components.buttons.slide-button.constants :as constants]))
|
||||
[quo2.components.buttons.slide-button.constants :as constants]
|
||||
[quo2.theme :as quo.theme]))
|
||||
|
||||
(defn- f-slider
|
||||
[{:keys [disabled?]}]
|
||||
@@ -20,14 +21,15 @@
|
||||
on-track-layout (fn [evt]
|
||||
(let [width (oops/oget evt "nativeEvent.layout.width")]
|
||||
(reset! track-width width)))]
|
||||
|
||||
(fn [{:keys [on-complete
|
||||
(fn [{:keys [on-reset
|
||||
on-complete
|
||||
track-text
|
||||
track-icon
|
||||
disabled?
|
||||
customization-color
|
||||
size
|
||||
container-style]}]
|
||||
container-style
|
||||
theme]}]
|
||||
(let [x-pos (reanimated/use-shared-value 0)
|
||||
dimensions (partial utils/get-dimensions
|
||||
(or @track-width constants/default-width)
|
||||
@@ -36,12 +38,19 @@
|
||||
x-pos
|
||||
(dimensions :usable-track)
|
||||
(dimensions :thumb))]
|
||||
|
||||
(rn/use-effect (fn []
|
||||
(when @sliding-complete?
|
||||
(on-complete)))
|
||||
[@sliding-complete?])
|
||||
|
||||
(rn/use-effect (fn []
|
||||
(when on-reset
|
||||
(reset! sliding-complete? false)
|
||||
(reset! gestures-disabled? false)
|
||||
(animations/reset-track-position x-pos)
|
||||
(on-reset)))
|
||||
[on-reset])
|
||||
|
||||
[gesture/gesture-detector
|
||||
{:gesture (animations/drag-gesture x-pos
|
||||
gestures-disabled?
|
||||
@@ -50,21 +59,25 @@
|
||||
sliding-complete?)}
|
||||
[reanimated/view
|
||||
{:test-ID :slide-button-track
|
||||
:style (merge (style/track disabled? customization-color (dimensions :track-height))
|
||||
:style (merge (style/track {:disabled? disabled?
|
||||
:customization-color customization-color
|
||||
:height (dimensions :track-height)
|
||||
:theme theme})
|
||||
container-style)
|
||||
:on-layout (when-not (some? @track-width)
|
||||
on-track-layout)}
|
||||
[reanimated/view {:style (style/track-cover interpolate-track)}
|
||||
[rn/view {:style (style/track-cover-text-container @track-width)}
|
||||
[icon/icon track-icon
|
||||
{:color (utils/slider-color :main customization-color)
|
||||
{:color (utils/slider-color :main customization-color theme)
|
||||
:size 20}]
|
||||
[rn/view {:width 4}]
|
||||
[rn/text {:style (style/track-text customization-color)} track-text]]]
|
||||
[rn/text {:style (style/track-text customization-color theme)} track-text]]]
|
||||
[reanimated/view
|
||||
{:style (style/thumb-container interpolate-track
|
||||
(dimensions :thumb)
|
||||
customization-color)}
|
||||
{:style (style/thumb-container {:interpolate-track interpolate-track
|
||||
:thumb-size (dimensions :thumb)
|
||||
:customization-color customization-color
|
||||
:theme theme})}
|
||||
[reanimated/view {:style (style/arrow-icon-container interpolate-track)}
|
||||
[icon/icon :arrow-right
|
||||
{:color colors/white
|
||||
@@ -76,16 +89,19 @@
|
||||
{:color colors/white
|
||||
:size 20}]]]]]))))
|
||||
|
||||
(defn view
|
||||
(defn- view-internal
|
||||
"Options
|
||||
- `on-complete` Callback called when the sliding is complete
|
||||
- `disabled?` Boolean that disables the button
|
||||
(_and gestures_)
|
||||
- `size` `:small`/`:large`
|
||||
- `size` :size/s-40`/`:size/s-48`
|
||||
- `track-text` Text that is shown on the track
|
||||
- `track-icon` Key of the icon shown on the track
|
||||
(e.g. `:face-id`)
|
||||
- `customization-color` Customization color
|
||||
- `on-reset` A callback which can be used to reset the component and run required functionality
|
||||
"
|
||||
[props]
|
||||
[:f> f-slider props])
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
(ns quo2.components.colors.color.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def color-button-common
|
||||
{:width 48
|
||||
:height 48
|
||||
:border-width 4
|
||||
:border-radius 24
|
||||
:margin-horizontal 4
|
||||
:transform [{:rotate "45deg"}]
|
||||
:border-color :transparent})
|
||||
|
||||
(defn color-button
|
||||
[color selected?]
|
||||
(merge color-button-common
|
||||
(when selected?
|
||||
{:border-top-color (colors/alpha color 0.4)
|
||||
:border-end-color (colors/alpha color 0.4)
|
||||
:border-bottom-color (colors/alpha color 0.2)
|
||||
:border-start-color (colors/alpha color 0.2)})))
|
||||
|
||||
(defn color-circle
|
||||
[color border?]
|
||||
{:width 40
|
||||
:height 40
|
||||
:transform [{:rotate "-45deg"}]
|
||||
:background-color color
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:border-color color
|
||||
:border-width (if border? 2 0)
|
||||
:overflow :hidden
|
||||
:border-radius 20})
|
||||
|
||||
(defn feng-shui
|
||||
[theme]
|
||||
{:width 40
|
||||
:height 40
|
||||
:transform [{:rotate "45deg"}]
|
||||
:overflow :hidden
|
||||
:border-color (colors/theme-colors colors/neutral-100 colors/white theme)
|
||||
:border-width 2
|
||||
:background-color (colors/theme-colors colors/neutral-100 colors/white theme)
|
||||
:border-radius 20})
|
||||
|
||||
(defn left-half
|
||||
[theme]
|
||||
{:flex 1
|
||||
:background-color (colors/theme-colors colors/white colors/neutral-100 theme)})
|
||||
|
||||
(defn right-half
|
||||
[theme]
|
||||
{:flex 1
|
||||
:background-color (colors/theme-colors colors/neutral-100 colors/white theme)})
|
||||
@@ -0,0 +1,50 @@
|
||||
(ns quo2.components.colors.color.view
|
||||
(:require
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[quo2.components.colors.color.style :as style]))
|
||||
|
||||
(defn- feng-shui
|
||||
[{:keys [color theme]}]
|
||||
[rn/view
|
||||
{:accessibility-label color
|
||||
:style (style/feng-shui theme)}
|
||||
[rn/view {:style (style/left-half theme)}]
|
||||
[rn/view {:style (style/right-half theme)}]])
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [color
|
||||
selected?
|
||||
on-press
|
||||
blur?
|
||||
theme]
|
||||
:as props}]
|
||||
(let [border? (and (not blur?) (not selected?))
|
||||
hex-color (if (= :feng-shui color)
|
||||
(colors/theme-colors colors/neutral-100 colors/white theme)
|
||||
(colors/theme-colors (colors/custom-color color 50)
|
||||
(colors/custom-color color 60)
|
||||
theme))]
|
||||
|
||||
[rn/pressable
|
||||
{:style (style/color-button hex-color selected?)
|
||||
:accessibility-label :color-picker-item
|
||||
:on-press #(on-press color)}
|
||||
(if (and (= :feng-shui color) (not selected?))
|
||||
[feng-shui
|
||||
(assoc props
|
||||
:hex-color hex-color
|
||||
:border? border?)]
|
||||
[rn/view
|
||||
{:accessibility-label color
|
||||
:style (style/color-circle hex-color border?)}
|
||||
(when selected?
|
||||
[icon/icon :i/check
|
||||
{:size 20
|
||||
:color (if (= :feng-shui color)
|
||||
(colors/theme-colors colors/white colors/neutral-100 theme)
|
||||
colors/white)}])])]))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -3,8 +3,6 @@
|
||||
[reagent.core :as reagent]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(def color-list [:blue :yellow :turquoise :copper :sky :camel :orange :army :pink :purple :magenta])
|
||||
|
||||
(h/describe "color-picker"
|
||||
(h/test "color picker rendered"
|
||||
(h/render [color-picker/view])
|
||||
@@ -26,6 +24,6 @@
|
||||
(h/render [color-picker/view])
|
||||
(js/Promise.all (map (fn [color]
|
||||
(h/is-truthy (h/get-all-by-label-text color)))
|
||||
color-list))))
|
||||
color-picker/color-list))))
|
||||
|
||||
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
(ns quo2.components.colors.color-picker.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def color-picker-container
|
||||
{:flex-direction :row
|
||||
:flex-wrap :wrap
|
||||
:justify-content :space-between})
|
||||
|
||||
(def flex-break
|
||||
{:flex-basis "100%"
|
||||
:height 10})
|
||||
|
||||
(def color-button-common
|
||||
{:width 48
|
||||
:height 48
|
||||
:border-width 4
|
||||
:border-radius 24
|
||||
:transform [{:rotate "45deg"}]
|
||||
:border-color :transparent})
|
||||
|
||||
(defn color-button
|
||||
[color selected?]
|
||||
(merge color-button-common
|
||||
(when selected?
|
||||
{:border-top-color (colors/alpha color 0.4)
|
||||
:border-end-color (colors/alpha color 0.4)
|
||||
:border-bottom-color (colors/alpha color 0.2)
|
||||
:border-start-color (colors/alpha color 0.2)})))
|
||||
|
||||
(defn color-circle
|
||||
[color border?]
|
||||
{:width 40
|
||||
:height 40
|
||||
:transform [{:rotate "-45deg"}]
|
||||
:background-color color
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:border-color color
|
||||
:border-width (if border? 2 0)
|
||||
:overflow :hidden
|
||||
:border-radius 20})
|
||||
|
||||
(defn secondary-overlay
|
||||
[secondary-color border?]
|
||||
{:width (if border? 18 20)
|
||||
:height 40
|
||||
:position :absolute
|
||||
:right 0
|
||||
:background-color secondary-color})
|
||||
|
||||
@@ -1,77 +1,34 @@
|
||||
(ns quo2.components.colors.color-picker.view
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.icon :as icon]
|
||||
[reagent.core :as reagent]
|
||||
[quo2.components.colors.color-picker.style :as style]))
|
||||
[quo2.components.colors.color.view :as color]))
|
||||
|
||||
;; TODO: using :no-color this to keep alignment of colors correct while b & w is being developed.
|
||||
;; https://github.com/status-im/status-mobile/issues/15442
|
||||
(def color-list
|
||||
[:blue :yellow :turquoise :copper :sky :camel :orange :army :pink :purple :magenta :no-color])
|
||||
|
||||
(defn picker-colors
|
||||
[blur?]
|
||||
(map (fn [color]
|
||||
{:name color
|
||||
:color (colors/custom-color-by-theme color (if blur? 60 50) 60)})
|
||||
color-list))
|
||||
[:blue :yellow :purple :turquoise :magenta :sky :orange :army :flamingo :camel :copper])
|
||||
|
||||
(defn- on-change-handler
|
||||
[selected color-name on-change]
|
||||
(reset! selected color-name)
|
||||
(when on-change (on-change color-name)))
|
||||
|
||||
(defn empty-color-item
|
||||
[]
|
||||
[rn/view {:style style/color-button-common}])
|
||||
|
||||
(defn- color-item
|
||||
[{:keys [name
|
||||
color
|
||||
secondary-color
|
||||
selected?
|
||||
on-press
|
||||
blur?]}]
|
||||
(let [border? (and (not blur?) (and secondary-color (not selected?)))]
|
||||
(if (= :no-color name)
|
||||
[empty-color-item]
|
||||
[rn/touchable-opacity
|
||||
{:style (style/color-button color selected?)
|
||||
:accessibility-label :color-picker-item
|
||||
:on-press #(on-press name)}
|
||||
[rn/view
|
||||
{:accessibile true
|
||||
:accessibility-label name
|
||||
:style (style/color-circle color border?)}
|
||||
(when (and secondary-color (not selected?))
|
||||
[rn/view
|
||||
{:style (style/secondary-overlay secondary-color border?)}])
|
||||
(when selected?
|
||||
[icon/icon :i/check
|
||||
{:size 20
|
||||
:color (or secondary-color
|
||||
colors/white)}])]])))
|
||||
|
||||
(defn view
|
||||
"Options
|
||||
- `default-selected?` Default selected color name.
|
||||
- `selected` Selected color name.
|
||||
- `default-selected` Default selected color name.
|
||||
- `on-change` Callback called when a color is selected `(fn [color-name])`.
|
||||
- `blur?` Boolean to enable blur background support.}"
|
||||
[{:keys [default-selected?]}]
|
||||
(let [internal-selected (reagent/atom default-selected?)]
|
||||
(fn [{:keys [blur? on-change selected]}]
|
||||
(when (and (not (nil? selected)) (not= @internal-selected selected))
|
||||
(reset! internal-selected selected))
|
||||
[rn/view {:style style/color-picker-container}
|
||||
(doall (map-indexed (fn [index color]
|
||||
[:<> {:key (color :name)}
|
||||
[color-item
|
||||
(merge color
|
||||
{:selected? (= (color :name) @internal-selected)
|
||||
:on-press #(on-change-handler internal-selected % on-change)
|
||||
:blur? blur?})]
|
||||
(when (= index 5) [rn/view {:style style/flex-break}])])
|
||||
(picker-colors blur?)))])))
|
||||
|
||||
[{:keys [default-selected]}]
|
||||
(let [selected (reagent/atom default-selected)]
|
||||
(fn [{:keys [blur? on-change feng-shui?]}]
|
||||
[rn/scroll-view
|
||||
{:horizontal true
|
||||
:shows-horizontal-scroll-indicator false}
|
||||
(doall (map (fn [color]
|
||||
[color/view
|
||||
{:selected? (= color @selected)
|
||||
:on-press #(on-change-handler selected % on-change)
|
||||
:blur? blur?
|
||||
:key color
|
||||
:color color}])
|
||||
;; TODO: using :feng-shui? temporarily while b & w is being developed.
|
||||
;; https://github.com/status-im/status-mobile/discussions/16676
|
||||
(if feng-shui? (conj color-list :feng-shui) color-list)))])))
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
(defn get-color
|
||||
[type customization-color theme]
|
||||
(case type
|
||||
:default (colors/custom-color customization-color 50)
|
||||
:default (colors/theme-colors (colors/custom-color customization-color 50)
|
||||
(colors/custom-color customization-color 60)
|
||||
theme)
|
||||
:secondary (colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5 theme)
|
||||
:grey (colors/theme-colors colors/neutral-10 colors/neutral-80 theme)
|
||||
:outline (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
(ns quo2.components.dropdowns.dropdown
|
||||
(:require [quo2.components.dropdowns.old-button-view :as old-button]))
|
||||
|
||||
(defn dropdown
|
||||
[_ _]
|
||||
(fn [{:keys [on-change selected] :as opts} children]
|
||||
;TODO: Dropdown needs to be implemented/refactored to be its own component -
|
||||
;https://github.com/status-im/status-mobile/issues/16456
|
||||
[old-button/button
|
||||
(merge
|
||||
opts
|
||||
{:after (if selected :i/chevron-top :i/chevron-down)
|
||||
:icon-size 12
|
||||
:icon-container-size 14
|
||||
:icon-container-rounded? true
|
||||
:override-after-margins {:left 7
|
||||
:right 9}
|
||||
:pressed selected
|
||||
:on-press #(when on-change (on-change selected))})
|
||||
children]))
|
||||
@@ -0,0 +1,35 @@
|
||||
(ns quo2.components.dropdowns.dropdown.component-spec
|
||||
(:require [quo2.components.dropdowns.dropdown.view :as dropdown]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "Dropdown"
|
||||
(h/test "default render"
|
||||
(let [label "Recent"]
|
||||
(h/render [dropdown/view {} label])
|
||||
(h/is-truthy (h/get-by-label-text :dropdown))
|
||||
(h/is-null (h/query-by-label-text :left-icon))
|
||||
(h/is-truthy (h/get-by-text label))
|
||||
(h/is-truthy (h/get-by-label-text :right-icon))))
|
||||
|
||||
(h/test "render with icon"
|
||||
(let [label "Recent"]
|
||||
(h/render [dropdown/view {:icon? 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/is-truthy (h/get-by-label-text :right-icon))))
|
||||
|
||||
(h/test "render only emoji"
|
||||
(let [label "🍑"]
|
||||
(h/render [dropdown/view {:emoji? true} label])
|
||||
(h/is-truthy (h/get-by-label-text :dropdown))
|
||||
(h/is-null (h/query-by-label-text :left-icon))
|
||||
(h/is-truthy (h/get-by-text label))
|
||||
(h/is-null (h/query-by-label-text :right-icon))))
|
||||
|
||||
(h/test "on-press"
|
||||
(let [event (h/mock-fn)
|
||||
label "Recent"]
|
||||
(h/render [dropdown/view {:on-press event} label])
|
||||
(h/fire-event :press (h/get-by-text label))
|
||||
(h/was-called event))))
|
||||
@@ -0,0 +1,120 @@
|
||||
(ns quo2.components.dropdowns.dropdown.properties
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def backgrounds #{:photo :blur})
|
||||
|
||||
(def sizes
|
||||
{:size-40 {:size 40
|
||||
:icon-size 20
|
||||
:emoji-size 20
|
||||
:emoji-padding 10
|
||||
:padding-vertical 9
|
||||
:padding-left {:default 16 :icon 12}
|
||||
:padding-right 12
|
||||
:border-radius 12
|
||||
:text-size :paragraph-1}
|
||||
:size-32 {:size 32
|
||||
:icon-size 20
|
||||
:emoji-size 20
|
||||
:emoji-padding 6
|
||||
:padding-vertical 5
|
||||
:padding-left {:default 12 :icon 8}
|
||||
:padding-right 8
|
||||
:border-radius 10
|
||||
:text-size :paragraph-1}
|
||||
:size-24 {:size 24
|
||||
:icon-size 12
|
||||
:emoji-size 12
|
||||
:emoji-padding 6
|
||||
:padding-vertical 3
|
||||
:padding-left {:default 8 :icon 8}
|
||||
:padding-right 8
|
||||
:border-radius 8
|
||||
:text-size :paragraph-2}})
|
||||
|
||||
(defn- custom-color-type
|
||||
[customization-color]
|
||||
{:left-icon-color colors/white-opa-70
|
||||
:right-icon-color colors/white-opa-20
|
||||
:right-icon-color-2 colors/white
|
||||
:label-color colors/white
|
||||
:background-color (colors/custom-color customization-color 50)})
|
||||
|
||||
(def sizes-to-exclude-blur-in-photo-bg #{:size-40})
|
||||
|
||||
(defn- grey-photo
|
||||
[theme active? size]
|
||||
{:left-icon-color (colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-40 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)
|
||||
:blur-overlay-color (when (and (= theme :dark) (nil? (sizes-to-exclude-blur-in-photo-bg size)))
|
||||
(if active? colors/neutral-80-opa-50 colors/neutral-80-opa-40))
|
||||
:blur-type (if (= theme :light) :light :dark)
|
||||
:background-color (cond
|
||||
(= theme :light)
|
||||
(if active? colors/white-opa-50 colors/white-opa-40)
|
||||
|
||||
(and (= theme :dark) (sizes-to-exclude-blur-in-photo-bg size))
|
||||
(if active? colors/neutral-80-opa-50 colors/neutral-80-opa-40))})
|
||||
|
||||
(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)
|
||||
:background-color (if active?
|
||||
(colors/theme-colors colors/neutral-80-opa-10 colors/white-opa-10 theme)
|
||||
(colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5 theme))})
|
||||
|
||||
(defn- outline-blur
|
||||
[theme active?]
|
||||
{:left-icon-color (colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-40 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-20 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)
|
||||
:background-color (if active?
|
||||
(colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
|
||||
(colors/theme-colors colors/neutral-5 colors/neutral-90 theme))})
|
||||
|
||||
(defn- ghost
|
||||
[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)
|
||||
:background-color (when active?
|
||||
(colors/theme-colors colors/neutral-10 colors/neutral-80 theme))})
|
||||
|
||||
(defn get-colors
|
||||
[{:keys [customization-color theme type state background size]}]
|
||||
(let [active? (= state :active)]
|
||||
(cond
|
||||
(and (= background :photo) (= type :grey)) (grey-photo theme active? size)
|
||||
(and (= background :blur) (= type :grey)) (grey-blur theme active?)
|
||||
(and (= background :blur) (= type :outline)) (outline-blur theme active?)
|
||||
(= type :outline) (outline theme active?)
|
||||
(= type :grey) (grey theme active?)
|
||||
(= type :ghost) (ghost theme active?)
|
||||
(= type :customization) (custom-color-type customization-color))))
|
||||
@@ -0,0 +1,53 @@
|
||||
(ns quo2.components.dropdowns.dropdown.style)
|
||||
|
||||
(def gap 4)
|
||||
|
||||
(def blur-view
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 0})
|
||||
|
||||
(def left-icon
|
||||
{:margin-right gap})
|
||||
|
||||
(defn right-icon
|
||||
[label-color]
|
||||
{:color label-color
|
||||
:margin-right gap})
|
||||
|
||||
(defn- add-styles-for-emoji
|
||||
[style size emoji-padding]
|
||||
(-> style
|
||||
(dissoc :padding-vertical :padding-left :padding-right)
|
||||
(assoc :width size
|
||||
:padding emoji-padding)))
|
||||
|
||||
(defn root-container
|
||||
[{:keys [size border-radius padding-vertical padding-right padding-left emoji-padding]}
|
||||
{:keys [background-color border-color]}
|
||||
{:keys [icon? emoji? state]}]
|
||||
(cond-> {:height size
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:flex-direction :row
|
||||
:padding-vertical padding-vertical
|
||||
:padding-left (:default padding-left)
|
||||
:padding-right padding-right
|
||||
:overflow :hidden
|
||||
:background-color background-color
|
||||
:border-radius border-radius}
|
||||
|
||||
icon?
|
||||
(assoc :padding-left (:icon padding-left))
|
||||
|
||||
emoji?
|
||||
(add-styles-for-emoji size emoji-padding)
|
||||
|
||||
border-color
|
||||
(assoc :border-color border-color
|
||||
:border-width 1)
|
||||
|
||||
(= state :disabled)
|
||||
(assoc :opacity 0.3)))
|
||||
@@ -0,0 +1,87 @@
|
||||
(ns quo2.components.dropdowns.dropdown.view
|
||||
(:require [quo2.components.dropdowns.dropdown.properties :as properties]
|
||||
[quo2.components.dropdowns.dropdown.style :as style]
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.customization-colors :as customization-colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [type size state background customization-color theme on-press icon-name icon? emoji?
|
||||
accessibility-label]
|
||||
:or {type :grey
|
||||
size :size-40
|
||||
state :default
|
||||
icon? false
|
||||
emoji? false
|
||||
icon-name :i/placeholder}
|
||||
:as props}
|
||||
text]
|
||||
(let [{:keys [icon-size text-size emoji-size border-radius]
|
||||
:as size-properties} (properties/sizes size)
|
||||
{:keys [left-icon-color right-icon-color right-icon-color-2 label-color blur-type
|
||||
blur-overlay-color]
|
||||
:as colors} (properties/get-colors props)
|
||||
right-icon (if (= state :active) :i/pullup :i/dropdown)
|
||||
customization-type? (= type :customization)
|
||||
show-blur-background? (and (= background :photo)
|
||||
(= type :grey)
|
||||
(nil? (properties/sizes-to-exclude-blur-in-photo-bg size)))]
|
||||
[rn/pressable
|
||||
{:accessibility-label (or accessibility-label :dropdown)
|
||||
:disabled (= state :disabled)
|
||||
:on-press on-press
|
||||
:style (style/root-container size-properties colors props)}
|
||||
(when show-blur-background?
|
||||
[blur/view
|
||||
{:blur-radius 20
|
||||
:blur-type blur-type
|
||||
:overlay-color blur-overlay-color
|
||||
:style style/blur-view}])
|
||||
(when customization-type?
|
||||
[customization-colors/overlay
|
||||
{:customization-color customization-color
|
||||
:theme theme
|
||||
:pressed? (= state :active)
|
||||
:border-radius border-radius}])
|
||||
(if emoji?
|
||||
[rn/text
|
||||
{:adjusts-font-size-to-fit true
|
||||
:style {:font-size emoji-size}}
|
||||
text]
|
||||
[:<>
|
||||
(when icon?
|
||||
[icon/icon
|
||||
icon-name
|
||||
{:accessibility-label :left-icon
|
||||
:color left-icon-color
|
||||
:size icon-size
|
||||
:container-style style/left-icon}])
|
||||
[text/text
|
||||
{:size text-size
|
||||
:weight :medium
|
||||
:number-of-lines 1
|
||||
:style (style/right-icon label-color)}
|
||||
text]
|
||||
[icon/icon
|
||||
right-icon
|
||||
{:size icon-size
|
||||
:accessibility-label :right-icon
|
||||
:color right-icon-color
|
||||
:color-2 right-icon-color-2}]])]))
|
||||
|
||||
(def view
|
||||
"Props:
|
||||
- type: :outline |:grey (default) | :ghost | :customization
|
||||
- size: :size-40 (default) | :size-32 | :size-24
|
||||
- state: :default (default) | :active | :disabled
|
||||
- emoji?: boolean
|
||||
- icon?: boolean
|
||||
- background: :blur | :photo (optional)
|
||||
- icon-name: keyword
|
||||
- on-press: function
|
||||
|
||||
Child: string - used as label or emoji (for emoji only)"
|
||||
(theme/with-theme view-internal))
|
||||
@@ -4,10 +4,10 @@
|
||||
(defn container-border-color
|
||||
[{:keys [state blur? theme pressed?]}]
|
||||
(let [default-color (if blur?
|
||||
colors/neutral-80-opa-5
|
||||
(colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5 theme)
|
||||
(colors/theme-colors colors/neutral-30 colors/neutral-70 theme))
|
||||
active-color (if blur?
|
||||
colors/neutral-80-opa-10
|
||||
(colors/theme-colors colors/neutral-80-opa-10 colors/white-opa-10 theme)
|
||||
(colors/theme-colors colors/neutral-40 colors/neutral-60 theme))]
|
||||
(condp = state
|
||||
:disabled default-color
|
||||
|
||||
@@ -1,264 +0,0 @@
|
||||
(ns quo2.components.dropdowns.old-button-style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def blur-view
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 0})
|
||||
|
||||
(defn before-icon-style
|
||||
[{:keys [override-margins size icon-container-size icon-background-color icon-container-rounded?
|
||||
icon-size]}]
|
||||
(merge
|
||||
{:margin-left (or (get override-margins :left)
|
||||
(if (= size 40) 12 8))
|
||||
:margin-right (or (get override-margins :right) 4)
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
(when icon-container-size
|
||||
{:width icon-container-size
|
||||
:height icon-container-size})
|
||||
(when icon-background-color
|
||||
{:background-color icon-background-color})
|
||||
(when icon-container-rounded?
|
||||
{:border-radius (/ (or icon-container-size icon-size) 2)})))
|
||||
|
||||
(defn after-icon-style
|
||||
[{:keys [override-margins size icon-container-size icon-background-color icon-container-rounded?
|
||||
icon-size]}]
|
||||
(merge
|
||||
{:margin-left (or (get override-margins :left) 4)
|
||||
:margin-right (or (get override-margins :right)
|
||||
(if (= size 40) 12 8))
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
(when icon-container-size
|
||||
{:width icon-container-size
|
||||
:height icon-container-size})
|
||||
(when icon-background-color
|
||||
{:background-color icon-background-color})
|
||||
(when icon-container-rounded?
|
||||
{:border-radius (/ (or icon-container-size icon-size) 2)})))
|
||||
|
||||
(defn themes
|
||||
[customization-color]
|
||||
{:light
|
||||
{:primary {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-70
|
||||
:label-color colors/white
|
||||
:background-color {:default (colors/custom-color customization-color 50)
|
||||
:pressed (colors/custom-color customization-color 60)
|
||||
:disabled (colors/custom-color customization-color 50)}}
|
||||
:secondary {:icon-color colors/primary-50
|
||||
:label-color colors/primary-50
|
||||
:background-color {:default colors/primary-50-opa-20
|
||||
:pressed colors/primary-50-opa-40
|
||||
:disabled colors/primary-50-opa-20}}
|
||||
:grey {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/neutral-10
|
||||
:pressed colors/neutral-20
|
||||
:disabled colors/neutral-10}}
|
||||
:dark-grey {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/neutral-20
|
||||
:pressed colors/neutral-30
|
||||
:disabled colors/neutral-20}}
|
||||
:outline {:icon-color colors/neutral-50
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:border-color {:default colors/neutral-30
|
||||
:pressed colors/neutral-40
|
||||
:disabled colors/neutral-30}}
|
||||
:ghost {:icon-color colors/neutral-50
|
||||
:icon-secondary-color colors/neutral-50
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:pressed colors/neutral-10}}
|
||||
:danger {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-70
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/danger-50
|
||||
:pressed colors/danger-60
|
||||
:disabled colors/danger-50}}
|
||||
:positive {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-70
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/success-50
|
||||
:pressed colors/success-60
|
||||
:disabled colors/success-50-opa-30}}
|
||||
:photo-bg {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-80-opa-40
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/white-opa-40
|
||||
:pressed colors/white-opa-50
|
||||
:disabled colors/white-opa-40}}
|
||||
:blur-bg {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-80-opa-40
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/neutral-80-opa-5
|
||||
:pressed colors/neutral-80-opa-10
|
||||
:disabled colors/neutral-80-opa-5}}
|
||||
:blurred {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-100
|
||||
:icon-background-color {:default colors/neutral-20
|
||||
:blurred colors/neutral-80-opa-10}
|
||||
:label-color colors/neutral-100
|
||||
:background-color {:default colors/neutral-10
|
||||
:pressed colors/neutral-10
|
||||
:disabled colors/neutral-10-opa-10-blur}
|
||||
:blur-overlay-color colors/neutral-10-opa-40-blur
|
||||
:blur-type :light}
|
||||
:blur-bg-outline {:icon-color colors/neutral-100
|
||||
:icon-secondary-color colors/neutral-80-opa-40
|
||||
:label-color colors/neutral-100
|
||||
:border-color {:default colors/neutral-80-opa-10
|
||||
:pressed colors/neutral-80-opa-20
|
||||
:disabled colors/neutral-80-opa-10}}
|
||||
:shell {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-95
|
||||
:pressed colors/neutral-95
|
||||
:disabled colors/neutral-95}}}
|
||||
:dark
|
||||
{:primary {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-70
|
||||
:label-color colors/white
|
||||
:background-color {:default (colors/custom-color customization-color 60)
|
||||
:pressed (colors/custom-color customization-color 50)
|
||||
:disabled (colors/custom-color customization-color 60)}}
|
||||
:secondary {:icon-color colors/primary-50
|
||||
:label-color colors/primary-50
|
||||
:background-color {:default colors/primary-50-opa-20
|
||||
:pressed colors/primary-50-opa-30
|
||||
:disabled colors/primary-50-opa-20}}
|
||||
:grey {:icon-color colors/white
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-90
|
||||
:pressed colors/neutral-60
|
||||
:disabled colors/neutral-90}}
|
||||
:dark-grey {:icon-color colors/white
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-70
|
||||
:pressed colors/neutral-60
|
||||
:disabled colors/neutral-70}}
|
||||
:outline {:icon-color colors/neutral-40
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:border-color {:default colors/neutral-70
|
||||
:pressed colors/neutral-60
|
||||
:disabled colors/neutral-70}}
|
||||
:ghost {:icon-color colors/neutral-40
|
||||
:icon-secondary-color colors/neutral-40
|
||||
:label-color colors/white
|
||||
:background-color {:pressed colors/neutral-80}}
|
||||
:danger {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-70
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/danger-60
|
||||
:pressed colors/danger-50
|
||||
:disabled colors/danger-60}}
|
||||
:positive {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-70
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/success-60
|
||||
:pressed colors/success-50
|
||||
:disabled colors/success-60-opa-30}}
|
||||
:photo-bg {:icon-color colors/white
|
||||
:icon-secondary-color colors/neutral-30
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-80-opa-40
|
||||
:pressed colors/neutral-80-opa-50
|
||||
:disabled colors/neutral-80-opa-40}}
|
||||
:blur-bg {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-70
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/white-opa-5
|
||||
:pressed colors/white-opa-10
|
||||
:disabled colors/white-opa-5}}
|
||||
:blurred {:icon-color colors/white
|
||||
:icon-secondary-color colors/white
|
||||
:icon-background-color {:default colors/neutral-80
|
||||
:blurred colors/white-opa-10}
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-90
|
||||
:pressed colors/neutral-90
|
||||
:disabled colors/neutral-90-opa-10-blur}
|
||||
:blur-overlay-color colors/neutral-80-opa-40
|
||||
:blur-type :dark}
|
||||
:blur-bg-outline {:icon-color colors/white
|
||||
:icon-secondary-color colors/white-opa-40
|
||||
:label-color colors/white
|
||||
:border-color {:default colors/white-opa-10
|
||||
:pressed colors/white-opa-20
|
||||
:disabled colors/white-opa-5}}
|
||||
:shell {:icon-color colors/white
|
||||
:label-color colors/white
|
||||
:background-color {:default colors/neutral-95}}}})
|
||||
|
||||
(defn shape-style-container
|
||||
[type icon size]
|
||||
{:height size
|
||||
:border-radius (if (and icon (#{:primary :secondary :danger} type))
|
||||
24
|
||||
(case size
|
||||
56 12
|
||||
40 12
|
||||
32 10
|
||||
24 8))})
|
||||
|
||||
(defn style-container
|
||||
[{:keys [type size disabled background-color border-color icon above width before after blur-active?]}]
|
||||
(merge {:height size
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:flex-direction (if above :column :row)
|
||||
:padding-horizontal (when-not (or icon before after)
|
||||
(case size
|
||||
56 16
|
||||
40 16
|
||||
32 12
|
||||
24 8))
|
||||
:padding-left (when-not (or icon before)
|
||||
(case size
|
||||
56 16
|
||||
40 16
|
||||
32 12
|
||||
24 8))
|
||||
:padding-right (when-not (or icon after)
|
||||
(case size
|
||||
56 16
|
||||
40 16
|
||||
32 12
|
||||
24 8))
|
||||
:padding-top (when-not (or icon before after)
|
||||
(case size
|
||||
56 0
|
||||
40 9
|
||||
32 5
|
||||
24 3))
|
||||
:padding-bottom (when-not (or icon before after)
|
||||
(case size
|
||||
56 0
|
||||
40 9
|
||||
32 5
|
||||
24 4))
|
||||
:overflow :hidden}
|
||||
(when (or (and (= type :blurred) (not blur-active?))
|
||||
(not= type :blurred))
|
||||
{:background-color background-color})
|
||||
(shape-style-container type icon size)
|
||||
(when width
|
||||
{:width width})
|
||||
(when icon
|
||||
{:width size})
|
||||
(when border-color
|
||||
{:border-color border-color
|
||||
:border-width 1})
|
||||
(when disabled
|
||||
{:opacity 0.3})))
|
||||
@@ -1,138 +0,0 @@
|
||||
(ns quo2.components.dropdowns.old-button-view
|
||||
(:require [quo2.components.icon :as quo2.icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.blur :as blur]
|
||||
[reagent.core :as reagent]
|
||||
[quo2.components.dropdowns.old-button-style :as style]))
|
||||
|
||||
(defn- button-internal
|
||||
"with label
|
||||
[button opts \"label\"]
|
||||
opts
|
||||
{:type :primary/:secondary/:grey/:dark-grey/:outline/:ghost/
|
||||
:danger/:photo-bg/:blur-bg/:blur-bg-outline/:shell/:community
|
||||
:size 40 [default] /32/24
|
||||
:icon true/false
|
||||
:community-color '#FFFFFF'
|
||||
:community-text-color '#000000'
|
||||
:before :icon-keyword
|
||||
:after :icon-keyword}
|
||||
|
||||
only icon
|
||||
[button {:icon true} :i/close-circle]"
|
||||
[_ _]
|
||||
(let [pressed-in (reagent/atom false)]
|
||||
(fn
|
||||
[{:keys [on-press disabled type size before after above icon-secondary-no-color
|
||||
width customization-color theme override-background-color pressed
|
||||
on-long-press accessibility-label icon icon-no-color style inner-style test-ID
|
||||
blur-active? override-before-margins override-after-margins icon-size icon-container-size
|
||||
icon-container-rounded?]
|
||||
:or {type :primary
|
||||
size 40
|
||||
customization-color :primary
|
||||
blur-active? true}}
|
||||
children]
|
||||
(let [{:keys [icon-color icon-secondary-color background-color label-color border-color blur-type
|
||||
blur-overlay-color icon-background-color]}
|
||||
(get-in (style/themes customization-color)
|
||||
[theme type])
|
||||
state (cond disabled :disabled
|
||||
(or @pressed-in pressed) :pressed
|
||||
:else :default)
|
||||
blur-state (if blur-active? :blurred :default)
|
||||
icon-size (or icon-size (when (= 24 size) 12))
|
||||
icon-secondary-color (or icon-secondary-color icon-color)]
|
||||
[rn/touchable-without-feedback
|
||||
(merge {:test-ID test-ID
|
||||
:disabled disabled
|
||||
:accessibility-label accessibility-label
|
||||
:on-press-in #(reset! pressed-in true)
|
||||
:on-press-out #(reset! pressed-in nil)}
|
||||
(when on-press
|
||||
{:on-press on-press})
|
||||
(when on-long-press
|
||||
{:on-long-press on-long-press}))
|
||||
[rn/view
|
||||
{:style (merge
|
||||
(style/shape-style-container type icon size)
|
||||
{:width width}
|
||||
style)}
|
||||
[rn/view
|
||||
{:style (merge
|
||||
(style/style-container {:type type
|
||||
:size size
|
||||
:disabled disabled
|
||||
:background-color
|
||||
(or override-background-color (get background-color state))
|
||||
:border-color
|
||||
(get border-color state)
|
||||
:icon icon
|
||||
:above above
|
||||
:width width
|
||||
:before before
|
||||
:after after
|
||||
:blur-active? blur-active?})
|
||||
(when (= state :pressed) {:opacity 0.9})
|
||||
inner-style)}
|
||||
(when (and (= type :blurred)
|
||||
blur-active?)
|
||||
[blur/view
|
||||
{:blur-radius 20
|
||||
:blur-type blur-type
|
||||
:overlay-color blur-overlay-color
|
||||
:style style/blur-view}])
|
||||
(when above
|
||||
[rn/view
|
||||
[quo2.icons/icon above
|
||||
{:container-style {:margin-bottom 2}
|
||||
:color icon-secondary-color
|
||||
:size icon-size}]])
|
||||
(when before
|
||||
[rn/view
|
||||
{:style (style/before-icon-style
|
||||
{:override-margins override-before-margins
|
||||
:size size
|
||||
:icon-container-size icon-container-size
|
||||
:icon-background-color (get icon-background-color blur-state)
|
||||
:icon-container-rounded? icon-container-rounded?
|
||||
:icon-size icon-size})}
|
||||
[quo2.icons/icon before
|
||||
{:color icon-secondary-color
|
||||
:size icon-size}]])
|
||||
[rn/view
|
||||
(cond
|
||||
(or icon icon-no-color)
|
||||
[quo2.icons/icon children
|
||||
{:color icon-color
|
||||
:no-color icon-no-color
|
||||
:size icon-size}]
|
||||
|
||||
(string? children)
|
||||
[text/text
|
||||
{:size (when (#{56 24} size) :paragraph-2)
|
||||
:weight :medium
|
||||
:number-of-lines 1
|
||||
:style {:color label-color}}
|
||||
|
||||
children]
|
||||
|
||||
(vector? children)
|
||||
children)]
|
||||
(when after
|
||||
[rn/view
|
||||
{:style (style/after-icon-style
|
||||
{:override-margins override-after-margins
|
||||
:size size
|
||||
:icon-container-size icon-container-size
|
||||
:icon-background-color (get icon-background-color blur-state)
|
||||
:icon-container-rounded? icon-container-rounded?
|
||||
:icon-size icon-size})}
|
||||
[quo2.icons/icon after
|
||||
{:no-color icon-secondary-no-color
|
||||
:color icon-secondary-color
|
||||
:size icon-size}]])]]]))))
|
||||
|
||||
(def button (theme/with-theme button-internal))
|
||||
@@ -21,21 +21,92 @@
|
||||
children))
|
||||
|
||||
(defn- clear-20
|
||||
[{:keys [color color-2] :as props}]
|
||||
(let [color (or color colors/neutral-100)
|
||||
color-2 (or color-2 colors/white)]
|
||||
[container props
|
||||
[svg/path
|
||||
{:d
|
||||
"M3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10C17 13.866 13.866 17 10 17C6.13401 17 3 13.866 3 10Z"
|
||||
:fill color}]
|
||||
[svg/path
|
||||
{:d
|
||||
"M9.15142 9.99998L7.07566 12.0757L7.9242 12.9243L9.99994 10.8485L12.0757 12.9242L12.9242 12.0757L10.8485 9.99998L12.9242 7.92421L12.0757 7.07568L9.99994 9.15145L7.92421 7.07572L7.07568 7.92425L9.15142 9.99998Z"
|
||||
:fill color-2}]]))
|
||||
[{:keys [color color-2]
|
||||
:or {color colors/neutral-100
|
||||
color-2 colors/white}
|
||||
:as props}]
|
||||
[container props
|
||||
[svg/path
|
||||
{:d
|
||||
"M3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10C17 13.866 13.866 17 10 17C6.13401 17 3 13.866 3 10Z"
|
||||
:fill color}]
|
||||
[svg/path
|
||||
{:d
|
||||
"M9.15142 9.99998L7.07566 12.0757L7.9242 12.9243L9.99994 10.8485L12.0757 12.9242L12.9242 12.0757L10.8485 9.99998L12.9242 7.92421L12.0757 7.07568L9.99994 9.15145L7.92421 7.07572L7.07568 7.92425L9.15142 9.99998Z"
|
||||
:fill color-2}]])
|
||||
|
||||
(defn- dropdown-20
|
||||
[{:keys [color color-2]
|
||||
:or {color colors/neutral-100
|
||||
color-2 colors/white}
|
||||
:as props}]
|
||||
[container props
|
||||
[svg/path
|
||||
{:d
|
||||
"M3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10C17 13.866 13.866 17 10 17C6.13401 17 3 13.866 3 10Z"
|
||||
:fill color}]
|
||||
[svg/path
|
||||
{:d
|
||||
"M7 8.5L10 11.5L13 8.5"
|
||||
:stroke color-2
|
||||
:stroke-width 1.2}]])
|
||||
|
||||
(defn- pullup-20
|
||||
[{:keys [color color-2]
|
||||
:or {color colors/neutral-100
|
||||
color-2 colors/white}
|
||||
:as props}]
|
||||
[container props
|
||||
[svg/path
|
||||
{:d
|
||||
"M3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10C17 13.866 13.866 17 10 17C6.13401 17 3 13.866 3 10Z"
|
||||
:fill color}]
|
||||
[svg/path
|
||||
{:d
|
||||
"M7 11.5L10 8.5L13 11.5"
|
||||
:stroke color-2
|
||||
:stroke-width 1.2}]])
|
||||
|
||||
(defn- dropdown-12
|
||||
[{:keys [color color-2]
|
||||
:or {color colors/neutral-100
|
||||
color-2 colors/white}
|
||||
:as props}]
|
||||
[container props
|
||||
[svg/circle
|
||||
{:cx 6
|
||||
:cy 6
|
||||
:r 6
|
||||
:fill color}]
|
||||
[svg/path
|
||||
{:d
|
||||
"M3.5 5L6 7.5L8.5 5"
|
||||
:stroke color-2
|
||||
:stroke-width 1.1}]])
|
||||
|
||||
(defn- pullup-12
|
||||
[{:keys [color color-2]
|
||||
:or {color colors/neutral-100
|
||||
color-2 colors/white}
|
||||
:as props}]
|
||||
[container props
|
||||
[svg/circle
|
||||
{:cx 6
|
||||
:cy 6
|
||||
:r 6
|
||||
:fill color}]
|
||||
[svg/path
|
||||
{:d
|
||||
"M3.5 7L6 4.5L8.5 7"
|
||||
:stroke color-2
|
||||
:stroke-width 1.1}]])
|
||||
|
||||
(def ^:private icons
|
||||
{:i/clear-20 clear-20})
|
||||
{:i/clear-20 clear-20
|
||||
:i/dropdown-20 dropdown-20
|
||||
:i/pullup-20 pullup-20
|
||||
:i/dropdown-12 dropdown-12
|
||||
:i/pullup-12 pullup-12})
|
||||
|
||||
(defn- append-to-keyword
|
||||
[k & xs]
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
(ns quo2.components.list-items.account.component-spec
|
||||
(:require [test-helpers.component :as h]
|
||||
[quo2.components.list-items.account.view :as account]
|
||||
[quo2.foundations.colors :as colors]))
|
||||
|
||||
(h/describe "List items: account"
|
||||
(h/test "default render'"
|
||||
(h/render [account/view])
|
||||
(h/is-truthy (h/query-by-label-text :container)))
|
||||
|
||||
(h/test "on-press-in changes state to :pressed"
|
||||
(h/render [account/view])
|
||||
(h/fire-event :on-press-in (h/get-by-label-text :container))
|
||||
(h/wait-for #(h/has-style (h/query-by-label-text :container)
|
||||
{:backgroundColor (colors/custom-color :blue 50 5)})))
|
||||
|
||||
(h/test "on-press-in changes state to :pressed with blur? enabled"
|
||||
(h/render [account/view {:blur? true}])
|
||||
(h/fire-event :on-press-in (h/get-by-label-text :container))
|
||||
(h/wait-for #(h/has-style (h/query-by-label-text :container)
|
||||
{:backgroundColor colors/white-opa-5})))
|
||||
|
||||
(h/test "on-press-out changes state to :active"
|
||||
(h/render [account/view])
|
||||
(h/fire-event :on-press-in (h/get-by-label-text :container))
|
||||
(h/fire-event :on-press-out (h/get-by-label-text :container))
|
||||
(h/wait-for #(h/has-style (h/query-by-label-text :container)
|
||||
{:backgroundColor (colors/custom-color :blue 50 10)})))
|
||||
|
||||
(h/test "on-press-out changes state to :active with blur? enabled"
|
||||
(h/render [account/view {:blur? true}])
|
||||
(h/fire-event :on-press-in (h/get-by-label-text :container))
|
||||
(h/fire-event :on-press-out (h/get-by-label-text :container))
|
||||
(h/wait-for #(h/has-style (h/query-by-label-text :container)
|
||||
{:backgroundColor colors/white-opa-10})))
|
||||
|
||||
(h/test "on-press-out changes state to :selected"
|
||||
(h/render [account/view {:selectable? true}])
|
||||
(h/fire-event :on-press-in (h/get-by-label-text :container))
|
||||
(h/fire-event :on-press-out (h/get-by-label-text :container))
|
||||
(h/wait-for #(h/is-truthy (h/query-by-label-text :check-icon))))
|
||||
|
||||
(h/test "on-press-out calls on-press"
|
||||
(let [on-press (h/mock-fn)]
|
||||
(h/render [account/view {:on-press on-press}])
|
||||
(h/fire-event :on-press-in (h/get-by-label-text :container))
|
||||
(h/fire-event :on-press-out (h/get-by-label-text :container))
|
||||
(h/was-called on-press)))
|
||||
|
||||
(h/test "renders token props if type :tag"
|
||||
(h/render [account/view {:type :tag}])
|
||||
(h/is-truthy (h/query-by-label-text :tag-container)))
|
||||
|
||||
(h/test "renders keycard icon if title-icon? is true"
|
||||
(h/render [account/view {:title-icon? true}])
|
||||
(h/is-truthy (h/query-by-label-text :keycard-icon)))
|
||||
|
||||
(h/test "doesn't render keycard icon if title-icon? is false"
|
||||
(h/render [account/view])
|
||||
(h/is-falsy (h/query-by-label-text :keycard-icon)))
|
||||
|
||||
(h/test "renders balance container but not arrow icon if type :balance-neutral"
|
||||
(h/render [account/view {:type :balance-neutral}])
|
||||
(h/is-truthy (h/query-by-label-text :balance-container))
|
||||
(h/is-falsy (h/query-by-label-text :arrow-icon)))
|
||||
|
||||
(h/test "renders balance container and negative arrow icon if type :balance-negative"
|
||||
(h/render [account/view {:type :balance-negative}])
|
||||
(h/is-truthy (h/query-by-label-text :balance-container))
|
||||
(h/is-truthy (h/query-by-label-text :icon-negative))
|
||||
(h/is-falsy (h/query-by-label-text :icon-positive)))
|
||||
|
||||
(h/test "renders balance container and positive arrow icon if type :balance-positive"
|
||||
(h/render [account/view {:type :balance-positive}])
|
||||
(h/is-truthy (h/query-by-label-text :balance-container))
|
||||
(h/is-falsy (h/query-by-label-text :icon-negative))
|
||||
(h/is-truthy (h/query-by-label-text :icon-positive)))
|
||||
|
||||
(h/test "renders options button if type :action"
|
||||
(let [on-options-press (h/mock-fn)]
|
||||
(h/render [account/view
|
||||
{:type :action
|
||||
:on-options-press on-options-press}])
|
||||
(h/is-truthy (h/query-by-label-text :options-button))
|
||||
(h/fire-event :on-press (h/get-by-label-text :options-button))
|
||||
(h/was-called on-options-press))))
|
||||
@@ -0,0 +1,110 @@
|
||||
(ns quo2.components.list-items.account.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(defn- background-color
|
||||
[{:keys [state blur? customization-color]}]
|
||||
(cond (or (= state :pressed) (= state :selected))
|
||||
(if blur? colors/white-opa-5 (colors/custom-color customization-color 50 5))
|
||||
(= state :active)
|
||||
(if blur? colors/white-opa-10 (colors/custom-color customization-color 50 10))
|
||||
(and (= state :pressed) blur?) colors/white-opa-10
|
||||
:else :transparent))
|
||||
|
||||
(defn container
|
||||
[props]
|
||||
{:height 56
|
||||
:border-radius 12
|
||||
:background-color (background-color props)
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:padding-horizontal 12
|
||||
:padding-vertical 6
|
||||
:justify-content :space-between})
|
||||
|
||||
(def left-container
|
||||
{:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(defn metric-text
|
||||
[type theme]
|
||||
{:color (case type
|
||||
:balance-positive (colors/theme-colors colors/success-50 colors/success-60 theme)
|
||||
:balance-negative (colors/theme-colors colors/danger-50 colors/danger-60 theme)
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))})
|
||||
|
||||
(defn dot-divider
|
||||
[type theme]
|
||||
{:width 2
|
||||
:height 2
|
||||
:border-radius 2
|
||||
:margin-horizontal 4
|
||||
:background-color (case type
|
||||
:balance-positive (colors/theme-colors colors/success-50-opa-40
|
||||
colors/success-60-opa-40
|
||||
theme)
|
||||
:balance-negative (colors/theme-colors colors/danger-50-opa-40
|
||||
colors/danger-50-opa-40
|
||||
theme)
|
||||
(colors/theme-colors colors/neutral-80-opa-40 colors/neutral-50-opa-40 theme))})
|
||||
|
||||
(defn arrow-icon
|
||||
[type theme]
|
||||
{:size 16
|
||||
:color (if (= type :balance-positive)
|
||||
(colors/theme-colors colors/success-50 colors/success-60 theme)
|
||||
(colors/theme-colors colors/danger-50 colors/danger-60 theme))})
|
||||
|
||||
(def arrow-icon-container
|
||||
{:margin-left 4})
|
||||
|
||||
(def account-container
|
||||
{:margin-left 8})
|
||||
|
||||
(def account-title-container
|
||||
{:flex-direction :row
|
||||
:height 22
|
||||
:align-items :center})
|
||||
|
||||
(defn account-address
|
||||
[blur? theme]
|
||||
{:height 18
|
||||
:color (if blur?
|
||||
colors/white-opa-40
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))})
|
||||
|
||||
(def keycard-icon-container
|
||||
{:margin-left 4})
|
||||
|
||||
(def token-tag-container
|
||||
{:height 40
|
||||
:padding-top 4})
|
||||
|
||||
(defn token-tag-text-container
|
||||
[blur? theme]
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:height 16
|
||||
:padding-horizontal 3
|
||||
:border-width 1
|
||||
:border-radius 6
|
||||
:border-color (if blur?
|
||||
colors/white-opa-10
|
||||
(colors/theme-colors colors/neutral-20
|
||||
colors/neutral-80
|
||||
theme))})
|
||||
|
||||
(defn token-tag-text
|
||||
[blur? theme]
|
||||
{:margin-top -1
|
||||
:color (if blur?
|
||||
colors/white-opa-70
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))})
|
||||
|
||||
(def balance-container
|
||||
{:align-items :flex-end
|
||||
:justify-content :space-between})
|
||||
|
||||
(def metrics-container
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:margin-top 2})
|
||||
@@ -0,0 +1,155 @@
|
||||
(ns quo2.components.list-items.account.view
|
||||
(:require [quo2.components.avatars.account-avatar.view :as account-avatar]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[quo2.components.list-items.account.style :as style]
|
||||
[reagent.core :as reagent]
|
||||
[quo2.components.icon :as icon]))
|
||||
|
||||
(defn- account-view
|
||||
[{:keys [account-props title-icon? blur? theme]
|
||||
:or {title-icon? false}}]
|
||||
[rn/view {:style style/left-container}
|
||||
[account-avatar/view (assoc account-props :size 32)]
|
||||
[rn/view {:style style/account-container}
|
||||
[rn/view
|
||||
{:style style/account-title-container}
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:size :paragraph-1}
|
||||
(:name account-props)]
|
||||
(when title-icon?
|
||||
[rn/view
|
||||
{:style style/keycard-icon-container
|
||||
:accessibility-label :keycard-icon}
|
||||
[icon/icon :i/keycard
|
||||
{:size 20
|
||||
:color (if blur?
|
||||
colors/white-opa-40
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))}]])]
|
||||
[text/text {:size :paragraph-2}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :monospace
|
||||
:style (style/account-address blur? theme)}
|
||||
(:address account-props)]]]])
|
||||
|
||||
(defn- balance-view
|
||||
[{:keys [balance-props type theme]}]
|
||||
[rn/view
|
||||
{:style style/balance-container
|
||||
:accessibility-label :balance-container}
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:size :paragraph-2}
|
||||
(:fiat-value balance-props)]
|
||||
[rn/view
|
||||
{:style style/metrics-container}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style (style/metric-text type theme)}
|
||||
(str (:percentage-change balance-props) "%")]
|
||||
[rn/view {:style (style/dot-divider type theme)}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style (style/metric-text type theme)}
|
||||
(:fiat-change balance-props)]
|
||||
(when (not= type :balance-neutral)
|
||||
[rn/view
|
||||
{:style style/arrow-icon-container
|
||||
:accessibility-label :arrow-icon}
|
||||
[icon/icon (if (= type :balance-positive) :i/positive :i/negative)
|
||||
(assoc (style/arrow-icon type theme)
|
||||
:accessibility-label
|
||||
(if (= type :balance-positive) :icon-positive :icon-negative))]])]])
|
||||
|
||||
(defn- token-tag
|
||||
[{:keys [token-props blur? theme]}]
|
||||
;; TODO: Use Tiny tag component when available (issue #17341)
|
||||
[rn/view
|
||||
{:style (style/token-tag-text-container blur? theme)
|
||||
:accessibility-label :tag-container}
|
||||
[text/text
|
||||
{:size :label
|
||||
:weight :medium
|
||||
:style (style/token-tag-text blur? theme)}
|
||||
(str (:value token-props) " " (:symbol token-props))]])
|
||||
|
||||
(defn- options-button
|
||||
[{:keys [on-options-press blur? theme]}]
|
||||
[rn/pressable
|
||||
{:accessibility-label :options-button
|
||||
:on-press #(when on-options-press
|
||||
(on-options-press))}
|
||||
[icon/icon :i/options
|
||||
{:color (if blur?
|
||||
colors/white-opa-70
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))}]])
|
||||
|
||||
(defn- check-icon
|
||||
[{:keys [blur? customization-color theme]}]
|
||||
[rn/view {:accessibility-label :check-icon}
|
||||
[icon/icon :i/check
|
||||
{:color (if blur?
|
||||
colors/white
|
||||
(colors/theme-colors (colors/custom-color customization-color 50)
|
||||
(colors/custom-color customization-color 60)
|
||||
theme))}]])
|
||||
|
||||
(defn- f-internal-view
|
||||
[]
|
||||
(let [state (reagent/atom :default)
|
||||
active-or-selected? (atom false)
|
||||
timer (atom nil)
|
||||
on-press-in (fn []
|
||||
(when-not (= @state :selected)
|
||||
(reset! timer (js/setTimeout #(reset! state :pressed) 100))))]
|
||||
(fn [{:keys [type selectable? blur? customization-color on-press]
|
||||
:or {customization-color :blue
|
||||
type :default
|
||||
blur? false}
|
||||
:as props}]
|
||||
(let [on-press-out (fn []
|
||||
(let [new-state (if @active-or-selected?
|
||||
:default
|
||||
(if (and (= type :default) selectable?)
|
||||
:selected
|
||||
:active))]
|
||||
(when @timer (js/clearTimeout @timer))
|
||||
(reset! timer nil)
|
||||
(reset! active-or-selected? (or (= new-state :active)
|
||||
(= new-state :selected)))
|
||||
(reset! state new-state)
|
||||
(when on-press
|
||||
(on-press))))]
|
||||
(rn/use-effect
|
||||
#(cond (and selectable? (= type :default) (= @state :active)) (reset! state :selected)
|
||||
(and (not selectable?) (= type :default) (= @state :selected)) (reset! state :active))
|
||||
[selectable?])
|
||||
[rn/pressable
|
||||
{:style (style/container
|
||||
{:state @state :blur? blur? :customization-color customization-color})
|
||||
:on-press-in on-press-in
|
||||
:on-press-out on-press-out
|
||||
:accessibility-label :container}
|
||||
[account-view props]
|
||||
[rn/view {:style (when (= type :tag) style/token-tag-container)}
|
||||
(when (or (= type :balance-neutral)
|
||||
(= type :balance-negative)
|
||||
(= type :balance-positive))
|
||||
[balance-view props])
|
||||
(when (= type :tag)
|
||||
[token-tag props])
|
||||
(when (= type :action)
|
||||
[options-button props])
|
||||
(when (and (= type :default)
|
||||
(= @state :selected))
|
||||
[check-icon props])]]))))
|
||||
|
||||
(defn- internal-view
|
||||
[props]
|
||||
[:f> f-internal-view props])
|
||||
|
||||
(def view (quo.theme/with-theme internal-view))
|
||||
@@ -38,7 +38,7 @@
|
||||
:on-press-in #(reset! pressed? true)
|
||||
:on-press-out #(reset! pressed? false)}
|
||||
[channel-avatar/view
|
||||
{:size :size/l
|
||||
{:size :size-32
|
||||
:locked? locked?
|
||||
:full-name name
|
||||
:customization-color customization-color
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
(ns quo2.components.list-items.saved-address.component-spec
|
||||
(:require [test-helpers.component :as h]
|
||||
[quo2.components.list-items.saved-address.view :as saved-address]
|
||||
[quo2.foundations.colors :as colors]))
|
||||
|
||||
(h/describe "List items: saved address"
|
||||
(h/test "default render"
|
||||
(h/render [saved-address/view])
|
||||
(h/is-truthy (h/query-by-label-text :container)))
|
||||
|
||||
(h/test "on-press-in changes state to :pressed"
|
||||
(h/render [saved-address/view])
|
||||
(h/fire-event :on-press-in (h/get-by-label-text :container))
|
||||
(h/wait-for #(h/has-style (h/query-by-label-text :container)
|
||||
{:backgroundColor (colors/custom-color :blue 50 5)})))
|
||||
|
||||
(h/test "on-press-in changes state to :pressed with blur? enabled"
|
||||
(h/render [saved-address/view {:blur? true}])
|
||||
(h/fire-event :on-press-in (h/get-by-label-text :container))
|
||||
(h/wait-for #(h/has-style (h/query-by-label-text :container)
|
||||
{:backgroundColor colors/white-opa-5})))
|
||||
|
||||
(h/test "on-press-out changes state to :active"
|
||||
(h/render [saved-address/view])
|
||||
(h/fire-event :on-press-in (h/get-by-label-text :container))
|
||||
(h/fire-event :on-press-out (h/get-by-label-text :container))
|
||||
(h/wait-for #(h/has-style (h/query-by-label-text :container)
|
||||
{:backgroundColor (colors/custom-color :blue 50 10)})))
|
||||
|
||||
(h/test "on-press-out changes state to :active with blur? enabled"
|
||||
(h/render [saved-address/view {:blur? true}])
|
||||
(h/fire-event :on-press-in (h/get-by-label-text :container))
|
||||
(h/fire-event :on-press-out (h/get-by-label-text :container))
|
||||
(h/wait-for #(h/has-style (h/query-by-label-text :container)
|
||||
{:backgroundColor colors/white-opa-10})))
|
||||
|
||||
(h/test "on-press-out calls on-press"
|
||||
(let [on-press (h/mock-fn)]
|
||||
(h/render [saved-address/view {:on-press on-press}])
|
||||
(h/fire-event :on-press-in (h/get-by-label-text :container))
|
||||
(h/fire-event :on-press-out (h/get-by-label-text :container))
|
||||
(h/was-called on-press)))
|
||||
|
||||
(h/test "renders options button if type :action"
|
||||
(let [on-options-press (h/mock-fn)]
|
||||
(h/render [saved-address/view
|
||||
{:type :action
|
||||
:on-options-press on-options-press}])
|
||||
(h/is-truthy (h/query-by-label-text :options-button))
|
||||
(h/fire-event :on-press (h/get-by-label-text :options-button))
|
||||
(h/was-called on-options-press))))
|
||||
@@ -0,0 +1,42 @@
|
||||
(ns quo2.components.list-items.saved-address.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(defn- background-color
|
||||
[{:keys [state blur? customization-color]}]
|
||||
(cond (and (or (= state :pressed) (= state :selected)) (not blur?))
|
||||
(colors/custom-color customization-color 50 5)
|
||||
(and (or (= state :pressed) (= state :selected)) blur?)
|
||||
colors/white-opa-5
|
||||
(and (= state :active) (not blur?))
|
||||
(colors/custom-color customization-color 50 10)
|
||||
(and (= state :active) blur?)
|
||||
colors/white-opa-10
|
||||
(and (= state :pressed) blur?) colors/white-opa-10
|
||||
:else :transparent))
|
||||
|
||||
(defn container
|
||||
[props]
|
||||
{:height 56
|
||||
:border-radius 12
|
||||
:background-color (background-color props)
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:padding-horizontal 12
|
||||
:padding-vertical 6
|
||||
:justify-content :space-between})
|
||||
|
||||
(def left-container
|
||||
{:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(def name-text
|
||||
{:height 22})
|
||||
|
||||
(def account-container
|
||||
{:margin-left 8})
|
||||
|
||||
(defn account-address
|
||||
[blur? theme]
|
||||
{:color (if blur?
|
||||
colors/white-opa-40
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))})
|
||||
@@ -0,0 +1,79 @@
|
||||
(ns quo2.components.list-items.saved-address.view
|
||||
(:require [quo2.components.avatars.wallet-user-avatar :as wallet-user-avatar]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[quo2.components.list-items.saved-address.style :as style]
|
||||
[reagent.core :as reagent]
|
||||
[quo2.components.icon :as icon]
|
||||
[clojure.string :as string]))
|
||||
|
||||
(defn- left-container
|
||||
[{:keys [blur? theme name 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
|
||||
: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)}
|
||||
address]]]]))
|
||||
|
||||
(defn- internal-view
|
||||
[]
|
||||
(let [state (reagent/atom :default)
|
||||
active? (atom false)
|
||||
timer (atom nil)
|
||||
on-press-in (fn []
|
||||
(when-not (= @state :selected)
|
||||
(reset! timer (js/setTimeout #(reset! state :pressed) 100))))]
|
||||
(fn [{:keys [blur? user-props customization-color
|
||||
on-press
|
||||
on-options-press
|
||||
theme]
|
||||
:or {customization-color :blue
|
||||
blur? false}}]
|
||||
(let [on-press-out (fn []
|
||||
(let [new-state (if @active? :default :active)]
|
||||
(when @timer (js/clearTimeout @timer))
|
||||
(reset! timer nil)
|
||||
(reset! active? (= new-state :active))
|
||||
(reset! state new-state)
|
||||
(when on-press
|
||||
(on-press))))]
|
||||
[rn/pressable
|
||||
{:style (style/container
|
||||
{:state @state :blur? blur? :customization-color customization-color})
|
||||
:on-press-in on-press-in
|
||||
:on-press-out on-press-out
|
||||
:accessibility-label :container}
|
||||
[left-container
|
||||
{:blur? blur?
|
||||
:theme theme
|
||||
:name (:name user-props)
|
||||
:address (:address user-props)
|
||||
:customization-color (:customization-color user-props)}]
|
||||
[rn/pressable
|
||||
{:accessibility-label :options-button
|
||||
:on-press #(when on-options-press
|
||||
(on-options-press))}
|
||||
[icon/icon :i/options
|
||||
{:color (if blur?
|
||||
colors/white-opa-70
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))}]]]))))
|
||||
|
||||
(def view (quo.theme/with-theme internal-view))
|
||||
@@ -19,12 +19,6 @@
|
||||
:align-items :center
|
||||
:justify-content (if centered? :center :flex-start)})
|
||||
|
||||
(def account-switcher-placeholder
|
||||
{:width 32
|
||||
:height 32
|
||||
:border-radius 10
|
||||
:background-color (colors/custom-color :purple 50)})
|
||||
|
||||
(def right-actions-container
|
||||
{:flex-direction :row})
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
(ns quo2.components.navigation.page-nav.view
|
||||
(:require [quo2.components.avatars.group-avatar.view :as group-avatar]
|
||||
[quo2.components.buttons.button.view :as button]
|
||||
[quo2.components.dropdowns.dropdown :as dropdown]
|
||||
[quo2.components.buttons.button.properties :as button-properties]
|
||||
[quo2.components.dropdowns.dropdown.view :as dropdown]
|
||||
[quo2.components.dropdowns.dropdown.properties :as dropdown-properties]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.navigation.page-nav.style :as style]
|
||||
@@ -28,6 +30,7 @@
|
||||
:icon-only? true
|
||||
:size 32
|
||||
:on-press on-press
|
||||
:background (when (button-properties/backgrounds background) background)
|
||||
:accessibility-label accessibility-label}
|
||||
icon-name])]
|
||||
children))
|
||||
@@ -45,20 +48,28 @@
|
||||
:icon-only? icon-name
|
||||
:size 32
|
||||
:accessible true
|
||||
:background (when (#{:photo :blur} background) background))
|
||||
:background (when (button-properties/backgrounds background) background))
|
||||
(or label icon-name)]))
|
||||
(interpose [right-section-spacing])))
|
||||
|
||||
(defn- account-switcher-content
|
||||
[{:keys [customization-color on-press emoji state]}]
|
||||
[dropdown/view
|
||||
{:type :customization
|
||||
:customization-color customization-color
|
||||
:state (or state :default)
|
||||
:size :size-32
|
||||
:on-press on-press
|
||||
:emoji? true}
|
||||
emoji])
|
||||
|
||||
(defn- right-content
|
||||
[{:keys [background content max-actions min-size? support-account-switcher?]
|
||||
[{:keys [background content max-actions min-size? support-account-switcher? account-switcher]
|
||||
:or {support-account-switcher? true}}]
|
||||
[rn/view (when min-size? {:style style/right-content-min-size})
|
||||
(cond
|
||||
;; TODO: use account-switcher when available (issue #16456)
|
||||
(and support-account-switcher? (= content :account-switcher))
|
||||
[rn/pressable
|
||||
{:style style/account-switcher-placeholder
|
||||
:on-press #(js/alert "Not implemented yet")}]
|
||||
[account-switcher-content account-switcher]
|
||||
|
||||
(coll? content)
|
||||
(into [rn/view {:style style/right-actions-container}]
|
||||
@@ -78,17 +89,19 @@
|
||||
title]])
|
||||
|
||||
(defn- dropdown-center
|
||||
[{:keys [theme background dropdown-on-change dropdown-selected? dropdown-text]}]
|
||||
(let [dropdown-type (cond
|
||||
(= background :photo) :grey
|
||||
(and (= theme :dark) (= background :blur)) :grey
|
||||
:else :ghost)]
|
||||
[{:keys [theme background dropdown-on-press dropdown-selected? dropdown-text]}]
|
||||
(let [dropdown-type (cond
|
||||
(= background :photo) :grey
|
||||
(and (= theme :dark) (= background :blur)) :grey
|
||||
:else :ghost)
|
||||
dropdown-state (if dropdown-selected? :active :default)]
|
||||
[rn/view {:style (style/center-content-container true)}
|
||||
[dropdown/dropdown
|
||||
{:type dropdown-type
|
||||
:size 32
|
||||
:on-change dropdown-on-change
|
||||
:selected dropdown-selected?}
|
||||
[dropdown/view
|
||||
{:type dropdown-type
|
||||
:state dropdown-state
|
||||
:size :size-32
|
||||
:background (when (dropdown-properties/backgrounds background) background)
|
||||
:on-press dropdown-on-press}
|
||||
dropdown-text]]))
|
||||
|
||||
(defn- token-center
|
||||
@@ -157,7 +170,7 @@
|
||||
shown-name]]))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [type right-side background text-align]
|
||||
[{:keys [type right-side background text-align account-switcher]
|
||||
:or {type :no-title
|
||||
text-align :center
|
||||
right-side :none
|
||||
@@ -173,28 +186,29 @@
|
||||
[page-nav-base props
|
||||
[title-center (assoc props :centered? centered?)]
|
||||
[right-content
|
||||
{:background background
|
||||
:content right-side
|
||||
:max-actions (if centered? 1 3)
|
||||
:min-size? centered?}]])
|
||||
{:background background
|
||||
:content right-side
|
||||
:max-actions (if centered? 1 3)
|
||||
:min-size? centered?
|
||||
:account-switcher account-switcher}]])
|
||||
|
||||
:dropdown
|
||||
[page-nav-base props
|
||||
[dropdown-center props]
|
||||
[rn/view {:style style/right-actions-container}
|
||||
(let [{button-icon :icon-name :as button-props} (first right-side)]
|
||||
[button/button
|
||||
(assoc button-props
|
||||
:type (button-type background)
|
||||
:icon-only? true
|
||||
:size 32
|
||||
:accessible true)
|
||||
button-icon])]]
|
||||
[right-content
|
||||
{:background background
|
||||
:content right-side
|
||||
:max-actions 1
|
||||
:support-account-switcher? false}]]
|
||||
|
||||
:token
|
||||
[page-nav-base props
|
||||
[token-center props]
|
||||
[right-content {:background background :content right-side :max-actions 3}]]
|
||||
[right-content
|
||||
{:background background
|
||||
:content right-side
|
||||
:max-actions 3
|
||||
:account-switcher account-switcher}]]
|
||||
|
||||
:channel
|
||||
[page-nav-base props
|
||||
@@ -224,10 +238,11 @@
|
||||
:number-of-lines 1}
|
||||
"NETWORK DROPDOWN"]]
|
||||
[right-content
|
||||
{:background background
|
||||
:content right-side
|
||||
:max-actions 1
|
||||
:min-size? true}]]
|
||||
{:background background
|
||||
:content right-side
|
||||
:max-actions 1
|
||||
:min-size? true
|
||||
:account-switcher account-switcher}]]
|
||||
|
||||
(:community :network)
|
||||
[page-nav-base props
|
||||
@@ -255,12 +270,19 @@
|
||||
:on-press (fn callback [] nil)
|
||||
:accessibility-label \"an optional label\"}
|
||||
|
||||
- account-switcher (optional)
|
||||
- props to render dropdown component (emoji only) e.g.:
|
||||
{:customization-color :purple
|
||||
:on-press (fn [] nil)
|
||||
:state :default (inherit dropdown states)
|
||||
:emoji \"🍑\"}
|
||||
|
||||
Depending on the `type` selected, different properties are accepted:
|
||||
`:title`
|
||||
- title
|
||||
- text-align: `:center` or `:left`
|
||||
`:dropdown`
|
||||
- dropdown-on-change: a callback
|
||||
- dropdown-on-press: a callback
|
||||
- dropdown-selected?: a boolean
|
||||
- dropdown-text
|
||||
`:token`
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
(ns quo2.components.settings.section-label.view
|
||||
(:require
|
||||
[quo2.theme :as quo.theme]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]))
|
||||
|
||||
(defn- get-text-color
|
||||
[theme blur?]
|
||||
(if blur?
|
||||
colors/white-opa-40
|
||||
(colors/theme-colors colors/neutral-50
|
||||
colors/neutral-40
|
||||
theme)))
|
||||
|
||||
(defn label-style
|
||||
[color]
|
||||
{:color color
|
||||
:margin-bottom 2})
|
||||
|
||||
(defn- view-internal
|
||||
"Props:
|
||||
- section - the label of the section
|
||||
- description (optional) - description of the section
|
||||
- blur? (optional) - use blurred styling
|
||||
- theme - light or dark"
|
||||
[{:keys [section description blur? theme]}]
|
||||
(let [color (get-text-color theme (or blur? false))
|
||||
description? (not (nil? description))]
|
||||
[:<>
|
||||
[text/text
|
||||
{:number-of-lines 1
|
||||
:size (if description? :paragraph-1 :paragraph-2)
|
||||
:weight :medium
|
||||
:style (label-style color)}
|
||||
section]
|
||||
(when description?
|
||||
[text/text
|
||||
{:size :paragraph-1
|
||||
:weight :regular
|
||||
:style {:color color}}
|
||||
description])]))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -0,0 +1,18 @@
|
||||
(ns quo2.components.switchers.base-card.component-spec
|
||||
(:require [test-helpers.component :as h]
|
||||
[quo2.components.switchers.base-card.view :as base-card]
|
||||
[quo2.foundations.colors :as colors]))
|
||||
|
||||
(h/describe "Switcher: Base card"
|
||||
(h/test "Default render"
|
||||
(h/render [base-card/base-card {}])
|
||||
(h/is-truthy (h/query-by-label-text :base-card)))
|
||||
(h/test "Banner render"
|
||||
(h/render [base-card/base-card {:banner {:source "banner"}}])
|
||||
(h/is-truthy (h/query-by-label-text :base-card))
|
||||
(h/is-truthy (h/query-by-label-text :banner)))
|
||||
(h/test "Customization color"
|
||||
(h/render [base-card/base-card {:customization-color :blue}])
|
||||
(h/has-style
|
||||
(h/query-by-label-text :base-card)
|
||||
{:backgroundColor (colors/custom-color :blue 50 40)})))
|
||||
@@ -0,0 +1,23 @@
|
||||
(ns quo2.components.switchers.base-card.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(defn base-container
|
||||
[customization-color]
|
||||
{:width 160
|
||||
:height 160
|
||||
:border-radius 16
|
||||
:background-color (colors/custom-color customization-color 50 40)})
|
||||
|
||||
(def thumb-card
|
||||
{:width 160
|
||||
:height 120
|
||||
:border-radius 16
|
||||
:bottom 0
|
||||
:position :absolute
|
||||
:background-color colors/neutral-95
|
||||
:padding 12})
|
||||
|
||||
(def close-button
|
||||
{:position :absolute
|
||||
:right 8
|
||||
:top 8})
|
||||
@@ -0,0 +1,31 @@
|
||||
(ns quo2.components.switchers.base-card.view
|
||||
(:require [quo.react-native :as rn]
|
||||
[quo2.components.buttons.button.view :as button]
|
||||
[quo2.components.switchers.base-card.style :as style]))
|
||||
|
||||
(defn base-card
|
||||
[]
|
||||
(let [card-ref (atom nil)
|
||||
set-ref #(reset! card-ref %)]
|
||||
(fn [{:keys [banner on-press on-close customization-color]} & children]
|
||||
[rn/touchable-opacity
|
||||
{:on-press on-press
|
||||
:ref set-ref
|
||||
:active-opacity 1}
|
||||
[rn/view
|
||||
{:accessibility-label :base-card
|
||||
:style (style/base-container customization-color)}
|
||||
(when banner
|
||||
[rn/image
|
||||
{:accessibility-label :banner
|
||||
:source (:source banner)
|
||||
:style {:width 160}}])
|
||||
[button/button
|
||||
{:size 24
|
||||
:type :grey
|
||||
:icon-only? true
|
||||
:on-press on-close
|
||||
:background :photo
|
||||
:container-style style/close-button}
|
||||
:i/close]
|
||||
(into [rn/view {:style style/thumb-card}] children)]])))
|
||||
@@ -0,0 +1,27 @@
|
||||
(ns quo2.components.switchers.card-content.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(defn content-container
|
||||
[status]
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items (if (= status :mention) :center :flex-end)})
|
||||
|
||||
(def notification-container
|
||||
{:width 20
|
||||
:height 20
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:margin-left 8})
|
||||
|
||||
(def message-text
|
||||
{:color colors/white})
|
||||
|
||||
(def sticker
|
||||
{:width 24
|
||||
:height 24})
|
||||
|
||||
(def gif
|
||||
{:width 24
|
||||
:height 24
|
||||
:border-radius 8})
|
||||
@@ -0,0 +1,98 @@
|
||||
(ns quo2.components.switchers.card-content.view
|
||||
(:require [react-native.core :as rn]
|
||||
[react-native.fast-image :as fast-image]
|
||||
[quo2.components.switchers.card-content.style :as style]
|
||||
[quo2.components.common.notification-dot.view :as notification-dot]
|
||||
[quo2.components.counter.counter.view :as counter]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.list-items.preview-list.view :as preview-list]
|
||||
[quo2.components.tags.context-tag.view :as tag]
|
||||
[quo2.components.code.snippet-preview.view :as snippet-preview]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn content-view
|
||||
[{:keys [type content customization-color]
|
||||
{:keys [text duration photos community-avatar
|
||||
community-name source]} :content}]
|
||||
[rn/view {:style {:max-width 108}}
|
||||
(case type
|
||||
:message
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :regular
|
||||
:number-of-lines 1
|
||||
:ellipsize-mode :tail
|
||||
:style style/message-text}
|
||||
text]
|
||||
|
||||
:photo
|
||||
[preview-list/view
|
||||
{:type :collectibles
|
||||
:more-than-99-label (i18n/label :t/counter-99-plus)
|
||||
:size :size/s-24}
|
||||
photos]
|
||||
|
||||
:sticker
|
||||
[fast-image/fast-image
|
||||
{:accessibility-label :sticker
|
||||
:source source
|
||||
:style style/sticker}]
|
||||
|
||||
:gif
|
||||
[fast-image/fast-image
|
||||
{:accessibility-label :gif
|
||||
:source source
|
||||
:style style/gif}]
|
||||
|
||||
:audio
|
||||
[tag/view
|
||||
{:type :audio
|
||||
:duration duration
|
||||
:customization-color customization-color}]
|
||||
|
||||
:community
|
||||
[tag/view
|
||||
{:type :community
|
||||
:community-name community-name
|
||||
:community-logo community-avatar
|
||||
:size 24}]
|
||||
|
||||
:link
|
||||
[tag/view
|
||||
{:type :icon
|
||||
:icon (:icon content)
|
||||
:context (:text content)
|
||||
:size 24}]
|
||||
|
||||
:code
|
||||
[snippet-preview/view
|
||||
{:language (:language content)}
|
||||
content]
|
||||
|
||||
nil)])
|
||||
|
||||
(defn notification-indicator
|
||||
[{:keys [status mention-count customization-color]}]
|
||||
(when (not= status :read)
|
||||
[rn/view {:style style/notification-container}
|
||||
(case status
|
||||
:unread
|
||||
[notification-dot/view
|
||||
{:customization-color customization-color}]
|
||||
|
||||
:mention
|
||||
[counter/view
|
||||
{:outline false
|
||||
:customization-color customization-color}
|
||||
mention-count]
|
||||
|
||||
nil)]))
|
||||
|
||||
(defn view
|
||||
[type status customization-color content]
|
||||
[rn/view {:style (style/content-container status)}
|
||||
[content-view {:type type :content content :customization-color customization-color}]
|
||||
[notification-indicator
|
||||
{:status status
|
||||
:customization-color customization-color
|
||||
:mention-count (:mention-count content)}]])
|
||||
@@ -0,0 +1,5 @@
|
||||
(ns quo2.components.switchers.card-main-info.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def subtitle
|
||||
{:color colors/neutral-40})
|
||||
@@ -0,0 +1,21 @@
|
||||
(ns quo2.components.switchers.card-main-info.view
|
||||
(:require [quo2.components.markdown.text :as text]
|
||||
[quo2.components.switchers.card-main-info.style :as style]
|
||||
[quo.react-native :as rn]))
|
||||
|
||||
(defn view
|
||||
[{:keys [title subtitle]}]
|
||||
[rn/view
|
||||
[text/text
|
||||
{:accessibility-label :title
|
||||
:size :paragraph-1
|
||||
:weight :semi-bold
|
||||
:number-of-lines 1
|
||||
:ellipsize-mode :tail}
|
||||
title]
|
||||
[text/text
|
||||
{:accessibility-label :subtitle
|
||||
:size :paragraph-2
|
||||
:weight :medium
|
||||
:style style/subtitle}
|
||||
subtitle]])
|
||||
@@ -0,0 +1,116 @@
|
||||
(ns quo2.components.switchers.group-messaging-card.component-spec
|
||||
(:require [test-helpers.component :as h]
|
||||
[quo2.components.switchers.group-messaging-card.view :as group-messaging-card]
|
||||
[quo2.components.switchers.utils :as utils]))
|
||||
|
||||
(def photos-list
|
||||
[{:source (js/require "../resources/images/mock2/photo1.png")}
|
||||
{:source (js/require "../resources/images/mock2/photo2.png")}
|
||||
{:source (js/require "../resources/images/mock2/photo3.png")}
|
||||
{:source (js/require "../resources/images/mock2/photo1.png")}
|
||||
{:source (js/require "../resources/images/mock2/photo2.png")}
|
||||
{:source (js/require "../resources/images/mock2/photo3.png")}])
|
||||
(def sticker {:source (js/require "../resources/images/mock2/sticker.png")})
|
||||
(def gif {:source (js/require "../resources/images/mock2/gif.png")})
|
||||
(def coinbase-community (js/require "../resources/images/mock2/coinbase.png"))
|
||||
(def link-icon (js/require "../resources/images/mock2/status-logo.png"))
|
||||
|
||||
(h/describe "Switcher: Group Messaging Card"
|
||||
(h/test "Default render"
|
||||
(h/render [group-messaging-card/view {}])
|
||||
(h/is-truthy (h/query-by-label-text :base-card)))
|
||||
|
||||
(h/test "Avatar render"
|
||||
(h/render [group-messaging-card/view {:avatar true}])
|
||||
(h/is-truthy (h/query-by-label-text :group-avatar)))
|
||||
|
||||
(h/test "Status: Read, Type: Message, Avatar: true"
|
||||
(h/render [group-messaging-card/view
|
||||
{:avatar true
|
||||
:status :read
|
||||
:type :message
|
||||
:title "Title"
|
||||
:content {:text "Last message"}}])
|
||||
(h/is-truthy (h/get-by-text "Title"))
|
||||
(h/is-truthy (h/get-by-text (utils/subtitle :message nil)))
|
||||
(h/is-truthy (h/get-by-text "Last message")))
|
||||
|
||||
(h/test "Status: Unread, Type: Message, Avatar: true"
|
||||
(h/render [group-messaging-card/view
|
||||
{:avatar true
|
||||
:status :unread
|
||||
:type :message
|
||||
:title "Title"}])
|
||||
(h/is-truthy (h/query-by-label-text :notification-dot)))
|
||||
|
||||
(h/test "Status: Mention, Type: Message, Avatar: true"
|
||||
(h/render [group-messaging-card/view
|
||||
{:avatar true
|
||||
:status :mention
|
||||
:type :message
|
||||
:title "Title"
|
||||
:content {:mention-count 5}}])
|
||||
(h/is-truthy (h/get-by-test-id :counter-component)))
|
||||
|
||||
(h/test "Status: Read, Type: Photo, Avatar: true"
|
||||
(h/render [group-messaging-card/view
|
||||
{:avatar true
|
||||
:status :read
|
||||
:type :photo
|
||||
:title "Title"
|
||||
:content {:photos photos-list}}])
|
||||
(h/is-truthy (h/get-by-text (utils/subtitle :photo {:photos photos-list}))))
|
||||
|
||||
(h/test "Status: Read, Type: Stciker, Avatar: true"
|
||||
(h/render [group-messaging-card/view
|
||||
{:avatar true
|
||||
:status :read
|
||||
:type :sticker
|
||||
:title "Title"
|
||||
:content sticker}])
|
||||
(h/is-truthy (h/get-by-text (utils/subtitle :sticker nil)))
|
||||
(h/is-truthy (h/get-by-label-text :sticker)))
|
||||
|
||||
(h/test "Status: Read, Type: Gif, Avatar: true"
|
||||
(h/render [group-messaging-card/view
|
||||
{:avatar true
|
||||
:status :read
|
||||
:type :gif
|
||||
:title "Title"
|
||||
:content gif}])
|
||||
(h/is-truthy (h/get-by-text (utils/subtitle :gif nil)))
|
||||
(h/is-truthy (h/get-by-label-text :gif)))
|
||||
|
||||
(h/test "Status: Read, Type: Audio, Avatar: true"
|
||||
(h/render [group-messaging-card/view
|
||||
{:avatar true
|
||||
:status :read
|
||||
:type :audio
|
||||
:title "Title"
|
||||
:content {:duration "00:32"}}])
|
||||
(h/is-truthy (h/get-by-text (utils/subtitle :audio nil)))
|
||||
(h/is-truthy (h/get-by-text "00:32")))
|
||||
|
||||
(h/test "Status: Read, Type: Community, Avatar: true"
|
||||
(h/render [group-messaging-card/view
|
||||
{:avatar true
|
||||
:status :read
|
||||
:type :community
|
||||
:title "Title"
|
||||
:content {:community-avatar coinbase-community
|
||||
:community-name "Coinbase"}}])
|
||||
(h/is-truthy (h/get-by-text (utils/subtitle :community nil)))
|
||||
(h/is-truthy (h/get-by-label-text :group-avatar))
|
||||
(h/is-truthy (h/get-by-text "Coinbase")))
|
||||
|
||||
(h/test "Status: Read, Type: Link, Avatar: true"
|
||||
(h/render [group-messaging-card/view
|
||||
{:avatar true
|
||||
:status :read
|
||||
:type :link
|
||||
:title "Title"
|
||||
:content {:icon :placeholder
|
||||
:text "Rolling St..."}}])
|
||||
(h/is-truthy (h/get-by-text (utils/subtitle :link nil)))
|
||||
(h/is-truthy (h/get-by-label-text :group-avatar))
|
||||
(h/is-truthy (h/get-by-text "Rolling St..."))))
|
||||
@@ -0,0 +1,16 @@
|
||||
(ns quo2.components.switchers.group-messaging-card.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def avatar-container
|
||||
{:left 10
|
||||
:top -30
|
||||
:border-radius 48
|
||||
:border-width 2
|
||||
:border-color colors/neutral-95
|
||||
:position :absolute})
|
||||
|
||||
(def content-container
|
||||
{:flex 1
|
||||
:flex-direction :column
|
||||
:justify-content :space-between
|
||||
:margin-top 16})
|
||||
@@ -0,0 +1,32 @@
|
||||
(ns quo2.components.switchers.group-messaging-card.view
|
||||
(:require
|
||||
[react-native.core :as rn]
|
||||
[quo2.components.avatars.group-avatar.view :as group-avatar]
|
||||
[quo2.components.switchers.base-card.view :as base-card]
|
||||
[quo2.components.switchers.card-main-info.view :as card-main-info]
|
||||
[quo2.components.switchers.card-content.view :as card-content]
|
||||
[quo2.components.switchers.group-messaging-card.style :as style]
|
||||
[quo2.components.switchers.utils :as utils]))
|
||||
|
||||
(defn view
|
||||
"Opts:
|
||||
:type - keyword -> :message/:photo/:sticker/:gif/:audio/:community/:link/:code
|
||||
:status - keyword -> :read/:unread/:mention
|
||||
:profile-color -> keyword or hexstring -> :blue/:army/... or #ABCEDF
|
||||
:customization-color -> keyword or hexstring -> :blue/:army/... or #ABCEDF"
|
||||
[{:keys [avatar type status title profile-color customization-color on-close content]
|
||||
:or {profile-color :blue avatar nil}}]
|
||||
[base-card/base-card
|
||||
{:customization-color customization-color
|
||||
:on-close on-close}
|
||||
[rn/view {:style style/avatar-container}
|
||||
[group-avatar/view
|
||||
{:customization-color customization-color
|
||||
:picture avatar
|
||||
:icon-name :i/members
|
||||
:size :size-48}]]
|
||||
[rn/view {:style style/content-container}
|
||||
[card-main-info/view
|
||||
{:title title
|
||||
:subtitle (utils/subtitle type content)}]
|
||||
[card-content/view type status profile-color content]]])
|
||||
@@ -0,0 +1,35 @@
|
||||
(ns quo2.components.switchers.utils
|
||||
(:require [utils.i18n :as i18n]))
|
||||
|
||||
(defn subtitle
|
||||
[type {:keys [photos]}]
|
||||
(case type
|
||||
:message
|
||||
(i18n/label :t/message)
|
||||
|
||||
:photo
|
||||
(i18n/label
|
||||
(if (= (count photos) 1)
|
||||
:t/one-photo
|
||||
:t/n-photos)
|
||||
{:count (count photos)})
|
||||
|
||||
:sticker
|
||||
(i18n/label :t/sticker)
|
||||
|
||||
:gif
|
||||
(i18n/label :t/gif)
|
||||
|
||||
:audio
|
||||
(i18n/label :t/audio-message)
|
||||
|
||||
:community
|
||||
(i18n/label :t/link-to-community)
|
||||
|
||||
:link
|
||||
(i18n/label :t/external-link)
|
||||
|
||||
:code
|
||||
(i18n/label :t/code-snippet)
|
||||
|
||||
""))
|
||||
@@ -7,13 +7,17 @@
|
||||
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-40 theme)
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
|
||||
|
||||
(def audio-tag-icon-container
|
||||
(defn audio-tag-icon-container
|
||||
[customization-color theme]
|
||||
{:width 20
|
||||
:height 20
|
||||
:border-radius 10
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:background-color colors/primary-50})
|
||||
:background-color (colors/theme-colors
|
||||
(colors/custom-color customization-color 50)
|
||||
(colors/custom-color customization-color 60)
|
||||
theme)})
|
||||
|
||||
(def audio-tag-icon-color colors/white)
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
|
||||
:audio
|
||||
[tag-skeleton {:theme theme :text (str duration)}
|
||||
[rn/view {:style style/audio-tag-icon-container}
|
||||
[rn/view {:style (style/audio-tag-icon-container customization-color theme)}
|
||||
[icons/icon :i/play {:color style/audio-tag-icon-color :size 12}]]]
|
||||
|
||||
:group
|
||||
|
||||
@@ -20,11 +20,13 @@
|
||||
{:width 32
|
||||
:height 32})
|
||||
|
||||
(def text-input
|
||||
(defn text-input
|
||||
[theme]
|
||||
(merge typography/heading-1
|
||||
{:font-weight "600"
|
||||
:margin-left 4
|
||||
:margin-left 8
|
||||
:margin-right (if platform/ios? 6 4)
|
||||
:color (colors/theme-colors colors/neutral-100 colors/white theme)
|
||||
:padding 0
|
||||
:text-align :center
|
||||
:height "100%"}))
|
||||
@@ -39,6 +41,6 @@
|
||||
(def data-container
|
||||
{:padding-top 4
|
||||
:padding-horizontal 20
|
||||
:height 28
|
||||
:flex-direction :row
|
||||
:justify-content :space-between})
|
||||
:justify-content :space-between
|
||||
:align-items :center})
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[quo2.foundations.common :as common]
|
||||
[quo2.components.wallet.token-input.style :as style]))
|
||||
[quo2.components.wallet.token-input.style :as style]
|
||||
[quo2.components.tags.network-tags.view :as network-tag]
|
||||
[quo2.components.dividers.divider-line.view :as divider-line]))
|
||||
|
||||
(defn calc-value
|
||||
[crypto? currency token value conversion]
|
||||
@@ -23,7 +25,7 @@
|
||||
value (reagent/atom 0)
|
||||
crypto? (reagent/atom true)
|
||||
input-ref (atom nil)]
|
||||
(fn [{:keys [theme token currency conversion]}]
|
||||
(fn [{:keys [theme token currency conversion networks title customization-color]}]
|
||||
[rn/view {:style (style/main-container width)}
|
||||
[rn/view {:style style/amount-container}
|
||||
[rn/pressable
|
||||
@@ -42,22 +44,26 @@
|
||||
:max-length 12
|
||||
:default-value @value
|
||||
:on-change-text #(reset! value %)
|
||||
:style style/text-input}]
|
||||
:style (style/text-input theme)
|
||||
:selection-color customization-color}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :semi-bold
|
||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
|
||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
|
||||
:margin-right 8
|
||||
:padding-bottom 2}}
|
||||
(string/upper-case (clj->js (if @crypto? token currency)))]]
|
||||
[button/button
|
||||
{:icon true
|
||||
:icon-only? true
|
||||
:size 32
|
||||
:on-press #(swap! crypto? not)
|
||||
:type :outline
|
||||
:accessibility-label :reorder}
|
||||
:i/reorder]]
|
||||
[rn/view {:style (style/divider width theme)}]
|
||||
[divider-line/view {:container-style {:margin-vertical 8}}]
|
||||
[rn/view {:style style/data-container}
|
||||
[text/text "[WIP] NETWORK TAG"]
|
||||
[network-tag/view {:networks networks :title title}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
|
||||
@@ -50,7 +50,8 @@
|
||||
(defn divider
|
||||
[theme]
|
||||
{:height 1
|
||||
:margin-vertical 4
|
||||
:margin-top 4
|
||||
:margin-bottom 3
|
||||
:background-color (colors/theme-colors colors/neutral-10 colors/neutral-80 theme)})
|
||||
|
||||
(defn extra-info-header
|
||||
|
||||
@@ -16,13 +16,6 @@
|
||||
{:flex-direction :row
|
||||
:padding-top 4})
|
||||
|
||||
(def network-dropdown
|
||||
{:border-color colors/neutral-50
|
||||
:border-width 1
|
||||
:border-radius 10
|
||||
:width 68
|
||||
:height 32})
|
||||
|
||||
(defn color-metrics
|
||||
[metrics theme]
|
||||
(if (= metrics :positive)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
(ns quo2.components.wallet.wallet-overview.view
|
||||
(:require [quo2.components.icon :as icons]
|
||||
(:require [quo2.components.dropdowns.network-dropdown.view :as network-dropdown]
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[react-native.core :as rn]
|
||||
[utils.i18n :as i18n]
|
||||
[quo2.components.wallet.wallet-overview.style :as style]
|
||||
[quo2.theme :as quo.theme]))
|
||||
[quo2.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(def ^:private time-frames
|
||||
{:one-week (i18n/label :t/one-week-int)
|
||||
@@ -15,22 +16,13 @@
|
||||
|
||||
(defn- loading-bars
|
||||
[bars theme]
|
||||
(map (fn [{:keys [width height margin]}]
|
||||
[rn/view {:style (style/loading-bar width height margin theme)}])
|
||||
bars))
|
||||
|
||||
;; temporary placeholder for network dropdown component
|
||||
(defn- network-dropdown-temporary
|
||||
[]
|
||||
[:<>
|
||||
[rn/view
|
||||
{:style (merge style/network-dropdown
|
||||
{:justify-content :center
|
||||
:align-items :center})}
|
||||
[text/text "[WIP]"]]])
|
||||
(map-indexed (fn [index {:keys [width height margin]}]
|
||||
^{:key index}
|
||||
[rn/view {:style (style/loading-bar width height margin theme)}])
|
||||
bars))
|
||||
|
||||
(defn- view-info-top
|
||||
[{:keys [state balance theme]}]
|
||||
[{:keys [state balance theme networks dropdown-on-press dropdown-state]}]
|
||||
[rn/view {:style style/container-info-top}
|
||||
(if (= state :loading)
|
||||
(loading-bars [{:width 201 :height 20 :margin 0}] theme)
|
||||
@@ -39,7 +31,11 @@
|
||||
:size :heading-1
|
||||
:style (style/style-text-heading theme)}
|
||||
balance])
|
||||
[network-dropdown-temporary]])
|
||||
[network-dropdown/view
|
||||
{:state (or dropdown-state :default)
|
||||
:blur? true
|
||||
:on-press dropdown-on-press}
|
||||
networks]])
|
||||
|
||||
(defn- view-metrics
|
||||
[{:keys [metrics currency-change percentage-change theme]}]
|
||||
@@ -59,7 +55,7 @@
|
||||
:style {:color (style/color-metrics metrics theme)
|
||||
:margin-right 4}}
|
||||
currency-change]
|
||||
[icons/icon
|
||||
[icon/icon
|
||||
(if (= metrics :positive) :i/positive :i/negative)
|
||||
{:color (style/color-metrics metrics theme)
|
||||
:size 16}]])
|
||||
@@ -90,7 +86,7 @@
|
||||
:size :paragraph-2
|
||||
:style (style/style-text-paragraph theme)}
|
||||
begin-date]
|
||||
[icons/icon :i/positive-right
|
||||
[icon/icon :i/positive-right
|
||||
{:color (style/color-text-paragraph theme)
|
||||
:size 16}]
|
||||
[text/text
|
||||
|
||||
+22
-6
@@ -21,6 +21,7 @@
|
||||
quo2.components.calendar.calendar-year.view
|
||||
quo2.components.code.snippet.view
|
||||
quo2.components.code.snippet-preview.view
|
||||
quo2.components.colors.color.view
|
||||
quo2.components.colors.color-picker.view
|
||||
quo2.components.common.notification-dot.view
|
||||
quo2.components.common.separator.view
|
||||
@@ -43,7 +44,7 @@
|
||||
quo2.components.drawers.drawer-buttons.view
|
||||
quo2.components.drawers.drawer-top.view
|
||||
quo2.components.drawers.permission-context.view
|
||||
quo2.components.dropdowns.dropdown
|
||||
quo2.components.dropdowns.dropdown.view
|
||||
quo2.components.dropdowns.network-dropdown.view
|
||||
quo2.components.empty-state.empty-state.view
|
||||
quo2.components.gradient.gradient-cover.view
|
||||
@@ -63,12 +64,14 @@
|
||||
quo2.components.links.link-preview.view
|
||||
quo2.components.links.url-preview-list.view
|
||||
quo2.components.links.url-preview.view
|
||||
quo2.components.list-items.account.view
|
||||
quo2.components.list-items.account-list-card.view
|
||||
quo2.components.list-items.channel.view
|
||||
quo2.components.list-items.community.view
|
||||
quo2.components.list-items.dapp.view
|
||||
quo2.components.list-items.menu-item
|
||||
quo2.components.list-items.preview-list.view
|
||||
quo2.components.list-items.saved-address.view
|
||||
quo2.components.list-items.token-value.view
|
||||
quo2.components.list-items.user-list
|
||||
quo2.components.loaders.skeleton-list.view
|
||||
@@ -90,6 +93,7 @@
|
||||
quo2.components.numbered-keyboard.numbered-keyboard.view
|
||||
quo2.components.onboarding.small-option-card.view
|
||||
quo2.components.password.tips.view
|
||||
quo2.components.profile.collectible.view
|
||||
quo2.components.profile.profile-card.view
|
||||
quo2.components.profile.select-profile.view
|
||||
quo2.components.profile.showcase-nav.view
|
||||
@@ -106,8 +110,10 @@
|
||||
quo2.components.settings.reorder-item.view
|
||||
quo2.components.settings.settings-item.view
|
||||
quo2.components.settings.category.view
|
||||
quo2.components.settings.section-label.view
|
||||
quo2.components.share.qr-code.view
|
||||
quo2.components.share.share-qr-code.view
|
||||
quo2.components.switchers.group-messaging-card.view
|
||||
quo2.components.tabs.account-selector
|
||||
quo2.components.tabs.segmented-tab
|
||||
quo2.components.tabs.tabs.view
|
||||
@@ -175,7 +181,7 @@
|
||||
|
||||
;;;; Colors
|
||||
(def color-picker quo2.components.colors.color-picker.view/view)
|
||||
(def picker-colors quo2.components.colors.color-picker.view/picker-colors)
|
||||
(def color quo2.components.colors.color.view/view)
|
||||
|
||||
;;;; Community
|
||||
(def community-card-view-item quo2.components.community.community-card-view/view)
|
||||
@@ -210,7 +216,7 @@
|
||||
(def permission-context quo2.components.drawers.permission-context.view/view)
|
||||
|
||||
;;;; Dropdowns
|
||||
(def dropdown quo2.components.dropdowns.dropdown/dropdown)
|
||||
(def dropdown quo2.components.dropdowns.dropdown.view/view)
|
||||
(def network-dropdown quo2.components.dropdowns.network-dropdown.view/view)
|
||||
|
||||
;;;; Empty State
|
||||
@@ -252,6 +258,7 @@
|
||||
(def url-preview-list quo2.components.links.url-preview-list.view/view)
|
||||
|
||||
;;;; List items
|
||||
(def account-item quo2.components.list-items.account.view/view)
|
||||
(def account-list-card quo2.components.list-items.account-list-card.view/view)
|
||||
(def channel quo2.components.list-items.channel.view/view)
|
||||
(def dapp quo2.components.list-items.dapp.view/view)
|
||||
@@ -259,6 +266,7 @@
|
||||
(def preview-list quo2.components.list-items.preview-list.view/view)
|
||||
(def user-list quo2.components.list-items.user-list/user-list)
|
||||
(def community-list-item quo2.components.list-items.community.view/view)
|
||||
(def saved-address quo2.components.list-items.saved-address.view/view)
|
||||
(def token-value quo2.components.list-items.token-value.view/view)
|
||||
|
||||
;;;; Loaders
|
||||
@@ -290,6 +298,7 @@
|
||||
(def tips quo2.components.password.tips.view/view)
|
||||
|
||||
;;;; Profile
|
||||
(def collectible quo2.components.profile.collectible.view/collectible)
|
||||
(def profile-card quo2.components.profile.profile-card.view/profile-card)
|
||||
(def select-profile quo2.components.profile.select-profile.view/view)
|
||||
(def showcase-nav quo2.components.profile.showcase-nav.view/view)
|
||||
@@ -308,19 +317,26 @@
|
||||
(def filter quo2.components.selectors.filter.view/view)
|
||||
(def reactions quo2.components.selectors.reactions.view/view)
|
||||
(def checkbox quo2.components.selectors.selectors.view/checkbox)
|
||||
(def toggle quo2.components.selectors.selectors.view/toggle)
|
||||
(def radio quo2.components.selectors.selectors.view/radio)
|
||||
(def checkbox-prefill quo2.components.selectors.selectors.view/checkbox-prefill)
|
||||
|
||||
;;;; Settings
|
||||
(def privacy-option quo2.components.settings.privacy-option.view/view)
|
||||
(def account quo2.components.settings.accounts.view/account)
|
||||
(def settings-item quo2.components.settings.settings-item.view/view)
|
||||
(def reorder-item quo2.components.settings.reorder-item.view/reorder-item)
|
||||
(def category quo2.components.settings.category.view/category)
|
||||
(def data-item quo2.components.settings.data-item.view/view)
|
||||
(def privacy-option quo2.components.settings.privacy-option.view/view)
|
||||
(def reorder-item quo2.components.settings.reorder-item.view/reorder-item)
|
||||
(def section-label quo2.components.settings.section-label.view/view)
|
||||
(def settings-item quo2.components.settings.settings-item.view/view)
|
||||
|
||||
;;;; Share
|
||||
(def qr-code quo2.components.share.qr-code.view/qr-code)
|
||||
(def share-qr-code quo2.components.share.share-qr-code.view/view)
|
||||
|
||||
;;;; SWITCHER
|
||||
(def group-messaging-card quo2.components.switchers.group-messaging-card.view/view)
|
||||
|
||||
;;;; Tabs
|
||||
(def tabs quo2.components.tabs.tabs.view/view)
|
||||
(def segmented-control quo2.components.tabs.segmented-tab/segmented-control)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
[quo2.components.drawers.drawer-buttons.component-spec]
|
||||
[quo2.components.drawers.drawer-top.component-spec]
|
||||
[quo2.components.drawers.permission-context.component-spec]
|
||||
[quo2.components.dropdowns.dropdown.component-spec]
|
||||
[quo2.components.dropdowns.network-dropdown.component-spec]
|
||||
[quo2.components.gradient.gradient-cover.component-spec]
|
||||
[quo2.components.graph.wallet-graph.component-spec]
|
||||
@@ -37,9 +38,11 @@
|
||||
[quo2.components.links.link-preview.component-spec]
|
||||
[quo2.components.links.url-preview-list.component-spec]
|
||||
[quo2.components.links.url-preview.component-spec]
|
||||
[quo2.components.list-items.account.component-spec]
|
||||
[quo2.components.list-items.channel.component-spec]
|
||||
[quo2.components.list-items.community.component-spec]
|
||||
[quo2.components.list-items.dapp.component-spec]
|
||||
[quo2.components.list-items.saved-address.component-spec]
|
||||
[quo2.components.list-items.token-value.component-spec]
|
||||
[quo2.components.loaders.skeleton-list.component-spec]
|
||||
[quo2.components.markdown.text-component-spec]
|
||||
@@ -62,6 +65,8 @@
|
||||
[quo2.components.settings.category.component-spec]
|
||||
[quo2.components.settings.data-item.component-spec]
|
||||
[quo2.components.share.share-qr-code.component-spec]
|
||||
[quo2.components.switchers.base-card.component-spec]
|
||||
[quo2.components.switchers.group-messaging-card.component-spec]
|
||||
[quo2.components.tags.network-tags.component-spec]
|
||||
[quo2.components.tags.status-tags-component-spec]
|
||||
[quo2.components.wallet.account-card.component-spec]
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
(def neutral-80-opa-20 (alpha neutral-80 0.2))
|
||||
(def neutral-80-opa-30 (alpha neutral-80 0.3))
|
||||
(def neutral-80-opa-40 (alpha neutral-80 0.4))
|
||||
(def neutral-80-opa-50 (alpha neutral-80 0.4))
|
||||
(def neutral-80-opa-50 (alpha neutral-80 0.5))
|
||||
(def neutral-80-opa-60 (alpha neutral-80 0.6))
|
||||
(def neutral-80-opa-70 (alpha neutral-80 0.7))
|
||||
(def neutral-80-opa-80 (alpha neutral-80 0.8))
|
||||
@@ -215,7 +215,7 @@
|
||||
60 "#CC6438"}
|
||||
:army {50 "#216266"
|
||||
60 "#1A4E52"}
|
||||
:pink {50 "#F66F8F"
|
||||
:flamingo {50 "#F66F8F"
|
||||
60 "#C55972"}
|
||||
:purple {50 "#7140FD"
|
||||
60 "#5A33CA"}
|
||||
|
||||
@@ -15,5 +15,5 @@
|
||||
(defn authenticate
|
||||
[{:keys [on-success on-fail reason options]}]
|
||||
(-> (.authenticate ^js touchid reason (clj->js options))
|
||||
(.then #(when on-success (on-success)))
|
||||
(.then #(when on-success (on-success %)))
|
||||
(.catch #(when on-fail (on-fail (aget % "code"))))))
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
[status-im.browser.permissions :as browser.permissions]
|
||||
[status-im.browser.webview-ref :as webview-ref]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[utils.i18n :as i18n]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
@@ -25,7 +24,9 @@
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.security.core :as security]))
|
||||
[utils.security.core :as security]
|
||||
[utils.ethereum.chain :as chain]
|
||||
[utils.address :as address]))
|
||||
|
||||
(rf/defn update-browser-option
|
||||
[{:keys [db]} option-key option-value]
|
||||
@@ -91,7 +92,7 @@
|
||||
host (url/url-host current-url)]
|
||||
(if (and (not resolved-url) (ens/is-valid-eth-name? host))
|
||||
{:db (update db :browser/options assoc :resolving? true)
|
||||
:browser/resolve-ens-contenthash {:chain-id (ethereum/chain-id db)
|
||||
:browser/resolve-ens-contenthash {:chain-id (chain/chain-id db)
|
||||
:ens-name host
|
||||
:cb resolve-ens-contenthash-callback}}
|
||||
{:db (update db :browser/options assoc :url (or resolved-url current-url) :resolving? false)}))))
|
||||
@@ -352,12 +353,19 @@
|
||||
:id (int id)
|
||||
:result result}}})
|
||||
|
||||
(defn utf8-to-hex
|
||||
[s]
|
||||
(let [hex (native-module/utf8-to-hex (str s))]
|
||||
(if (empty? hex)
|
||||
nil
|
||||
hex)))
|
||||
|
||||
(defn normalize-message
|
||||
"NOTE (andrey) there is no spec for this, so this implementation just to be compatible with MM"
|
||||
[message]
|
||||
(if (string/starts-with? message "0x")
|
||||
message
|
||||
(ethereum/utf8-to-hex message)))
|
||||
(utf8-to-hex message)))
|
||||
|
||||
(defn normalize-sign-message-params
|
||||
"NOTE (andrey) we need this function, because params may be mixed up"
|
||||
@@ -365,9 +373,9 @@
|
||||
(let [[first-param second-param] params]
|
||||
(when (and (string? first-param) (string? second-param))
|
||||
(cond
|
||||
(ethereum/address? first-param)
|
||||
(address/address? first-param)
|
||||
[first-param (if typed? second-param (normalize-message second-param))]
|
||||
(ethereum/address? second-param)
|
||||
(address/address? second-param)
|
||||
[second-param (if typed? first-param (normalize-message first-param))]))))
|
||||
|
||||
(rf/defn send-to-bridge
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
;(`wallet_switchEthereumChain`)
|
||||
(ns status-im.browser.eip3326
|
||||
(:require [status-im2.constants :as constants]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ui.screens.browser.eip3326.sheet :as sheet]
|
||||
[utils.re-frame :as rf]))
|
||||
[utils.re-frame :as rf]
|
||||
[utils.ethereum.chain :as chain]))
|
||||
|
||||
(rf/defn deny-permission
|
||||
{:events [:eip3326.ui/dapp-permission-denied]}
|
||||
@@ -20,8 +20,8 @@
|
||||
[{:keys [db] :as cofx} dapp-name id message-id {:keys [chainId] :as params}]
|
||||
(let [target-chain-id (js/parseInt chainId 16)
|
||||
networks (vals (get-in db [:networks/networks]))
|
||||
exist-chain-ids (set (map ethereum/network->chain-id networks))
|
||||
current-chain-id (ethereum/chain-id db)]
|
||||
exist-chain-ids (set (map chain/network->chain-id networks))
|
||||
current-chain-id (chain/chain-id db)]
|
||||
(if (exist-chain-ids target-chain-id)
|
||||
(if (= current-chain-id target-chain-id)
|
||||
{:browser/send-to-bridge {:type constants/web3-send-async-callback
|
||||
@@ -29,10 +29,10 @@
|
||||
:result {:jsonrpc "2.0"
|
||||
:id (int id)
|
||||
:result nil}}}
|
||||
(let [target-network (first (filter #(= (ethereum/network->chain-id %1) target-chain-id)
|
||||
(let [target-network (first (filter #(= (chain/network->chain-id %1) target-chain-id)
|
||||
networks))
|
||||
target-network-id (:id target-network)
|
||||
current-network (ethereum/current-network db)
|
||||
current-network (chain/current-network db)
|
||||
network-from (:name current-network)
|
||||
network-to (:name target-network)
|
||||
params (assoc params
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(ns status-im.commands.core
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[utils.re-frame :as rf]))
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.wallet.utils :as wallet.utils]))
|
||||
|
||||
(rf/defn handle-prepare-accept-request-address-for-transaction
|
||||
{:events [::prepare-accept-request-address-for-transaction]}
|
||||
@@ -9,7 +9,8 @@
|
||||
{:db (assoc db
|
||||
:commands/select-account
|
||||
{:message message
|
||||
:from (ethereum/get-default-account (:profile/wallet-accounts db))})
|
||||
:from (wallet.utils/get-default-account (:profile/wallet-accounts
|
||||
db))})
|
||||
:show-select-acc-sheet nil})
|
||||
|
||||
(rf/defn set-selected-account
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
(:require [clojure.set :as set]
|
||||
[clojure.string :as string]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.utils.gfycat.core :as gfycat]))
|
||||
[status-im.utils.gfycat.core :as gfycat]
|
||||
[utils.address :as address]))
|
||||
|
||||
(defn public-key->new-contact
|
||||
[public-key]
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
(defn- contact-by-address
|
||||
[[addr contact] address]
|
||||
(when (ethereum/address= addr address)
|
||||
(when (address/address= addr address)
|
||||
contact))
|
||||
|
||||
(defn find-contact-by-address
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
(ns status-im.data-store.settings
|
||||
(:require [status-im.data-store.visibility-status-updates :as visibility-status-updates]
|
||||
[status-im.ethereum.eip55 :as eip55]
|
||||
[utils.ethereum.eip.eip55 :as eip55]
|
||||
[status-im2.config :as config]
|
||||
[clojure.set :as set]))
|
||||
|
||||
|
||||
+19
-12
@@ -5,8 +5,7 @@
|
||||
[clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.bottom-sheet.events :as bottom-sheet]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.eip55 :as eip55]
|
||||
[utils.ethereum.eip.eip55 :as eip55]
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im.ethereum.stateofus :as stateofus]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
@@ -15,7 +14,9 @@
|
||||
[status-im.utils.random :as random]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im2.constants :as constants]
|
||||
[taoensso.timbre :as log]))
|
||||
[taoensso.timbre :as log]
|
||||
[utils.ethereum.chain :as chain]
|
||||
[status-im.wallet.utils :as wallet.utils]))
|
||||
|
||||
(defn fullname
|
||||
[custom-domain? username]
|
||||
@@ -102,7 +103,7 @@
|
||||
[{:keys [db] :as cofx} custom-domain? username redirect-to-summary? connected?]
|
||||
(let [name (fullname custom-domain? username)
|
||||
names (get-in db [:ens/names] [])
|
||||
chain-id (ethereum/chain-id db)]
|
||||
chain-id (chain/chain-id db)]
|
||||
(rf/merge cofx
|
||||
(cond-> {:dispatch-n [[:ens/update-usernames [{:username name :chain-id chain-id}]]]}
|
||||
connected? (assoc :json-rpc/call
|
||||
@@ -124,9 +125,9 @@
|
||||
{:events [::set-pub-key]}
|
||||
[{:keys [db]}]
|
||||
(let [{:keys [username address custom-domain?]} (:ens/registration db)
|
||||
address (or address (ethereum/default-address db))
|
||||
address (or address (wallet.utils/default-address db))
|
||||
{:keys [public-key]} (:profile/profile db)
|
||||
chain-id (ethereum/chain-id db)
|
||||
chain-id (chain/chain-id db)
|
||||
username (fullname custom-domain? username)]
|
||||
{:db (assoc-in db [:ens/registration :action] constants/ens-action-type-set-pub-key)
|
||||
:json-rpc/call [{:method "ens_setPubKeyPrepareTx"
|
||||
@@ -192,7 +193,7 @@
|
||||
(let [{:keys [username]}
|
||||
(:ens/registration db)
|
||||
{:keys [public-key]} (:profile/profile db)
|
||||
chain-id (ethereum/chain-id db)]
|
||||
chain-id (chain/chain-id db)]
|
||||
{:db (assoc-in db [:ens/registration :action] constants/ens-action-type-register)
|
||||
:json-rpc/call [{:method "ens_registerPrepareTx"
|
||||
:params [chain-id {:from address} username public-key]
|
||||
@@ -225,6 +226,12 @@
|
||||
:searching)
|
||||
:else :invalid))
|
||||
|
||||
(defn addresses-without-watch
|
||||
[db]
|
||||
(into #{}
|
||||
(remove #(= (:type %) :watch)
|
||||
(map #(eip55/address->checksum (:address %)) (get db :profile/wallet-accounts)))))
|
||||
|
||||
;;NOTE we want to handle only last resolve
|
||||
(def resolve-last-id (atom nil))
|
||||
|
||||
@@ -243,8 +250,8 @@
|
||||
(when (= state :searching)
|
||||
(let [{:profile/keys [profile]} db
|
||||
{:keys [public-key]} profile
|
||||
addresses (ethereum/addresses-without-watch db)
|
||||
chain-id (ethereum/chain-id db)]
|
||||
addresses (addresses-without-watch db)
|
||||
chain-id (chain/chain-id db)]
|
||||
{::resolve-owner [chain-id
|
||||
(fullname custom-domain? username)
|
||||
#(on-resolve-owner
|
||||
@@ -266,8 +273,8 @@
|
||||
;; we reset navigation so that navigate back doesn't return
|
||||
;; into the registration flow
|
||||
(navigation/navigate-back-to :my-profile)
|
||||
(navigation/navigate-to :ens-main {})
|
||||
))
|
||||
(navigation/navigate-to :ens-main {})))
|
||||
|
||||
|
||||
(rf/defn switch-domain-type
|
||||
{:events [::switch-domain-type]}
|
||||
@@ -320,7 +327,7 @@
|
||||
(rf/defn navigate-to-name
|
||||
{:events [::navigate-to-name]}
|
||||
[{:keys [db] :as cofx} username]
|
||||
(let [chain-id (ethereum/chain-id db)]
|
||||
(let [chain-id (chain/chain-id db)]
|
||||
(rf/merge cofx
|
||||
{::get-expiration-time
|
||||
[chain-id
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
(ns status-im.ethereum.contracts
|
||||
(:require [status-im.ethereum.core :as ethereum]))
|
||||
|
||||
(def contracts
|
||||
{:status/snt
|
||||
{:mainnet "0x744d70fdbe2ba4cf95131626614a1763df805b9e"
|
||||
:goerli "0x3D6AFAA395C31FCd391fE3D562E75fe9E8ec7E6a"}
|
||||
:status/stickers
|
||||
{:mainnet "0x0577215622f43a39f4bc9640806dfea9b10d2a36"
|
||||
:goerli "0x07f7CB0C0a4ab3e0999AfE8b3997Da34880f05d0"}
|
||||
:status/sticker-market
|
||||
{:mainnet "0x12824271339304d3a9f7e096e62a2a7e73b4a7e7"
|
||||
:goerli "0xf1E149A7DF70D5Ff1E265daAa738d785D3274717"}
|
||||
:status/sticker-pack
|
||||
{:mainnet "0x110101156e8F0743948B2A61aFcf3994A8Fb172e"
|
||||
:goerli "0x8D3fD2EA24bD53a8Bd2b1026727db8bbe9A8C8Af"}})
|
||||
|
||||
(defn get-address
|
||||
[db contract]
|
||||
(let [chain-keyword (ethereum/chain-keyword db)]
|
||||
(get-in contracts [contract chain-keyword])))
|
||||
@@ -1,202 +0,0 @@
|
||||
(ns status-im.ethereum.core
|
||||
(:require [clojure.string :as string]
|
||||
[status-im.ethereum.eip55 :as eip55]
|
||||
[native-module.core :as native-module]))
|
||||
|
||||
(defn sha3
|
||||
[s]
|
||||
(when s
|
||||
(native-module/sha3 (str s))))
|
||||
|
||||
(defn utf8-to-hex
|
||||
[s]
|
||||
(let [hex (native-module/utf8-to-hex (str s))]
|
||||
(if (empty? hex)
|
||||
nil
|
||||
hex)))
|
||||
|
||||
(defn hex-to-utf8
|
||||
[s]
|
||||
(let [utf8 (native-module/hex-to-utf8 s)]
|
||||
(if (empty? utf8)
|
||||
nil
|
||||
utf8)))
|
||||
|
||||
(def BSC-mainnet-chain-id 56)
|
||||
(def BSC-testnet-chain-id 97)
|
||||
|
||||
;; IDs standardized in https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md#list-of-chain-ids
|
||||
(def chains
|
||||
{:mainnet {:id 1 :name "Mainnet"}
|
||||
:xdai {:id 100 :name "xDai"}
|
||||
:goerli {:id 5 :name "Goerli"}
|
||||
:bsc {:id BSC-mainnet-chain-id
|
||||
:name "BSC"}
|
||||
:bsc-testnet {:id BSC-testnet-chain-id
|
||||
:name "BSC tetnet"}})
|
||||
|
||||
(defn chain-id->chain-keyword
|
||||
[i]
|
||||
(or (some #(when (= i (:id (val %))) (key %)) chains)
|
||||
:custom))
|
||||
|
||||
(defn chain-id->chain-name
|
||||
[i]
|
||||
(or (some #(when (= i (:id (val %))) (:name (val %))) chains)
|
||||
:custom))
|
||||
|
||||
(defn chain-keyword->chain-id
|
||||
[k]
|
||||
(get-in chains [k :id]))
|
||||
|
||||
(defn chain-keyword->snt-symbol
|
||||
[k]
|
||||
(case k
|
||||
:mainnet :SNT
|
||||
:STT))
|
||||
|
||||
(defn testnet?
|
||||
[id]
|
||||
(contains? #{(chain-keyword->chain-id :goerli)
|
||||
(chain-keyword->chain-id :bsc-testnet)}
|
||||
id))
|
||||
|
||||
(defn sidechain?
|
||||
[id]
|
||||
(contains? #{(chain-keyword->chain-id :xdai)
|
||||
(chain-keyword->chain-id :bsc)}
|
||||
id))
|
||||
|
||||
(defn network-with-upstream-rpc?
|
||||
[network]
|
||||
(get-in network [:config :UpstreamConfig :Enabled]))
|
||||
|
||||
(def hex-prefix "0x")
|
||||
|
||||
(defn normalized-hex
|
||||
[hex]
|
||||
(when hex
|
||||
(if (string/starts-with? hex hex-prefix)
|
||||
hex
|
||||
(str hex-prefix hex))))
|
||||
|
||||
(defn current-address
|
||||
[db]
|
||||
(-> (get-in db [:profile/profile :address])
|
||||
normalized-hex))
|
||||
|
||||
(defn get-default-account
|
||||
[accounts]
|
||||
(some #(when (:wallet %) %) accounts))
|
||||
|
||||
(defn default-address
|
||||
[db]
|
||||
(-> (get db :profile/wallet-accounts)
|
||||
get-default-account
|
||||
:address))
|
||||
|
||||
(defn addresses-without-watch
|
||||
[db]
|
||||
(into #{}
|
||||
(remove #(= (:type %) :watch)
|
||||
(map #(eip55/address->checksum (:address %)) (get db :profile/wallet-accounts)))))
|
||||
|
||||
(defn naked-address
|
||||
[s]
|
||||
(when s
|
||||
(string/replace s hex-prefix "")))
|
||||
|
||||
(def public-key-length 128)
|
||||
|
||||
(defn coordinates
|
||||
[public-key]
|
||||
(when-let [hex (naked-address public-key)]
|
||||
(when (= public-key-length (count (subs hex 2)))
|
||||
{:x (normalized-hex (subs hex 2 66))
|
||||
:y (normalized-hex (subs hex 66))})))
|
||||
|
||||
(defn address?
|
||||
[s]
|
||||
(when s
|
||||
(native-module/address? s)))
|
||||
|
||||
(defn network->chain-id
|
||||
[network]
|
||||
(get-in network [:config :NetworkId]))
|
||||
|
||||
(defn network->chain-keyword
|
||||
[network]
|
||||
(chain-id->chain-keyword (network->chain-id network)))
|
||||
|
||||
(defn current-network
|
||||
[db]
|
||||
(let [networks (get db :networks/networks)
|
||||
network-id (get db :networks/current-network)]
|
||||
(get networks network-id)))
|
||||
|
||||
(defn binance-chain-id?
|
||||
[chain-id]
|
||||
(or (= BSC-mainnet-chain-id chain-id)
|
||||
(= BSC-testnet-chain-id chain-id)))
|
||||
|
||||
(defn binance-chain?
|
||||
[db]
|
||||
(-> db
|
||||
current-network
|
||||
network->chain-id
|
||||
binance-chain-id?))
|
||||
|
||||
(def custom-rpc-node-id-len 45)
|
||||
|
||||
(defn custom-rpc-node?
|
||||
[{:keys [id]}]
|
||||
(= custom-rpc-node-id-len (count id)))
|
||||
|
||||
(defn network->network-name
|
||||
[network]
|
||||
(chain-id->chain-name (network->chain-id network)))
|
||||
|
||||
(defn network->chain-name
|
||||
[network]
|
||||
(-> network
|
||||
network->chain-keyword
|
||||
name))
|
||||
|
||||
(defn get-current-network
|
||||
[m]
|
||||
(get (:networks/networks m) (:networks/current-network m)))
|
||||
|
||||
(defn chain-keyword
|
||||
[db]
|
||||
(network->chain-keyword (get-current-network db)))
|
||||
|
||||
(defn chain-id
|
||||
[db]
|
||||
(network->chain-id (get-current-network db)))
|
||||
|
||||
(defn snt-symbol
|
||||
[db]
|
||||
(chain-keyword->snt-symbol (chain-keyword db)))
|
||||
|
||||
(defn address=
|
||||
[address1 address2]
|
||||
(and address1
|
||||
address2
|
||||
(= (string/lower-case (normalized-hex address1))
|
||||
(string/lower-case (normalized-hex address2)))))
|
||||
|
||||
(defn public-key->address
|
||||
[public-key]
|
||||
(let [length (count public-key)
|
||||
normalized-key (case length
|
||||
132 (str "0x" (subs public-key 4))
|
||||
130 public-key
|
||||
128 (str "0x" public-key)
|
||||
nil)]
|
||||
(when normalized-key
|
||||
(subs (sha3 normalized-key) 26))))
|
||||
|
||||
(defn hex->text
|
||||
"Converts a hexstring to UTF8 text."
|
||||
[data]
|
||||
(or (hex-to-utf8 data) data))
|
||||
@@ -1,16 +0,0 @@
|
||||
(ns status-im.ethereum.core-test
|
||||
(:require [cljs.test :refer-macros [deftest is]]
|
||||
[status-im.ethereum.core :as ethereum]))
|
||||
|
||||
(deftest chain-id->chain-keyword
|
||||
(is (= (ethereum/chain-id->chain-keyword 1) :mainnet))
|
||||
(is (= (ethereum/chain-id->chain-keyword 5) :goerli))
|
||||
(is (= (ethereum/chain-id->chain-keyword 5777) :custom)))
|
||||
|
||||
(deftest coordinates
|
||||
(is
|
||||
(=
|
||||
{:x "0x46fa4851f3cccd01e3b8d96c130c00bf812502354939eacf06a68fa519ebcbd1"
|
||||
:y "0xeb08bebe7403856c0d9686210b9b2e324aa0179747bbba56d53f304a002f31c3"}
|
||||
(ethereum/coordinates
|
||||
"0x0446fa4851f3cccd01e3b8d96c130c00bf812502354939eacf06a68fa519ebcbd1eb08bebe7403856c0d9686210b9b2e324aa0179747bbba56d53f304a002f31c3"))))
|
||||
@@ -5,10 +5,11 @@
|
||||
|
||||
e.g. ethereum:0x1234@1/transfer?to=0x5678&value=1e18&gas=5000"
|
||||
(:require [clojure.string :as string]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im.ethereum.tokens :as tokens]
|
||||
[utils.money :as money]))
|
||||
[utils.money :as money]
|
||||
[utils.ethereum.chain :as chain]
|
||||
[utils.address :as address]))
|
||||
|
||||
(def scheme "ethereum")
|
||||
(def scheme-separator ":")
|
||||
@@ -64,16 +65,16 @@
|
||||
Invalid URI will be parsed as `nil`."
|
||||
[s]
|
||||
(when (string? s)
|
||||
(if (ethereum/address? s)
|
||||
(if (address/address? s)
|
||||
{:address s}
|
||||
(let [[_ authority-path query] (re-find uri-pattern s)]
|
||||
(when authority-path
|
||||
(let [[_ raw-address chain-id function-name] (re-find authority-path-pattern authority-path)]
|
||||
(when (or (or (ens/is-valid-eth-name? raw-address) (ethereum/address? raw-address))
|
||||
(when (or (or (ens/is-valid-eth-name? raw-address) (address/address? raw-address))
|
||||
(when (string/starts-with? raw-address "pay-")
|
||||
(let [pay-address (string/replace-first raw-address "pay-" "")]
|
||||
(or (ens/is-valid-eth-name? pay-address)
|
||||
(ethereum/address? pay-address)))))
|
||||
(address/address? pay-address)))))
|
||||
(let [address (if (string/starts-with? raw-address "pay-")
|
||||
(string/replace-first raw-address "pay-" "")
|
||||
raw-address)]
|
||||
@@ -81,12 +82,12 @@
|
||||
(let [contract-address (get-in arguments [:function-arguments :address])]
|
||||
(if-not (or (not contract-address)
|
||||
(or (ens/is-valid-eth-name? contract-address)
|
||||
(ethereum/address? contract-address)))
|
||||
(address/address? contract-address)))
|
||||
nil
|
||||
(merge {:address address
|
||||
:chain-id (if chain-id
|
||||
(js/parseInt chain-id)
|
||||
(ethereum/chain-keyword->chain-id :mainnet))}
|
||||
(chain/chain-keyword->chain-id :mainnet))}
|
||||
arguments))))))))))))
|
||||
|
||||
(defn parse-eth-value
|
||||
@@ -124,12 +125,12 @@
|
||||
"Generate a EIP 681 URI based on `address` and a map (keywords / {bignumbers/strings} ) of extra properties.
|
||||
No validation of address format is performed."
|
||||
[address {:keys [chain-id function-name function-arguments] :as m}]
|
||||
(when (ethereum/address? address)
|
||||
(when (address/address? address)
|
||||
(let [parameters (dissoc (into {} (filter second m)) :chain-id)] ;; filter nil values
|
||||
(str scheme
|
||||
scheme-separator
|
||||
address
|
||||
(when (and chain-id (not= chain-id (ethereum/chain-keyword->chain-id :mainnet)))
|
||||
(when (and chain-id (not= chain-id (chain/chain-keyword->chain-id :mainnet)))
|
||||
;; Add chain-id if specified and is not main-net
|
||||
(str chain-id-separator chain-id))
|
||||
(when-not (empty? parameters)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(ns status-im.ethereum.eip681-test
|
||||
(:require [cljs.test :refer-macros [deftest is] :as test]
|
||||
(:require [cljs.test :refer-macros [deftest is]]
|
||||
[status-im.ethereum.eip681 :as eip681]
|
||||
[utils.money :as money]))
|
||||
|
||||
|
||||
@@ -189,10 +189,6 @@
|
||||
(-> (sanitize-passphrase s)
|
||||
(string/split #" "))))
|
||||
|
||||
(defn words->passphrase
|
||||
[v]
|
||||
(string/join " " v))
|
||||
|
||||
(def valid-word-counts #{12 15 18 21 24})
|
||||
|
||||
(defn valid-word-counts?
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
(ns status-im.ethereum.stateofus
|
||||
(:require [clojure.string :as string]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im2.config :as config]))
|
||||
|
||||
@@ -33,23 +32,9 @@
|
||||
(when config/test-stateofus?
|
||||
{:goerli "0xD1f7416F91E7Eb93dD96A61F12FC092aD6B67B11"})))
|
||||
|
||||
(def registrars-cache (atom {}))
|
||||
|
||||
(defn get-registrar
|
||||
[chain callback]
|
||||
(if-let [contract (get @registrars-cache chain)]
|
||||
(callback contract)
|
||||
(ens/owner
|
||||
(ethereum/chain-keyword->chain-id chain)
|
||||
domain
|
||||
(fn [addr]
|
||||
(let [addr (or addr (get old-registrars chain))]
|
||||
(swap! registrars-cache assoc chain addr)
|
||||
(callback addr))))))
|
||||
|
||||
(defn get-cached-registrar
|
||||
[chain]
|
||||
(get @registrars-cache chain (get old-registrars chain)))
|
||||
(get old-registrars chain))
|
||||
|
||||
(defn lower-case?
|
||||
[s]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(ns status-im.ethereum.subscriptions
|
||||
(:require [status-im.ethereum.eip55 :as eip55]
|
||||
(:require [utils.ethereum.eip.eip55 :as eip55]
|
||||
[status-im.ethereum.transactions.core :as transactions]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.wallet.core :as wallet.core]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
(ns status-im.ethereum.tokens
|
||||
(:require [clojure.string :as string]
|
||||
[status-im.ethereum.core :as ethereum])
|
||||
[utils.ethereum.chain :as chain])
|
||||
(:require-macros [status-im.ethereum.macros :as ethereum.macros :refer [resolve-icons]]))
|
||||
|
||||
(def default-native-currency
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
(defn native-currency
|
||||
[{sym :symbol :as current-network}]
|
||||
(let [chain (ethereum/network->chain-keyword current-network)]
|
||||
(let [chain (chain/network->chain-keyword current-network)]
|
||||
(get all-native-currencies chain (default-native-currency sym))))
|
||||
|
||||
(defn ethereum?
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
(ns status-im.ethereum.transactions.core
|
||||
(:require [cljs.spec.alpha :as spec]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.decode :as decode]
|
||||
[status-im.ethereum.eip55 :as eip55]
|
||||
[utils.ethereum.eip.eip55 :as eip55]
|
||||
[status-im.ethereum.encode :as encode]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.mobile-sync :as utils.mobile-sync]
|
||||
[status-im.wallet.core :as wallet]
|
||||
[status-im2.common.json-rpc.events :as json-rpc]
|
||||
[taoensso.timbre :as log]))
|
||||
[taoensso.timbre :as log]
|
||||
[utils.ethereum.chain :as chain]))
|
||||
|
||||
(def confirmations-count-threshold 12)
|
||||
|
||||
(def etherscan-supported?
|
||||
#{(ethereum/chain-keyword->chain-id :mainnet)
|
||||
(ethereum/chain-keyword->chain-id :goerli)})
|
||||
#{(chain/chain-keyword->chain-id :mainnet)
|
||||
(chain/chain-keyword->chain-id :goerli)})
|
||||
|
||||
(def binance-mainnet-chain-id (ethereum/chain-keyword->chain-id :bsc))
|
||||
(def binance-testnet-chain-id (ethereum/chain-keyword->chain-id :bsc-testnet))
|
||||
(def binance-mainnet-chain-id (chain/chain-keyword->chain-id :bsc))
|
||||
(def binance-testnet-chain-id (chain/chain-keyword->chain-id :bsc-testnet))
|
||||
|
||||
(def network->subdomain {5 "goerli"})
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
[clojure.string :as string]
|
||||
[day8.re-frame.test :as rf-test]
|
||||
[re-frame.core :as rf]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
status-im.events
|
||||
status-im2.events
|
||||
[status-im.multiaccounts.logout.core :as logout]
|
||||
@@ -12,7 +11,8 @@
|
||||
status-im2.navigation.core
|
||||
status-im2.subs.root ; so integration tests can run independently
|
||||
[taoensso.timbre :as log]
|
||||
[status-im2.constants :as constants]))
|
||||
[status-im2.constants :as constants]
|
||||
[native-module.core :as native-module]))
|
||||
|
||||
(def password "testabc")
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
[]
|
||||
(rf/dispatch-sync [:wallet.accounts/start-adding-new-account {:type :generate}])
|
||||
(rf/dispatch-sync [:set-in [:add-account :account :name] account-name])
|
||||
(rf/dispatch [:wallet.accounts/add-new-account (ethereum/sha3 password)]))
|
||||
(rf/dispatch [:wallet.accounts/add-new-account (native-module/sha3 password)]))
|
||||
|
||||
(defn assert-new-account-created
|
||||
[]
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.bottom-sheet.events :as bottom-sheet]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[utils.i18n :as i18n]
|
||||
[status-im.keycard.nfc :as nfc]
|
||||
[status-im.popover.core :as popover]
|
||||
@@ -13,7 +12,8 @@
|
||||
[react-native.platform :as platform]
|
||||
[status-im.utils.deprecated-types :as types]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]))
|
||||
[taoensso.timbre :as log]
|
||||
[utils.address :as address]))
|
||||
|
||||
(def default-pin "000000")
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
(when key-uid
|
||||
(->> (:profile/profiles-overview db)
|
||||
vals
|
||||
(filter #(= (ethereum/normalized-hex key-uid) (:key-uid %)))
|
||||
(filter #(= (address/normalized-hex key-uid) (:key-uid %)))
|
||||
first)))
|
||||
|
||||
(defn get-pairing
|
||||
@@ -354,7 +354,7 @@
|
||||
:puk-retry-counter 5
|
||||
:pin-retry-counter 3)
|
||||
(assoc-in [:keycard :profile/profile]
|
||||
(update account-data :whisper-public-key ethereum/normalized-hex))
|
||||
(update account-data :whisper-public-key address/normalized-hex))
|
||||
(assoc-in [:keycard :flow] nil)
|
||||
(update :profile/login assoc
|
||||
:password encryption-public-key
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
(ns status-im.keycard.login
|
||||
(:require [status-im.bottom-sheet.events :as bottom-sheet]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.keycard.common :as common]
|
||||
status-im.keycard.fx
|
||||
[status-im.keycard.onboarding :as onboarding]
|
||||
@@ -9,7 +8,8 @@
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.deprecated-types :as types]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]))
|
||||
[taoensso.timbre :as log]
|
||||
[utils.address :as address]))
|
||||
|
||||
(rf/defn login-got-it-pressed
|
||||
{:events [:keycard.login.pin.ui/got-it-pressed
|
||||
@@ -162,7 +162,7 @@
|
||||
(assoc-in [:keycard :pin :status] nil)
|
||||
(assoc-in [:keycard :pin :login] [])
|
||||
(assoc-in [:keycard :profile/profile]
|
||||
(update account-data :whisper-public-key ethereum/normalized-hex))
|
||||
(update account-data :whisper-public-key address/normalized-hex))
|
||||
(assoc-in [:keycard :flow] nil)
|
||||
(update :profile/login assoc
|
||||
:password encryption-public-key
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
(:require ["react-native" :as rn]
|
||||
["react-native-status-keycard" :default status-keycard]
|
||||
[clojure.string :as string]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.keycard.keycard :as keycard]
|
||||
[native-module.core :as native-module]
|
||||
[react-native.platform :as platform]
|
||||
[status-im.utils.deprecated-types :as types]
|
||||
[taoensso.timbre :as log]))
|
||||
[taoensso.timbre :as log]
|
||||
[utils.address :as address]))
|
||||
|
||||
(defonce event-emitter
|
||||
(if platform/ios?
|
||||
@@ -114,7 +114,7 @@
|
||||
(then (fn [response]
|
||||
(let [info (-> response
|
||||
(js->clj :keywordize-keys true)
|
||||
(update :key-uid ethereum/normalized-hex))]
|
||||
(update :key-uid address/normalized-hex))]
|
||||
(on-success info))))
|
||||
(catch on-failure)))
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
(then (fn [response]
|
||||
(let [info (-> response
|
||||
(js->clj :keywordize-keys true)
|
||||
(update :key-uid ethereum/normalized-hex))]
|
||||
(update :key-uid address/normalized-hex))]
|
||||
(on-success info))))
|
||||
(catch on-failure)))
|
||||
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.bottom-sheet.events :as bottom-sheet]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.eip55 :as eip55]
|
||||
[utils.ethereum.eip.eip55 :as eip55]
|
||||
[utils.i18n :as i18n]
|
||||
[status-im.keycard.common :as common]
|
||||
status-im.keycard.fx
|
||||
@@ -19,7 +18,8 @@
|
||||
[status-im.utils.deprecated-types :as types]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.security.core :as security]))
|
||||
[utils.security.core :as security]
|
||||
[utils.address :as address]))
|
||||
|
||||
(rf/defn pair*
|
||||
[_ password]
|
||||
@@ -203,7 +203,7 @@
|
||||
:address address
|
||||
:public-key public-key
|
||||
:keycard-instance-uid instance-uid
|
||||
:key-uid (ethereum/normalized-hex key-uid)
|
||||
:key-uid (address/normalized-hex key-uid)
|
||||
:keycard-pairing pairing
|
||||
:keycard-paired-on paired-on
|
||||
:chat-key whisper-private-key}
|
||||
@@ -272,9 +272,9 @@
|
||||
settings {:keycard-instance-uid instance-uid
|
||||
:keycard-paired-on paired-on
|
||||
:keycard-pairing pairing}
|
||||
password (ethereum/sha3 (security/safe-unmask-data (get-in db
|
||||
[:keycard
|
||||
:migration-password])))
|
||||
password (native-module/sha3 (security/safe-unmask-data (get-in db
|
||||
[:keycard
|
||||
:migration-password])))
|
||||
encryption-pass (get-in db [:keycard :profile/profile :encryption-public-key])
|
||||
login-params {:key-uid key-uid
|
||||
:multiaccount-data (types/clj->json account)
|
||||
@@ -316,20 +316,20 @@
|
||||
(assoc-in
|
||||
[:keycard :profile/profile]
|
||||
(-> account-data
|
||||
(update :address ethereum/normalized-hex)
|
||||
(update :whisper-address ethereum/normalized-hex)
|
||||
(update :wallet-address ethereum/normalized-hex)
|
||||
(update :wallet-root-address ethereum/normalized-hex)
|
||||
(update :public-key ethereum/normalized-hex)
|
||||
(update :whisper-public-key ethereum/normalized-hex)
|
||||
(update :wallet-public-key ethereum/normalized-hex)
|
||||
(update :wallet-root-public-key ethereum/normalized-hex)
|
||||
(update :address address/normalized-hex)
|
||||
(update :whisper-address address/normalized-hex)
|
||||
(update :wallet-address address/normalized-hex)
|
||||
(update :wallet-root-address address/normalized-hex)
|
||||
(update :public-key address/normalized-hex)
|
||||
(update :whisper-public-key address/normalized-hex)
|
||||
(update :wallet-public-key address/normalized-hex)
|
||||
(update :wallet-root-public-key address/normalized-hex)
|
||||
(update :instance-uid #(get-in db [:keycard :profile/profile :instance-uid] %))))
|
||||
(assoc-in [:keycard :multiaccount-wallet-address] (:wallet-address account-data))
|
||||
(assoc-in [:keycard :multiaccount-whisper-public-key] (:whisper-public-key account-data))
|
||||
(assoc-in [:keycard :pin :status] nil)
|
||||
(assoc-in [:keycard :application-info :key-uid]
|
||||
(ethereum/normalized-hex (:key-uid account-data)))
|
||||
(address/normalized-hex (:key-uid account-data)))
|
||||
(update :keycard dissoc :recovery-phrase :creating-backup? :converting-account?)
|
||||
(update-in [:keycard :secrets] dissoc :pin :puk :password :mnemonic)
|
||||
(assoc :multiaccounts/new-installation-id (random-guid-generator)))}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user