Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e48ffb632f | ||
|
|
919ee4b9ab | ||
|
|
d664653921 | ||
|
|
36dd828a55 | ||
|
|
bcc175041a | ||
|
|
d4cc0189d2 | ||
|
|
1770ff24ce | ||
|
|
265d9be6c2 | ||
|
|
b432aab701 | ||
|
|
1abd1e9420 | ||
|
|
4dc834b079 | ||
|
|
c6a9148e20 | ||
|
|
7c1850b901 | ||
|
|
b88dcf1072 | ||
|
|
afbd890a04 | ||
|
|
933a5a1a9e | ||
|
|
6e897f0ea6 | ||
|
|
b73ac6b107 | ||
|
|
d80fb0b3de | ||
|
|
ef80fc567f | ||
|
|
7043e03dd4 | ||
|
|
c2833ae33d | ||
|
|
a7f0566050 | ||
|
|
1812cfb8dc | ||
|
|
d5a71e2ce0 | ||
|
|
aa2345d35c | ||
|
|
b534b33a09 | ||
|
|
69df5a7e2f | ||
|
|
191f5de6f1 | ||
|
|
df2b5147cd | ||
|
|
4235c71b2f | ||
|
|
aef2f2cfed | ||
|
|
f065aa1c05 | ||
|
|
fbe30d7b18 | ||
|
|
878a1cc285 | ||
|
|
26ae434d07 | ||
|
|
26a702799c | ||
|
|
f5038f8e24 | ||
|
|
5b765f873b | ||
|
|
a13d3a175b | ||
|
|
dfc972079f | ||
|
|
1286188005 | ||
|
|
9fb37d3a48 |
@@ -9,23 +9,29 @@
|
||||
status-im.utils.styles/defn clojure.core/defn
|
||||
test-helpers.unit/deftest-sub clojure.core/defn
|
||||
taoensso.tufte/defnp clojure.core/defn}
|
||||
:linters {:clj-kondo-config {:level :error}
|
||||
:linters {:case-duplicate-test {:level :error}
|
||||
:case-quoted-test {:level :error}
|
||||
:case-symbol-test {:level :error}
|
||||
:clj-kondo-config {:level :error}
|
||||
:cond-else {:level :error}
|
||||
:consistent-alias {:level :error
|
||||
:aliases {clojure.string string
|
||||
clojure.set set
|
||||
clojure.walk walk
|
||||
taoensso.timbre log}}
|
||||
:deprecated-namespace {:level :warning}
|
||||
:docstring-blank {:level :error}
|
||||
:equals-true {:level :error}
|
||||
:inline-def {:level :error}
|
||||
:invalid-arity {:skip-args [status-im.utils.fx/defn utils.re-frame/defn]}
|
||||
:loop-without-recur {:level :error}
|
||||
:minus-one {:level :error}
|
||||
:misplaced-docstring {:level :error}
|
||||
:missing-body-in-when {:level :error}
|
||||
:missing-clause-in-try {:level :error}
|
||||
:missing-else-branch {:level :error}
|
||||
:not-empty? {:level :error}
|
||||
:quoted-case-test-constant {:level :error}
|
||||
:plus-one {:level :error}
|
||||
:redundant-do {:level :error}
|
||||
:redundant-let {:level :error}
|
||||
:refer-all {:level :error}
|
||||
@@ -48,6 +54,8 @@
|
||||
number
|
||||
status-im.test-helpers/restore-app-db]}
|
||||
:unresolved-var {:level :error}
|
||||
:uninitialized-var {:level :error}
|
||||
:unused-alias {:level :warning}
|
||||
:unused-binding {:level :error}
|
||||
:unused-import {:level :error}
|
||||
:unused-namespace {:level :error}
|
||||
|
||||
@@ -33,3 +33,4 @@ SWAP_ENABLED=1
|
||||
STICKERS_TEST_ENABLED=1
|
||||
LOCAL_PAIRING_ENABLED=1
|
||||
TEST_STATEOFUS=1
|
||||
FAST_CREATE_COMMUNITY_ENABLED=1
|
||||
|
||||
@@ -19,3 +19,4 @@ ENABLE_ROOT_ALERT=1
|
||||
MAX_IMAGES_BATCH=1
|
||||
DELETE_MESSAGE_ENABLED=1
|
||||
COLLECTIBLES_ENABLED=1
|
||||
FAST_CREATE_COMMUNITY_ENABLED=0
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
"defview" :arg1-body
|
||||
"letsubs" :binding
|
||||
"with-let" "let"
|
||||
"reg-event-fx" :arg1-pair
|
||||
"testing" :arg1-body
|
||||
"deftest-sub" :arg1-body
|
||||
"wait-for" :arg1-body
|
||||
|
||||
@@ -309,10 +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 && \
|
||||
sh scripts/lint-old-quo-usage.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 && \
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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}
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,42 @@ To do this:
|
||||
|
||||

