Compare commits

...
Author SHA1 Message Date
Alexander a428e39711 Merge branch 'develop' into revert-unviewed-message-count-changes 2023-10-05 15:21:17 +02:00
Parvesh Monu c2833ae33d fix wrong counter color in jump-to screen (#17554) 2023-10-05 18:46:25 +05:30
Ibrahem Khalil a7f0566050 Copy update (#17487) 2023-10-05 14:04:08 +03:00
Omar Basem 1812cfb8dc fixes (#17519)
Fix onboarding UI
2023-10-05 08:26:44 +04:00
John Ngei d5a71e2ce0 updated selected item view
* updated selected-item view to match design

* fix show bottom margin on selected item on bottom sheet

* fixed image message dimensions

* fix: selected item view issues

* fix: reviews

* fix: bottom sheet shaking when item is selected
2023-10-05 01:42:53 +03:00
Icaro Motta aa2345d35c Reduce Clojure linter warning noise (#17491)
Change the make "lint" target default behavior to NOT show clj-kondo warnings.

In the CI, I kept the same behavior, i.e. show all warnings and errors
simultaneously.

Motivation:
When devs run make lint, most of the time, they don't want to see a long list of
warnings. Their focus is on the errors. Additionally, the majority of devs in
the mobile team see clj-kondo warnings in their editors of choice already.

We (some of us) believe the editor feedback/warnings are sufficiently noisy.

Add the following somewhere in your config files if you want to see
warnings.

    export CLJ_LINTER_PRINT_WARNINGS=true
2023-10-04 16:06:54 -03:00
Volodymyr Kozieiev b534b33a09 Doc updated with instruction how to view db content (#17535)
* Doc updated with instruction to view db content
2023-10-04 19:29:55 +01:00
omahs 69df5a7e2f fix: typos (#17484) 2023-10-04 16:54:32 +02:00
alwx 430ec7dd9f Revert unviewed message count changes 2023-10-04 15:34:33 +02:00
Omar Basem 191f5de6f1 Wallet: Create Account UI (2) (#17468)
* Wallet: create account UI (2)
2023-10-04 14:17:55 +04:00
Omar Basem df2b5147cd Wallet: Add address to watch (#17479)
wallet: add address to watch
2023-10-04 14:04:33 +04:00
Parvesh Monu 4235c71b2f Remove options to create community from mobile from release and nightly builds (#17495) 2023-10-04 15:12:16 +05:30
Mohamed Javid aef2f2cfed Implement wallet-networks type to the page-nav component (#17485)
This commit adds the wallet-networks type to the page-nav component.

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2023-10-04 14:18:34 +05:30
BalogunofAfrica f065aa1c05 fix(identifier): emoji hash line height (#17386) 2023-10-04 08:44:44 +01:00
Vitaliy Vlasov fbe30d7b18 Update status-go to v0.167.6
https://github.com/status-im/status-go/compare/b3213172...e1354016
Signed-off-by: Vitaliy Vlasov <siphiuel@protonmail.com>
2023-10-04 01:16:25 +03:00
Brian Sztamfater 878a1cc285 feat: implement saved contact address list item component (#17400)
Signed-off-by: Brian Sztamfater <brian@status.im>
2023-10-03 15:51:11 -03:00
Mohsen 26ae434d07 [#17396] fix: Mention is displayed as public key in PNs (#17461) 2023-10-03 19:53:33 +03:00
Ibrahem Khalil 26a702799c [16845] Wrong buttons background color on community home screen's page nav (#17003) 2023-10-03 19:37:11 +03:00
Ibrahem Khalil f5038f8e24 Only count images in an album in photo selector (#17459) 2023-10-03 19:00:51 +03:00
Tetiana Churikova 5b765f873b e2e: small alignments (#17477) 2023-10-03 14:53:57 +02:00
Jinho Jang a13d3a175b Update ja.json (#17438) 2023-10-03 14:11:42 +02:00
Lungu Cristian dfc972079f fix: show hashtag in chat when replying/copying (#17374) 2023-10-03 11:55:22 +03:00
Lungu Cristian 1286188005 fix: show links inside activity-center mention (#17424) 2023-10-03 11:17:32 +03:00
Volodymyr Kozieiev 9fb37d3a48 Collection avatar component (#17462)
* Collection avatar component
2023-10-02 21:46:47 +01:00
Mohsen ee85d6d596 [#17288] refactor: migrate previews to new api (#17470) 2023-10-02 16:28:35 +03:00
Omar Basem d8d8a6c7a0 Quo2: Token Input followup (#17419)
* Quo2: token input followup
2023-10-02 09:01:39 +04:00
jakub f5f1e6302d ci: use new OpenSea API keys
They are split by both platform and build type.

Depends on:
https://github.com/status-im/status-jenkins-lib/pull/74

Signed-off-by: Jakub Sokołowski <jakub@status.im>
2023-09-29 16:32:45 +02:00
Mohamed Javid 9c26a54006 Add network-dropdown to wallet-overview component (#17440)
This commit adds the "network-dropdown" component to the "wallet-overview" component.

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2023-09-29 18:53:06 +05:30
codemaster ab868a6ae5 Implement switcher group messaging card (#16802) 2023-09-29 23:11:21 +10:00
Parvesh Monu 695bbcbe81 fix bottom tabs unread badge for group chats (#17454) 2023-09-29 17:59:35 +05:30
Mohamed Javid bf76ca167a Implement dropdown component and update it's usage across the codebase (#17412)
This commit: 

- Removes the existing dropdown component which uses the old button component under the hood
- Implements the Dropdown component
- Updates the usage in the page-nav component for types dropdown, token and wallet-networks
- Updates the usage in the photo selector bottom sheet
- Updates the usage in the Quo2 preview main screen

---------

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2023-09-29 17:37:27 +05:30
Ulises Manuel af1942dff3 [#17220] - New 64 avatars size (#17283)
* Add 64 size for user-avatar

* Add 64 size for channel-avatar

* Add 64 size for account-avatar

* Add 64 size for wallet-avatar
2023-09-29 03:48:02 -06:00
yqrashawn 1c31127a6f fix: missing/empty user-avatar in component previews (#17430) 2023-09-29 15:30:04 +08:00
Ajay Sivan fe404ab005 Remove old quo code from status_im2 namespace (#17404) 2023-09-28 09:27:31 -07:00
Brian Sztamfater 8869271054 feat: implement account list item component (#17303)
Signed-off-by: Brian Sztamfater <brian@status.im>
2023-09-28 12:27:36 -03:00
Brian Sztamfater 5ea78084d1 feat: implement saved address component (#17398)
Signed-off-by: Brian Sztamfater <brian@status.im>
2023-09-28 12:13:49 -03:00
Mohsen ba57ab9ae4 [#17288] refactor: migrate previews to new api (#17420) 2023-09-28 15:26:15 +03:00
0522120c66 Standardized in-app authentication (#16916)
* chore: move password input to connected component
---------

Co-authored-by: Jamie Caprani <jamiecaprani@gmail.com>
Co-authored-by: frank <lovefree103@gmail.com>
2023-09-28 04:23:15 -07:00
Parvesh Monu 6b9b5fa300 Only use animated loading skeleton for ios (#17432) 2023-09-27 20:43:21 +05:30
Omar Basem 77733b3a65 Quo2: Color picker (#17405)
* Quo2: color picker
2023-09-27 15:34:16 +04:00
Volodymyr Kozieiev 79f7b6c6ba Transaction summary design followup fixes (#17360) 2023-09-27 11:54:41 +01:00
flexsurfer db787f9d4b remove status-im.utils.clocks (#17434) 2023-09-27 12:04:40 +02:00
flexsurfer a847f508f9 [#17410] migrate status-im.ethereum.core (#17422) 2023-09-27 11:57:51 +02:00
Lungu Cristian 4152b9318b Quo2: section label (#17219)
* feat: added section-label to quo2

* fix: addressed review comments

* ref: reorder and small change

* fix: blur only for dark and adjusted styling
2023-09-27 12:07:10 +03:00
272 changed files with 4586 additions and 2475 deletions
-5
View File
@@ -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
+1
View File
@@ -33,3 +33,4 @@ SWAP_ENABLED=1
STICKERS_TEST_ENABLED=1
LOCAL_PAIRING_ENABLED=1
TEST_STATEOFUS=1
FAST_CREATE_COMMUNITY_ENABLED=1
+1
View File
@@ -19,3 +19,4 @@ ENABLE_ROOT_ALERT=1
MAX_IMAGES_BATCH=1
DELETE_MESSAGE_ENABLED=1
COLLECTIBLES_ENABLED=1
FAST_CREATE_COMMUNITY_ENABLED=0
+3 -1
View File
@@ -309,9 +309,11 @@ $$(comm -23 <(sort <(git ls-files --cached --others --exclude-standard)) <(sort
endef
lint: export TARGET := clojure
lint: export CLJ_LINTER_PRINT_WARNINGS ?= false
lint: ##@test Run code style checks
@sh scripts/lint-re-frame-in-quo-components.sh && \
clj-kondo --config .clj-kondo/config.edn --cache false --fail-level error --lint src && \
sh scripts/lint-old-quo-usage.sh && \
clj-kondo --config .clj-kondo/config.edn --cache false --fail-level error --lint src $(if $(filter $(CLJ_LINTER_PRINT_WARNINGS),true),,| grep -v ': warning: ') && \
ALL_CLOJURE_FILES=$(call find_all_clojure_files) && \
zprint '{:search-config? true}' -sfc $$ALL_CLOJURE_FILES && \
sh scripts/lint-trailing-newline.sh && \
+1 -1
View File
@@ -16,7 +16,7 @@ We believe in a medium of pure free trade, economies with fair, permission-less
We want to take responsibility for our data, the way we conduct ourselves privately and promote this way of life to a mass audience.
We want deep insights into our own economies so we can make informed, data-driven decisions on how to make our lives better. The Ethereum blockchain, Smart Contracts, Swarm and Whisper provides us a path forward.
We want deep insights into our own economies so we can make informed, data-driven decisions on how to make our lives better. The Ethereum blockchain, Smart Contracts, Swarm and Whisper provide us a path forward.
If this interests you, **help us make Status a reality** - anyone can contribute and we need everyone at any skill level to participate.
+1 -1
View File
@@ -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 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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()
+2 -2
View File
@@ -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()
@@ -48,7 +48,7 @@ pipeline {
steps {
sh """#!/bin/bash
set -eo pipefail
make lint 2>&1 | tee ${LOG_FILE}
make lint CLJ_LINTER_PRINT_WARNINGS=true 2>&1 | tee ${LOG_FILE}
"""
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.14'
library 'status-jenkins-lib@v1.7.15'
pipeline {
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.14'
library 'status-jenkins-lib@v1.7.15'
pipeline {
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.14'
library 'status-jenkins-lib@v1.7.15'
pipeline {
+1 -1
View File
@@ -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 -1
View File
@@ -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 -1
View File
@@ -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
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.7.14'
library 'status-jenkins-lib@v1.7.15'
pipeline {
agent {
+37
View File
@@ -45,6 +45,42 @@ To do this:
![geth.log path](images/debugging/geth-path.png)
## Inspecting database content
Encrypted database can be found using commands:
```
cd ~/Library/Developer/CoreSimulator/Devices
find ./ -name accounts.sql
```
To get unencrypted database you need to export it first:
- open the status app in simulator
- on login screen enter the correct password without logging in
- using repl execute statement to export db:
```
(re-frame.core/dispatch [:multiaccounts.login.ui/export-db-submitted])
```
- save generated `export.db` file
Now you can locate the `export.db` and open it with preferred db viewer.
**Android:**
```sh
adb root
adb pull /storage/emulated/0/Android/data/im.status.ethereum.debug/files/Download/export.db /path/to/store/export.db
```
If you're using a release build, change the path to `/storage/emulated/0/Android/data/im.status.ethereum/files/Download`
**iOS**
```
cd ~/Library/Developer/CoreSimulator/Devices
find ./ -name export.db
```
## Tips
### From @ilmotta:
@@ -62,3 +98,4 @@ Also to inspect logs in a more flexible manner, instead of the strict output fro
```
adb logcat | grep 'ReactNativeJS\|StatusModule\|GoLog'
```
+1 -1
View File
@@ -12,4 +12,4 @@
[vector-icons/icon :icon-name {:color ...}]
```
2x@2x
4. If you want paltform specific icon use `.android` or `.ios` suffixes. Example `icon_name@2x.android.png`.:w
4. If you want platform specific icon use `.android` or `.ios` suffixes. Example `icon_name@2x.android.png`.:w
+3 -3
View File
@@ -19,7 +19,7 @@ For now we support e2e for Android only.
## What's happening when any e2e job is running
Whenever we need to push set of test scripts we create 16 parallel sessions (max, but depending on amount of cases that are included in job) and each thread: 1) uploads Android .apk file to SauceLabs -> 2) runs through the test steps -> 3) receives results whether test failed on particular step or succeeded with no errors -> 3) Parse test results and push them as a Github comment (if the suite ran against respective PR) and into TestRail.
We push **whole automation test suite (currently 155, amout is changing)** against each nightly build (if the nightly builds job succeeded). Results of the test run are saved in TestRail.
We push **whole automation test suite (currently 155, amount is changing)** against each nightly build (if the nightly builds job succeeded). Results of the test run are saved in TestRail.
And also we push set of autotests whenever PR with successful builds got moved in to `E2E Tests` column from [Pipeline for QA dashboard ](https://github.com/status-im/status-react/projects/7).
In that case we save results in TestRail as well and push a comment with test results in a respective PR.
@@ -49,8 +49,8 @@ Params to specify:
- apk: [url_to_apk_build_here]
- pr_id: pull request number (e.g. 1234)
- branch: branch name from which the test are taken (in most of cases `develop`)
- keyword expression: tests by area (let's say `ens` or `chat`, thay can be combined`ens or chat or send_tx`. All keywords can be found in testrail, ping Chu for details)
- test_marks: tests by priorities (by default: `critical or high or medium`, which corresponds the whole suite; to lauch the same suite as in PRs, use `critical or high`)
- keyword expression: tests by area (let's say `ens` or `chat`, they can be combined`ens or chat or send_tx`. All keywords can be found in testrail, ping Chu for details)
- test_marks: tests by priorities (by default: `critical or high or medium`, which corresponds the whole suite; to launch the same suite as in PRs, use `critical or high`)
- testrail_case_id: here is the list of test cases which you may find in test rail (4-digit value)
For easier access you can hit `Rerun tests` in GH comment and testrail_case_id/ apk_name/ pr_id will be filled automatically. For making sure that tests are being rerun on most recent e2e build it is recommended to paste link to the last e2e build in apk_name field. The list of PR builds can be found in Jenkins Builds block on PR page.
+1 -1
View File
@@ -90,7 +90,7 @@ Press the green run button
<img src="images/ide-setup/8_REPL_6.png" width=75% />
You should now see an dialog with the following message:
You should now see a dialog with the following message:
```shell
Connecting to remote nREPL server...
+4 -4
View File
@@ -4,7 +4,7 @@ This document provides information on how to start developing Status App.
# Getting Started
To start developing start a shell for platform you are interested in.
To start developing start a shell for the platform you are interested in.
```
make shell TARGET=android
```
@@ -55,7 +55,7 @@ Some manual steps are necessary for [developing on a physical iOS Device](#physi
# Build release
To build the app, your can simply run on of the following:
To build the app, you can simply run on of the following:
```
make release-android
make release-ios
@@ -88,9 +88,9 @@ https://facebook.github.io/react-native/docs/getting-started.html
## Configure GitHub Account
The optimal way of pushing to GitHubis using SSH instead of user/pass auth.
The optimal way of pushing to GitHub is using SSH instead of user/pass auth.
It's recommented that you [add your public SSH key to your GitHub account](https://help.github.com/en/github/authenticating-to-github/adding-a-new-ssh-key-to-your-github-account).
It's recommended that you [add your public SSH key to your GitHub account](https://help.github.com/en/github/authenticating-to-github/adding-a-new-ssh-key-to-your-github-account).
## Configure GPG Keys for signing commits
+1 -1
View File
@@ -707,7 +707,7 @@ SPEC CHECKSUMS:
FBLazyVector: a8af91c2b5a0029d12ff6b32e428863d63c48991
FBReactNativeSpec: 1b2309b096448a1dc9d0c43999216f8fda809ae8
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
glog: d93527a855523adb8c113837db4be68fb00e230d
glog: 166d178815c300e8126de9a7900101814eb16253
HMSegmentedControl: 34c1f54d822d8308e7b24f5d901ec674dfa31352
Keycard: ac6df4d91525c3c82635ac24d4ddd9a80aca5fc8
libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef
+1 -1
View File
@@ -22,7 +22,7 @@ buildGoPackage {
runHook preBuild
go build \
-buildmode='c-archive' \
-tags='gowaku_skip_migrations' \
-tags='gowaku_skip_migrations gowaku_no_rln' \
-o "$out/libstatus.a" \
$NIX_BUILD_TOP/main.go
runHook postBuild
+1 -1
View File
@@ -48,7 +48,7 @@ in buildGoPackage {
-target=${concatStringsSep "," targets} \
${optionalString isAndroid "-androidapi=${platformVersion}" } \
${optionalString isIOS "-iosversion=${platformVersion}" } \
-tags='${optionalString isIOS "nowatchdog"} gowaku_skip_migrations' \
-tags='${optionalString isIOS "nowatchdog"} gowaku_skip_migrations gowaku_no_rln' \
-o ${outputFileName} \
${source.goPackagePath}/mobile
BIN
View File
Binary file not shown.
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

+13
View File
@@ -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
+1
View File
@@ -129,6 +129,7 @@
;; needed because we use deref in tests
:static-fns false
:optimizations :simple
:warnings {:fn-deprecated false}
:infer-externs true}}
;; mock.js-dependencies is mocking the react-native libraries
+5 -3
View File
@@ -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]])
@@ -0,0 +1,16 @@
(ns quo2.components.avatars.collection-avatar.component-spec
(:require [quo2.components.avatars.collection-avatar.view :as collection-avatar]
[quo2.foundations.resources :as resources]
[test-helpers.component :as h]))
(h/describe "collection avatar"
(h/describe "Profile picture"
(h/test "Doesn't crash without image"
(h/render
[collection-avatar/view])
(h/is-truthy (h/get-by-label-text :collection-avatar)))
(h/test "Renders with image"
(h/render
[collection-avatar/view {:image (resources/get-image :bored-ape)}])
(h/is-truthy (h/get-by-label-text :collection-avatar)))))
@@ -0,0 +1,10 @@
(ns quo2.components.avatars.collection-avatar.style
(:require [quo2.foundations.colors :as colors]))
(defn collection-avatar
[theme]
{:width 24
:height 24
:border-width 1
:border-color (colors/theme-colors colors/neutral-80-opa-10 colors/white-opa-10 theme)
:border-radius 6})
@@ -0,0 +1,17 @@
(ns quo2.components.avatars.collection-avatar.view
(:require [quo2.components.avatars.collection-avatar.style :as style]
[quo2.theme :as quo.theme]
[react-native.fast-image :as fast-image]))
(defn- view-internal
"Opts:
:image - collection image
:theme - keyword -> :light/:dark"
[{:keys [image theme]}]
[fast-image/fast-image
{:accessibility-label :collection-avatar
:source image
:style (style/collection-avatar theme)}])
(def view (quo.theme/with-theme view-internal))
@@ -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,35 @@
(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? container-style]}]
[rn/scroll-view
{:horizontal true
:shows-horizontal-scroll-indicator false
:content-container-style container-style}
(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))
+101 -13
View File
@@ -21,21 +21,109 @@
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}]])
(defn- contact-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
"M2.79504 9.01494C2.89473 8.85584 3.00297 8.70977 3.11963 8.5761C3.90594 7.67512 4.97212 7.45024 5.99992 7.45024C7.02772 7.45024 8.0939 7.67512 8.88021 8.5761C8.99688 8.70978 9.10512 8.85585 9.2048 9.01495C8.9501 9.28561 8.66149 9.52401 8.34577 9.72335C8.25403 9.55824 8.15512 9.41818 8.05145 9.29939C7.56503 8.74204 6.88121 8.55024 5.99992 8.55024C5.11862 8.55024 4.43481 8.74204 3.94839 9.29939C3.84472 9.41818 3.74582 9.55824 3.65408 9.72334C3.33835 9.524 3.04975 9.2856 2.79504 9.01494ZM5.99992 3.5502C5.47525 3.5502 5.04992 3.97552 5.04992 4.5002C5.04992 5.02487 5.47525 5.4502 5.99992 5.4502C6.52459 5.4502 6.94992 5.02487 6.94992 4.5002C6.94992 3.97552 6.52459 3.5502 5.99992 3.5502ZM3.94992 4.5002C3.94992 3.36801 4.86773 2.4502 5.99992 2.4502C7.1321 2.4502 8.04992 3.36801 8.04992 4.5002C8.04992 5.63238 7.1321 6.5502 5.99992 6.5502C4.86773 6.5502 3.94992 5.63238 3.94992 4.5002Z"
:fill color-2}]])
(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
:i/contact-12 contact-12})
(defn- append-to-keyword
[k & xs]
+2 -2
View File
@@ -82,8 +82,8 @@
:size 20})
(defn input
[colors-by-status small? multiple-lines?]
(let [base-props (assoc (text/text-style {:size :paragraph-1 :weight :regular})
[colors-by-status small? multiple-lines? weight]
(let [base-props (assoc (text/text-style {:size :paragraph-1 :weight (or weight :regular)})
:flex 1
:padding-right 0
:padding-left (if small? 4 8)
+5 -4
View File
@@ -58,7 +58,7 @@
:label :char-limit :on-char-limit-reach :icon-name :multiline? :on-focus :on-blur])
(defn- base-input
[{:keys [on-change-text on-char-limit-reach]}]
[{:keys [on-change-text on-char-limit-reach container-style weight]}]
(let [status (reagent/atom :default)
internal-on-focus #(reset! status :focus)
internal-on-blur #(reset! status :default)
@@ -84,21 +84,22 @@
colors-by-status (style/status-colors status-kw blur? theme)
variant-colors (style/variants-colors blur? theme)
clean-props (apply dissoc props custom-props)]
[:<>
[rn/view {:style container-style}
(when (or label char-limit)
[label-&-counter
{:variant-colors variant-colors
:label label
:current-chars @char-count
:char-limit char-limit}])
[rn/view {:style (style/input-container colors-by-status small? disabled?)}
[rn/view
{:style (style/input-container colors-by-status small? disabled?)}
(when-let [{:keys [icon-name]} left-icon]
[left-accessory
{:variant-colors variant-colors
:small? small?
:icon-name icon-name}])
[rn/text-input
(cond-> {:style (style/input colors-by-status small? @multiple-lines?)
(cond-> {:style (style/input colors-by-status small? @multiple-lines? weight)
:accessibility-label :input
:placeholder-text-color (:placeholder colors-by-status)
:keyboard-appearance (quo.theme/theme-value :light :dark theme)
@@ -49,5 +49,6 @@
[title-input/view
(merge title-input-props
{:blur? true
:size :heading-2
:placeholder placeholder
:customization-color customization-color})]]]))
@@ -20,6 +20,7 @@
placeholder
max-length
default-value
size
theme
container-style]
:or {max-length 0
@@ -39,7 +40,7 @@
[rn/text-input
{:style
(text/text-style
{:size :heading-2
{:size (or size :heading-1)
:weight :semi-bold
:style (style/title-text theme)})
:default-value default-value
@@ -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))
@@ -0,0 +1,53 @@
(ns quo2.components.list-items.saved-contact-address.component-spec
(:require [test-helpers.component :as h]
[quo2.components.list-items.saved-contact-address.view :as saved-contact-address]
[quo2.foundations.colors :as colors]))
(def account
{:name "New House"
:address "0x21a...49e"
:emoji "🍔"
:customization-color :purple})
(h/describe "List items: saved contact address"
(h/test "default render"
(h/render [saved-contact-address/view])
(h/is-truthy (h/query-by-label-text :container)))
(h/test "renders account detail when passing one account"
(h/render [saved-contact-address/view {:accounts (repeat 1 account)}])
(h/is-truthy (h/query-by-label-text :account-container)))
(h/test "renders account count when passing multiple accounts"
(h/render [saved-contact-address/view {:accounts (repeat 2 account)}])
(h/is-truthy (h/query-by-label-text :accounts-count)))
(h/test "on-press-in changes state to :pressed"
(h/render [saved-contact-address/view {:accounts (repeat 1 account)}])
(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-out changes state to :active if active-state? is true (default value)"
(h/render [saved-contact-address/view {:accounts (repeat 1 account)}])
(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 :default if active-state? is false"
(h/render [saved-contact-address/view
{:accounts (repeat 1 account)
:active-state? false}])
(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 :transparent})))
(h/test "on-press calls on-press"
(let [on-press (h/mock-fn)]
(h/render [saved-contact-address/view
{:on-press on-press
:accounts (repeat 1 account)}])
(h/fire-event :on-press (h/get-by-label-text :container))
(h/was-called on-press))))
@@ -0,0 +1,62 @@
(ns quo2.components.list-items.saved-contact-address.style
(:require [quo2.foundations.colors :as colors]))
(defn- background-color
[{:keys [state customization-color]}]
(cond (or (= state :pressed) (= state :selected))
(colors/custom-color customization-color 50 5)
(= state :active)
(colors/custom-color customization-color 50 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 dot-divider
[theme]
{:width 2
:height 2
:border-radius 2
:margin-horizontal 4
:background-color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
(def saved-contact-container
{:margin-left 8})
(def account-container
{:flex-direction :row
:align-items :center})
(def account-title-container
{:flex-direction :row
:height 22
:align-items :center})
(defn account-name
[theme]
{:margin-left 4
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
(defn accounts-count
[theme]
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
(defn account-address
[theme]
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
(def contact-icon-container
{:margin-left 4
:margin-top 1.5})
@@ -0,0 +1,93 @@
(ns quo2.components.list-items.saved-contact-address.view
(:require [quo2.components.avatars.user-avatar.view :as user-avatar]
[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.saved-contact-address.style :as style]
[reagent.core :as reagent]
[quo2.components.icon :as icon]
[utils.i18n :as i18n]))
(defn- account
[{:keys [emoji name address customization-color theme]}]
[rn/view
{:accessibility-label :account-container
:style style/account-container}
[account-avatar/view
{:emoji emoji
:size 16
:customization-color customization-color}]
[text/text
{:size :paragraph-2
:weight :monospace
:style (style/account-name theme)}
name]
[rn/view {:style (style/dot-divider theme)}]
[text/text
{:size :paragraph-2
:weight :monospace
:style (style/account-address 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 [contact-props accounts active-state? customization-color on-press theme]
:or {customization-color :blue
accounts []
active-state? true}}]
(let [accounts-count (count accounts)
account-props (when (= accounts-count 1)
(first accounts))
on-press-out (fn []
(let [new-state (if (or (not active-state?) @active?) :default :active)]
(when @timer (js/clearTimeout @timer))
(reset! timer nil)
(reset! active? (= new-state :active))
(reset! state new-state)))]
[rn/pressable
{:style (style/container
{:state @state :customization-color customization-color})
:on-press-in on-press-in
:on-press-out on-press-out
:on-press #(when on-press
(on-press))
:accessibility-label :container}
[rn/view {:style style/left-container}
[user-avatar/user-avatar (assoc contact-props :size :small)]
[rn/view {:style style/saved-contact-container}
[rn/view
{:style style/account-title-container}
[text/text
{:weight :semi-bold
:size :paragraph-1}
(:full-name contact-props)]
[icon/icon :i/contact
{:container-style style/contact-icon-container
:accessibility-label :contact-icon
:size 12
:color (colors/theme-colors colors/primary-50 colors/primary-60 theme)
:color-2 colors/white}]]
(if account-props
[account (assoc account-props :theme theme)]
[text/text
{:accessibility-label :accounts-count
:size :paragraph-2
:style (style/accounts-count theme)}
(i18n/label :t/accounts-count {:count accounts-count})])]]
(when (> accounts-count 1)
[icon/icon :i/chevron-right
{:accessibility-label :check-icon
:size 20
:color (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,10 @@
(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.dropdowns.network-dropdown.view :as network-dropdown]
[quo2.components.icon :as icons]
[quo2.components.markdown.text :as text]
[quo2.components.navigation.page-nav.style :as style]
@@ -18,7 +21,7 @@
:blur :grey})
(defn- page-nav-base
[{:keys [margin-top background on-press accessibility-label icon-name]
[{:keys [margin-top background on-press accessibility-label icon-name behind-overlay?]
:or {background :white}}
& children]
(into [rn/view {:style (style/container margin-top)}
@@ -28,6 +31,9 @@
:icon-only? true
:size 32
:on-press on-press
:background (if behind-overlay?
:blur
(button-properties/backgrounds background))
:accessibility-label accessibility-label}
icon-name])]
children))
@@ -35,7 +41,7 @@
(defn- right-section-spacing [] [rn/view {:style style/right-actions-spacing}])
(defn- add-right-buttons-xf
[max-actions background]
[max-actions background behind-overlay?]
(comp (filter map?)
(take max-actions)
(map (fn [{:keys [icon-name label] :as button-props}]
@@ -45,24 +51,35 @@
:icon-only? icon-name
:size 32
:accessible true
:background (when (#{:photo :blur} background) background))
:background (if behind-overlay?
:blur
(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
behind-overlay?]
: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}]
(add-right-buttons-xf max-actions background)
(add-right-buttons-xf max-actions background behind-overlay?)
content)
:else
@@ -78,17 +95,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
@@ -156,8 +175,17 @@
:number-of-lines 1}
shown-name]]))
(defn- wallet-networks-center
[{:keys [networks networks-on-press background]}]
[rn/view {:style (style/center-content-container true)}
[network-dropdown/view
{:state :default
:on-press networks-on-press
:blur? (= background :blur)} networks]])
(defn- view-internal
[{:keys [type right-side background text-align]
"behind-overlay is necessary for us to know if the page-nav buttons are under the bottom sheet overlay or not."
[{:keys [type right-side background text-align account-switcher behind-overlay?]
:or {type :no-title
text-align :center
right-side :none
@@ -166,35 +194,37 @@
(case type
:no-title
[page-nav-base props
[right-content {:background background :content right-side :max-actions 3}]]
[right-content
{:background background :content right-side :max-actions 3 :behind-overlay? behind-overlay?}]]
:title
(let [centered? (= text-align :center)]
[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
@@ -216,18 +246,13 @@
:wallet-networks
[page-nav-base props
;; TODO: use wallet-networks when available (issue #16946)
[rn/view {:style (style/center-content-container true)}
[text/text
{:weight :regular
:size :paragraph-1
:number-of-lines 1}
"NETWORK DROPDOWN"]]
[wallet-networks-center props]
[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 +280,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`
@@ -276,7 +308,8 @@
- description
- picture: a valid rn/image `:source` value
`:wallet-network`
(Not implemented yet)
- networks: a vector of network image source
- networks-on-press: a callback
`:community`
- community-name
- community-logo: a valid rn/image `:source` value
@@ -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))
@@ -13,9 +13,10 @@
{:flex-direction :row
:align-items (if (or tag description) :flex-start :center)})
(def sub-container
(defn sub-container
[align-action]
{:flex-direction :row
:align-items :center})
:align-items (or align-action :center)})
(def left-container
{:margin-left 12
@@ -28,7 +28,7 @@
[{:keys [description-props blur? theme]}]
(let [{:keys [text icon]} description-props]
[rn/view
{:style style/sub-container}
{:style (style/sub-container :center)}
[text/text
{:size :paragraph-2
:style (style/color blur? theme)}
@@ -93,15 +93,15 @@
(case action
:arrow [icon/icon :i/chevron-right (style/color blur? theme)]
:button [button/button
{:type :outline
:size 24
:on-press (:on-press action-props)}
(merge action-props
{:type :outline
:size 24})
(:button-text action-props)]
:selector [selectors/toggle action-props]
nil)])
(defn- internal-view
[{:keys [title on-press accessibility-label] :as props}]
[{:keys [title on-press action-props accessibility-label] :as props}]
[rn/pressable
{:style (style/container props)
:on-press on-press
@@ -112,7 +112,7 @@
[text/text {:weight :medium} title]
[description-component props]
[tag-component props]]]
[rn/view {:style style/sub-container}
[rn/view {:style (style/sub-container (:alignment action-props))}
[label-component props]
[action-component props]]])
@@ -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]]])
+35
View File
@@ -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

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