|
||||
|
||||
## 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'
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
### How should the paste button behave when clipboard is empty?
|
||||
|
||||
This question first came up as a review comment to this PR
|
||||
https://github.com/status-im/status-mobile/pull/16852
|
||||
|
||||
There were 2 considerations :
|
||||
- Either keep the paste button disabled when there is nothing in the clipboard OR
|
||||
- Always keep the paste button enabled
|
||||
|
||||
There were positives and negatives for both approaches.
|
||||
|
||||
Positives of keeping paste button disabled when there is nothing in clipboard would require us to
|
||||
check the value of clipboard as soon as the component is mounted (i.e when the user first sees
|
||||
the screen). In iOS this means a native permissions dialog would appear requesting for permissions
|
||||
to paste from the clipboard.
|
||||
|
||||
Negatives of this approach is that as soon as any user navigates to this screen they are greeted with
|
||||
this popup which can be annoying sometimes.
|
||||
|
||||
Positives of keeping paste button always enabled is that we can trigger a request to the clipboard on
|
||||
tap of the paste button which would trigger the native permissions dialog requesting for permissions
|
||||
to paste from the clipboard.
|
||||
In this case seeing this dialog is okay because the user has initiated a paste action.
|
||||
|
||||
Negatives of this approach is that in the event the clipboard is empty the user will still see the
|
||||
system dialog and on approving nothing will be pasted (because the clipboard was empty).
|
||||
This behaviour can be confusing.
|
||||
|
||||
On consulting the Design Team via discord it was concluded that out of the two approaches
|
||||
having the paste button always enabled is a better UX overall.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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...
|
||||
|
||||
@@ -467,21 +467,28 @@ Prefer the pure version of `:json-rpc/call` (no callbacks).
|
||||
|
||||
### Registering event handlers
|
||||
|
||||
Events must always be declared with the `utils.fx/defn` macro. Also, don't use
|
||||
Register events with `re-frame.core/reg-event-fx` and follow [re-frame's best
|
||||
practice](https://github.com/day8/re-frame/blob/39adca93673f334dc751ee2d99d340b51a9cc6db/docs/FAQs/BestPractice.md#use-the-fx-effect)
|
||||
so use only `:db` and `:fx` effects. `rf/merge` is deprecated and should not be
|
||||
used in the new code in `src/status_im2/`. Don't use
|
||||
`re-frame.core/reg-event-db`.
|
||||
|
||||
```clojure
|
||||
;; bad
|
||||
(re-frame/reg-event-fx
|
||||
:wakuv2.ui/save-all-confirmed
|
||||
(fn [{:keys [db] :as cofx}]
|
||||
...))
|
||||
(rf/defn invite-people-pressed
|
||||
{:events [:communities/invite-people-pressed]}
|
||||
[cofx id]
|
||||
(rf/merge cofx
|
||||
(reset-community-id-input id)
|
||||
(bottom-sheet/hide-bottom-sheet)
|
||||
(navigation/open-modal :invite-people-community {:invite? true})))
|
||||
|
||||
;; good
|
||||
(fx/defn save-all
|
||||
{:events [:wakuv2.ui/save-all-confirmed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
...)
|
||||
(re-frame/reg-event-fx :communities/invite-people-pressed
|
||||
(fn [{:keys [db]} [id]]
|
||||
{:db (assoc db :communities/community-id-input id)
|
||||
:fx [[:dispatch [:hide-bottom-sheet]]
|
||||
[:dispatch [:open-modal :invite-people-community {:invite? true}]]]}))
|
||||
```
|
||||
|
||||
### Registering top-level re-frame subscriptions
|
||||
@@ -805,7 +812,7 @@ alternative.
|
||||
Please check the [Clojure Style](https://guide.clojure.style/#deprecated) documentation
|
||||
|
||||
To reduce visual clutter from deprecated methods in your text editor, consult this [example](https://rider-support.jetbrains.com/hc/en-us/community/posts/4419728641810-How-to-disable-the-the-strike-thru-for-deprecated-methods-in-Javascript-#:~:text=Try%20disabling%20%22Preferences%20%7C%20Editor%20%7C,It%20works%20for%20me). The approach can be adapted for settings in VSCode, Emacs, VIM, and others.
|
||||
|
||||
|
||||
### Test structure
|
||||
|
||||
[Unit tests](#glossary) should be created alongside their respective source
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -38,6 +38,19 @@ in {
|
||||
};
|
||||
});
|
||||
|
||||
# Clojure's linter receives frequent upgrades, and we want to take advantage
|
||||
# of the latest available rules.
|
||||
clj-kondo = super.clj-kondo.override rec {
|
||||
buildGraalvmNativeImage = args: super.buildGraalvmNativeImage (args // rec {
|
||||
inherit (args) pname;
|
||||
version = "2023.09.07";
|
||||
src = super.fetchurl {
|
||||
url = "https://github.com/clj-kondo/${pname}/releases/download/v${version}/${pname}-${version}-standalone.jar";
|
||||
sha256 = "sha256-F7ePdITYKkGB6nsR3EFJ7zLDCUoT0g3i+AAjXzBd624=";
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
# Checks fail on darwin.
|
||||
git-lfs = super.git-lfs.overrideAttrs (old: {
|
||||
doCheck = false;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"i18n-js": "^3.3.0",
|
||||
"node-libs-react-native": "^1.2.1",
|
||||
"qrcode": "^1.4.1",
|
||||
"react": "18.0.0",
|
||||
"react-dom": "18.0.0",
|
||||
"react-native": "0.69.10",
|
||||
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 781 B |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 216 KiB |
|
Before Width: | Height: | Size: 539 KiB After Width: | Height: | Size: 430 KiB |
@@ -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
|
||||
|
||||
@@ -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))
|
||||
@@ -35,7 +35,7 @@
|
||||
:indicator-size status indicator outer radius, set to nil or 0 when no indicator
|
||||
:indicator-border `indicator-size`-`indicator-border` is the inner radius
|
||||
:indicator-color color for status indicator
|
||||
:theme :light or :dark
|
||||
:theme :light or :dark
|
||||
:background-color intials avatar background color
|
||||
:color intials avatar text color
|
||||
:size intials avatar radius
|
||||
|
||||
@@ -28,11 +28,11 @@
|
||||
(defn wallet-user-avatar
|
||||
"params, first name, last name, color, size
|
||||
and if it's dark or not!"
|
||||
[{:keys [f-name l-name color size]
|
||||
:or {f-name "John"
|
||||
l-name "Doe"
|
||||
color :red
|
||||
size :x-large}}]
|
||||
[{:keys [f-name l-name customization-color size]
|
||||
:or {f-name "John"
|
||||
l-name "Doe"
|
||||
customization-color :red
|
||||
size :x-large}}]
|
||||
(let [circle-size (size circle-sizes)
|
||||
small? (= size :small)
|
||||
f-name-initial (-> f-name
|
||||
@@ -41,8 +41,8 @@
|
||||
l-name-initial (-> l-name
|
||||
string/upper-case
|
||||
(subs 0 1))
|
||||
circle-color (colors/custom-color color 50 20)
|
||||
text-color (colors/custom-color-by-theme color 50 60)]
|
||||
circle-color (colors/custom-color customization-color 50 20)
|
||||
text-color (colors/custom-color-by-theme customization-color 50 60)]
|
||||
[rn/view
|
||||
{:style {:width circle-size
|
||||
:height circle-size
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
[{:keys [pressed? blur? theme]}]
|
||||
(cond
|
||||
(and pressed? blur?) (colors/theme-colors colors/neutral-80-opa-20 colors/white-opa-20 theme)
|
||||
(= pressed? true) (colors/theme-colors colors/neutral-40 colors/neutral-60 theme)
|
||||
(= blur? true) (colors/theme-colors colors/neutral-80-opa-10 colors/white-opa-10 theme)
|
||||
pressed? (colors/theme-colors colors/neutral-40 colors/neutral-60 theme)
|
||||
blur? (colors/theme-colors colors/neutral-80-opa-10 colors/white-opa-10 theme)
|
||||
:else (colors/theme-colors colors/neutral-30 colors/neutral-70 theme)))
|
||||
|
||||
(defn get-label-color
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
(defn get-border-color
|
||||
[{:keys [pressed? theme]}]
|
||||
(if (= pressed? true)
|
||||
(if pressed?
|
||||
(colors/theme-colors colors/neutral-40 colors/neutral-60 theme)
|
||||
(colors/theme-colors colors/neutral-30 colors/neutral-70 theme)))
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
(defn generate-years
|
||||
[current-year]
|
||||
(let [current-year current-year]
|
||||
(reverse (vec (range (- current-year 100) (+ current-year 1))))))
|
||||
(reverse (vec (range (- current-year 100) (inc current-year))))))
|
||||
|
||||
(defn current-year
|
||||
[]
|
||||
|
||||
@@ -18,10 +18,11 @@
|
||||
- `blur?` Boolean to enable blur background support.}"
|
||||
[{:keys [default-selected]}]
|
||||
(let [selected (reagent/atom default-selected)]
|
||||
(fn [{:keys [blur? on-change feng-shui?]}]
|
||||
(fn [{:keys [blur? on-change feng-shui? container-style]}]
|
||||
[rn/scroll-view
|
||||
{:horizontal true
|
||||
:shows-horizontal-scroll-indicator false}
|
||||
:shows-horizontal-scroll-indicator false
|
||||
:content-container-style container-style}
|
||||
(doall (map (fn [color]
|
||||
[color/view
|
||||
{:selected? (= color @selected)
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
[rn/view {:accessibility-label :line-chart}
|
||||
[charts/line-chart
|
||||
{:height 96
|
||||
:width (+ width 1)
|
||||
:width (inc width)
|
||||
:max-value max-value
|
||||
:min-value 0
|
||||
:adjust-to-width true
|
||||
|
||||
@@ -21,11 +21,15 @@
|
||||
^{:key icon-name}
|
||||
(if-let [svg-icon (icons.svg/get-icon icon-name size)]
|
||||
[svg-icon
|
||||
{:size size
|
||||
:color (when (valid-color? color) color)
|
||||
:color-2 (when (valid-color? color-2) color-2)
|
||||
:accessibility-label accessibility-label
|
||||
:style container-style}]
|
||||
(cond-> {:size size
|
||||
:accessibility-label accessibility-label
|
||||
:style container-style}
|
||||
|
||||
(and color (valid-color? color))
|
||||
(assoc :color color)
|
||||
|
||||
(and color-2 (valid-color? color-2))
|
||||
(assoc :color-2 color-2))]
|
||||
[rn/image
|
||||
{:style
|
||||
(merge {:width size
|
||||
|
||||
@@ -101,12 +101,29 @@
|
||||
: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/dropdown-20 dropdown-20
|
||||
:i/pullup-20 pullup-20
|
||||
:i/dropdown-12 dropdown-12
|
||||
:i/pullup-12 pullup-12})
|
||||
:i/pullup-12 pullup-12
|
||||
:i/contact-12 contact-12})
|
||||
|
||||
(defn- append-to-keyword
|
||||
[k & xs]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,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))
|
||||
@@ -14,7 +14,8 @@
|
||||
(defn chat-key-text
|
||||
[]
|
||||
{:color (colors/theme-colors colors/neutral-40 colors/neutral-50)
|
||||
:margin-left 8})
|
||||
:margin-left 8
|
||||
:padding-top 1})
|
||||
|
||||
(defn middle-dot-chat-key
|
||||
[]
|
||||
|
||||
@@ -12,12 +12,13 @@
|
||||
:align-items :center})
|
||||
|
||||
(defn center-content-container
|
||||
[centered?]
|
||||
[centered? center-opacity]
|
||||
{:flex 1
|
||||
:margin-horizontal 12
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content (if centered? :center :flex-start)})
|
||||
:justify-content (if centered? :center :flex-start)
|
||||
:opacity center-opacity})
|
||||
|
||||
(def right-actions-container
|
||||
{:flex-direction :row})
|
||||
@@ -79,6 +80,7 @@
|
||||
:text-align-vertical :center}))
|
||||
|
||||
(def community-network-logo
|
||||
{:width 24
|
||||
:height 24
|
||||
:margin-right 6})
|
||||
{:width 24
|
||||
:height 24
|
||||
:border-radius 12
|
||||
:margin-right 6})
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
[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]
|
||||
@@ -20,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)}
|
||||
@@ -30,7 +31,9 @@
|
||||
:icon-only? true
|
||||
:size 32
|
||||
:on-press on-press
|
||||
:background (when (button-properties/backgrounds background) background)
|
||||
:background (if behind-overlay?
|
||||
:blur
|
||||
(button-properties/backgrounds background))
|
||||
:accessibility-label accessibility-label}
|
||||
icon-name])]
|
||||
children))
|
||||
@@ -38,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}]
|
||||
@@ -48,7 +51,9 @@
|
||||
:icon-only? icon-name
|
||||
:size 32
|
||||
:accessible true
|
||||
:background (when (button-properties/backgrounds background) background))
|
||||
:background (if behind-overlay?
|
||||
:blur
|
||||
(when (button-properties/backgrounds background) background)))
|
||||
(or label icon-name)]))
|
||||
(interpose [right-section-spacing])))
|
||||
|
||||
@@ -64,7 +69,8 @@
|
||||
emoji])
|
||||
|
||||
(defn- right-content
|
||||
[{:keys [background content max-actions min-size? support-account-switcher? 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
|
||||
@@ -73,15 +79,15 @@
|
||||
|
||||
(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
|
||||
nil)])
|
||||
|
||||
(defn- title-center
|
||||
[{:keys [centered? title]}]
|
||||
[rn/view {:style (style/center-content-container centered?)}
|
||||
[{:keys [centered? title center-opacity]}]
|
||||
[rn/view {:style (style/center-content-container centered? center-opacity)}
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:size :paragraph-1
|
||||
@@ -89,13 +95,13 @@
|
||||
title]])
|
||||
|
||||
(defn- dropdown-center
|
||||
[{:keys [theme background dropdown-on-press dropdown-selected? dropdown-text]}]
|
||||
[{:keys [theme background dropdown-on-press dropdown-selected? dropdown-text center-opacity]}]
|
||||
(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)}
|
||||
[rn/view {:style (style/center-content-container true center-opacity)}
|
||||
[dropdown/view
|
||||
{:type dropdown-type
|
||||
:state dropdown-state
|
||||
@@ -105,8 +111,8 @@
|
||||
dropdown-text]]))
|
||||
|
||||
(defn- token-center
|
||||
[{:keys [theme background token-logo token-name token-abbreviation]}]
|
||||
[rn/view {:style (style/center-content-container false)}
|
||||
[{:keys [theme background token-logo token-name token-abbreviation center-opacity]}]
|
||||
[rn/view {:style (style/center-content-container false center-opacity)}
|
||||
[rn/image {:style style/token-logo :source token-logo}]
|
||||
[text/text
|
||||
{:style style/token-name
|
||||
@@ -122,8 +128,8 @@
|
||||
token-abbreviation]])
|
||||
|
||||
(defn- channel-center
|
||||
[{:keys [theme background channel-emoji channel-name channel-icon]}]
|
||||
[rn/view {:style (style/center-content-container false)}
|
||||
[{:keys [theme background channel-emoji channel-name channel-icon center-opacity]}]
|
||||
[rn/view {:style (style/center-content-container false center-opacity)}
|
||||
[rn/text {:style style/channel-emoji}
|
||||
channel-emoji]
|
||||
[text/text
|
||||
@@ -135,11 +141,11 @@
|
||||
[icons/icon channel-icon {:size 16 :color (style/channel-icon-color theme background)}]])
|
||||
|
||||
(defn- title-description-center
|
||||
[{:keys [background theme picture title description]}]
|
||||
[rn/view {:style (style/center-content-container false)}
|
||||
[{:keys [background theme picture title description center-opacity]}]
|
||||
[rn/view {:style (style/center-content-container false center-opacity)}
|
||||
(when picture
|
||||
[rn/view {:style style/group-avatar-picture}
|
||||
[group-avatar/view {:picture picture :size 28}]])
|
||||
[group-avatar/view {:picture picture :size :size-28}]])
|
||||
[rn/view {:style style/title-description-container}
|
||||
[text/text
|
||||
{:style style/title-description-title
|
||||
@@ -155,11 +161,11 @@
|
||||
description]]])
|
||||
|
||||
(defn- community-network-center
|
||||
[{:keys [type community-logo network-logo community-name network-name]}]
|
||||
[{:keys [type community-logo network-logo community-name network-name center-opacity]}]
|
||||
(let [community? (= type :community)
|
||||
shown-logo (if community? community-logo network-logo)
|
||||
shown-name (if community? community-name network-name)]
|
||||
[rn/view {:style (style/center-content-container false)}
|
||||
[rn/view {:style (style/center-content-container false center-opacity)}
|
||||
[rn/image
|
||||
{:style style/community-network-logo
|
||||
:source shown-logo}]
|
||||
@@ -169,8 +175,17 @@
|
||||
:number-of-lines 1}
|
||||
shown-name]]))
|
||||
|
||||
(defn- wallet-networks-center
|
||||
[{:keys [networks networks-on-press background center-opacity]}]
|
||||
[rn/view {:style (style/center-content-container true center-opacity)}
|
||||
[network-dropdown/view
|
||||
{:state :default
|
||||
:on-press networks-on-press
|
||||
:blur? (= background :blur)} networks]])
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [type right-side background text-align account-switcher]
|
||||
"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
|
||||
@@ -179,7 +194,8 @@
|
||||
(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)]
|
||||
@@ -230,13 +246,7 @@
|
||||
|
||||
: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
|
||||
@@ -298,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
|
||||
|
||||
@@ -6,10 +6,14 @@
|
||||
|
||||
(def text-container {:flex 1})
|
||||
|
||||
(def title
|
||||
(def icon-title
|
||||
{:color colors/white
|
||||
:height 22})
|
||||
|
||||
(def main-title
|
||||
{:color colors/white
|
||||
:height 26})
|
||||
|
||||
(def subtitle
|
||||
{:color colors/white-opa-70
|
||||
:height 18})
|
||||
@@ -33,21 +37,23 @@
|
||||
:height 32})
|
||||
|
||||
(def main-variant
|
||||
{:flex 1
|
||||
:margin-bottom -8})
|
||||
{:flex 1})
|
||||
|
||||
(def main-variant-text-container
|
||||
{:height 62
|
||||
:padding-top 10
|
||||
:padding-bottom 12
|
||||
:padding-horizontal 12})
|
||||
|
||||
(def touchable-overlay {:border-radius 16})
|
||||
(defn main-variant-image
|
||||
[max-height]
|
||||
{:flex 1
|
||||
:max-height max-height})
|
||||
|
||||
(def main-button
|
||||
{:padding-horizontal 12 :margin-bottom 12 :margin-top 8})
|
||||
|
||||
(defn card
|
||||
[height]
|
||||
{:background-color colors/white-opa-5
|
||||
:border-radius 16
|
||||
:height height})
|
||||
|
||||
(def main-variant-extra-space {:height 8})
|
||||
|
||||
@@ -1,55 +1,71 @@
|
||||
(ns quo2.components.onboarding.small-option-card.view
|
||||
(:require [quo2.components.markdown.text :as text]
|
||||
[quo2.components.onboarding.small-option-card.style :as style]
|
||||
[quo2.components.buttons.button.view :as button]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.fast-image :as fast-image]))
|
||||
|
||||
(defn- texts
|
||||
[{:keys [title subtitle]}]
|
||||
[rn/view {:style style/text-container}
|
||||
[text/text
|
||||
{:style style/title
|
||||
:size :paragraph-1
|
||||
:weight :semi-bold
|
||||
:number-of-lines 1}
|
||||
title]
|
||||
[text/text
|
||||
{:style style/subtitle
|
||||
:size :paragraph-2
|
||||
:weight :regular
|
||||
:number-of-lines 1}
|
||||
subtitle]])
|
||||
|
||||
(defn- icon-variant
|
||||
[{:keys [title subtitle image]}]
|
||||
[rn/view {:style style/icon-variant}
|
||||
[{:keys [title subtitle image accessibility-label on-press]}]
|
||||
[rn/pressable
|
||||
{:accessibility-label accessibility-label
|
||||
:style style/icon-variant
|
||||
:underlay-color colors/white-opa-5
|
||||
:on-press on-press}
|
||||
[rn/view {:style style/icon-variant-image-container}
|
||||
[fast-image/fast-image
|
||||
{:accessibility-label :small-option-card-icon-image
|
||||
:style style/icon-variant-image
|
||||
:resize-mode :contain
|
||||
:source image}]]
|
||||
[texts
|
||||
{:title title
|
||||
:subtitle subtitle}]])
|
||||
[rn/view {:style style/text-container}
|
||||
[text/text
|
||||
{:style style/icon-title
|
||||
:size :paragraph-1
|
||||
:weight :semi-bold
|
||||
:number-of-lines 1}
|
||||
title]
|
||||
[text/text
|
||||
{:style style/subtitle
|
||||
:size :paragraph-2
|
||||
:weight :regular
|
||||
:number-of-lines 1}
|
||||
subtitle]]])
|
||||
|
||||
(defn- main-variant
|
||||
[{:keys [title subtitle image max-height]}]
|
||||
[{:keys [title subtitle button-label image max-height accessibility-label on-press]}]
|
||||
[rn/view {:style style/main-variant}
|
||||
[rn/view {:style style/main-variant-text-container}
|
||||
[texts
|
||||
{:title title
|
||||
:subtitle subtitle}]]
|
||||
[text/text
|
||||
{:style style/main-title
|
||||
:size :heading-2
|
||||
:weight :semi-bold
|
||||
:number-of-lines 1}
|
||||
title]
|
||||
[text/text
|
||||
{:style style/subtitle
|
||||
:size :paragraph-2
|
||||
:weight :regular
|
||||
:number-of-lines 1}
|
||||
subtitle]]
|
||||
[fast-image/fast-image
|
||||
{:accessibility-label :small-option-card-main-image
|
||||
:style {:flex 1 :max-height max-height}
|
||||
:style (style/main-variant-image max-height)
|
||||
:resize-mode :contain
|
||||
:source image}]])
|
||||
:source image}]
|
||||
[button/button
|
||||
{:on-press on-press
|
||||
:accessibility-label accessibility-label
|
||||
:type :grey
|
||||
:size 40
|
||||
:container-style style/main-button
|
||||
:theme :dark
|
||||
:background :blur}
|
||||
button-label]])
|
||||
|
||||
(defn small-option-card
|
||||
"Variants: `:main` or `:icon`"
|
||||
[{:keys [variant title subtitle image max-height on-press accessibility-label]
|
||||
[{:keys [variant title subtitle button-label image max-height on-press accessibility-label]
|
||||
:or {variant :main accessibility-label :small-option-card}}]
|
||||
(let [main-variant? (= variant :main)
|
||||
card-component (if main-variant? main-variant icon-variant)
|
||||
@@ -57,18 +73,12 @@
|
||||
(not main-variant?) style/icon-variant-height
|
||||
max-height (min max-height style/main-variant-height)
|
||||
:else style/main-variant-height)]
|
||||
[rn/view
|
||||
[rn/touchable-highlight
|
||||
{:accessibility-label accessibility-label
|
||||
:style style/touchable-overlay
|
||||
:active-opacity 1
|
||||
:underlay-color colors/white-opa-5
|
||||
:on-press on-press}
|
||||
[rn/view {:style (style/card card-height)}
|
||||
[card-component
|
||||
{:title title
|
||||
:subtitle subtitle
|
||||
:image image
|
||||
:max-height max-height}]]]
|
||||
(when main-variant?
|
||||
[rn/view {:style style/main-variant-extra-space}])]))
|
||||
[rn/view {:style (style/card card-height)}
|
||||
[card-component
|
||||
{:title title
|
||||
:subtitle subtitle
|
||||
:button-label button-label
|
||||
:on-press on-press
|
||||
:accessibility-label accessibility-label
|
||||
:image image
|
||||
:max-height max-height}]]))
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
(ns quo2.components.reactions.reaction
|
||||
(:require [quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.reactions.resource :as resource]
|
||||
[quo2.components.reactions.style :as style]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn- add-reaction-internal
|
||||
[{:keys [on-press theme]}]
|
||||
[rn/touchable-opacity
|
||||
{:on-press on-press
|
||||
:accessibility-label :emoji-reaction-add
|
||||
:style (style/add-reaction theme)}
|
||||
[icons/icon :i/add-reaction
|
||||
{:size 20
|
||||
:color (colors/theme-colors colors/neutral-50
|
||||
colors/neutral-40
|
||||
theme)}]])
|
||||
|
||||
(def add-reaction (theme/with-theme add-reaction-internal))
|
||||
|
||||
(defn reaction-internal
|
||||
"Add your emoji as a param here"
|
||||
[{:keys [emoji clicks neutral? on-press accessibility-label on-long-press theme]}]
|
||||
(let [numeric-value (int clicks)]
|
||||
[rn/touchable-opacity
|
||||
{:on-press on-press
|
||||
:on-long-press on-long-press
|
||||
:accessibility-label accessibility-label
|
||||
:style (style/reaction neutral? theme)}
|
||||
[rn/image
|
||||
{:style {:width 16 :height 16}
|
||||
:accessibility-label :emoji
|
||||
:source (resource/get-reaction emoji)}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :semi-bold
|
||||
:style style/reaction-count}
|
||||
(str (if (pos? numeric-value) numeric-value 1))]]))
|
||||
|
||||
(def reaction (theme/with-theme reaction-internal))
|
||||
@@ -1,33 +0,0 @@
|
||||
(ns quo2.components.reactions.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def reaction-styling
|
||||
{:flex-direction :row
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:padding-horizontal 8
|
||||
:border-radius 8
|
||||
:height 24})
|
||||
|
||||
(defn add-reaction
|
||||
[theme]
|
||||
(merge reaction-styling
|
||||
{:padding-horizontal 8
|
||||
:border-width 1
|
||||
:border-color (colors/theme-colors colors/neutral-20
|
||||
colors/neutral-70
|
||||
theme)}))
|
||||
|
||||
(defn reaction
|
||||
[neutral? theme]
|
||||
(merge reaction-styling
|
||||
{:border-color (colors/theme-colors colors/neutral-20
|
||||
colors/neutral-80
|
||||
theme)
|
||||
:border-width 1
|
||||
:background-color (if neutral?
|
||||
(colors/theme-colors colors/neutral-10
|
||||
colors/neutral-80-opa-40)
|
||||
:transparent)}))
|
||||
|
||||
(def reaction-count {:margin-left 4})
|
||||
@@ -0,0 +1,12 @@
|
||||
(ns quo2.components.selectors.react.style)
|
||||
|
||||
(def container
|
||||
{:flex-direction :row
|
||||
:justify-content :flex-start
|
||||
:flex 1
|
||||
:flex-wrap :wrap
|
||||
:margin-bottom -6})
|
||||
|
||||
(def reaction-container
|
||||
{:margin-bottom 6
|
||||
:margin-right 6})
|
||||
@@ -0,0 +1,26 @@
|
||||
(ns quo2.components.selectors.react.view
|
||||
(:require [quo2.components.selectors.react-selector.view :as react-selector]
|
||||
[quo2.components.selectors.react.style :as style]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn view
|
||||
[{:keys [reactions on-press on-long-press add-reaction? on-press-add use-case container-style]}]
|
||||
[rn/view {:style (merge style/container container-style)}
|
||||
(for [emoji-reaction reactions
|
||||
:let [{:keys [emoji emoji-id emoji-reaction-id quantity own]} emoji-reaction]]
|
||||
[react-selector/view
|
||||
{:key emoji-reaction-id
|
||||
:emoji emoji
|
||||
:state (if own :pressed :not-pressed)
|
||||
:use-case use-case
|
||||
:container-style style/reaction-container
|
||||
:clicks quantity
|
||||
:on-press #(on-press emoji-reaction)
|
||||
:on-long-press #(on-long-press emoji-reaction)
|
||||
:accessibility-label (str "emoji-reaction-" emoji-id)}])
|
||||
(when add-reaction?
|
||||
[react-selector/view
|
||||
{:on-press on-press-add
|
||||
:state :add-reaction
|
||||
:use-case use-case
|
||||
:accessibility-label (str "emoji-add-reaction")}])])
|
||||
@@ -0,0 +1,44 @@
|
||||
(ns quo2.components.selectors.react-selector.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(defn add-reaction
|
||||
[pinned? theme]
|
||||
(let [border-color (if pinned?
|
||||
(colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5 theme)
|
||||
(colors/theme-colors colors/neutral-20 colors/neutral-70 theme))]
|
||||
(cond-> {:justify-content :center
|
||||
:align-items :center
|
||||
:padding-horizontal 7
|
||||
:border-radius 8
|
||||
:border-width 1
|
||||
:height 24
|
||||
:border-color border-color})))
|
||||
|
||||
(defn reaction
|
||||
[pressed? pinned? theme]
|
||||
(let [background-color (cond
|
||||
(not pressed?) :transparent
|
||||
pinned? (colors/theme-colors colors/neutral-80-opa-5
|
||||
colors/white-opa-5
|
||||
theme)
|
||||
:else (colors/theme-colors colors/neutral-10
|
||||
colors/neutral-80-opa-40
|
||||
theme))
|
||||
border-color (if pinned?
|
||||
(colors/theme-colors colors/neutral-80-opa-5
|
||||
colors/white-opa-5
|
||||
theme)
|
||||
(colors/theme-colors colors/neutral-20
|
||||
colors/neutral-80
|
||||
theme))]
|
||||
{:flex-direction :row
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:padding-horizontal 8
|
||||
:border-radius 8
|
||||
:height 24
|
||||
:border-width 1
|
||||
:background-color background-color
|
||||
:border-color border-color}))
|
||||
|
||||
(def reaction-count {:margin-left 4})
|
||||
@@ -0,0 +1,46 @@
|
||||
(ns quo2.components.selectors.react-selector.view
|
||||
(:require [quo2.components.markdown.text :as text]
|
||||
[quo2.components.selectors.reaction-resource :as reaction.resource]
|
||||
[quo2.components.selectors.react-selector.style :as style]
|
||||
[quo2.theme :as quo.theme]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.icon :as icons]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [emoji clicks state use-case on-press accessibility-label on-long-press container-style
|
||||
theme]}]
|
||||
(let [numeric-value (int clicks)
|
||||
icon-color (if (= :pinned use-case)
|
||||
(colors/theme-colors colors/neutral-80-opa-70 colors/white-opa-70 theme)
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))]
|
||||
(if (= :add-reaction state)
|
||||
[rn/touchable-opacity
|
||||
{:on-press on-press
|
||||
:accessibility-label :emoji-reaction-add
|
||||
:style (style/add-reaction
|
||||
(= :pinned use-case)
|
||||
theme)}
|
||||
[icons/icon :i/add-reaction
|
||||
{:size 20
|
||||
:color icon-color}]]
|
||||
|
||||
[rn/touchable-opacity
|
||||
{:on-press on-press
|
||||
:on-long-press on-long-press
|
||||
:accessibility-label accessibility-label
|
||||
:style (merge (style/reaction (= :pressed state)
|
||||
(= :pinned use-case)
|
||||
theme)
|
||||
container-style)}
|
||||
[rn/image
|
||||
{:style {:width 15 :height 15}
|
||||
:accessibility-label :emoji
|
||||
:source (reaction.resource/get-reaction emoji)}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :semi-bold
|
||||
:style style/reaction-count}
|
||||
(str (if (pos? numeric-value) numeric-value 1))]])))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -1,4 +1,4 @@
|
||||
(ns quo2.components.reactions.resource
|
||||
(ns quo2.components.selectors.reaction-resource
|
||||
(:require [clojure.java.io :as io]
|
||||
[clojure.string :as string]))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(ns quo2.components.reactions.resource
|
||||
(:require-macros [quo2.components.reactions.resource :refer [resolve-all-reactions]]))
|
||||
(ns quo2.components.selectors.reaction-resource
|
||||
(:require-macros [quo2.components.selectors.reaction-resource :refer [resolve-all-reactions]]))
|
||||
|
||||
(def ^:private reactions
|
||||
(resolve-all-reactions))
|
||||
@@ -1,25 +0,0 @@
|
||||
(ns quo2.components.selectors.reactions.view
|
||||
(:require [quo2.components.reactions.resource :as reactions.resource]
|
||||
[quo2.components.selectors.reactions.style :as style]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn view
|
||||
[_ {:keys [start-pressed?]}]
|
||||
(let [pressed? (reagent/atom start-pressed?)]
|
||||
(fn [emoji
|
||||
{:keys [container-style on-press
|
||||
accessibility-label]
|
||||
:or {accessibility-label :reaction}}]
|
||||
[rn/touchable-without-feedback
|
||||
{:accessibility-label accessibility-label
|
||||
:on-press (fn [e]
|
||||
(swap! pressed? not)
|
||||
(when on-press
|
||||
(on-press e)))}
|
||||
[rn/view
|
||||
{:style (merge (style/container @pressed?)
|
||||
container-style)}
|
||||
[rn/image
|
||||
{:source (reactions.resource/get-reaction emoji)
|
||||
:style {:width 20 :height 20}}]]])))
|
||||
@@ -1,23 +1,26 @@
|
||||
(ns quo2.components.selectors.reactions.component-spec
|
||||
(:require [quo2.components.selectors.reactions.view :as view]
|
||||
(ns quo2.components.selectors.reactions-selector.component-spec
|
||||
(:require [quo2.components.selectors.reactions-selector.view :as view]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "Selectors > Reactions"
|
||||
(h/test "renders component"
|
||||
(h/render [view/view :reaction/sad])
|
||||
(h/render [view/view {:emoji :reaction/sad}])
|
||||
(h/is-truthy (h/get-by-label-text :reaction)))
|
||||
|
||||
(h/describe "on-press event"
|
||||
(h/test "starts with released state"
|
||||
(let [on-press (h/mock-fn)]
|
||||
(h/render [view/view :reaction/love {:on-press on-press}])
|
||||
(h/render [view/view
|
||||
{:emoji :reaction/love
|
||||
:on-press on-press}])
|
||||
(h/fire-event :press (h/get-by-label-text :reaction))
|
||||
(h/was-called on-press)))
|
||||
|
||||
(h/test "starts with pressed state"
|
||||
(let [on-press (h/mock-fn)]
|
||||
(h/render [view/view :reaction/love
|
||||
{:on-press on-press
|
||||
(h/render [view/view
|
||||
{:emoji :reaction/love
|
||||
:on-press on-press
|
||||
:start-pressed? true}])
|
||||
(h/fire-event :press (h/get-by-label-text :reaction))
|
||||
(h/was-called on-press)))))
|
||||
@@ -1,4 +1,4 @@
|
||||
(ns quo2.components.selectors.reactions.style
|
||||
(ns quo2.components.selectors.reactions-selector.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(defn container
|
||||
@@ -0,0 +1,23 @@
|
||||
(ns quo2.components.selectors.reactions-selector.view
|
||||
(:require [quo2.components.selectors.reaction-resource :as reactions.resource]
|
||||
[quo2.components.selectors.reactions-selector.style :as style]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn view
|
||||
[{:keys [start-pressed?]}]
|
||||
(let [pressed? (reagent/atom start-pressed?)]
|
||||
(fn [{:keys [emoji container-style on-press
|
||||
accessibility-label]
|
||||
:or {accessibility-label :reaction}}]
|
||||
[rn/pressable
|
||||
{:accessibility-label accessibility-label
|
||||
:style (merge (style/container @pressed?)
|
||||
container-style)
|
||||
:on-press (fn [e]
|
||||
(swap! pressed? not)
|
||||
(when on-press
|
||||
(on-press e)))}
|
||||
[rn/image
|
||||
{:source (reactions.resource/get-reaction emoji)
|
||||
:style {:width 20 :height 20}}]])))
|
||||
@@ -4,7 +4,6 @@
|
||||
[quo2.components.settings.reorder-item.types :as types]
|
||||
[quo2.components.settings.reorder-item.view :as reorder-item]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[quo2.components.settings.category.style :as style]
|
||||
[quo2.theme :as quo.theme]
|
||||
@@ -20,8 +19,6 @@
|
||||
[{:keys [label data blur? theme]}]
|
||||
(reagent/with-let [atom-data (reagent/atom data)]
|
||||
[rn/view {:style style/container}
|
||||
(when blur?
|
||||
[rn/view (style/blur-container) [blur/view (style/blur-view)]])
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:size :paragraph-2
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.settings.settings-item.view :as settings-item]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[quo2.components.settings.category.style :as style]
|
||||
[quo2.theme :as quo.theme]))
|
||||
@@ -11,8 +10,6 @@
|
||||
(defn- category-internal
|
||||
[{:keys [label data blur? theme]}]
|
||||
[rn/view {:style style/container}
|
||||
(when blur?
|
||||
[rn/view (style/blur-container) [blur/view (style/blur-view)]])
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:size :paragraph-2
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
|
||||
(defn container
|
||||
[size card? blur? theme]
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:padding-vertical (when (= size :default) 8)
|
||||
:padding-horizontal (when (= size :default) 12)
|
||||
|
||||
@@ -57,8 +57,11 @@
|
||||
(i18n/label :t/days)])])
|
||||
|
||||
(defn- left-side
|
||||
[{:keys [theme title status size blur? description icon subtitle label icon-color customization-color
|
||||
emoji]}]
|
||||
"The description can either be given as a string `description` or a component `custom-subtitle`"
|
||||
[{:keys [theme title status size blur? description custom-subtitle icon subtitle label icon-color
|
||||
customization-color
|
||||
emoji]
|
||||
:as props}]
|
||||
[rn/view {:style style/left-side}
|
||||
[left-title
|
||||
{:title title
|
||||
@@ -70,19 +73,21 @@
|
||||
{:size size
|
||||
:blur? blur?
|
||||
:theme theme}]
|
||||
[left-subtitle
|
||||
{:theme theme
|
||||
:size size
|
||||
:description description
|
||||
:icon icon
|
||||
:icon-color icon-color
|
||||
:blur? blur?
|
||||
:subtitle subtitle
|
||||
:customization-color customization-color
|
||||
:emoji emoji}])])
|
||||
(if custom-subtitle
|
||||
[custom-subtitle props]
|
||||
[left-subtitle
|
||||
{:theme theme
|
||||
:size size
|
||||
:description description
|
||||
:icon icon
|
||||
:icon-color icon-color
|
||||
:blur? blur?
|
||||
:subtitle subtitle
|
||||
:customization-color customization-color
|
||||
:emoji emoji}]))])
|
||||
|
||||
(defn- right-side
|
||||
[{:keys [label icon-right? icon-color communities-list]}]
|
||||
[{:keys [label icon-right? icon icon-color communities-list]}]
|
||||
[rn/view {:style style/right-container}
|
||||
(case label
|
||||
:preview [preview-list/view
|
||||
@@ -95,16 +100,15 @@
|
||||
nil)
|
||||
(when icon-right?
|
||||
[rn/view {:style (style/right-icon label)}
|
||||
[icons/icon
|
||||
(if (= :none label)
|
||||
:i/copy
|
||||
:i/chevron-right)
|
||||
[icons/icon icon
|
||||
{:accessibility-label :icon-right
|
||||
:color icon-color
|
||||
:size 20}]])])
|
||||
|
||||
(def view-internal
|
||||
(fn [{:keys [blur? card? icon-right? label status size theme on-press communities-list] :as props}]
|
||||
(fn [{:keys [blur? card? icon-right? icon label status size theme on-press communities-list
|
||||
container-style]
|
||||
:as props}]
|
||||
(let [icon-color (if (or blur? (= :dark theme))
|
||||
colors/neutral-40
|
||||
colors/neutral-50)]
|
||||
@@ -114,12 +118,13 @@
|
||||
{:accessibility-label :data-item
|
||||
:disabled (not icon-right?)
|
||||
:on-press on-press
|
||||
:style (style/container size card? blur? theme)}
|
||||
:style (merge (style/container size card? blur? theme) container-style)}
|
||||
[left-side props]
|
||||
(when (and (= :default status) (not= :small size))
|
||||
[right-side
|
||||
{:label label
|
||||
:icon-right? icon-right?
|
||||
:icon icon
|
||||
:icon-color icon-color
|
||||
:communities-list communities-list}])]))))
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
(defn reorder-item
|
||||
[item type {:keys [blur? drag]}]
|
||||
(case type
|
||||
(condp = type
|
||||
types/item [item/view item blur? drag]
|
||||
types/placeholder [placeholder/view item]
|
||||
types/skeleton [skeleton/view]
|
||||
|
||||
@@ -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]]])
|
||||
|
||||
|
||||
@@ -1,14 +1,44 @@
|
||||
(ns quo2.components.share.qr-code.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def container
|
||||
{:flex-direction :row
|
||||
:justify-content :center})
|
||||
(defn container
|
||||
[size]
|
||||
(if size
|
||||
{:width size
|
||||
:height size}
|
||||
{:flex 1}))
|
||||
|
||||
(defn image
|
||||
[width height]
|
||||
{:width width
|
||||
:height height
|
||||
(def avatar-overlay
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:right 0
|
||||
:left 0
|
||||
:bottom 0
|
||||
:justify-content :center
|
||||
:align-items :center})
|
||||
|
||||
(defn qr-image
|
||||
[size]
|
||||
{:width (or size "100%")
|
||||
:height (or size "100%")
|
||||
:background-color colors/white-opa-70
|
||||
:border-radius 12
|
||||
:aspect-ratio 1})
|
||||
|
||||
(def ^:private avatar-container-common
|
||||
{:width 68
|
||||
:height 68
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color colors/white})
|
||||
|
||||
(def avatar-container-circular
|
||||
(assoc avatar-container-common :border-radius 33))
|
||||
|
||||
(def avatar-container-rounded
|
||||
(assoc avatar-container-common :border-radius 16))
|
||||
|
||||
(def community-logo-image
|
||||
{:width 64
|
||||
:height 64
|
||||
:border-radius 32})
|
||||
|
||||
@@ -1,12 +1,76 @@
|
||||
(ns quo2.components.share.qr-code.view
|
||||
(:require [quo2.components.share.qr-code.style :as style]
|
||||
(:require [quo2.components.avatars.account-avatar.view :as account-avatar]
|
||||
[quo2.components.avatars.channel-avatar.view :as channel-avatar]
|
||||
[quo2.components.avatars.user-avatar.view :as user-avatar]
|
||||
[quo2.components.avatars.wallet-user-avatar :as wallet-avatar]
|
||||
[quo2.components.share.qr-code.style :as style]
|
||||
[react-native.core :as rn]
|
||||
[react-native.fast-image :as fast-image]))
|
||||
|
||||
(defn qr-code
|
||||
[{:keys [source width height]}]
|
||||
[rn/view
|
||||
{:style style/container}
|
||||
(defn- avatar-image
|
||||
[{avatar-type :avatar
|
||||
:as props}]
|
||||
[rn/view {:style style/avatar-overlay}
|
||||
[rn/view
|
||||
{:style (if (= avatar-type :wallet-account)
|
||||
style/avatar-container-rounded
|
||||
style/avatar-container-circular)}
|
||||
(case avatar-type
|
||||
:profile
|
||||
[user-avatar/user-avatar
|
||||
(assoc props
|
||||
:size :size-64
|
||||
:status-indicator? false
|
||||
:online? false
|
||||
:ring? false)]
|
||||
|
||||
:wallet-account
|
||||
[account-avatar/view (assoc props :size :size-64 :type :default)]
|
||||
|
||||
:community
|
||||
[rn/image
|
||||
{:style style/community-logo-image
|
||||
:source (:picture props)}]
|
||||
|
||||
:channel
|
||||
[channel-avatar/view (assoc props :locked? nil :size :size-64)]
|
||||
|
||||
:saved-address
|
||||
[wallet-avatar/wallet-user-avatar (assoc props :size :size-64)]
|
||||
|
||||
nil)]])
|
||||
|
||||
(defn view
|
||||
"Receives a URL to show a QR code with an avatar (optional) over it.
|
||||
Parameters:
|
||||
- qr-image-uri: A valid uri representing the QR code to display using `fast-image`
|
||||
- size: if not provided, the QR code image will grow according to its parent
|
||||
- avatar: Type of the avatar, defaults to `:none` and it can be:
|
||||
`:profile`, `:wallet-account`, `:community`, `:channel` or `:saved-address`
|
||||
|
||||
Depending on the type selected, different properties are accepted:
|
||||
`:profile`:
|
||||
- profile-picture
|
||||
- full-name
|
||||
- customization-color
|
||||
`:wallet-account`
|
||||
- emoji
|
||||
- customization-color
|
||||
`:community`
|
||||
- picture
|
||||
`:channel`
|
||||
- emoji
|
||||
- customization-color
|
||||
`:saved-address`
|
||||
- f-name
|
||||
- l-name
|
||||
- customization-color"
|
||||
[{:keys [avatar size qr-image-uri]
|
||||
:or {avatar :none}
|
||||
:as props}]
|
||||
[rn/view {:style (style/container size)}
|
||||
[fast-image/fast-image
|
||||
{:source source
|
||||
:style (style/image width height)}]])
|
||||
{:style (style/qr-image size)
|
||||
:source {:uri qr-image-uri}}]
|
||||
(when-not (= avatar :none)
|
||||
[avatar-image props])])
|
||||
|
||||
@@ -8,15 +8,11 @@
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn view
|
||||
[{:keys [source link-title
|
||||
url-on-press url-on-long-press qr-url share-on-press]}]
|
||||
[{:keys [qr-image-uri link-title url-on-press url-on-long-press qr-url share-on-press]}]
|
||||
[blur/ios-view
|
||||
{:style style/qr-code-container
|
||||
:blur-type :light}
|
||||
[qr-code/qr-code
|
||||
{:source source
|
||||
:width "100%"
|
||||
:height 311}]
|
||||
[qr-code/view {:qr-image-uri qr-image-uri}]
|
||||
[rn/view {:style style/profile-address-container}
|
||||
[rn/view {:style style/profile-address-column}
|
||||
[text/text
|
||||
|
||||
@@ -33,12 +33,15 @@
|
||||
[theme blur?]
|
||||
{:border-width 1
|
||||
:border-radius 6
|
||||
:margin-right 8
|
||||
:margin-right 4
|
||||
:padding-horizontal 2
|
||||
:border-color (if-not blur?
|
||||
(colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
|
||||
colors/white-opa-10)})
|
||||
|
||||
(def timestamp-container
|
||||
{:margin-left 4})
|
||||
|
||||
(defn timestamp
|
||||
[theme blur?]
|
||||
{:color (if-not blur?
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
:size :label
|
||||
:style (style/transaction-counter theme)}
|
||||
(i18n/label :t/x-counter {:counter counter})]])
|
||||
[rn/view
|
||||
[rn/view {:style style/timestamp-container}
|
||||
[text/text
|
||||
{:weight :regular
|
||||
:size :label
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
(def container-info
|
||||
{:padding-horizontal 20
|
||||
:padding-top 12
|
||||
:flex-grow 1
|
||||
:padding-bottom 32
|
||||
:flex-grow 1
|
||||
:max-height 98})
|
||||
|
||||
(def container-info-top
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
(:require
|
||||
quo2.components.avatars.account-avatar.view
|
||||
quo2.components.avatars.channel-avatar.view
|
||||
quo2.components.avatars.collection-avatar.view
|
||||
quo2.components.avatars.group-avatar.view
|
||||
quo2.components.avatars.icon-avatar
|
||||
quo2.components.avatars.user-avatar.view
|
||||
@@ -72,6 +73,7 @@
|
||||
quo2.components.list-items.menu-item
|
||||
quo2.components.list-items.preview-list.view
|
||||
quo2.components.list-items.saved-address.view
|
||||
quo2.components.list-items.saved-contact-address.view
|
||||
quo2.components.list-items.token-value.view
|
||||
quo2.components.list-items.user-list
|
||||
quo2.components.loaders.skeleton-list.view
|
||||
@@ -97,12 +99,13 @@
|
||||
quo2.components.profile.profile-card.view
|
||||
quo2.components.profile.select-profile.view
|
||||
quo2.components.profile.showcase-nav.view
|
||||
quo2.components.reactions.reaction
|
||||
quo2.components.record-audio.record-audio.view
|
||||
quo2.components.record-audio.soundtrack.view
|
||||
quo2.components.selectors.disclaimer.view
|
||||
quo2.components.selectors.filter.view
|
||||
quo2.components.selectors.reactions.view
|
||||
quo2.components.selectors.reactions-selector.view
|
||||
quo2.components.selectors.react.view
|
||||
quo2.components.selectors.react-selector.view
|
||||
quo2.components.selectors.selectors.view
|
||||
quo2.components.settings.accounts.view
|
||||
quo2.components.settings.data-item.view
|
||||
@@ -146,6 +149,7 @@
|
||||
;;;; Avatar
|
||||
(def account-avatar quo2.components.avatars.account-avatar.view/view)
|
||||
(def channel-avatar quo2.components.avatars.channel-avatar.view/view)
|
||||
(def collection-avatar quo2.components.avatars.collection-avatar.view/view)
|
||||
(def group-avatar quo2.components.avatars.group-avatar.view/view)
|
||||
(def icon-avatar quo2.components.avatars.icon-avatar/icon-avatar)
|
||||
(def user-avatar quo2.components.avatars.user-avatar.view/user-avatar)
|
||||
@@ -267,6 +271,7 @@
|
||||
(def user-list quo2.components.list-items.user-list/user-list)
|
||||
(def community-list-item quo2.components.list-items.community.view/view)
|
||||
(def saved-address quo2.components.list-items.saved-address.view/view)
|
||||
(def saved-contact-address quo2.components.list-items.saved-contact-address.view/view)
|
||||
(def token-value quo2.components.list-items.token-value.view/view)
|
||||
|
||||
;;;; Loaders
|
||||
@@ -303,10 +308,6 @@
|
||||
(def select-profile quo2.components.profile.select-profile.view/view)
|
||||
(def showcase-nav quo2.components.profile.showcase-nav.view/view)
|
||||
|
||||
;;;; Reactions
|
||||
(def reaction quo2.components.reactions.reaction/reaction)
|
||||
(def add-reaction quo2.components.reactions.reaction/add-reaction)
|
||||
|
||||
;;;; Record Audio
|
||||
(def record-audio quo2.components.record-audio.record-audio.view/record-audio)
|
||||
(def soundtrack quo2.components.record-audio.soundtrack.view/f-soundtrack)
|
||||
@@ -315,7 +316,9 @@
|
||||
(def author quo2.components.messages.author.view/author)
|
||||
(def disclaimer quo2.components.selectors.disclaimer.view/view)
|
||||
(def filter quo2.components.selectors.filter.view/view)
|
||||
(def reactions quo2.components.selectors.reactions.view/view)
|
||||
(def reactions-selector quo2.components.selectors.reactions-selector.view/view)
|
||||
(def react quo2.components.selectors.react.view/view)
|
||||
(def react-selector quo2.components.selectors.react-selector.view/view)
|
||||
(def checkbox quo2.components.selectors.selectors.view/checkbox)
|
||||
(def toggle quo2.components.selectors.selectors.view/toggle)
|
||||
(def radio quo2.components.selectors.selectors.view/radio)
|
||||
@@ -331,7 +334,7 @@
|
||||
(def settings-item quo2.components.settings.settings-item.view/view)
|
||||
|
||||
;;;; Share
|
||||
(def qr-code quo2.components.share.qr-code.view/qr-code)
|
||||
(def qr-code quo2.components.share.qr-code.view/view)
|
||||
(def share-qr-code quo2.components.share.share-qr-code.view/view)
|
||||
|
||||
;;;; SWITCHER
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
[quo2.components.list-items.community.component-spec]
|
||||
[quo2.components.list-items.dapp.component-spec]
|
||||
[quo2.components.list-items.saved-address.component-spec]
|
||||
[quo2.components.list-items.saved-contact-address.component-spec]
|
||||
[quo2.components.list-items.token-value.component-spec]
|
||||
[quo2.components.loaders.skeleton-list.component-spec]
|
||||
[quo2.components.markdown.text-component-spec]
|
||||
@@ -58,7 +59,7 @@
|
||||
[quo2.components.record-audio.soundtrack.component-spec]
|
||||
[quo2.components.selectors.disclaimer.component-spec]
|
||||
[quo2.components.selectors.filter.component-spec]
|
||||
[quo2.components.selectors.reactions.component-spec]
|
||||
[quo2.components.selectors.reactions-selector.component-spec]
|
||||
[quo2.components.selectors.selectors.component-spec]
|
||||
[quo2.components.settings.reorder-item.component-spec]
|
||||
[quo2.components.settings.settings-item.component-spec]
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
{:keycard-logo (js/require "../resources/images/ui2/keycard-logo.png")
|
||||
:keycard-chip-light (js/require "../resources/images/ui2/keycard-chip-light.png")
|
||||
:keycard-chip-dark (js/require "../resources/images/ui2/keycard-chip-dark.png")
|
||||
:keycard-watermark (js/require "../resources/images/ui2/keycard-watermark.png")})
|
||||
:keycard-watermark (js/require "../resources/images/ui2/keycard-watermark.png")
|
||||
:bored-ape (js/require "../resources/images/mock2/bored-ape.png")})
|
||||
|
||||
(defn get-image
|
||||
[k]
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
[quo2.foundations.colors :as quo2.colors]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.utils.deprecated-types :as types]
|
||||
[status-im.ui.components.emoji-thumbnail.styles :as emoji-thumbnail-styles]
|
||||
[status-im.utils.universal-links.core :as universal-links]
|
||||
[status-im.bottom-sheet.events :as bottom-sheet]
|
||||
[status-im2.common.toasts.events :as toasts]
|
||||
@@ -457,50 +456,17 @@
|
||||
[{:keys [db]}]
|
||||
{:db (assoc db :communities/create-channel {})})
|
||||
|
||||
(rf/defn invite-people-pressed
|
||||
{:events [:communities/invite-people-pressed]}
|
||||
[cofx id]
|
||||
(rf/merge cofx
|
||||
(reset-community-id-input id)
|
||||
(bottom-sheet/hide-bottom-sheet-old)
|
||||
(navigation/open-modal :invite-people-community {:invite? true})))
|
||||
(re-frame/reg-event-fx :communities/invite-people-pressed
|
||||
(fn [{:keys [db]} [id]]
|
||||
{:db (assoc db :communities/community-id-input id)
|
||||
:fx [[:dispatch [:hide-bottom-sheet]]
|
||||
[:dispatch [:open-modal :invite-people-community {:invite? true}]]]}))
|
||||
|
||||
(rf/defn share-community-pressed
|
||||
{:events [:communities/share-community-pressed]}
|
||||
[cofx id]
|
||||
(rf/merge cofx
|
||||
(reset-community-id-input id)
|
||||
(bottom-sheet/hide-bottom-sheet-old)
|
||||
(navigation/open-modal :invite-people-community {})))
|
||||
|
||||
(rf/defn create-channel-pressed
|
||||
{:events [::create-channel-pressed]}
|
||||
[{:keys [db] :as cofx} id]
|
||||
(rf/merge cofx
|
||||
(reset-community-id-input id)
|
||||
(reset-channel-info)
|
||||
(rf/dispatch [::create-channel-fields
|
||||
(rand-nth emoji-thumbnail-styles/emoji-picker-default-thumbnails)])
|
||||
(navigation/open-modal :create-community-channel {:community-id id})))
|
||||
|
||||
(rf/defn edit-channel-pressed
|
||||
{:events [::edit-channel-pressed]}
|
||||
[{:keys [db] :as cofx} community-id chat-name description color emoji chat-id category-id position]
|
||||
(let [{:keys [color emoji]} (if (string/blank? emoji)
|
||||
(rand-nth emoji-thumbnail-styles/emoji-picker-default-thumbnails)
|
||||
{:color color :emoji emoji})]
|
||||
(rf/merge cofx
|
||||
{:db (assoc db
|
||||
:communities/create-channel
|
||||
{:name chat-name
|
||||
:description description
|
||||
:color color
|
||||
:community-id community-id
|
||||
:emoji emoji
|
||||
:edit-channel-id chat-id
|
||||
:category-id category-id
|
||||
:position position})}
|
||||
(navigation/open-modal :edit-community-channel nil))))
|
||||
(re-frame/reg-event-fx :communities/share-community-pressed
|
||||
(fn [{:keys [db]} [id]]
|
||||
{:db (assoc db :communities/community-id-input id)
|
||||
:fx [[:dispatch [:hide-bottom-sheet]]
|
||||
[:dispatch [:open-modal :invite-people-community {}]]]}))
|
||||
|
||||
(rf/defn community-created
|
||||
{:events [::community-created]}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
(defn- rpc->type
|
||||
[{:keys [type name] :as chat}]
|
||||
(case type
|
||||
(condp = type
|
||||
notification-types/reply
|
||||
(assoc chat
|
||||
:chat-name name
|
||||
|
||||
@@ -54,7 +54,6 @@
|
||||
status-im2.contexts.shell.jump-to.events
|
||||
status-im2.contexts.onboarding.events
|
||||
status-im.chat.models.gaps
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im2.common.theme.core :as theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
@@ -250,10 +249,7 @@
|
||||
:on-success (fn [on-ramps]
|
||||
(re-frame/dispatch [::crypto-loaded on-ramps]))}]})
|
||||
|
||||
(rf/defn open-buy-crypto-screen
|
||||
{:events [:buy-crypto.ui/open-screen]}
|
||||
[cofx]
|
||||
(rf/merge
|
||||
cofx
|
||||
(navigation/open-modal :buy-crypto nil)
|
||||
(wallet/keep-watching-history)))
|
||||
(re-frame/reg-event-fx :buy-crypto.ui/open-screen
|
||||
(fn []
|
||||
{:fx [[:dispatch [:wallet/keep-watching]]
|
||||
[:dispatch [:open-modal :buy-crypto nil]]]}))
|
||||
|
||||
@@ -41,13 +41,16 @@
|
||||
|
||||
(defn contact-two-names-by-identity
|
||||
[contact profile contact-identity]
|
||||
(let [me? (= (:public-key profile) contact-identity)]
|
||||
(let [{:keys [public-key preferred-name display-name]} profile
|
||||
{:keys [primary-name secondary-name]} contact
|
||||
me? (= public-key contact-identity)]
|
||||
(if me?
|
||||
[(or (:preferred-name profile)
|
||||
(:display-name profile)
|
||||
(:primary-name contact)
|
||||
(gfycat/generate-gfy contact-identity))]
|
||||
[(:primary-name contact) (:secondary-name contact)])))
|
||||
[(cond
|
||||
(not (string/blank? preferred-name)) preferred-name
|
||||
(not (string/blank? display-name)) display-name
|
||||
(not (string/blank? primary-name)) primary-name
|
||||
:else (gfycat/generate-gfy contact-identity))]
|
||||
[primary-name secondary-name])))
|
||||
|
||||
(defn displayed-photo
|
||||
[{:keys [images]}]
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
(ns status-im.stickers.core
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.config :as config]
|
||||
[utils.re-frame :as rf]
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.wallet.utils :as wallet.utils]
|
||||
[status-im2.constants :as constants]
|
||||
[utils.ethereum.chain :as chain]
|
||||
[status-im.wallet.utils :as wallet.utils]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:stickers/set-pending-timeout-fx
|
||||
@@ -115,12 +112,6 @@
|
||||
[{:keys [db]} packs]
|
||||
{:db (assoc db :stickers/recent-stickers packs)})
|
||||
|
||||
(rf/defn open-sticker-pack
|
||||
{:events [:stickers/open-sticker-pack]}
|
||||
[{{:networks/keys [current-network]} :db :as cofx} id]
|
||||
(when (and id (or config/stickers-test-enabled? (string/starts-with? current-network "mainnet")))
|
||||
(navigation/open-modal cofx :stickers-pack {:id id})))
|
||||
|
||||
(rf/defn select-pack
|
||||
{:events [:stickers/select-pack]}
|
||||
[{:keys [db]} id]
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
[shadow.test :as st]
|
||||
[shadow.test.env :as env]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im2.setup.interceptors :as interceptors]
|
||||
status-im2.setup.i18n-resources))
|
||||
|
||||
(defonce repl? (atom false))
|
||||
@@ -113,6 +114,7 @@
|
||||
(defn ^:export main
|
||||
[& args]
|
||||
(reset-test-data!)
|
||||
(interceptors/register-global-interceptors)
|
||||
(rf/set-mergeable-keys #{:filters/load-filters
|
||||
:pairing/set-installation-metadata
|
||||
:dispatch-n
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
[status-im.wallet.core :as wallet]))
|
||||
|
||||
(rf/defn process-next
|
||||
{:events [:transport/process-next]}
|
||||
[cofx ^js response-js sync-handler]
|
||||
(if sync-handler
|
||||
(sync-handler cofx response-js true)
|
||||
@@ -60,7 +61,7 @@
|
||||
(js-delete response-js "chats")
|
||||
(rf/merge cofx
|
||||
(process-next response-js sync-handler)
|
||||
(chat.events/ensure-chats (map data-store.chats/<-rpc (types/js->clj chats)))))
|
||||
#(chat.events/ensure-chats % [(map data-store.chats/<-rpc (types/js->clj chats))])))
|
||||
|
||||
(seq messages)
|
||||
(models.message/receive-many cofx response-js)
|
||||
|
||||
@@ -199,10 +199,11 @@
|
||||
(defn contact-request-status-label
|
||||
[state]
|
||||
[rn/view {:style (style/contact-request-status-label state)}
|
||||
(case state
|
||||
(condp = state
|
||||
constants/contact-request-message-state-pending [contact-request-status-pending]
|
||||
constants/contact-request-message-state-accepted [contact-request-status-accepted]
|
||||
constants/contact-request-message-state-declined [contact-request-status-declined])])
|
||||
constants/contact-request-message-state-declined [contact-request-status-declined]
|
||||
nil)])
|
||||
|
||||
;;;; SYSTEM
|
||||
|
||||
|
||||
@@ -389,10 +389,11 @@
|
||||
:background-color (when (= :retry state)
|
||||
colors/blue-light)
|
||||
:border-width 1
|
||||
:border-color (case state
|
||||
:border-color (condp = state
|
||||
constants/contact-request-message-state-accepted colors/green-transparent-10
|
||||
constants/contact-request-message-state-declined colors/red-light
|
||||
constants/contact-request-message-state-pending colors/gray-lighter)
|
||||
constants/contact-request-message-state-pending colors/gray-lighter
|
||||
nil)
|
||||
:padding-vertical 10
|
||||
:padding-horizontal 16})
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
[status-im.utils.gfycat.core :as gfy]
|
||||
[status-im.utils.universal-links.utils :as universal-links]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im2.common.qr-code-viewer.view :as qr-code-viewer]
|
||||
[status-im2.common.qr-codes.view :as qr-codes]
|
||||
[status-im2.config :as config]
|
||||
[utils.i18n :as i18n])
|
||||
(:require-macros [status-im.utils.views :as views]))
|
||||
@@ -32,7 +32,9 @@
|
||||
[react/view {:on-layout #(reset! width (-> ^js % .-nativeEvent .-layout .-width))}
|
||||
[react/view {:style {:padding-top 16 :padding-horizontal 16}}
|
||||
(when @width
|
||||
[qr-code-viewer/qr-code-view (- @width 32) address])
|
||||
[qr-codes/qr-code
|
||||
{:url address
|
||||
:size (- @width 32)}])
|
||||
(when ens-name
|
||||
[react/view
|
||||
[copyable-text/copyable-text-view
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
[reagent.core :as reagent]
|
||||
[utils.ethereum.eip.eip55 :as eip55]
|
||||
[status-im.ethereum.eip681 :as eip681]
|
||||
[utils.i18n :as i18n]
|
||||
[status-im.ui.components.copyable-text :as copyable-text]
|
||||
[status-im2.common.qr-code-viewer.view :as qr-code-viewer]
|
||||
[status-im.ui.components.react :as react])
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im2.common.qr-codes.view :as qr-codes]
|
||||
[utils.i18n :as i18n])
|
||||
(:require-macros [status-im.utils.views :as views]))
|
||||
|
||||
(views/defview share-address
|
||||
@@ -18,9 +18,9 @@
|
||||
[react/view {:on-layout #(reset! width (-> ^js % .-nativeEvent .-layout .-width))}
|
||||
[react/view {:style {:padding-top 16 :padding-horizontal 16}}
|
||||
(when @width
|
||||
[qr-code-viewer/qr-code-view
|
||||
(- @width 32)
|
||||
(eip681/generate-uri address {:chain-id chain-id})])
|
||||
[qr-codes/qr-code
|
||||
{:url (eip681/generate-uri address {:chain-id chain-id})
|
||||
:size (- @width 32)}])
|
||||
[copyable-text/copyable-text-view
|
||||
{:label :t/ethereum-address
|
||||
:container-style {:margin-top 12 :margin-bottom 4}
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
:pending (transaction-icon :main-icons/arrow-right
|
||||
colors/black-transparent
|
||||
colors/gray)
|
||||
(throw (str "Unknown transaction type: " k))))
|
||||
(throw (js/Error. (str "Unknown transaction type: " k)))))
|
||||
|
||||
(defn render-transaction
|
||||
[{:keys [label contact address contact-accessibility-label
|
||||
|
||||
@@ -197,12 +197,10 @@
|
||||
:on-success #(re-frame/dispatch [::collectible-assets-fetch-success address
|
||||
collectible-slug %])}]}))
|
||||
|
||||
(rf/defn show-nft-details
|
||||
{:events [::show-nft-details]}
|
||||
[cofx asset]
|
||||
(rf/merge cofx
|
||||
{:db (assoc (:db cofx) :wallet/selected-collectible asset)}
|
||||
(navigation/open-modal :nft-details {})))
|
||||
(re-frame/reg-event-fx ::show-nft-details
|
||||
(fn [{:keys [db]} [asset]]
|
||||
{:db (assoc db :wallet/selected-collectible asset)
|
||||
:fx [[:dispatch [:open-modal :nft-details {}]]]}))
|
||||
|
||||
(defn rpc->token
|
||||
[tokens]
|
||||
@@ -610,14 +608,11 @@
|
||||
{:db (assoc-in db [:wallet/prepare-transaction field] value)}
|
||||
(bottom-sheet/hide-bottom-sheet-old)))
|
||||
|
||||
(rf/defn navigate-to-recipient-code
|
||||
{:events [:wallet.send/navigate-to-recipient-code]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc :wallet/recipient {}))}
|
||||
(bottom-sheet/hide-bottom-sheet-old)
|
||||
(navigation/open-modal :recipient nil)))
|
||||
(re-frame/reg-event-fx :wallet.send/navigate-to-recipient-code
|
||||
(fn [{:keys [db]}]
|
||||
{:db (-> db (assoc :wallet/recipient {}))
|
||||
:fx [[:dispatch [:bottom-sheet/hide-old]]
|
||||
[:dispatch [:open-modal :recipient nil]]]}))
|
||||
|
||||
(rf/defn show-delete-account-confirmation
|
||||
{:events [:wallet.settings/show-delete-account-confirmation]}
|
||||
|
||||
@@ -6,18 +6,18 @@
|
||||
|
||||
(deftest test-too-precise-amount?
|
||||
(testing "try both decimal and scientific or hex format"
|
||||
(is (= false (#'status-im.wallet.db/too-precise-amount? "100" 2)))
|
||||
(is (= false (#'status-im.wallet.db/too-precise-amount? "100" 0)))
|
||||
(is (= true (#'status-im.wallet.db/too-precise-amount? "100.1" 0)))
|
||||
(is (= false (#'status-im.wallet.db/too-precise-amount? "100.23" 2)))
|
||||
(is (= true (#'status-im.wallet.db/too-precise-amount? "100.233" 2)))
|
||||
(is (= true (#'status-im.wallet.db/too-precise-amount? "100.0000000000000000001" 18)))
|
||||
(is (= false (#'status-im.wallet.db/too-precise-amount? "100.000000000000000001" 18)))
|
||||
(is (= false (#'status-im.wallet.db/too-precise-amount? "1e-18" 18)))
|
||||
(is (= true (#'status-im.wallet.db/too-precise-amount? "1e-19" 18)))
|
||||
(is (= true (#'status-im.wallet.db/too-precise-amount? "0xa.a" 2))) ;; 0xa.a is 10.625
|
||||
(is (= false (#'status-im.wallet.db/too-precise-amount? "0xa.a" 3)))
|
||||
(is (= false (#'status-im.wallet.db/too-precise-amount? "1000" 3)))))
|
||||
(is (false? (#'status-im.wallet.db/too-precise-amount? "100" 2)))
|
||||
(is (false? (#'status-im.wallet.db/too-precise-amount? "100" 0)))
|
||||
(is (true? (#'status-im.wallet.db/too-precise-amount? "100.1" 0)))
|
||||
(is (false? (#'status-im.wallet.db/too-precise-amount? "100.23" 2)))
|
||||
(is (true? (#'status-im.wallet.db/too-precise-amount? "100.233" 2)))
|
||||
(is (true? (#'status-im.wallet.db/too-precise-amount? "100.0000000000000000001" 18)))
|
||||
(is (false? (#'status-im.wallet.db/too-precise-amount? "100.000000000000000001" 18)))
|
||||
(is (false? (#'status-im.wallet.db/too-precise-amount? "1e-18" 18)))
|
||||
(is (true? (#'status-im.wallet.db/too-precise-amount? "1e-19" 18)))
|
||||
(is (true? (#'status-im.wallet.db/too-precise-amount? "0xa.a" 2))) ;; 0xa.a is 10.625
|
||||
(is (false? (#'status-im.wallet.db/too-precise-amount? "0xa.a" 3)))
|
||||
(is (false? (#'status-im.wallet.db/too-precise-amount? "1000" 3)))))
|
||||
|
||||
(defn- equal-results?
|
||||
[a b]
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
(ns status-im.wallet.swap.core
|
||||
(:require [re-frame.db :as re-frame.db]
|
||||
[re-frame.core :as re-frame]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im2.navigation.events :as navigation]))
|
||||
|
||||
(rf/defn open-asset-selector-modal
|
||||
"source? true signinfies we are selecting the source asset. false implies selection of sink asset"
|
||||
{:events [::open-asset-selector-modal]}
|
||||
[{:keys [db]} source?]
|
||||
(rf/merge {:db (assoc db :wallet/modal-selecting-source-token? source?)}
|
||||
(navigation/open-modal :swap-asset-selector {})))
|
||||
;; "source? true" means we are selecting the source asset. false implies
|
||||
;; selection of sink asset."
|
||||
(re-frame/reg-event-fx ::open-asset-selector-modal
|
||||
(fn [{:keys [db]} [source?]]
|
||||
{:db (assoc db :wallet/modal-selecting-source-token? source?)
|
||||
:fx [[:dispatch [:open-modal :swap-asset-selector {}]]]}))
|
||||
|
||||
(rf/defn set-from-token
|
||||
{:events [::set-from-token]}
|
||||
@@ -48,4 +49,3 @@
|
||||
:wallet/all-tokens
|
||||
vals
|
||||
(map #(str (:name %) "-" (:symbol %)))))
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
:border-top-right-radius 20
|
||||
:overflow (when-not selected-item :hidden)
|
||||
:flex 1
|
||||
:padding-bottom (or padding-bottom-override (+ bottom 8))
|
||||
:padding-bottom (or padding-bottom-override (+ bottom))
|
||||
:background-color (if shell?
|
||||
:transparent
|
||||
(colors/theme-colors colors/white colors/neutral-95 theme))})
|
||||
@@ -44,14 +44,21 @@
|
||||
:top 0
|
||||
:bottom 0})
|
||||
|
||||
(defn sheet-content
|
||||
[theme padding-bottom-override insets bottom-margin]
|
||||
{:background-color (colors/theme-colors colors/white colors/neutral-95 theme)
|
||||
:border-top-left-radius 20
|
||||
:border-top-right-radius 20
|
||||
:padding-bottom (or padding-bottom-override (+ (:bottom insets) bottom-margin))})
|
||||
|
||||
(defn selected-item
|
||||
[theme window-height sheet-height {:keys [top]}]
|
||||
[theme top bottom sheet-bottom-margin border-radius]
|
||||
{:position :absolute
|
||||
:bottom 10
|
||||
:max-height (- window-height sheet-height top)
|
||||
:top (when-not sheet-bottom-margin (- 0 top))
|
||||
:bottom bottom
|
||||
:overflow :hidden
|
||||
:left 0
|
||||
:right 0
|
||||
:border-radius 12
|
||||
:border-radius border-radius
|
||||
:margin-horizontal 8
|
||||
:background-color (colors/theme-colors colors/white colors/neutral-95 theme)})
|
||||
:background-color (colors/theme-colors colors/white colors/neutral-90 theme)})
|
||||
|
||||