Compare commits
39
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fba9da9d3 | ||
|
|
f5948fa016 | ||
|
|
919fbf2091 | ||
|
|
728d9d01c5 | ||
|
|
9ac14b6fac | ||
|
|
4414f8ffd3 | ||
|
|
1e8ea3fd16 | ||
|
|
17f5ad79f4 | ||
|
|
d76e64b1bb | ||
|
|
ac675e28eb | ||
|
|
5755d2e21a | ||
|
|
cf2a3bfce7 | ||
|
|
dcda44fab6 | ||
|
|
362aa476ae | ||
|
|
25b088833d | ||
|
|
3395baa966 | ||
|
|
4327653b0b | ||
|
|
26dcc16ea6 | ||
|
|
9ed68ee7d1 | ||
|
|
4d7cf3e94e | ||
|
|
4decba8d00 | ||
|
|
229a806f12 | ||
|
|
abe653c086 | ||
|
|
f047665f75 | ||
|
|
ea3b090265 | ||
|
|
c52bf965f7 | ||
|
|
e260187cf5 | ||
|
|
ca0915c940 | ||
|
|
2b4b357c32 | ||
|
|
19ca8e28a5 | ||
|
|
8978e92042 | ||
|
|
c2c79cc1ac | ||
|
|
affd2a5e76 | ||
|
|
ef99bf2ad6 | ||
|
|
1f6f907d57 | ||
|
|
97b254c514 | ||
|
|
ca2ed9d37e | ||
|
|
e64ff76e0b | ||
|
|
88884064b1 |
@@ -14,6 +14,13 @@
|
||||
clojure.set set
|
||||
clojure.walk walk
|
||||
taoensso.timbre log}}
|
||||
:shadowed-var {:level :error
|
||||
;; We temporarily use :include to define an
|
||||
;; allowlist of core Clojure vars. In the
|
||||
;; future, as we progressively fix shadowed
|
||||
;; vars, we should be able to delete this
|
||||
;; option and lint all vars.
|
||||
:include [count iter key time]}
|
||||
:invalid-arity {:skip-args [status-im.utils.fx/defn utils.re-frame/defn]}
|
||||
;; TODO remove number when this is fixed
|
||||
;; https://github.com/borkdude/clj-kondo/issues/867
|
||||
|
||||
@@ -43,4 +43,4 @@ As a <user|developer|...>, I want to <task> so that <goal>.
|
||||
[comment]: # (if on Android please replicate bug whilst running adb logcat)
|
||||
```
|
||||
...
|
||||
```
|
||||
```
|
||||
|
||||
@@ -14,17 +14,17 @@ WHITE := $(shell tput -Txterm setaf 7)
|
||||
YELLOW := $(shell tput -Txterm setaf 3)
|
||||
RESET := $(shell tput -Txterm sgr0)
|
||||
HELP_FUN = \
|
||||
%help; \
|
||||
while(<>) { push @{$$help{$$2 // 'options'}}, [$$1, $$3] if /^([a-zA-Z\-]+)\s*:.*\#\#(?:@([a-zA-Z\-]+))?\s(.*)$$/ }; \
|
||||
print "Usage: make [target]\n\nSee STARTING_GUIDE.md for more info.\n\n"; \
|
||||
for (sort keys %help) { \
|
||||
print "${WHITE}$$_:${RESET}\n"; \
|
||||
for (@{$$help{$$_}}) { \
|
||||
$$sep = " " x (32 - length $$_->[0]); \
|
||||
print " ${YELLOW}$$_->[0]${RESET}$$sep${GREEN}$$_->[1]${RESET}\n"; \
|
||||
}; \
|
||||
print "\n"; \
|
||||
}
|
||||
%help; \
|
||||
while(<>) { push @{$$help{$$2 // 'options'}}, [$$1, $$3] if /^([a-zA-Z\-]+)\s*:.*\#\#(?:@([a-zA-Z\-]+))?\s(.*)$$/ }; \
|
||||
print "Usage: make [target]\n\nSee STARTING_GUIDE.md for more info.\n\n"; \
|
||||
for (sort keys %help) { \
|
||||
print "${WHITE}$$_:${RESET}\n"; \
|
||||
for (@{$$help{$$_}}) { \
|
||||
$$sep = " " x (32 - length $$_->[0]); \
|
||||
print " ${YELLOW}$$_->[0]${RESET}$$sep${GREEN}$$_->[1]${RESET}\n"; \
|
||||
}; \
|
||||
print "\n"; \
|
||||
}
|
||||
HOST_OS := $(shell uname | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
# This can come from Jenkins
|
||||
@@ -307,6 +307,7 @@ lint: ##@test Run code style checks
|
||||
clj-kondo --config .clj-kondo/config.edn --cache false --lint src && \
|
||||
ALL_CLOJURE_FILES=$(call find_all_clojure_files) && \
|
||||
zprint '{:search-config? true}' -sfc $$ALL_CLOJURE_FILES && \
|
||||
sh scripts/lint-trailing-newline.sh && \
|
||||
yarn prettier
|
||||
|
||||
# NOTE: We run the linter twice because of https://github.com/kkinnear/zprint/issues/271
|
||||
@@ -315,9 +316,9 @@ lint-fix: ##@test Run code style checks and fix issues
|
||||
ALL_CLOJURE_FILES=$(call find_all_clojure_files) && \
|
||||
zprint '{:search-config? true}' -sw $$ALL_CLOJURE_FILES && \
|
||||
zprint '{:search-config? true}' -sw $$ALL_CLOJURE_FILES && \
|
||||
sh scripts/lint-trailing-newline.sh --fix && \
|
||||
yarn prettier
|
||||
|
||||
|
||||
shadow-server: export TARGET := clojure
|
||||
shadow-server:##@ Start shadow-cljs in server mode for watching
|
||||
yarn shadow-cljs server
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
# Version requirements used throughout the Gradle scripts
|
||||
kotlinVersion=1.6.20
|
||||
minSdkVersion=23
|
||||
compileSdkVersion=31
|
||||
targetSdkVersion=31
|
||||
compileSdkVersion=33
|
||||
targetSdkVersion=33
|
||||
buildToolsVersion=31.0.0
|
||||
supportLibVersion=28.0.0
|
||||
# This should match version from nix/mobile/android/maven-and-npm-deps/maven/default.nix
|
||||
|
||||
@@ -74,7 +74,7 @@ pipeline {
|
||||
sh 'cp -f $TEST_ETH_ACCOUNTS_FILE users.py'
|
||||
sh """
|
||||
python3 -m pytest \
|
||||
--numprocesses 4 \
|
||||
--numprocesses 6 \
|
||||
--rerun_count=2 \
|
||||
--testrail_report=True \
|
||||
-m testrail_id \
|
||||
|
||||
@@ -123,7 +123,7 @@ pipeline {
|
||||
sh 'cp -f $TEST_ETH_ACCOUNTS_FILE users.py'
|
||||
sh """
|
||||
python3 -m pytest \
|
||||
--numprocesses 4 \
|
||||
--numprocesses 6 \
|
||||
--rerun_count=2 \
|
||||
--testrail_report=True \
|
||||
-k \"${params.KEYWORD_EXPRESSION}\" \
|
||||
|
||||
@@ -45,4 +45,4 @@ The `State` field in the Pivotal story is used to track the progress of a Pivota
|
||||
| 5 points | 2 - 3 days |
|
||||
| 8 points | ~1 week |
|
||||
|
||||
We should avoid 8 point stories by breaking them down into smaller stories as much as possible.
|
||||
We should avoid 8 point stories by breaking them down into smaller stories as much as possible.
|
||||
|
||||
@@ -80,6 +80,52 @@ This mistake mostly happens with functional components
|
||||
|
||||
it's important to name functional components with `f-` prefix
|
||||
|
||||
### Component props and API scheme to match Figma as closely as possible
|
||||
|
||||
Ideally, the prop names for components (particularly in quo2 Design System) should match the Figma properties as best as possible. This makes it easier for the developer using that component to configure it correctly for the screen it is being used on and avoids unnecessary overwrites and adjustments being made.
|
||||
|
||||
#### Avoid unnecessarily grouping categories to reduce the number of props
|
||||
For example in Figma if there is a component and it has the following variants:
|
||||
|
||||
|theme: "light" blur: "False"|theme: "dark" blur: "False"|theme: "light" blur: "True"|theme: "dark" blur: "True"|
|
||||
|----------------------------|---------------------------|---------------------------|---------------------------|
|
||||
| type :neutral label "ABC" | type :neutral label "ABC" | | |
|
||||
| type :active label "ABC" | type :active label "ABC" | | |
|
||||
| type :danger label "ABC" | type :danger label "ABC" | type :danger label "ABC" | type :danger label "ABC" |
|
||||
|
||||
```clojure
|
||||
;; bad
|
||||
"theme - :light or :dark
|
||||
type - can be :neutral :active :danger :danger-blur"
|
||||
(defn my-component [{:keys [theme type]} label])
|
||||
|
||||
;; good
|
||||
"theme - :light or :dark
|
||||
type - can be :neutral :active :danger
|
||||
blur? - boolean
|
||||
"
|
||||
(defn my-component [{:keys [theme blur? type]} label])
|
||||
```
|
||||
|
||||
Please note this is only for the external API of the component and there should be no restriction of how the component manages its internal API as that will not affect the developer using the component with the issues described above.
|
||||
|
||||
In some cases this is not always possible or does not make sense. However the thought process should be how easy will it be for another developer to use this component with the correct configuration given the screen designs for Figma.
|
||||
|
||||
#### Avoid unnecessarily renaming props
|
||||
In general it can be helpful to avoid renaming props from their counterpart in Figma.
|
||||
|
||||
For example if Figma has sizes `:small`, `:medium` and `:large`
|
||||
|
||||
```clojure
|
||||
;; bad
|
||||
":size - :little, :default or :big"
|
||||
(defn my-component [{:keys [size]}])
|
||||
|
||||
;; good
|
||||
":size - :small, :medium or :large"
|
||||
(defn my-component [{:keys [size]}])
|
||||
```
|
||||
|
||||
### Component styles
|
||||
|
||||
Prefer to define styles in a separate file named `style.cljs`, colocated with
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -833,6 +833,37 @@ void _SaveAccountAndLogin(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
}
|
||||
|
||||
void _CreateAccountAndLogin(const FunctionCallbackInfo<Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
Local<Context> context = isolate->GetCurrentContext();
|
||||
|
||||
if (args.Length() != 1) {
|
||||
// Throw an Error that is passed back to JavaScript
|
||||
isolate->ThrowException(Exception::TypeError(
|
||||
String::NewFromUtf8Literal(isolate, "Wrong number of arguments for SaveAccountAndLogin")));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the argument types
|
||||
|
||||
if (!args[0]->IsString()) {
|
||||
isolate->ThrowException(Exception::TypeError(
|
||||
String::NewFromUtf8Literal(isolate, "Wrong argument type for 'settingsJSON'")));
|
||||
return;
|
||||
}
|
||||
|
||||
String::Utf8Value arg0Obj(isolate, args[0]->ToString(context).ToLocalChecked());
|
||||
char *arg0 = *arg0Obj;
|
||||
|
||||
// Call exported Go function, which returns a C string
|
||||
char *c = CreateAccountAndLogin(arg0);
|
||||
|
||||
Local<String> ret = String::NewFromUtf8(isolate, c).ToLocalChecked();
|
||||
args.GetReturnValue().Set(ret);
|
||||
delete c;
|
||||
|
||||
}
|
||||
|
||||
void _GenerateAlias(const FunctionCallbackInfo<Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
Local<Context> context = isolate->GetCurrentContext();
|
||||
@@ -1929,6 +1960,7 @@ void init(Local<Object> exports) {
|
||||
NODE_SET_METHOD(exports, "hashMessage", _HashMessage);
|
||||
NODE_SET_METHOD(exports, "resetChainData", _ResetChainData);
|
||||
NODE_SET_METHOD(exports, "saveAccountAndLogin", _SaveAccountAndLogin);
|
||||
NODE_SET_METHOD(exports, "createAccountAndLogin", _CreateAccountAndLogin);
|
||||
NODE_SET_METHOD(exports, "generateAlias", _GenerateAlias);
|
||||
NODE_SET_METHOD(exports, "validateMnemonic", _ValidateMnemonic);
|
||||
NODE_SET_METHOD(exports, "multiformatSerializePublicKey", _MultiformatSerializePublicKey);
|
||||
|
||||
@@ -18,4 +18,4 @@
|
||||
"url": "https://github.com/status-im/react-native-status/issues"
|
||||
},
|
||||
"homepage": "https://github.com/status-im/react-native-status#readme"
|
||||
}
|
||||
}
|
||||
|
||||
+36
-51
@@ -9492,16 +9492,16 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "com/google/auto/value/auto-value-annotations/1.10.1",
|
||||
"path": "com/google/auto/value/auto-value-annotations/1.10.2",
|
||||
"repo": "https://repo.maven.apache.org/maven2",
|
||||
"files": {
|
||||
"auto-value-annotations-1.10.1.pom": {
|
||||
"sha1": "72aa2e866fd52dc58222aacc490b6f469ff8a50f",
|
||||
"sha256": "sha256-n7rMhpTRkE37TVrx5KVGD9ZMHKnQBJ0YFFQs0q0osEc="
|
||||
"auto-value-annotations-1.10.2.pom": {
|
||||
"sha1": "bdae7d62039b58f8e6099403bd8d663064e00805",
|
||||
"sha256": "sha256-ck+V7NRFowDEx39LIHU+xe2rcLmth1Hez3CcgWUKdyE="
|
||||
},
|
||||
"auto-value-annotations-1.10.1.jar": {
|
||||
"sha1": "9e5162c15f6033c524134cba05a5e93dc1d37c4b",
|
||||
"sha256": "sha256-pP4KIRkl6TioUQ10F2PuEXGhG/kx9Yke9NTuhPynK+I="
|
||||
"auto-value-annotations-1.10.2.jar": {
|
||||
"sha1": "337954851fc17058d9b4b692b6e67e57b20e14f0",
|
||||
"sha256": "sha256-Pzt+369/u9iGQve9WwlIe43PK55fOhnx63s+U/IPFLo="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -9529,12 +9529,12 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "com/google/auto/value/auto-value-parent/1.10.1",
|
||||
"path": "com/google/auto/value/auto-value-parent/1.10.2",
|
||||
"repo": "https://repo.maven.apache.org/maven2",
|
||||
"files": {
|
||||
"auto-value-parent-1.10.1.pom": {
|
||||
"sha1": "cfd31b18489357b9f2b0acee57d6674394575c37",
|
||||
"sha256": "sha256-9y2jrhi84YuHRM1yM6qDSjLTvR4LRTsV9tujP3lzz+k="
|
||||
"auto-value-parent-1.10.2.pom": {
|
||||
"sha1": "8828fce3eb0708d36059af557545ab9b0c5a82de",
|
||||
"sha256": "sha256-kdaz5RX4jKobwFyqsbvciU/27dY1Se8PCaVYTJeT7mk="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -10186,27 +10186,27 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "com/google/guava/guava-parent/32.0.1-jre",
|
||||
"path": "com/google/guava/guava-parent/32.1.1-jre",
|
||||
"repo": "https://repo.maven.apache.org/maven2",
|
||||
"files": {
|
||||
"guava-parent-32.0.1-jre.pom": {
|
||||
"sha1": "88c9e60e238868208ca8e375a475a23142e52ac6",
|
||||
"sha256": "sha256-Q+0ONrNT9B5et1zXVmZ8ni35fO8G6xYGaWcVih0DTSo="
|
||||
"guava-parent-32.1.1-jre.pom": {
|
||||
"sha1": "01c4a3f0686592f40c1052b273c9b533f6a71e6d",
|
||||
"sha256": "sha256-BqpdGsBo8vgJUw8/9T+1yMlAFSolNiPQtTxPU/WhOj0="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "com/google/guava/guava-testlib/32.0.1-jre",
|
||||
"path": "com/google/guava/guava-testlib/32.1.1-jre",
|
||||
"repo": "https://repo.maven.apache.org/maven2",
|
||||
"files": {
|
||||
"guava-testlib-32.0.1-jre.pom": {
|
||||
"sha1": "a15680d2a8dd88549afda6094b5dc79ec008a5bb",
|
||||
"sha256": "sha256-kPF5mSKi2TRJl+1qpiD6HnzEJuOleB9/ufksEPWFAhs="
|
||||
"guava-testlib-32.1.1-jre.pom": {
|
||||
"sha1": "db7f2a81be1c208ea156572f3e344b6e47b4402f",
|
||||
"sha256": "sha256-8vbywCb/80CvDqzmn1SHRUG62UPLj8nvh7rm0z5yT1w="
|
||||
},
|
||||
"guava-testlib-32.0.1-jre.jar": {
|
||||
"sha1": "53ebb9303be258ba8fda12881f04be811e0f496e",
|
||||
"sha256": "sha256-yXURhJpeCFKA8QbfKwWVZv69KAsRjTPWqeBo0jgQC2M="
|
||||
"guava-testlib-32.1.1-jre.jar": {
|
||||
"sha1": "7cf13628fd8fedd5c612b928858912d9d6573d28",
|
||||
"sha256": "sha256-d+b5cAvGPxiz2iTScB9BucnhzEpXNG8hztZssAZtojU="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -10377,16 +10377,16 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "com/google/guava/guava/32.0.1-jre",
|
||||
"path": "com/google/guava/guava/32.1.1-jre",
|
||||
"repo": "https://repo.maven.apache.org/maven2",
|
||||
"files": {
|
||||
"guava-32.0.1-jre.pom": {
|
||||
"sha1": "4b29ff9dfc268252e73839b0f7324ef705e07108",
|
||||
"sha256": "sha256-QsJX9/c203ezGv7u6XirJtcwzXCvYN3nZi4YI1LiSCo="
|
||||
"guava-32.1.1-jre.pom": {
|
||||
"sha1": "0e5cbc6d9046ce986b121a842f8d30ee6d81a900",
|
||||
"sha256": "sha256-LJBx19FSKwx2IFfDToub+uOZJ6DrdVw2qnZRlyGHDXs="
|
||||
},
|
||||
"guava-32.0.1-jre.jar": {
|
||||
"sha1": "6e5d51a72d142f2d40a57dfb897188b36a95b489",
|
||||
"sha256": "sha256-vX+iJ1kfuFCWd9DREiz5UVjzuKn0VlP1goHYefbcSMU="
|
||||
"guava-32.1.1-jre.jar": {
|
||||
"sha1": "ad575652d84153075dd41ec6177ccb15251262b2",
|
||||
"sha256": "sha256-kfu6N/HIslHPnqnn06Np63nrHmpd8dS79IPdA4B0AoE="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -14254,16 +14254,16 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/checkerframework/checker-qual/3.35.0",
|
||||
"path": "org/checkerframework/checker-qual/3.36.0",
|
||||
"repo": "https://repo.maven.apache.org/maven2",
|
||||
"files": {
|
||||
"checker-qual-3.35.0.pom": {
|
||||
"sha1": "5211a7196b70c37b573e3405d14661cd82e1eddb",
|
||||
"sha256": "sha256-CzlY7JehFV7QAHwXbMICwUrdZm1PV1gPuhzpy2mb+KM="
|
||||
"checker-qual-3.36.0.pom": {
|
||||
"sha1": "6718527e5d8619731637618c68b4d49aa1649c0d",
|
||||
"sha256": "sha256-kLwP0YLqKfP2kkuLYmzMaqTmSm1Apw7klU1j4gb/zvQ="
|
||||
},
|
||||
"checker-qual-3.35.0.jar": {
|
||||
"sha1": "3baabaf8eecea6e9e22b8e39cd25953ff4813e0e",
|
||||
"sha256": "sha256-IQYPqght/eyDCkD5RgZ3p1673P/nzcASrRBp6cwwqVk="
|
||||
"checker-qual-3.36.0.jar": {
|
||||
"sha1": "62ea2b911acf3a3eecd25a1a2986864b7403f6d2",
|
||||
"sha256": "sha256-uj7BaeB28uXYLfpRQubunxbnayvvMMrc5FV+1fq3gu0="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -15304,21 +15304,6 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/jetbrains/kotlin/kotlin-android-extensions-runtime/1.6.20",
|
||||
"repo": "https://repo.maven.apache.org/maven2",
|
||||
"files": {
|
||||
"kotlin-android-extensions-runtime-1.6.20.pom": {
|
||||
"sha1": "ebb28a424c03b500fec21a389cb8e5211abc4199",
|
||||
"sha256": "sha256-aJZg78aYpodPIR0zSpaxDQAoHlc+4lck0kQiysDpJCk="
|
||||
},
|
||||
"kotlin-android-extensions-runtime-1.6.20.jar": {
|
||||
"sha1": "e0d69c8bf97c1f31ef152fb1d53507d9c2ee6b0c",
|
||||
"sha256": "sha256-rIkvod8Te+3ooK2xan7esT1tw4ly5/Ic5fsChSvIY0s="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/jetbrains/kotlin/kotlin-android-extensions/1.6.10",
|
||||
"repo": "https://repo.maven.apache.org/maven2",
|
||||
|
||||
@@ -717,7 +717,6 @@ org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.4.1
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.0
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.2
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1
|
||||
org.jetbrains.kotlin:kotlin-android-extensions-runtime:1.6.20
|
||||
org.jetbrains.kotlin:kotlin-android-extensions:1.6.20
|
||||
org.jetbrains.kotlin:kotlin-annotations-jvm:1.3.72
|
||||
org.jetbrains.kotlin:kotlin-annotation-processing-gradle:1.6.20
|
||||
|
||||
@@ -634,10 +634,10 @@ https://repo.maven.apache.org/maven2/com/google/auto/auto-parent/6/auto-parent-6
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/auto-parent/7/auto-parent-7.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-annotations/1.6.2/auto-value-annotations-1.6.2.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-annotations/1.6.3/auto-value-annotations-1.6.3.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-annotations/1.10.1/auto-value-annotations-1.10.1.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-annotations/1.10.2/auto-value-annotations-1.10.2.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-parent/1.6.2/auto-value-parent-1.6.2.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-parent/1.6.3/auto-value-parent-1.6.3.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-parent/1.10.1/auto-value-parent-1.10.1.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-parent/1.10.2/auto-value-parent-1.10.2.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value/1.5.2/auto-value-1.5.2.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/code/findbugs/jsr305/1.3.9/jsr305-1.3.9.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/code/findbugs/jsr305/3.0.1/jsr305-3.0.1.pom
|
||||
@@ -688,8 +688,8 @@ https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/29.0-jre/guav
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/30.1-android/guava-parent-30.1-android.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/30.1-jre/guava-parent-30.1-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/31.0.1-jre/guava-parent-31.0.1-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/32.0.1-jre/guava-parent-32.0.1-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava-testlib/32.0.1-jre/guava-testlib-32.0.1-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/32.1.1-jre/guava-parent-32.1.1-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava-testlib/32.1.1-jre/guava-testlib-32.1.1-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava/17.0/guava-17.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava/22.0/guava-22.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava/23.0/guava-23.0.pom
|
||||
@@ -701,7 +701,7 @@ https://repo.maven.apache.org/maven2/com/google/guava/guava/29.0-jre/guava-29.0-
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava/30.1-android/guava-30.1-android.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava/30.1-jre/guava-30.1-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava/31.0.1-jre/guava-31.0.1-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava/32.0.1-jre/guava-32.0.1-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/guava/32.1.1-jre/guava-32.1.1-jre.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/listenablefuture/1.0/listenablefuture-1.0.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.pom
|
||||
https://repo.maven.apache.org/maven2/com/google/j2objc/j2objc-annotations/1.1/j2objc-annotations-1.1.pom
|
||||
@@ -988,7 +988,7 @@ https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/2.8.1/che
|
||||
https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/2.11.1/checker-qual-2.11.1.pom
|
||||
https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/3.5.0/checker-qual-3.5.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/3.12.0/checker-qual-3.12.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/3.35.0/checker-qual-3.35.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/3.36.0/checker-qual-3.36.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/codehaus/codehaus-parent/4/codehaus-parent-4.pom
|
||||
https://repo.maven.apache.org/maven2/org/codehaus/groovy/groovy-xml/3.0.10/groovy-xml-3.0.10.pom
|
||||
https://repo.maven.apache.org/maven2/org/codehaus/groovy/groovy/3.0.9/groovy-3.0.9.pom
|
||||
@@ -1065,7 +1065,6 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-co
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.5.2/kotlinx-coroutines-core-jvm-1.5.2.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core/1.4.1/kotlinx-coroutines-core-1.4.1.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlinx/kotlinx-metadata-jvm/0.1.0/kotlinx-metadata-jvm-0.1.0.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-android-extensions-runtime/1.6.20/kotlin-android-extensions-runtime-1.6.20.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-android-extensions/1.6.10/kotlin-android-extensions-1.6.10.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-android-extensions/1.6.20/kotlin-android-extensions-1.6.20.pom
|
||||
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-annotations-jvm/1.3.72/kotlin-annotations-jvm-1.3.72.pom
|
||||
|
||||
@@ -15,7 +15,7 @@ androidenv.composeAndroidPackages {
|
||||
toolsVersion = "26.1.1";
|
||||
platformToolsVersion = "33.0.3";
|
||||
buildToolsVersions = [ "31.0.0" ];
|
||||
platformVersions = [ "31" ];
|
||||
platformVersions = [ "33" ];
|
||||
cmakeVersions = [ "3.18.1" ];
|
||||
ndkVersion = "22.1.7171670";
|
||||
includeNDK = true;
|
||||
|
||||
+6
-6
@@ -18,7 +18,7 @@
|
||||
"@react-native-async-storage/async-storage": "^1.17.9",
|
||||
"@react-native-community/audio-toolkit": "git+https://github.com/tbenr/react-native-audio-toolkit.git#refs/tags/v2.0.3-status-v6",
|
||||
"@react-native-community/blur": "git+https://github.com/status-im/react-native-blur#refs/tags/v4.3.3-status",
|
||||
"@react-native-community/cameraroll": "git+https://github.com/status-im/react-native-cameraroll.git#refs/tags/v4.0.4-status.0",
|
||||
"@react-native-community/cameraroll": "git+https://github.com/status-im/react-native-cameraroll.git#refs/tags/v4.0.4-status.1_1",
|
||||
"@react-native-community/clipboard": "^1.2.2",
|
||||
"@react-native-community/hooks": "^3.0.0",
|
||||
"@react-native-community/masked-view": "^0.1.6",
|
||||
@@ -41,7 +41,7 @@
|
||||
"react-native": "0.69.10",
|
||||
"react-native-background-timer": "^2.1.1",
|
||||
"react-native-blob-util": "^0.13.18",
|
||||
"react-native-camera-kit": "^13.0.0",
|
||||
"react-native-camera-kit": "git+https://github.com/rasom/react-native-camera-kit.git#refs/tags/status-test",
|
||||
"react-native-config": "^1.5.0",
|
||||
"react-native-dialogs": "^1.0.4",
|
||||
"react-native-draggable-flatlist": "^3.0.3",
|
||||
@@ -50,7 +50,7 @@
|
||||
"react-native-fs": "^2.14.1",
|
||||
"react-native-gesture-handler": "2.6.1",
|
||||
"react-native-haptic-feedback": "^1.9.0",
|
||||
"react-native-hole-view": "git+https://github.com/status-im/react-native-hole-view.git#refs/tags/v2.1.3-status",
|
||||
"react-native-hole-view": "git+https://github.com/status-im/react-native-hole-view.git#refs/tags/v2.2.1-status",
|
||||
"react-native-image-crop-picker": "git+https://github.com/status-im/react-native-image-crop-picker.git#refs/tags/v0.36.2-status.0",
|
||||
"react-native-image-resizer": "^1.2.3",
|
||||
"react-native-image-viewing": "git+https://github.com/status-im/react-native-image-viewing.git#refs/tags/v0.2.1.status",
|
||||
@@ -58,8 +58,8 @@
|
||||
"react-native-languages": "^3.0.2",
|
||||
"react-native-linear-gradient": "^2.5.6",
|
||||
"react-native-lottie-splash-screen": "^1.0.1",
|
||||
"react-native-mail": "git+https://github.com/status-im/react-native-mail.git#refs/tags/v6.1.2-status",
|
||||
"react-native-navigation": "^7.27.1",
|
||||
"react-native-mail": "git+https://github.com/status-im/react-native-mail.git#refs/tags/v6.1.3_4-status",
|
||||
"react-native-navigation": "^7.30.1",
|
||||
"react-native-orientation-locker": "^1.5.0",
|
||||
"react-native-permissions": "^2.1.5",
|
||||
"react-native-randombytes": "^3.6.1",
|
||||
@@ -72,7 +72,7 @@
|
||||
"react-native-svg": "^9.8.4",
|
||||
"react-native-touch-id": "^4.4.1",
|
||||
"react-native-transparent-video": "git+https://github.com/status-im/react-native-transparent-video.git#refs/tags/0.0.9",
|
||||
"react-native-webview": "git+https://github.com/status-im/react-native-webview.git#refs/tags/v11.16.0-status",
|
||||
"react-native-webview": "git+https://github.com/status-im/react-native-webview.git#refs/tags/android-13-fix_4",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"rn-emoji-keyboard": "0.7.0",
|
||||
"tdigest": "^0.1.1"
|
||||
|
||||
@@ -194,4 +194,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eof pipefail
|
||||
|
||||
FILES=$(comm -23 <(sort <(git ls-files --cached --others --exclude-standard)) <(sort <(git ls-files --deleted)) | grep --ignore-case -E '\.(java|cpp|nix|json|sh|md|js|clj|cljs|cljc|edn)$')
|
||||
N_FILES=$(echo "$FILES" | wc -l)
|
||||
LINT_SHOULD_FIX=0
|
||||
|
||||
if [[ -n $1 && $1 != '--fix' ]]; then
|
||||
echo "Unknown option '$1'" >&2
|
||||
exit 1
|
||||
elif [[ $1 == '--fix' ]]; then
|
||||
LINT_SHOULD_FIX=1
|
||||
fi
|
||||
|
||||
echo "Checking ${N_FILES} files for missing trailing newlines."
|
||||
|
||||
# Do not process the whole file and only check the last character. Ignore empty
|
||||
# files. Taken from https://stackoverflow.com/a/10082466.
|
||||
for file in $FILES; do
|
||||
if [ -s "$file" ] && [ "$(tail -c1 "$file"; echo x)" != $'\nx' ]; then
|
||||
if [[ $LINT_SHOULD_FIX -eq 1 ]]; then
|
||||
echo "" >>"$file"
|
||||
else
|
||||
LINT_ERROR=1
|
||||
echo "No trailing newline: $file" >&2
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $LINT_ERROR -eq 1 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
@@ -6,3 +6,10 @@ export function infoLayout(input, isTop) {
|
||||
return isTop ? input.value : -input.value;
|
||||
});
|
||||
}
|
||||
|
||||
export function textSheet(input, isHeight) {
|
||||
return useDerivedValue(function () {
|
||||
'worklet';
|
||||
return isHeight ? input.value : -input.value;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -287,11 +287,11 @@
|
||||
and then compressed. Example input/output :
|
||||
input key = zQ3shTAten2v9CwyQD1Kc7VXAqNPDcHZAMsfbLHCZEx6nFqk9 and
|
||||
output key = 0x025596a7ff87da36860a84b0908191ce60a504afc94aac93c1abd774f182967ce6"
|
||||
[key callback]
|
||||
[input-key callback]
|
||||
(log/info "[native-module] Deserializing and then compressing public key"
|
||||
{:fn :deserialize-and-compress-key
|
||||
:key key})
|
||||
(.deserializeAndCompressKey ^js (status) key callback))
|
||||
:key input-key})
|
||||
(.deserializeAndCompressKey ^js (status) input-key callback))
|
||||
|
||||
(defn compressed-key->public-key
|
||||
"Provides compressed key to status-go and gets back the uncompressed public key via deserialization"
|
||||
|
||||
@@ -235,31 +235,6 @@
|
||||
[value velocity snap-points]
|
||||
(.snapPoint ^js redash value velocity (to-array snap-points)))
|
||||
|
||||
(defn cancelable-loop
|
||||
[{:keys [clock duration finished on-reach]}]
|
||||
(let [time (value 0)
|
||||
frame-time (value 0)
|
||||
position (value 0)
|
||||
to-value (value 1)
|
||||
state {:time time
|
||||
:frameTime frame-time
|
||||
:finished finished
|
||||
:position position}
|
||||
config {:toValue to-value
|
||||
:duration duration
|
||||
:easing (:linear easings)}]
|
||||
(block
|
||||
[(timing clock state config)
|
||||
(cond* (and* finished
|
||||
(eq position to-value))
|
||||
(call* [] on-reach))
|
||||
(cond* finished
|
||||
[(set finished 0)
|
||||
(set time 0)
|
||||
(set frame-time 0)
|
||||
(set position 0)])
|
||||
position])))
|
||||
|
||||
(defn with-easing
|
||||
[{val :value
|
||||
:keys [snap-points velocity offset state easing duration
|
||||
|
||||
@@ -11,4 +11,4 @@
|
||||
(for [i (keys icons/icons)]
|
||||
[rn/view {:flex-direction :row}
|
||||
[icons/icon (keyword i)]
|
||||
[rn/text i]])])
|
||||
[rn/text i]])])
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
(ns quo.previews.preview)
|
||||
|
||||
(defn descriptor->values
|
||||
[{:keys [key options type]}]
|
||||
{key (case type
|
||||
:boolean [false true]
|
||||
:text [nil "Just simple text"] ; NOTE(Ferossgp): add example with long text?
|
||||
:select (mapv :key options))})
|
||||
|
||||
(defmacro list-comp
|
||||
[[binding seq-expr & bindings] body-expr]
|
||||
(cond (not binding)
|
||||
|
||||
@@ -68,8 +68,8 @@
|
||||
:background-color (:ui-background @colors/theme)})
|
||||
|
||||
(defn customizer-boolean
|
||||
[{:keys [label key state]}]
|
||||
(let [state* (reagent/cursor state [key])]
|
||||
[{:keys [label state] :as args}]
|
||||
(let [state* (reagent/cursor state [(:key args)])]
|
||||
[rn/view {:style container}
|
||||
[label-view state label]
|
||||
[rn/view
|
||||
@@ -95,8 +95,8 @@
|
||||
"False"]]]]))
|
||||
|
||||
(defn customizer-text
|
||||
[{:keys [label key state]}]
|
||||
(let [state* (reagent/cursor state [key])]
|
||||
[{:keys [label state] :as args}]
|
||||
(let [state* (reagent/cursor state [(:key args)])]
|
||||
[rn/view {:style container}
|
||||
[label-view state label]
|
||||
[rn/view {:style {:flex 0.6}}
|
||||
@@ -117,8 +117,8 @@
|
||||
(defn customizer-select
|
||||
[]
|
||||
(let [open (reagent/atom nil)]
|
||||
(fn [{:keys [label key state options]}]
|
||||
(let [state* (reagent/cursor state [key])
|
||||
(fn [{:keys [label state options] :as args}]
|
||||
(let [state* (reagent/cursor state [(:key args)])
|
||||
selected (value-for-key @state* options)]
|
||||
[rn/view {:style container}
|
||||
[label-view state label]
|
||||
@@ -133,15 +133,15 @@
|
||||
[rn/view {:style (modal-view)}
|
||||
[rn/scroll-view
|
||||
(doall
|
||||
(for [{:keys [key value]} options]
|
||||
^{:key key}
|
||||
(for [{k :key v :value} options]
|
||||
^{:key k}
|
||||
[rn/touchable-opacity
|
||||
{:style (select-option-style (= @state* key))
|
||||
{:style (select-option-style (= @state* k))
|
||||
:on-press #(do
|
||||
(reset! open false)
|
||||
(reset! state* key))}
|
||||
[quo/text {:color (if (= @state* key) :link :secondary)}
|
||||
value]]))
|
||||
(reset! state* k))}
|
||||
[quo/text {:color (if (= @state* k) :link :secondary)}
|
||||
v]]))
|
||||
[rn/view {:flex-direction :row}
|
||||
[rn/touchable-opacity
|
||||
{:style (select-option-style false)
|
||||
@@ -175,17 +175,15 @@
|
||||
{:style {:flex 1}
|
||||
:padding-horizontal 16}
|
||||
(doall
|
||||
(for [{:keys [key type]
|
||||
:as desc}
|
||||
descriptors
|
||||
:let [descriptor (merge desc
|
||||
{:state state})]]
|
||||
^{:key key}
|
||||
(for [desc descriptors
|
||||
:let [descriptor (merge desc {:state state})]]
|
||||
^{:key (:key desc)}
|
||||
[:<>
|
||||
(case type
|
||||
(case (:type desc)
|
||||
:boolean [customizer-boolean descriptor]
|
||||
:text [customizer-text descriptor]
|
||||
:select [customizer-select descriptor])]))])
|
||||
:select [customizer-select descriptor]
|
||||
nil)]))])
|
||||
|
||||
(comment
|
||||
[{:label "Show error:"
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
(ns quo2.components.avatars.channel-avatar
|
||||
(:require [quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn channel-avatar
|
||||
[{:keys [big? locked? emoji-background-color emoji]}]
|
||||
(let [lock-exists? locked?
|
||||
dark? (theme/dark?)]
|
||||
[rn/view
|
||||
{:style {:width (if big? 32 24)
|
||||
:height (if big? 32 24)
|
||||
:border-radius (if big? 32 24)
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color emoji-background-color}}
|
||||
[rn/view
|
||||
{:style {:display :flex
|
||||
:justify-content :center
|
||||
:align-items :center}}
|
||||
[text/text
|
||||
{:size (if big?
|
||||
:paragraph-1
|
||||
:label)} emoji]
|
||||
(when lock-exists?
|
||||
[rn/view
|
||||
{:style {:position :absolute
|
||||
:left (if big?
|
||||
14
|
||||
8)
|
||||
:top (if big?
|
||||
15
|
||||
8)
|
||||
:background-color (if dark?
|
||||
colors/neutral-90
|
||||
colors/white)
|
||||
:border-radius 15
|
||||
:padding 2}}
|
||||
[icons/icon
|
||||
(if locked?
|
||||
:main-icons/locked
|
||||
:main-icons/unlocked)
|
||||
{:color (if dark?
|
||||
colors/neutral-40
|
||||
colors/neutral-50)
|
||||
:container-style {:width 12
|
||||
:height 12}
|
||||
:size 12}]])]]))
|
||||
@@ -0,0 +1,35 @@
|
||||
(ns quo2.components.avatars.channel-avatar.component-spec
|
||||
(:require [quo2.components.avatars.channel-avatar.view :as component]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "Channel Avatar"
|
||||
(h/test "default render"
|
||||
(h/render [component/view])
|
||||
(h/is-truthy (h/query-by-label-text :initials))
|
||||
(h/is-null (h/query-by-label-text :emoji))
|
||||
(h/is-null (h/query-by-label-text :lock)))
|
||||
|
||||
(h/test "with emoji, no lock set, large size"
|
||||
(let [emoji "🍓"]
|
||||
(h/render [component/view {:emoji emoji :size :size/l}])
|
||||
(h/is-null (h/query-by-label-text :initials))
|
||||
(h/is-truthy (h/query-by-text emoji))
|
||||
(h/is-null (h/query-by-label-text :lock))))
|
||||
|
||||
(h/test "locked"
|
||||
(h/render [component/view {:locked? true}])
|
||||
(h/is-truthy (h/query-by-label-text :lock)))
|
||||
|
||||
(h/test "unlocked"
|
||||
(h/render [component/view {:locked? false}])
|
||||
(h/is-truthy (h/query-by-label-text :lock)))
|
||||
|
||||
(h/test "no emoji, smaller size"
|
||||
(h/render [component/view {:full-name "Status Mobile"}])
|
||||
(h/is-truthy (h/query-by-text "S")))
|
||||
|
||||
(h/test "no emoji, large size"
|
||||
(h/render [component/view
|
||||
{:full-name "Status Mobile"
|
||||
:size :size/l}])
|
||||
(h/is-truthy (h/query-by-text "SM"))))
|
||||
@@ -0,0 +1,28 @@
|
||||
(ns quo2.components.avatars.channel-avatar.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def lock-icon-size 12)
|
||||
|
||||
(defn outer-container
|
||||
[{:keys [size color]}]
|
||||
(let [size (if (= size :size/l) 32 24)]
|
||||
{:width size
|
||||
:height size
|
||||
:border-radius size
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color (colors/theme-alpha color 0.1 0.1)}))
|
||||
|
||||
(defn lock-container
|
||||
[size]
|
||||
(let [distance (if (= size :size/l) 20 12)]
|
||||
{:position :absolute
|
||||
:left distance
|
||||
:top distance
|
||||
:background-color (colors/theme-colors colors/white colors/neutral-95)
|
||||
:border-radius (* 2 lock-icon-size)
|
||||
:padding 2}))
|
||||
|
||||
(def lock-icon
|
||||
{:width lock-icon-size
|
||||
:height lock-icon-size})
|
||||
@@ -0,0 +1,60 @@
|
||||
(ns quo2.components.avatars.channel-avatar.view
|
||||
(:require [clojure.string :as string]
|
||||
[quo2.components.avatars.channel-avatar.style :as style]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
utils.string))
|
||||
|
||||
(defn- initials
|
||||
[full-name size color]
|
||||
(let [amount-initials (if (= size :size/l) 2 1)]
|
||||
[text/text
|
||||
{:accessibility-label :initials
|
||||
:size :paragraph-2
|
||||
:weight :semi-bold
|
||||
:style {:color color}}
|
||||
(utils.string/get-initials full-name amount-initials)]))
|
||||
|
||||
(defn- lock
|
||||
[locked? size]
|
||||
;; When `locked?` is nil, we must not display the unlocked icon.
|
||||
(when (boolean? locked?)
|
||||
[rn/view
|
||||
{:accessibility-label :lock
|
||||
:style (style/lock-container size)}
|
||||
[icons/icon (if locked? :i/locked :i/unlocked)
|
||||
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40)
|
||||
:container-style style/lock-icon
|
||||
:size 12}]]))
|
||||
|
||||
(defn view
|
||||
"Options:
|
||||
|
||||
:size - keyword (default nil) - Container size, for the moment,
|
||||
only :size/l (meaning large) is supported.
|
||||
|
||||
:emoji - string (default nil)
|
||||
|
||||
:customization-color - color (default nil) If the component is used for a
|
||||
community channel, then the default color should be the community custom
|
||||
color.
|
||||
|
||||
:locked? - nil/bool (default nil) - When true/false display a locked/unlocked
|
||||
icon respectively. When nil does not show icon.
|
||||
|
||||
:full-name - string (default nil) - When :emoji is blank, this value will be
|
||||
used to extract the initials.
|
||||
"
|
||||
[{:keys [size emoji customization-color locked? full-name]}]
|
||||
[rn/view
|
||||
{:accessibility-label :channel-avatar
|
||||
:style (style/outer-container {:size size :color customization-color})}
|
||||
(if (string/blank? emoji)
|
||||
[initials full-name size customization-color]
|
||||
[text/text
|
||||
{:accessibility-label :emoji
|
||||
:size (if (= size :size/l) :paragraph-1 :label)}
|
||||
(string/trim emoji)])
|
||||
[lock locked? size]])
|
||||
@@ -1,22 +1,9 @@
|
||||
(ns quo2.components.avatars.user-avatar.view
|
||||
(:require [clojure.string :as string]
|
||||
[quo2.components.avatars.user-avatar.style :as style]
|
||||
(:require [quo2.components.avatars.user-avatar.style :as style]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[react-native.core :as rn]
|
||||
[react-native.fast-image :as fast-image]))
|
||||
|
||||
(defn trim-whitespace [s] (string/join " " (string/split (string/trim s) #"\s+")))
|
||||
|
||||
(defn- extract-initials
|
||||
[full-name amount-initials]
|
||||
(let [upper-case-first-letter (comp string/upper-case first)
|
||||
names-list (string/split (trim-whitespace full-name) " ")]
|
||||
(if (= (first names-list) "")
|
||||
""
|
||||
(->> names-list
|
||||
(map upper-case-first-letter)
|
||||
(take amount-initials)
|
||||
(string/join)))))
|
||||
[react-native.fast-image :as fast-image]
|
||||
utils.string))
|
||||
|
||||
(defn initials-avatar
|
||||
[{:keys [full-name size draw-ring? customization-color]}]
|
||||
@@ -29,7 +16,7 @@
|
||||
{:style style/initials-avatar-text
|
||||
:size font-size
|
||||
:weight :semi-bold}
|
||||
(extract-initials full-name amount-initials)]]))
|
||||
(utils.string/get-initials full-name amount-initials)]]))
|
||||
|
||||
(def valid-ring-sizes #{:big :medium :small})
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
(ns quo2.components.buttons.--tests--.buttons-component-spec
|
||||
(:require ["@testing-library/react-native" :as rtl]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn render-button
|
||||
([options label]
|
||||
(rtl/render (reagent/as-element [button/button options label]))))
|
||||
|
||||
(js/global.test "default render of button component"
|
||||
(fn []
|
||||
(render-button {:accessibility-label "test-button"} "")
|
||||
(-> (js/expect (rtl/screen.getByLabelText "test-button"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "button renders with a label"
|
||||
(fn []
|
||||
(render-button {} "test-label")
|
||||
(-> (js/expect (rtl/screen.getByText "test-label"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "button on-press works"
|
||||
(let [event (js/jest.fn)]
|
||||
(fn []
|
||||
(render-button {:on-press event} "test-label")
|
||||
(rtl/fireEvent.press (rtl/screen.getByText "test-label"))
|
||||
(-> (js/expect event)
|
||||
(.toHaveBeenCalledTimes 1)))))
|
||||
@@ -0,0 +1,18 @@
|
||||
(ns quo2.components.buttons.button.component-spec
|
||||
(:require [quo2.components.buttons.button.view :as button]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "button tests"
|
||||
(h/test "default render of button component"
|
||||
(h/render [button/button {:accessibility-label "test-button"} ""])
|
||||
(h/is-truthy (h/get-by-label-text "test-button")))
|
||||
|
||||
(h/test "button renders with a label"
|
||||
(h/render [button/button {} "test-label"])
|
||||
(h/is-truthy (h/get-by-text "test-label")))
|
||||
|
||||
(h/test "button on-press works"
|
||||
(let [event (h/mock-fn)]
|
||||
(h/render [button/button {:on-press event} "test-label"])
|
||||
(h/fire-event :press (h/get-by-text "test-label"))
|
||||
(h/was-called event))))
|
||||
+44
-139
@@ -1,12 +1,46 @@
|
||||
(ns quo2.components.buttons.button
|
||||
(:require [quo2.components.icon :as quo2.icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.blur :as blur]
|
||||
[reagent.core :as reagent]
|
||||
[quo2.components.buttons.style :as style]))
|
||||
(ns quo2.components.buttons.button.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def blur-view
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 0})
|
||||
|
||||
(defn before-icon-style
|
||||
[{:keys [override-margins size icon-container-size icon-background-color icon-container-rounded?
|
||||
icon-size]}]
|
||||
(merge
|
||||
{:margin-left (or (get override-margins :left)
|
||||
(if (= size 40) 12 8))
|
||||
:margin-right (or (get override-margins :right) 4)
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
(when icon-container-size
|
||||
{:width icon-container-size
|
||||
:height icon-container-size})
|
||||
(when icon-background-color
|
||||
{:background-color icon-background-color})
|
||||
(when icon-container-rounded?
|
||||
{:border-radius (/ (or icon-container-size icon-size) 2)})))
|
||||
|
||||
(defn after-icon-style
|
||||
[{:keys [override-margins size icon-container-size icon-background-color icon-container-rounded?
|
||||
icon-size]}]
|
||||
(merge
|
||||
{:margin-left (or (get override-margins :left) 4)
|
||||
:margin-right (or (get override-margins :right)
|
||||
(if (= size 40) 12 8))
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
(when icon-container-size
|
||||
{:width icon-container-size
|
||||
:height icon-container-size})
|
||||
(when icon-background-color
|
||||
{:background-color icon-background-color})
|
||||
(when icon-container-rounded?
|
||||
{:border-radius (/ (or icon-container-size icon-size) 2)})))
|
||||
|
||||
(defn themes
|
||||
[customization-color]
|
||||
@@ -179,7 +213,7 @@
|
||||
24 8))})
|
||||
|
||||
(defn style-container
|
||||
[type size disabled background-color border-color icon above width before after blur-active?]
|
||||
[{:keys [type size disabled background-color border-color icon above width before after blur-active?]}]
|
||||
(merge {:height size
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
@@ -228,132 +262,3 @@
|
||||
:border-width 1})
|
||||
(when disabled
|
||||
{:opacity 0.3})))
|
||||
|
||||
(defn- button-internal
|
||||
"with label
|
||||
[button opts \"label\"]
|
||||
opts
|
||||
{:type :primary/:secondary/:grey/:dark-grey/:outline/:ghost/
|
||||
:danger/:photo-bg/:blur-bg/:blur-bg-outline/:shell/:community
|
||||
:size 40 [default] /32/24
|
||||
:icon true/false
|
||||
:community-color '#FFFFFF'
|
||||
:community-text-color '#000000'
|
||||
:before :icon-keyword
|
||||
:after :icon-keyword}
|
||||
|
||||
only icon
|
||||
[button {:icon true} :i/close-circle]"
|
||||
[_ _]
|
||||
(let [pressed-in (reagent/atom false)]
|
||||
(fn
|
||||
[{:keys [on-press disabled type size before after above icon-secondary-no-color
|
||||
width customization-color theme override-background-color pressed
|
||||
on-long-press accessibility-label icon icon-no-color style inner-style test-ID
|
||||
blur-active? override-before-margins override-after-margins icon-size icon-container-size
|
||||
icon-container-rounded?]
|
||||
:or {type :primary
|
||||
size 40
|
||||
customization-color :primary
|
||||
blur-active? true}}
|
||||
children]
|
||||
(let [{:keys [icon-color icon-secondary-color background-color label-color border-color blur-type
|
||||
blur-overlay-color icon-background-color]}
|
||||
(get-in (themes customization-color)
|
||||
[theme type])
|
||||
state (cond disabled :disabled
|
||||
(or @pressed-in pressed) :pressed
|
||||
:else :default)
|
||||
blur-state (if blur-active? :blurred :default)
|
||||
icon-size (or icon-size (when (= 24 size) 12))
|
||||
icon-secondary-color (or icon-secondary-color icon-color)]
|
||||
[rn/touchable-without-feedback
|
||||
(merge {:test-ID test-ID
|
||||
:disabled disabled
|
||||
:accessibility-label accessibility-label
|
||||
:on-press-in #(reset! pressed-in true)
|
||||
:on-press-out #(reset! pressed-in nil)}
|
||||
(when on-press
|
||||
{:on-press on-press})
|
||||
(when on-long-press
|
||||
{:on-long-press on-long-press}))
|
||||
[rn/view
|
||||
{:style (merge
|
||||
(shape-style-container type icon size)
|
||||
{:width width}
|
||||
style)}
|
||||
[rn/view
|
||||
{:style (merge
|
||||
(style-container
|
||||
type
|
||||
size
|
||||
disabled
|
||||
(or override-background-color (get background-color state))
|
||||
(get border-color state)
|
||||
icon
|
||||
above
|
||||
width
|
||||
before
|
||||
after
|
||||
blur-active?)
|
||||
(when (= state :pressed) {:opacity 0.9})
|
||||
inner-style)}
|
||||
(when (and (= type :blurred)
|
||||
blur-active?)
|
||||
[blur/view
|
||||
{:blur-radius 20
|
||||
:blur-type blur-type
|
||||
:overlay-color blur-overlay-color
|
||||
:style style/blur-view}])
|
||||
(when above
|
||||
[rn/view
|
||||
[quo2.icons/icon above
|
||||
{:container-style {:margin-bottom 2}
|
||||
:color icon-secondary-color
|
||||
:size icon-size}]])
|
||||
(when before
|
||||
[rn/view
|
||||
{:style (style/before-icon-style
|
||||
{:override-margins override-before-margins
|
||||
:size size
|
||||
:icon-container-size icon-container-size
|
||||
:icon-background-color (get icon-background-color blur-state)
|
||||
:icon-container-rounded? icon-container-rounded?
|
||||
:icon-size icon-size})}
|
||||
[quo2.icons/icon before
|
||||
{:color icon-secondary-color
|
||||
:size icon-size}]])
|
||||
[rn/view
|
||||
(cond
|
||||
(or icon icon-no-color)
|
||||
[quo2.icons/icon children
|
||||
{:color icon-color
|
||||
:no-color icon-no-color
|
||||
:size icon-size}]
|
||||
|
||||
(string? children)
|
||||
[text/text
|
||||
{:size (when (#{56 24} size) :paragraph-2)
|
||||
:weight :medium
|
||||
:number-of-lines 1
|
||||
:style {:color label-color}}
|
||||
|
||||
children]
|
||||
|
||||
(vector? children)
|
||||
children)]
|
||||
(when after
|
||||
[rn/view
|
||||
{:style (style/after-icon-style
|
||||
{:override-margins override-after-margins
|
||||
:size size
|
||||
:icon-container-size icon-container-size
|
||||
:icon-background-color (get icon-background-color blur-state)
|
||||
:icon-container-rounded? icon-container-rounded?
|
||||
:icon-size icon-size})}
|
||||
[quo2.icons/icon after
|
||||
{:no-color icon-secondary-no-color
|
||||
:color icon-secondary-color
|
||||
:size icon-size}]])]]]))))
|
||||
|
||||
(def button (theme/with-theme button-internal))
|
||||
@@ -0,0 +1,138 @@
|
||||
(ns quo2.components.buttons.button.view
|
||||
(:require [quo2.components.icon :as quo2.icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.blur :as blur]
|
||||
[reagent.core :as reagent]
|
||||
[quo2.components.buttons.button.style :as style]))
|
||||
|
||||
(defn- button-internal
|
||||
"with label
|
||||
[button opts \"label\"]
|
||||
opts
|
||||
{:type :primary/:secondary/:grey/:dark-grey/:outline/:ghost/
|
||||
:danger/:photo-bg/:blur-bg/:blur-bg-outline/:shell/:community
|
||||
:size 40 [default] /32/24
|
||||
:icon true/false
|
||||
:community-color '#FFFFFF'
|
||||
:community-text-color '#000000'
|
||||
:before :icon-keyword
|
||||
:after :icon-keyword}
|
||||
|
||||
only icon
|
||||
[button {:icon true} :i/close-circle]"
|
||||
[_ _]
|
||||
(let [pressed-in (reagent/atom false)]
|
||||
(fn
|
||||
[{:keys [on-press disabled type size before after above icon-secondary-no-color
|
||||
width customization-color theme override-background-color pressed
|
||||
on-long-press accessibility-label icon icon-no-color style inner-style test-ID
|
||||
blur-active? override-before-margins override-after-margins icon-size icon-container-size
|
||||
icon-container-rounded?]
|
||||
:or {type :primary
|
||||
size 40
|
||||
customization-color :primary
|
||||
blur-active? true}}
|
||||
children]
|
||||
(let [{:keys [icon-color icon-secondary-color background-color label-color border-color blur-type
|
||||
blur-overlay-color icon-background-color]}
|
||||
(get-in (style/themes customization-color)
|
||||
[theme type])
|
||||
state (cond disabled :disabled
|
||||
(or @pressed-in pressed) :pressed
|
||||
:else :default)
|
||||
blur-state (if blur-active? :blurred :default)
|
||||
icon-size (or icon-size (when (= 24 size) 12))
|
||||
icon-secondary-color (or icon-secondary-color icon-color)]
|
||||
[rn/touchable-without-feedback
|
||||
(merge {:test-ID test-ID
|
||||
:disabled disabled
|
||||
:accessibility-label accessibility-label
|
||||
:on-press-in #(reset! pressed-in true)
|
||||
:on-press-out #(reset! pressed-in nil)}
|
||||
(when on-press
|
||||
{:on-press on-press})
|
||||
(when on-long-press
|
||||
{:on-long-press on-long-press}))
|
||||
[rn/view
|
||||
{:style (merge
|
||||
(style/shape-style-container type icon size)
|
||||
{:width width}
|
||||
style)}
|
||||
[rn/view
|
||||
{:style (merge
|
||||
(style/style-container {:type type
|
||||
:size size
|
||||
:disabled disabled
|
||||
:background-color
|
||||
(or override-background-color (get background-color state))
|
||||
:border-color
|
||||
(get border-color state)
|
||||
:icon icon
|
||||
:above above
|
||||
:width width
|
||||
:before before
|
||||
:after after
|
||||
:blur-active? blur-active?})
|
||||
(when (= state :pressed) {:opacity 0.9})
|
||||
inner-style)}
|
||||
(when (and (= type :blurred)
|
||||
blur-active?)
|
||||
[blur/view
|
||||
{:blur-radius 20
|
||||
:blur-type blur-type
|
||||
:overlay-color blur-overlay-color
|
||||
:style style/blur-view}])
|
||||
(when above
|
||||
[rn/view
|
||||
[quo2.icons/icon above
|
||||
{:container-style {:margin-bottom 2}
|
||||
:color icon-secondary-color
|
||||
:size icon-size}]])
|
||||
(when before
|
||||
[rn/view
|
||||
{:style (style/before-icon-style
|
||||
{:override-margins override-before-margins
|
||||
:size size
|
||||
:icon-container-size icon-container-size
|
||||
:icon-background-color (get icon-background-color blur-state)
|
||||
:icon-container-rounded? icon-container-rounded?
|
||||
:icon-size icon-size})}
|
||||
[quo2.icons/icon before
|
||||
{:color icon-secondary-color
|
||||
:size icon-size}]])
|
||||
[rn/view
|
||||
(cond
|
||||
(or icon icon-no-color)
|
||||
[quo2.icons/icon children
|
||||
{:color icon-color
|
||||
:no-color icon-no-color
|
||||
:size icon-size}]
|
||||
|
||||
(string? children)
|
||||
[text/text
|
||||
{:size (when (#{56 24} size) :paragraph-2)
|
||||
:weight :medium
|
||||
:number-of-lines 1
|
||||
:style {:color label-color}}
|
||||
|
||||
children]
|
||||
|
||||
(vector? children)
|
||||
children)]
|
||||
(when after
|
||||
[rn/view
|
||||
{:style (style/after-icon-style
|
||||
{:override-margins override-after-margins
|
||||
:size size
|
||||
:icon-container-size icon-container-size
|
||||
:icon-background-color (get icon-background-color blur-state)
|
||||
:icon-container-rounded? icon-container-rounded?
|
||||
:icon-size icon-size})}
|
||||
[quo2.icons/icon after
|
||||
{:no-color icon-secondary-no-color
|
||||
:color icon-secondary-color
|
||||
:size icon-size}]])]]]))))
|
||||
|
||||
(def button (theme/with-theme button-internal))
|
||||
@@ -62,7 +62,7 @@
|
||||
:customization-color customize jump-to and mention button color}"
|
||||
[_]
|
||||
(let [pressed? (reagent/atom false)]
|
||||
(fn [{:keys [type label on-press count customization-color style]}]
|
||||
(fn [{:keys [type label on-press customization-color style] :as args}]
|
||||
[rn/touchable-opacity
|
||||
{:on-press-in #(reset! pressed? true)
|
||||
:on-press-out #(reset! pressed? false)
|
||||
@@ -102,6 +102,6 @@
|
||||
(case type
|
||||
:jump-to label
|
||||
:search-with-label label
|
||||
(:mention :notification-down :notification-up) (str count))])
|
||||
(:mention :notification-down :notification-up) (str (:count args)))])
|
||||
(when (#{:jump-to :notification-down :notification-up} type)
|
||||
[icon-view type])]])))
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.components.buttons.predictive-keyboard.style :as style]
|
||||
[quo2.components.info.info-message :as info-message]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.linear-gradient :as linear-gradient]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.buttons.button :as button]))
|
||||
[quo2.components.buttons.button.view :as button]))
|
||||
|
||||
(def ^:private gradients
|
||||
{:light [(colors/alpha colors/neutral-40 0.05) (colors/alpha colors/neutral-40 0)]
|
||||
@@ -12,32 +13,33 @@
|
||||
:blur [colors/white-opa-5 colors/white-opa-0]})
|
||||
|
||||
(defn- word-component
|
||||
[word _ _ {:keys [blur? on-press]}]
|
||||
[word _ _ {:keys [on-press]}]
|
||||
[button/button
|
||||
(merge {:type :blur-bg
|
||||
:size 32
|
||||
:on-press #(on-press word)}
|
||||
(when blur? {:override-theme :dark}))
|
||||
{:type :blur-bg
|
||||
:size 32
|
||||
:on-press #(on-press word)}
|
||||
|
||||
word])
|
||||
|
||||
(defn- separator
|
||||
[]
|
||||
[rn/view {:style {:width 8}}])
|
||||
|
||||
(defn view
|
||||
(defn- view-internal
|
||||
"Options
|
||||
- `type` `:words`/`:error`/`:info`/`:empty`.
|
||||
- `blur?` Boolean to enable blur background support.
|
||||
- `text` error/info text.
|
||||
- `words` List of words to display in the keyboard.
|
||||
- `on-press` Callback called when a word is pressed `(fn [word])`."
|
||||
[{:keys [type blur? text words on-press]}]
|
||||
- `on-press` Callback called when a word is pressed `(fn [word])`
|
||||
- `theme` :light or :dark, received from with-theme HOC."
|
||||
[{:keys [type blur? text words on-press theme]}]
|
||||
[linear-gradient/linear-gradient
|
||||
{:style {:flex-direction :row}
|
||||
:accessibility-label :predictive-keyboard
|
||||
:colors (if blur?
|
||||
(gradients :blur)
|
||||
(colors/theme-colors (gradients :light) (gradients :dark)))}
|
||||
(colors/theme-colors (gradients :light) (gradients :dark) theme))}
|
||||
[rn/view {:style (style/wrapper type)}
|
||||
(case type
|
||||
:words
|
||||
@@ -46,8 +48,7 @@
|
||||
:data words
|
||||
:content-container-style style/word-list
|
||||
:render-fn word-component
|
||||
:render-data {:blur? blur?
|
||||
:on-press on-press}
|
||||
:render-data {:on-press on-press}
|
||||
:shows-horizontal-scroll-indicator false
|
||||
:separator [separator]
|
||||
:horizontal true
|
||||
@@ -70,3 +71,5 @@
|
||||
:icon-color colors/white-opa-70}))
|
||||
text]
|
||||
nil)]])
|
||||
|
||||
(def view (theme/with-theme view-internal))
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
(ns quo2.components.buttons.style)
|
||||
|
||||
(def blur-view
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 0})
|
||||
|
||||
(defn before-icon-style
|
||||
[{:keys [override-margins size icon-container-size icon-background-color icon-container-rounded?
|
||||
icon-size]}]
|
||||
(merge
|
||||
{:margin-left (or (get override-margins :left)
|
||||
(if (= size 40) 12 8))
|
||||
:margin-right (or (get override-margins :right) 4)
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
(when icon-container-size
|
||||
{:width icon-container-size
|
||||
:height icon-container-size})
|
||||
(when icon-background-color
|
||||
{:background-color icon-background-color})
|
||||
(when icon-container-rounded?
|
||||
{:border-radius (/ (or icon-container-size icon-size) 2)})))
|
||||
|
||||
(defn after-icon-style
|
||||
[{:keys [override-margins size icon-container-size icon-background-color icon-container-rounded?
|
||||
icon-size]}]
|
||||
(merge
|
||||
{:margin-left (or (get override-margins :left) 4)
|
||||
:margin-right (or (get override-margins :right)
|
||||
(if (= size 40) 12 8))
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
(when icon-container-size
|
||||
{:width icon-container-size
|
||||
:height icon-container-size})
|
||||
(when icon-background-color
|
||||
{:background-color icon-background-color})
|
||||
(when icon-container-rounded?
|
||||
{:border-radius (/ (or icon-container-size icon-size) 2)})))
|
||||
@@ -1,7 +1,7 @@
|
||||
(ns quo2.components.code.snippet
|
||||
(:require [cljs-bean.core :as bean]
|
||||
[clojure.string :as string]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.buttons.button.view :as button]
|
||||
[quo2.components.code.code.style :as style]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[react-native.core :as rn]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
(ns quo2.components.separator
|
||||
(ns quo2.components.common.separator.view
|
||||
(:require [quo2.foundations.colors :as quo2.colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
:outline colors/neutral-70}})
|
||||
|
||||
(defn get-color
|
||||
[key]
|
||||
(get-in themes [(theme/get-theme) key]))
|
||||
[k]
|
||||
(get-in themes [(theme/get-theme) k]))
|
||||
|
||||
(defn counter
|
||||
[{:keys [type override-text-color override-bg-color style accessibility-label max-value]
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
(colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-10 theme)
|
||||
(colors/theme-colors colors/neutral-20 colors/neutral-80 theme)))
|
||||
|
||||
(def active-background-color (colors/custom-color :blue 50 10))
|
||||
(def complete-background-color (colors/custom-color :blue 50))
|
||||
(defn active-background-color [customization-color] (colors/custom-color customization-color 50 10))
|
||||
(defn complete-background-color [customization-color] (colors/custom-color customization-color 50))
|
||||
|
||||
(defn container
|
||||
[size type in-blur-view? theme]
|
||||
[{:keys [size type in-blur-view? theme customization-color]}]
|
||||
(cond-> container-base
|
||||
(#{1 2} size) (assoc :width 20)
|
||||
(= size 3) (assoc :width 28)
|
||||
@@ -28,10 +28,10 @@
|
||||
:border-color (neutral-border-color in-blur-view? theme))
|
||||
|
||||
(= type :active)
|
||||
(assoc :background-color active-background-color)
|
||||
(assoc :background-color (active-background-color customization-color))
|
||||
|
||||
(= type :complete)
|
||||
(assoc :background-color complete-background-color)))
|
||||
(assoc :background-color (complete-background-color customization-color))))
|
||||
|
||||
(defn text-color
|
||||
([type] (text-color type nil))
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
[react-native.core :as rn]
|
||||
[utils.number]))
|
||||
|
||||
(defn themed-step
|
||||
[{:keys [type accessibility-label theme in-blur-view?]} value]
|
||||
(defn step-internal
|
||||
[{:keys [type accessibility-label theme in-blur-view? customization-color]} value]
|
||||
(let [type (or type :neutral)
|
||||
value (utils.number/parse-int value)
|
||||
label (str value)
|
||||
@@ -15,10 +15,14 @@
|
||||
[rn/view
|
||||
{:accessible true
|
||||
:accessibility-label (or accessibility-label :step-counter)
|
||||
:style (style/container size type in-blur-view? theme)}
|
||||
:style (style/container {:size size
|
||||
:type type
|
||||
:in-blur-view? in-blur-view?
|
||||
:theme theme
|
||||
:customization-color customization-color})}
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:size :label
|
||||
:style {:color (style/text-color type theme)}} label]]))
|
||||
|
||||
(def step (theme/with-theme themed-step))
|
||||
(def step (theme/with-theme step-internal))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
(ns quo2.components.dividers.date
|
||||
(:require [quo2.components.markdown.text :as text]
|
||||
[quo2.components.separator :as separator]
|
||||
[quo2.components.common.separator.view :as separator]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
(ns quo2.components.dividers.divider-label
|
||||
(:require [quo2.theme :as theme]
|
||||
[quo2.components.icon :as icons]
|
||||
(:require [quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as markdown.text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def chevron-icon-container-width 20)
|
||||
@@ -36,18 +36,18 @@
|
||||
padding-top (if increase-padding-top? 16 8)
|
||||
text-and-icon-color (if dark? colors/neutral-40 colors/neutral-50)
|
||||
counter-text-color (if dark? colors/white colors/neutral-100)]
|
||||
[rn/touchable-without-feedback
|
||||
{:on-press on-press}
|
||||
[rn/touchable-without-feedback {:on-press on-press}
|
||||
[rn/view
|
||||
{:accessible true
|
||||
:accessibility-label :divider-label
|
||||
:style (merge {:border-top-width 1
|
||||
:border-top-color border-and-counter-bg-color
|
||||
:padding-top padding-top
|
||||
:padding-bottom padding-bottom
|
||||
:padding-horizontal 16
|
||||
:align-items :center
|
||||
:flex-direction :row}
|
||||
:style (merge {:border-top-width 1
|
||||
:border-top-color border-and-counter-bg-color
|
||||
:padding-top padding-top
|
||||
:padding-bottom padding-bottom
|
||||
:padding-left 16
|
||||
:padding-right 16
|
||||
:align-items :center
|
||||
:flex-direction :row}
|
||||
container-style)}
|
||||
(when (= chevron-position :left)
|
||||
[rn/view
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
(ns quo2.components.drawers.documentation-drawers.style)
|
||||
(ns quo2.components.drawers.documentation-drawers.style
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[react-native.safe-area :as safe-area]))
|
||||
|
||||
(def outer-container
|
||||
;; Margin negative to fill the bottom-sheet container where this component is used
|
||||
{:margin-bottom (- (+ (safe-area/get-bottom) 8))})
|
||||
|
||||
(def container
|
||||
{:align-items :flex-start
|
||||
@@ -6,4 +12,10 @@
|
||||
|
||||
(def content
|
||||
{:margin-top 8
|
||||
:margin-bottom 16})
|
||||
:margin-bottom (+ (safe-area/get-bottom) 8)})
|
||||
|
||||
(defn title
|
||||
[shell?]
|
||||
{:color (colors/theme-colors colors/neutral-100
|
||||
colors/white
|
||||
(when shell? :dark))})
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
(ns quo2.components.drawers.documentation-drawers.view
|
||||
(:require [quo2.components.markdown.text :as text]
|
||||
(:require [quo2.components.buttons.button.view :as button]
|
||||
[quo2.components.drawers.documentation-drawers.style :as style]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[react-native.core :as rn]
|
||||
[react-native.gesture :as gesture]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.foundations.colors :as colors]))
|
||||
[react-native.gesture :as gesture]))
|
||||
|
||||
(defn view
|
||||
"Options
|
||||
@@ -14,18 +13,18 @@
|
||||
- `button-icon` button icon
|
||||
- `on-press-button` On press handler for the button
|
||||
- `shell?` use shell theme
|
||||
|
||||
`content` Content of the drawer
|
||||
"
|
||||
[{:keys [title show-button? on-press-button button-label button-icon shell?]} content]
|
||||
[gesture/scroll-view
|
||||
{:style style/outer-container
|
||||
:always-bounce-vertical false
|
||||
:content-inset-adjustment-behavior :never}
|
||||
[rn/view {:style style/container}
|
||||
[text/text
|
||||
{:size :heading-2
|
||||
:accessibility-label :documentation-drawer-title
|
||||
:style {:color (colors/theme-colors colors/neutral-100
|
||||
colors/white
|
||||
(when shell? :dark))}
|
||||
:style (style/title shell?)
|
||||
:weight :semi-bold}
|
||||
title]
|
||||
[rn/view {:style style/content :accessibility-label :documentation-drawer-content}
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
(ns quo2.components.drawers.drawer-buttons.component-spec
|
||||
(:require [quo2.components.drawers.drawer-buttons.view :as drawer-buttons]
|
||||
[react-native.core :as rn]
|
||||
[test-helpers.component :as h]))
|
||||
[test-helpers.component :as h]
|
||||
[react-native.safe-area :as safe-area]))
|
||||
|
||||
(h/describe "drawer-buttons"
|
||||
(h/before-each
|
||||
(fn []
|
||||
(h/use-fake-timers)))
|
||||
|
||||
(h/after-each
|
||||
(fn []
|
||||
(h/clear-all-timers)
|
||||
(h/use-real-timers)))
|
||||
|
||||
(h/test "the top heading and subheading render"
|
||||
(h/render [drawer-buttons/view
|
||||
{:top-card {:heading :top-heading}
|
||||
@@ -29,15 +39,16 @@
|
||||
|
||||
(h/test "it clicks the top card"
|
||||
(let [event (h/mock-fn)]
|
||||
(h/render [drawer-buttons/view
|
||||
{:top-card {:on-press event
|
||||
:heading :top-heading}
|
||||
:bottom-card {:heading :bottom-heading}}
|
||||
:top-sub-heading
|
||||
:bottom-sub-heading])
|
||||
(h/fire-event :press (h/get-by-text "top-heading"))
|
||||
(-> (js/expect event)
|
||||
(.toHaveBeenCalled))))
|
||||
(with-redefs [safe-area/get-top (fn [] 10)]
|
||||
(h/render [drawer-buttons/view
|
||||
{:top-card {:on-press event
|
||||
:heading :top-heading}
|
||||
:bottom-card {:heading :bottom-heading}}
|
||||
:top-sub-heading
|
||||
:bottom-sub-heading])
|
||||
(h/fire-event :press (h/get-by-text "top-heading"))
|
||||
(-> (js/expect event)
|
||||
(.toHaveBeenCalled)))))
|
||||
|
||||
(h/test "it clicks the bottom card"
|
||||
(let [event (h/mock-fn)]
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
(ns quo2.components.drawers.drawer-buttons.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[react-native.reanimated :as reanimated]))
|
||||
|
||||
(def outer-container
|
||||
{:height 216
|
||||
:border-top-left-radius 20
|
||||
:border-top-right-radius 20
|
||||
:overflow :hidden})
|
||||
(defn outer-container
|
||||
[height border-radius container-style]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:height height
|
||||
:border-top-left-radius border-radius
|
||||
:border-top-right-radius border-radius}
|
||||
(assoc
|
||||
container-style
|
||||
:position :absolute
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 0
|
||||
:overflow :hidden)))
|
||||
|
||||
(def top-card
|
||||
{:flex 1
|
||||
@@ -17,7 +26,6 @@
|
||||
|
||||
(def bottom-card
|
||||
{:position :absolute
|
||||
:top 80
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 0
|
||||
@@ -41,6 +49,20 @@
|
||||
:align-items :center
|
||||
:border-color colors/white-opa-5})
|
||||
|
||||
(def blur-view-style
|
||||
{:flex 1
|
||||
:border-top-left-radius 20
|
||||
:border-top-right-radius 20})
|
||||
|
||||
(def blur-content-style
|
||||
{:flex 1
|
||||
:background-color :transparent
|
||||
:position :absolute
|
||||
:top 0
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 0})
|
||||
|
||||
(def bottom-text
|
||||
{:flex 1
|
||||
:color colors/white-70-blur})
|
||||
@@ -51,4 +73,4 @@
|
||||
(defn heading-text
|
||||
[gap]
|
||||
{:color colors/white
|
||||
:margin-bottom gap})
|
||||
:margin-bottom gap})
|
||||
|
||||
@@ -4,7 +4,12 @@
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.blur :as blur]
|
||||
[quo2.components.drawers.drawer-buttons.style :as style]))
|
||||
[quo2.components.drawers.drawer-buttons.style :as style]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.safe-area :as safe-area]))
|
||||
|
||||
(def default-height 216)
|
||||
|
||||
(defn render-bottom
|
||||
[children]
|
||||
@@ -29,35 +34,74 @@
|
||||
children]]
|
||||
[render-bottom children]))
|
||||
|
||||
(defn render-children-top
|
||||
[children]
|
||||
(if (label? children)
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style style/top-text
|
||||
:weight :semi-bold}
|
||||
children]
|
||||
children))
|
||||
(defn- f-render-children-top
|
||||
[children top-children-opacity]
|
||||
(let [scale (reanimated/interpolate top-children-opacity [1 0] [1 1.1])
|
||||
padding-left (reanimated/interpolate scale [1 1.1] [0 14])]
|
||||
[reanimated/view
|
||||
{:style (reanimated/apply-animations-to-style
|
||||
{:opacity top-children-opacity
|
||||
:transform [{:scale scale}
|
||||
{:translate-x padding-left}]}
|
||||
{})}
|
||||
(if (label? children)
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style style/top-text
|
||||
:weight :semi-bold}
|
||||
children]
|
||||
children)]))
|
||||
|
||||
(defn card
|
||||
[{:keys [on-press style heading gap accessibility-label top?]} children]
|
||||
(defn- f-card
|
||||
[{:keys [on-press default-on-press style heading gap accessibility-label top? top-title-opacity
|
||||
top-children-opacity
|
||||
animated-heading]
|
||||
:or {top-title-opacity (reanimated/use-shared-value 1)}}
|
||||
children]
|
||||
[rn/touchable-highlight
|
||||
{:accessibility-label accessibility-label
|
||||
:on-press on-press
|
||||
:on-press (fn []
|
||||
(when on-press
|
||||
(on-press))
|
||||
(when default-on-press
|
||||
(default-on-press)))
|
||||
:border-radius 20
|
||||
:style style
|
||||
:underlay-color (:background-color style)}
|
||||
[rn/view
|
||||
[text/text
|
||||
{:size :heading-1
|
||||
:style (style/heading-text gap)
|
||||
:weight :semi-bold}
|
||||
heading]
|
||||
[reanimated/view
|
||||
{:style (reanimated/apply-animations-to-style
|
||||
{:opacity top-title-opacity}
|
||||
{})}
|
||||
[text/text
|
||||
{:size :heading-1
|
||||
:style (style/heading-text gap)
|
||||
:weight :semi-bold}
|
||||
heading]]
|
||||
(when animated-heading
|
||||
(let [animated-heading-opacity (reanimated/interpolate top-children-opacity [1 0] [0 1])]
|
||||
[reanimated/view
|
||||
{:style (reanimated/apply-animations-to-style
|
||||
{:opacity top-title-opacity}
|
||||
{:position :absolute})}
|
||||
[reanimated/view
|
||||
{:style (reanimated/apply-animations-to-style
|
||||
{:opacity animated-heading-opacity}
|
||||
{})}
|
||||
[text/text
|
||||
{:size :heading-1
|
||||
:style (style/heading-text gap)
|
||||
:weight :semi-bold}
|
||||
animated-heading]]]))
|
||||
(if top?
|
||||
[render-children-top children]
|
||||
[:f> f-render-children-top children top-children-opacity]
|
||||
[render-children-bottom children])]])
|
||||
|
||||
(defn view
|
||||
(defn card
|
||||
[props children]
|
||||
[:f> f-card props children])
|
||||
|
||||
(defn f-view
|
||||
"[view opts]
|
||||
opts
|
||||
{:container-style style-object
|
||||
@@ -70,29 +114,101 @@
|
||||
child-1 string, keyword or hiccup
|
||||
child-2 string, keyword or hiccup
|
||||
"
|
||||
[{:keys [container-style top-card bottom-card]} child-1 child-2]
|
||||
[rn/view
|
||||
{:style (merge container-style style/outer-container)}
|
||||
[blur/view
|
||||
{:blur-type :dark
|
||||
:blur-amount 10
|
||||
:style {:flex 1
|
||||
:border-top-left-radius 20
|
||||
:border-top-right-radius 20}}]
|
||||
[rn/view
|
||||
{:style {:flex 1
|
||||
:background-color :transparent
|
||||
:position :absolute
|
||||
:top 0
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 0}}
|
||||
[card
|
||||
(merge {:gap 4
|
||||
:top? true
|
||||
:style style/top-card}
|
||||
top-card) child-1]
|
||||
[card
|
||||
(merge {:style style/bottom-card
|
||||
:gap 20}
|
||||
bottom-card) child-2]]])
|
||||
[{:keys [container-style top-card bottom-card on-init animations-duration animations-delay]}
|
||||
child-1
|
||||
child-2]
|
||||
(let [max-height (+ (:height (rn/get-window)) (if platform/android? (safe-area/get-top) 0))
|
||||
height (reanimated/use-shared-value default-height)
|
||||
top-padding (reanimated/use-shared-value 12)
|
||||
border-radius (reanimated/use-shared-value 20)
|
||||
bottom-view-top (reanimated/use-shared-value 80)
|
||||
top-title-opacity (reanimated/use-shared-value 1)
|
||||
top-children-opacity (reanimated/use-shared-value 1)
|
||||
animations-delay (/ animations-delay 1.4)
|
||||
start-top-animation (fn []
|
||||
(reanimated/animate-shared-value-with-delay bottom-view-top
|
||||
(:height (rn/get-screen))
|
||||
animations-duration
|
||||
:easing4
|
||||
animations-delay)
|
||||
(reanimated/animate-shared-value-with-delay
|
||||
height
|
||||
max-height
|
||||
animations-duration
|
||||
:easing4
|
||||
animations-delay)
|
||||
(reanimated/animate-shared-value-with-delay
|
||||
top-padding
|
||||
(+ 68 (safe-area/get-top))
|
||||
animations-duration
|
||||
:easing4
|
||||
animations-delay)
|
||||
(reanimated/animate-shared-value-with-delay
|
||||
top-children-opacity
|
||||
0
|
||||
animations-duration
|
||||
:easing4 animations-delay)
|
||||
(reanimated/animate-shared-value-with-delay
|
||||
top-title-opacity
|
||||
0
|
||||
0
|
||||
:linear
|
||||
(+ animations-delay animations-duration 500)))
|
||||
reset-top-animation (fn []
|
||||
(reanimated/set-shared-value top-title-opacity 1)
|
||||
(reanimated/animate-shared-value-with-delay bottom-view-top
|
||||
80
|
||||
animations-duration
|
||||
:easing4
|
||||
50)
|
||||
(reanimated/animate-shared-value-with-timing
|
||||
height
|
||||
default-height
|
||||
animations-duration
|
||||
:easing4)
|
||||
(reanimated/animate-shared-value-with-timing
|
||||
top-padding
|
||||
12
|
||||
animations-duration
|
||||
:easing4)
|
||||
(reanimated/animate-shared-value-with-timing
|
||||
top-children-opacity
|
||||
1
|
||||
animations-duration
|
||||
:easing4))]
|
||||
(rn/use-effect (fn []
|
||||
(when on-init
|
||||
(on-init reset-top-animation))))
|
||||
[reanimated/view {:style (style/outer-container height border-radius container-style)}
|
||||
[blur/view
|
||||
{:blur-type :dark
|
||||
:blur-amount 10
|
||||
:style style/blur-view-style}
|
||||
[rn/view
|
||||
{:style style/blur-content-style}
|
||||
[reanimated/view
|
||||
{:style (reanimated/apply-animations-to-style
|
||||
{:padding-top top-padding}
|
||||
style/top-card)}
|
||||
[card
|
||||
(merge {:gap 4
|
||||
:top? true
|
||||
:style {:flex 1}
|
||||
:top-children-opacity top-children-opacity
|
||||
:top-title-opacity top-title-opacity
|
||||
:default-on-press start-top-animation}
|
||||
top-card)
|
||||
child-1]]
|
||||
[reanimated/view
|
||||
{:style (reanimated/apply-animations-to-style
|
||||
{:top bottom-view-top}
|
||||
style/bottom-card)}
|
||||
[card
|
||||
(merge {:style {:flex 1}
|
||||
:gap 10}
|
||||
bottom-card)
|
||||
child-2]]]]]))
|
||||
|
||||
(defn view
|
||||
[props child-1 child-2]
|
||||
[:f> f-view props child-1 child-2])
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(ns quo2.components.dropdowns.dropdown
|
||||
(:require [quo2.components.buttons.button :as button]))
|
||||
(:require [quo2.components.buttons.button.view :as button]))
|
||||
|
||||
(defn dropdown
|
||||
[_ _]
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
(ns quo2.components.empty-state.empty-state.view
|
||||
(:require [quo2.components.buttons.button :as button]
|
||||
(:require [quo2.components.buttons.button.view :as button]
|
||||
[quo2.components.empty-state.empty-state.styles :as styles]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[react-native.core :as rn]
|
||||
[react-native.fast-image :as fast-image]))
|
||||
[react-native.fast-image :as fast-image]
|
||||
[quo2.theme :as theme]))
|
||||
|
||||
(defn empty-state
|
||||
(defn- empty-state-internal
|
||||
[{:keys [customization-color image title description blur?]
|
||||
upper-button :upper-button
|
||||
lower-button :lower-button
|
||||
@@ -32,19 +33,18 @@
|
||||
upper-button-on-press :on-press} upper-button]
|
||||
[rn/view {:style styles/button-container}
|
||||
[button/button
|
||||
(cond-> {:type :primary
|
||||
:size 32
|
||||
:override-background-color (styles/upper-button-color customization-color)
|
||||
:on-press upper-button-on-press}
|
||||
blur? (assoc :override-theme :dark))
|
||||
{:type :primary
|
||||
:size 32
|
||||
:override-background-color (styles/upper-button-color customization-color)
|
||||
:on-press upper-button-on-press}
|
||||
upper-button-text]
|
||||
|
||||
(when-let [{lower-button-text :text
|
||||
lower-button-on-press :on-press} lower-button]
|
||||
[button/button
|
||||
(cond-> {:style {:margin-top 12}
|
||||
:size 32
|
||||
:type :blur-bg
|
||||
:on-press lower-button-on-press}
|
||||
blur? (assoc :override-theme :dark))
|
||||
{:style {:margin-top 12}
|
||||
:size 32
|
||||
:type :blur-bg
|
||||
:on-press lower-button-on-press}
|
||||
lower-button-text])])])
|
||||
|
||||
(def empty-state (theme/with-theme empty-state-internal))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
(ns quo2.components.header
|
||||
(:require [oops.core :refer [oget]]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.buttons.button.view :as button]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
:error colors/danger-60}})
|
||||
|
||||
(defn get-color
|
||||
[key]
|
||||
(get-in themes [(theme/get-theme) key]))
|
||||
[k]
|
||||
(get-in themes [(theme/get-theme) k]))
|
||||
|
||||
(defn info-message
|
||||
"[info-message opts \"message\"]
|
||||
|
||||
@@ -30,12 +30,12 @@
|
||||
:close-button colors/white}})
|
||||
|
||||
(defn get-color
|
||||
[theme key]
|
||||
(get-in themes [theme key]))
|
||||
[theme k]
|
||||
(get-in themes [theme k]))
|
||||
|
||||
(defn get-color-by-type
|
||||
[theme type key]
|
||||
(get-in themes [theme type key]))
|
||||
[theme type k]
|
||||
(get-in themes [theme type k]))
|
||||
|
||||
(defn container
|
||||
[{:keys [theme type include-button?]}]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
(ns quo2.components.info.information-box.view
|
||||
(:require [clojure.string :as string]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.buttons.button.view :as button]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.info.information-box.style :as style]
|
||||
[quo2.components.markdown.text :as text]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
(ns quo2.components.inputs.profile-input.view
|
||||
(:require
|
||||
[quo2.components.buttons.button :as buttons]
|
||||
[quo2.components.buttons.button.view :as buttons]
|
||||
[quo2.components.avatars.user-avatar.view :as user-avatar]
|
||||
[quo2.components.inputs.profile-input.style :as style]
|
||||
[quo2.components.inputs.title-input.view :as title-input]
|
||||
@@ -37,7 +37,6 @@
|
||||
[buttons/button
|
||||
{:accessibility-label :select-profile-picture-button
|
||||
:type :grey
|
||||
:override-theme :dark
|
||||
:override-background-color (colors/alpha colors/white 0.05)
|
||||
:on-press on-press
|
||||
:icon-size 20
|
||||
@@ -50,6 +49,5 @@
|
||||
[title-input/title-input
|
||||
(merge title-input-props
|
||||
{:blur? true
|
||||
:override-theme :dark
|
||||
:placeholder placeholder
|
||||
:customization-color customization-color})]]])
|
||||
|
||||
@@ -3,50 +3,50 @@
|
||||
[react-native.platform :as platform]))
|
||||
|
||||
(defn get-focused-placeholder-color
|
||||
[blur? override-theme]
|
||||
[blur? theme]
|
||||
(if blur?
|
||||
(colors/theme-colors colors/neutral-80-opa-20 colors/white-opa-20 override-theme)
|
||||
(colors/theme-colors colors/neutral-30 colors/neutral-60 override-theme))
|
||||
(colors/theme-colors colors/neutral-80-opa-20 colors/white-opa-20 theme)
|
||||
(colors/theme-colors colors/neutral-30 colors/neutral-60 theme))
|
||||
)
|
||||
|
||||
(defn get-placeholder-color
|
||||
[blur? override-theme]
|
||||
[blur? theme]
|
||||
(if blur?
|
||||
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-30 override-theme)
|
||||
(colors/theme-colors colors/neutral-40 colors/neutral-50 override-theme)))
|
||||
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-30 theme)
|
||||
(colors/theme-colors colors/neutral-40 colors/neutral-50 theme)))
|
||||
|
||||
(defn- get-disabled-color
|
||||
[blur? override-theme]
|
||||
[blur? theme]
|
||||
(if blur?
|
||||
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-30)
|
||||
(colors/theme-colors colors/neutral-40 colors/neutral-50 override-theme)))
|
||||
(colors/theme-colors colors/neutral-40 colors/neutral-50 theme)))
|
||||
|
||||
(defn- get-char-count-color
|
||||
[blur? override-theme]
|
||||
[blur? theme]
|
||||
(if blur?
|
||||
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-40)
|
||||
(colors/theme-colors colors/neutral-40 colors/neutral-50 override-theme)))
|
||||
(colors/theme-colors colors/neutral-40 colors/neutral-50 theme)))
|
||||
|
||||
(defn get-selection-color
|
||||
[customization-color blur? override-theme]
|
||||
[customization-color blur? theme]
|
||||
(colors/alpha (if blur?
|
||||
(colors/theme-colors colors/neutral-100 colors/white override-theme)
|
||||
(colors/theme-colors colors/neutral-100 colors/white theme)
|
||||
(colors/custom-color customization-color
|
||||
(if (or (= :dark override-theme) colors/dark?) 60 50)))
|
||||
(if (or (= :dark theme) colors/dark?) 60 50)))
|
||||
(if platform/ios? 1 0.2)))
|
||||
|
||||
(def text-input-container {:flex 1})
|
||||
|
||||
(defn title-text
|
||||
[disabled? blur? override-theme]
|
||||
[disabled? blur? theme]
|
||||
{:text-align-vertical :bottom
|
||||
:color (if disabled?
|
||||
(get-disabled-color blur? override-theme)
|
||||
(colors/theme-colors colors/neutral-100 colors/white override-theme))})
|
||||
(get-disabled-color blur? theme)
|
||||
(colors/theme-colors colors/neutral-100 colors/white theme))})
|
||||
|
||||
(defn char-count
|
||||
[blur? override-theme]
|
||||
{:color (get-char-count-color blur? override-theme)})
|
||||
[blur? theme]
|
||||
{:color (get-char-count-color blur? theme)})
|
||||
|
||||
(def container
|
||||
{:flex-direction :row
|
||||
|
||||
@@ -12,14 +12,14 @@
|
||||
(str 0 value)
|
||||
value))
|
||||
|
||||
(defn title-input
|
||||
(defn- title-input-internal
|
||||
[{:keys [blur?
|
||||
on-change-text
|
||||
auto-focus
|
||||
placeholder
|
||||
max-length
|
||||
default-value
|
||||
override-theme]
|
||||
theme]
|
||||
:or {max-length 0
|
||||
auto-focus false
|
||||
default-value ""}}]
|
||||
@@ -38,10 +38,10 @@
|
||||
(text/text-style
|
||||
{:size :heading-2
|
||||
:weight :semi-bold
|
||||
:style (style/title-text disabled? blur? override-theme)})
|
||||
:style (style/title-text disabled? blur? theme)})
|
||||
:default-value default-value
|
||||
:accessibility-label :profile-title-input
|
||||
:keyboard-appearance (theme/theme-value :light :dark override-theme)
|
||||
:keyboard-appearance (theme/theme-value :light :dark theme)
|
||||
:on-focus #(swap! focused? (constantly true))
|
||||
:on-blur #(swap! focused? (constantly false))
|
||||
:auto-focus auto-focus
|
||||
@@ -50,22 +50,24 @@
|
||||
:editable (not disabled?)
|
||||
:max-length max-length
|
||||
:placeholder placeholder
|
||||
:selection-color (style/get-selection-color customization-color blur? override-theme)
|
||||
:selection-color (style/get-selection-color customization-color blur? theme)
|
||||
:placeholder-text-color (if @focused?
|
||||
(style/get-focused-placeholder-color blur? override-theme)
|
||||
(style/get-placeholder-color blur? override-theme))}]]
|
||||
(style/get-focused-placeholder-color blur? theme)
|
||||
(style/get-placeholder-color blur? theme))}]]
|
||||
[rn/view
|
||||
{:style style/counter-container}
|
||||
[text/text
|
||||
[text/text
|
||||
{:style (style/char-count blur? override-theme)
|
||||
{:style (style/char-count blur? theme)
|
||||
:size :paragraph-2}
|
||||
(pad-0
|
||||
(str
|
||||
(count @value)))]
|
||||
[text/text
|
||||
{:style (style/char-count blur? override-theme)
|
||||
{:style (style/char-count blur? theme)
|
||||
:size :paragraph-2}
|
||||
(str "/"
|
||||
(pad-0
|
||||
(str max-length)))]]]])))
|
||||
|
||||
(def title-input (theme/with-theme title-input-internal))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(ns quo2.components.links.link-preview.view
|
||||
(:require [quo2.components.buttons.button :as button]
|
||||
(:require [quo2.components.buttons.button.view :as button]
|
||||
[quo2.components.links.link-preview.style :as style]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
(ns quo2.components.list-items.channel
|
||||
(:require [quo2.components.avatars.channel-avatar :as channel-avatar]
|
||||
(:require [quo2.components.avatars.channel-avatar.view :as channel-avatar]
|
||||
[quo2.components.common.unread-grey-dot.view :as unread-grey-dot]
|
||||
[quo2.components.counter.counter :as quo2.counter]
|
||||
[quo2.components.icon :as quo2.icons]
|
||||
[quo2.components.markdown.text :as quo2.text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[quo2.components.common.unread-grey-dot.view :refer [unread-grey-dot]]))
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def ^:private custom-props
|
||||
[:name :locked? :mentions-count :unread-messages?
|
||||
@@ -14,61 +13,56 @@
|
||||
|
||||
(defn list-item
|
||||
[{:keys [locked? mentions-count unread-messages?
|
||||
muted? is-active-channel? emoji channel-color]
|
||||
:or {channel-color colors/primary-50}
|
||||
muted? is-active-channel? emoji channel-color
|
||||
default-color]
|
||||
:as props}]
|
||||
(let [standard-props (apply dissoc props custom-props)
|
||||
(let [channel-color (or channel-color default-color)
|
||||
standard-props (apply dissoc props custom-props)
|
||||
name-text (:name props)]
|
||||
[rn/touchable-opacity standard-props
|
||||
[rn/view
|
||||
{:style (merge {:height 48
|
||||
:display :flex
|
||||
:border-radius 12
|
||||
:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center
|
||||
:width "100%"
|
||||
:padding-left 12
|
||||
:padding-right 12}
|
||||
(when is-active-channel?
|
||||
{:background-color (colors/theme-alpha channel-color 0.05 0.05)}))}
|
||||
{:style (cond-> {:height 48
|
||||
:border-radius 12
|
||||
:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center
|
||||
:width "100%"
|
||||
:padding-left 12
|
||||
:padding-right 12}
|
||||
is-active-channel? (assoc :background-color
|
||||
(colors/theme-alpha channel-color 0.05 0.05)))}
|
||||
[rn/view
|
||||
{:display :flex
|
||||
:flex-direction :row
|
||||
:justify-content :flex-start
|
||||
:align-items :center
|
||||
{:style {:flex-direction :row
|
||||
:justify-content :flex-start
|
||||
:align-items :center}
|
||||
:accessible true
|
||||
:accessibility-label :chat-name-text}
|
||||
[channel-avatar/channel-avatar
|
||||
{:big? true
|
||||
:locked? locked?
|
||||
:emoji-background-color (colors/theme-alpha channel-color 0.1 0.1)
|
||||
:emoji emoji}]
|
||||
[channel-avatar/view
|
||||
{:size :size/l
|
||||
:locked? locked?
|
||||
:full-name (:name props)
|
||||
:customization-color channel-color
|
||||
:emoji emoji}]
|
||||
[quo2.text/text
|
||||
{:style (merge {:margin-left 12}
|
||||
(when (and (not locked?) muted?)
|
||||
{:color (if (theme/dark?) colors/neutral-60 colors/neutral-40)}))
|
||||
{:style (cond-> {:margin-left 12}
|
||||
(and (not locked?) muted?)
|
||||
(assoc :color (colors/theme-colors colors/neutral-40 colors/neutral-60)))
|
||||
:weight :medium
|
||||
:size :paragraph-1} (str "# " name-text)]]
|
||||
[rn/view
|
||||
{:style {:height 20
|
||||
:justify-content :center}}
|
||||
(when (and (not locked?)
|
||||
muted?)
|
||||
[quo2.icons/icon :i/muted
|
||||
{:size 20
|
||||
:color colors/neutral-40
|
||||
:container-style {:margin-right 1
|
||||
:margin-top 2}}])
|
||||
(when (and (not locked?)
|
||||
(not muted?)
|
||||
(pos? (int mentions-count)))
|
||||
[rn/view
|
||||
{:style {:margin-right 2
|
||||
:margin-top 2}}
|
||||
[quo2.counter/counter {:override-bg-color channel-color} mentions-count]])
|
||||
(when (and (not locked?)
|
||||
(not muted?)
|
||||
(not (pos? (int mentions-count)))
|
||||
unread-messages?)
|
||||
[unread-grey-dot :unviewed-messages-public])]]]))
|
||||
:size :paragraph-1}
|
||||
(str "# " name-text)]]
|
||||
(when-not locked?
|
||||
[rn/view {:style {:height 20 :justify-content :center}}
|
||||
(cond
|
||||
muted?
|
||||
[quo2.icons/icon :i/muted
|
||||
{:size 20
|
||||
:color colors/neutral-40
|
||||
:container-style {:margin-right 1 :margin-top 2}}]
|
||||
|
||||
(pos? (int mentions-count))
|
||||
[rn/view {:style {:margin-right 2 :margin-top 2}}
|
||||
[quo2.counter/counter {:override-bg-color channel-color}
|
||||
mentions-count]]
|
||||
|
||||
unread-messages?
|
||||
[unread-grey-dot/unread-grey-dot :unviewed-messages-public])])]]))
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
(ns quo2.components.loaders.skeleton.constants)
|
||||
|
||||
(def ^:const layout-dimensions
|
||||
{:messages {:height 56
|
||||
:padding-top 12}
|
||||
:list-items {:height 56
|
||||
:padding-top 12}
|
||||
:notifications {:height 90
|
||||
:padding-top 8}})
|
||||
|
||||
(def ^:const content-dimensions
|
||||
{:messages {0 {:author {:width 112
|
||||
:height 8
|
||||
:margin-bottom 8}
|
||||
:message {:width 144
|
||||
:height 16
|
||||
:margin-bottom 0}}
|
||||
1 {:author {:width 96
|
||||
:height 8
|
||||
:margin-bottom 8}
|
||||
:message {:width 212
|
||||
:height 16
|
||||
:margin-bottom 0}}
|
||||
2 {:author {:width 80
|
||||
:height 8
|
||||
:margin-bottom 8}
|
||||
:message {:width 249
|
||||
:height 16
|
||||
:margin-bottom 0}}
|
||||
3 {:author {:width 124
|
||||
:height 8
|
||||
:margin-bottom 8}
|
||||
:message {:width 156
|
||||
:height 16
|
||||
:margin-bottom 0}}}
|
||||
:list-items {0 {:author {:width 112
|
||||
:height 8
|
||||
:margin-bottom 0}
|
||||
:message {:width 144
|
||||
:height 16
|
||||
:margin-bottom 8}}
|
||||
1 {:author {:width 96
|
||||
:height 8
|
||||
:margin-bottom 0}
|
||||
:message {:width 212
|
||||
:height 16
|
||||
:margin-bottom 8}}
|
||||
2 {:author {:width 80
|
||||
:height 8
|
||||
:margin-bottom 0}
|
||||
:message {:width 249
|
||||
:height 16
|
||||
:margin-bottom 8}}
|
||||
3 {:author {:width 124
|
||||
:height 8
|
||||
:margin-bottom 0}
|
||||
:message {:width 156
|
||||
:height 16
|
||||
:margin-bottom 8}}}
|
||||
:notifications {0 {:author {:width 109
|
||||
:height 8
|
||||
:margin-bottom 8}
|
||||
:message {:width 167
|
||||
:height 16
|
||||
:margin-bottom 8}
|
||||
:message2 {:width 242
|
||||
:height 30
|
||||
:margin-bottom 0}}
|
||||
1 {:author {:width 165
|
||||
:height 8
|
||||
:margin-bottom 8}
|
||||
:message {:width 112
|
||||
:height 16
|
||||
:margin-bottom 8}
|
||||
:message2 {:width 294
|
||||
:height 30
|
||||
:margin-bottom 0}}
|
||||
2 {:author {:width 136
|
||||
:height 8
|
||||
:margin-bottom 8}
|
||||
:message {:width 178
|
||||
:height 16
|
||||
:margin-bottom 8}
|
||||
:message2 {:width 178
|
||||
:height 30
|
||||
:margin-bottom 0}}
|
||||
3 {:author {:width 136
|
||||
:height 8
|
||||
:margin-bottom 8}
|
||||
:message {:width 166
|
||||
:height 16
|
||||
:margin-bottom 8}
|
||||
:message2 {:width 256
|
||||
:height 30
|
||||
:margin-bottom 0}}}})
|
||||
@@ -0,0 +1,29 @@
|
||||
(ns quo2.components.loaders.skeleton.style
|
||||
(:require [quo2.components.loaders.skeleton.constants :as constants]))
|
||||
|
||||
(defn container
|
||||
[content]
|
||||
{:flex-direction :row
|
||||
:padding 12
|
||||
:padding-top (get-in constants/layout-dimensions [content :padding-top])
|
||||
:height (get-in constants/layout-dimensions [content :height])})
|
||||
|
||||
(defn avatar
|
||||
[color]
|
||||
{:height 32
|
||||
:width 32
|
||||
:border-radius 16
|
||||
:background-color color})
|
||||
|
||||
(def content-container
|
||||
{:padding-left 8})
|
||||
|
||||
(defn content-view
|
||||
[{:keys [type index content color]}]
|
||||
(let [{:keys [width height margin-bottom]}
|
||||
(get-in constants/content-dimensions [content index type])]
|
||||
{:height height
|
||||
:width width
|
||||
:border-radius 6
|
||||
:background-color color
|
||||
:margin-bottom margin-bottom}))
|
||||
@@ -0,0 +1,46 @@
|
||||
(ns quo2.components.loaders.skeleton.view
|
||||
(:require [quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.loaders.skeleton.style :as style]
|
||||
[quo2.components.loaders.skeleton.constants :as constants]))
|
||||
|
||||
(defn- skeleton-item
|
||||
[index content color]
|
||||
[rn/view {:style (style/container content)}
|
||||
[rn/view {:style (style/avatar color)}]
|
||||
[rn/view {:style style/content-container}
|
||||
[rn/view
|
||||
{:style (style/content-view
|
||||
{:type (if (= content :list-items) :message :author)
|
||||
:index index
|
||||
:content content
|
||||
:color color})}]
|
||||
[rn/view
|
||||
{:style (style/content-view
|
||||
{:type (if (= content :list-items) :author :message)
|
||||
:index index
|
||||
:content content
|
||||
:color color})}]
|
||||
(when (= content :notifications)
|
||||
[rn/view
|
||||
{:style (style/content-view {:type :message2
|
||||
:index index
|
||||
:content content
|
||||
:color color})}])]])
|
||||
|
||||
(defn- internal-view
|
||||
[{:keys [content theme blur? parent-height]}]
|
||||
(let [number-of-skeletons (int (Math/floor (/ parent-height
|
||||
(get-in constants/layout-dimensions [content :height]))))
|
||||
color (cond
|
||||
blur? colors/white-opa-5
|
||||
(= theme :dark) colors/neutral-90
|
||||
:else colors/neutral-5)]
|
||||
[rn/view {:style {:padding 8}}
|
||||
(doall
|
||||
(for [index (range number-of-skeletons)]
|
||||
^{:key index}
|
||||
[skeleton-item (mod index 4) content color]))]))
|
||||
|
||||
(def view (theme/with-theme internal-view))
|
||||
@@ -0,0 +1,38 @@
|
||||
(ns quo2.components.markdown.list.component-spec
|
||||
(:require [quo2.components.markdown.list.view :as list]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "tests for markdown/list component"
|
||||
(h/test "renders component with title"
|
||||
(h/render [list/view {:title "test title"}])
|
||||
(h/is-truthy (h/get-by-text "test title")))
|
||||
|
||||
(h/test "renders component with description"
|
||||
(h/render [list/view
|
||||
{:title "test title"
|
||||
:description "test description"}])
|
||||
(h/is-truthy (h/get-by-text "test description")))
|
||||
|
||||
(h/test "renders component with title and description"
|
||||
(h/render [list/view
|
||||
{:title "test title"
|
||||
:description "test description"}])
|
||||
(h/is-truthy (h/get-by-text "test title"))
|
||||
(h/is-truthy (h/get-by-text "test description")))
|
||||
|
||||
(h/test "renders step component when step-number is valid and type is step"
|
||||
(h/render [list/view
|
||||
{:type :step
|
||||
:step-number 1}])
|
||||
(h/is-truthy (h/get-by-label-text :step-counter)))
|
||||
|
||||
(h/test "renders decription with a context tag component and description after the tag"
|
||||
(h/render [list/view
|
||||
{:step-number 1
|
||||
:description "Lorem ipsum "
|
||||
:tag-name "dolor"
|
||||
:description-after-tag "text after tag"}])
|
||||
(h/is-truthy (h/get-by-text "Lorem ipsum"))
|
||||
(h/is-truthy (h/get-by-label-text :user-avatar))
|
||||
(h/is-truthy (h/get-by-text "dolor"))
|
||||
(h/is-truthy (h/get-by-text "text after tag"))))
|
||||
@@ -0,0 +1,15 @@
|
||||
(ns quo2.components.markdown.list.style)
|
||||
|
||||
(defn container
|
||||
[container-style]
|
||||
(merge container-style
|
||||
{:flex-direction :row
|
||||
:flex 1
|
||||
:align-items :flex-start}))
|
||||
|
||||
(def index
|
||||
{:margin-left 5})
|
||||
|
||||
(def text-container
|
||||
{:margin-left 8
|
||||
:flex 1})
|
||||
@@ -0,0 +1,65 @@
|
||||
(ns quo2.components.markdown.list.view
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.counter.step.view :as step]
|
||||
[quo2.components.markdown.list.style :as style]
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[quo2.components.tags.context-tag.view :as context-tag]))
|
||||
|
||||
(defn get-colors
|
||||
[theme blur?]
|
||||
(cond (and blur? (= theme :dark)) colors/white-opa-40
|
||||
(= theme :dark) colors/neutral-50
|
||||
:else colors/neutral-40))
|
||||
|
||||
(defn description-text
|
||||
[{:keys [description tag-name tag-picture description-after-tag blur?]}]
|
||||
(if-not tag-name
|
||||
[text/text
|
||||
{:accessibility-label :list-item-description
|
||||
:size :paragraph-2}
|
||||
description]
|
||||
[rn/view {:style {:flex-direction :row :align-items :center}}
|
||||
[text/text
|
||||
{:accessibility-label :list-item-description
|
||||
:size :paragraph-2}
|
||||
description]
|
||||
[rn/view {:style {:margin-left 4}}
|
||||
[context-tag/context-tag {:blur? blur?} tag-picture tag-name]]
|
||||
[text/text
|
||||
{:style {:margin-left 4}
|
||||
:accessibility-label :list-item-description-after-tag
|
||||
:size :paragraph-2}
|
||||
description-after-tag]]))
|
||||
|
||||
(defn- internal-view
|
||||
[{:keys [theme title description tag-picture tag-name description-after-tag step-number
|
||||
customization-color type blur? container-style]
|
||||
:or {type :bullet}}]
|
||||
[rn/view {:style (style/container container-style)}
|
||||
[rn/view {:style style/index}
|
||||
(if (= type :step)
|
||||
[step/step
|
||||
{:in-blur-view? blur?
|
||||
:customization-color customization-color
|
||||
:type (if customization-color :complete :neutral)} step-number]
|
||||
[icon/icon :i/bullet {:color (get-colors theme blur?)}])]
|
||||
[rn/view {:style style/text-container}
|
||||
(when title
|
||||
[text/text
|
||||
{:accessibility-label :list-item-title
|
||||
:weight :semi-bold
|
||||
:size :paragraph-2}
|
||||
title])
|
||||
(when description
|
||||
[rn/view (when title {:style {:margin-top 0}})
|
||||
[description-text
|
||||
{:description description
|
||||
:tag-name tag-name
|
||||
:tag-picture tag-picture
|
||||
:description-after-tag description-after-tag
|
||||
:blur? blur?}]])]])
|
||||
|
||||
(def view (theme/with-theme internal-view))
|
||||
@@ -17,8 +17,8 @@
|
||||
:background colors/neutral-95}})
|
||||
|
||||
(defn get-color
|
||||
[key]
|
||||
(get-in themes [(theme/get-theme) key]))
|
||||
[k]
|
||||
(get-in themes [(theme/get-theme) k]))
|
||||
|
||||
(def ui-images
|
||||
{:light {:horizontal (js/require "../resources/images/ui/message-gap-hborder-light.png")
|
||||
@@ -28,8 +28,8 @@
|
||||
:circles (js/require "../resources/images/ui/message-gap-circle-bg-dark.png")}})
|
||||
|
||||
(defn get-image
|
||||
[key]
|
||||
(get-in ui-images [(theme/get-theme) key]))
|
||||
[k]
|
||||
(get-in ui-images [(theme/get-theme) k]))
|
||||
|
||||
;;; components
|
||||
;;;; borders
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
|
||||
(defn dynamic-button-view
|
||||
[type dynamic-buttons style]
|
||||
(when-let [{:keys [count on-press customization-color label]} (get dynamic-buttons type)]
|
||||
(when-let [{:keys [on-press customization-color label] :as props} (get dynamic-buttons type)]
|
||||
[dynamic-button/dynamic-button
|
||||
{:type type
|
||||
:label label
|
||||
:on-press on-press
|
||||
:count count
|
||||
:count (:count props)
|
||||
:style style
|
||||
:customization-color customization-color}]))
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
(ns quo2.components.navigation.page-nav
|
||||
(:require [clojure.string :as string]
|
||||
[quo2.components.avatars.user-avatar.view :as user-avatar]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.buttons.button.view :as button]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]))
|
||||
[react-native.core :as rn]
|
||||
[quo2.theme :as theme]))
|
||||
|
||||
(def ^:private centrify-style
|
||||
{:display :flex
|
||||
@@ -30,7 +31,7 @@
|
||||
{:no-color true})))
|
||||
|
||||
(defn left-section-view
|
||||
[{:keys [on-press icon accessibility-label type icon-background-color icon-override-theme]
|
||||
[{:keys [on-press icon accessibility-label type icon-background-color]
|
||||
:or {type :grey}}
|
||||
put-middle-section-on-left?]
|
||||
[rn/view {:style (when put-middle-section-on-left? {:margin-right 5})}
|
||||
@@ -40,7 +41,6 @@
|
||||
:type type
|
||||
:size 32
|
||||
:accessibility-label accessibility-label
|
||||
:override-theme icon-override-theme
|
||||
:override-background-color icon-background-color}
|
||||
icon]])
|
||||
|
||||
@@ -87,10 +87,10 @@
|
||||
|
||||
(defn- mid-section-view
|
||||
[{:keys [horizontal-description? one-icon-align-left? type left-align?
|
||||
main-text right-icon main-text-icon-color left-icon on-press avatar]
|
||||
main-text right-icon main-text-icon-color left-icon on-press avatar theme]
|
||||
:as props}]
|
||||
(let [text-color (if (colors/dark?) colors/neutral-5 colors/neutral-95)
|
||||
text-secondary-color (if (colors/dark?) colors/neutral-40 colors/neutral-50)
|
||||
(let [text-color (colors/theme-colors colors/neutral-95 colors/neutral-5 theme)
|
||||
text-secondary-color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
|
||||
component-instance [mid-section-comp (assoc props :text-secondary-color text-secondary-color)]]
|
||||
[rn/touchable-opacity {:on-press on-press}
|
||||
[rn/view
|
||||
@@ -152,7 +152,7 @@
|
||||
:justify-content :flex-end)}
|
||||
(let [last-icon-index (-> right-section-buttons count dec)]
|
||||
(map-indexed (fn [index
|
||||
{:keys [icon on-press type style icon-override-theme icon-background-color
|
||||
{:keys [icon on-press type style icon-background-color
|
||||
accessibility-label label]
|
||||
:or {type :grey}}]
|
||||
^{:key index}
|
||||
@@ -168,12 +168,11 @@
|
||||
:type type
|
||||
:before (when label icon)
|
||||
:size 32
|
||||
:override-theme icon-override-theme
|
||||
:override-background-color icon-background-color}
|
||||
(if label label icon)]])
|
||||
right-section-buttons))])
|
||||
|
||||
(defn page-nav
|
||||
(defn- page-nav-internal
|
||||
"[page-nav opts]
|
||||
opts
|
||||
{ :one-icon-align-left? true/false
|
||||
@@ -198,25 +197,26 @@
|
||||
{:type button-type
|
||||
:on-press event
|
||||
:icon icon
|
||||
:icon-override-theme :light/:dark
|
||||
}
|
||||
:right-section-buttons vector of
|
||||
{:type button-type
|
||||
:on-press event
|
||||
:icon icon
|
||||
:icon-override-theme :light/:dark
|
||||
}
|
||||
:theme :light or :dark
|
||||
}
|
||||
"
|
||||
[{:keys [container-style one-icon-align-left? horizontal-description?
|
||||
align-mid? page-nav-color page-nav-background-uri
|
||||
mid-section
|
||||
left-section
|
||||
right-section-buttons]}]
|
||||
right-section-buttons
|
||||
theme]}]
|
||||
(let [put-middle-section-on-left? (or align-mid?
|
||||
(> (count right-section-buttons) 1))
|
||||
mid-section-props
|
||||
{:type (:type mid-section)
|
||||
:theme theme
|
||||
:horizontal-description? horizontal-description?
|
||||
:description-img (:description-img mid-section)
|
||||
:main-text (:main-text mid-section)
|
||||
@@ -258,3 +258,5 @@
|
||||
(not put-middle-section-on-left?)
|
||||
[mid-section-view mid-section-props]))]
|
||||
[right-section-view right-section-buttons]]))
|
||||
|
||||
(def page-nav (theme/with-theme page-nav-internal))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(ns quo2.components.notifications.activity-log.view
|
||||
(:require [clojure.string :as string]
|
||||
[quo.core :as quo]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.buttons.button.view :as button]
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.notifications.activity-log.style :as style]
|
||||
@@ -150,8 +150,8 @@
|
||||
[activity-reply-text-input props reply-input])
|
||||
(when items
|
||||
[rn/view style/footer-container
|
||||
(for [{:keys [key] :as item} items]
|
||||
^{:key key}
|
||||
(for [item items]
|
||||
^{:key (:key item)}
|
||||
[footer-item-view item replying? reply-input])])])))
|
||||
|
||||
(defn view
|
||||
|
||||
@@ -30,10 +30,10 @@
|
||||
:path-length path-length}))
|
||||
|
||||
(defn- linear-ease
|
||||
[time start goal duration]
|
||||
[input-time start goal duration]
|
||||
(if (zero? duration)
|
||||
start
|
||||
(-> time
|
||||
(-> input-time
|
||||
(/ duration)
|
||||
(* goal)
|
||||
(+ start))))
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn info-count
|
||||
([count]
|
||||
(info-count {} count))
|
||||
([props count]
|
||||
(when (> count 0)
|
||||
([amount]
|
||||
(info-count {} amount))
|
||||
([props amount]
|
||||
(when (> amount 0)
|
||||
[rn/view
|
||||
(merge props
|
||||
{:style (merge {:width 16
|
||||
@@ -23,4 +23,4 @@
|
||||
{:style (merge typography/font-medium
|
||||
typography/label
|
||||
{:color colors/white :text-align :center})}
|
||||
count]])))
|
||||
amount]])))
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
|
||||
(defn toast-undo-action
|
||||
[duration on-press override-theme]
|
||||
[toast-action-container
|
||||
{:on-press on-press :accessibility-label :toast-undo-action}
|
||||
[toast-action-container {:on-press on-press :accessibility-label :toast-undo-action}
|
||||
[rn/view {:style {:margin-right 5}}
|
||||
[count-down-circle/circle-timer {:duration duration}]]
|
||||
[text/text
|
||||
@@ -31,17 +30,17 @@
|
||||
|
||||
(defn- toast-container
|
||||
[{:keys [left title text right container-style override-theme]}]
|
||||
[rn/view
|
||||
{:style (merge style/box-container container-style)}
|
||||
[rn/view {:style (merge style/box-container container-style)}
|
||||
[blur/view
|
||||
{:style style/blur-container
|
||||
:blur-amount 13
|
||||
:blur-radius 10
|
||||
:blur-type :transparent
|
||||
:overlay-color :transparent}]
|
||||
[rn/view
|
||||
{:style (style/content-container override-theme)}
|
||||
[rn/view {:style style/left-side-container} left]
|
||||
|
||||
[rn/view {:style (style/content-container override-theme)}
|
||||
[rn/view {:style style/left-side-container}
|
||||
left]
|
||||
[rn/view {:style style/right-side-container}
|
||||
(when title
|
||||
[text/text
|
||||
@@ -57,7 +56,7 @@
|
||||
:style (style/text override-theme)
|
||||
:accessibility-label :toast-content}
|
||||
text])]
|
||||
(when right right)]])
|
||||
right]])
|
||||
|
||||
(defn toast
|
||||
[{:keys [icon icon-color title text action undo-duration undo-on-press container-style
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.hole-view :as hole-view]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.buttons.button.view :as button]
|
||||
[quo2.components.profile.profile-card.style :as style]
|
||||
[quo2.components.avatars.user-avatar.view :as user-avatar]))
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn :refer [use-effect]]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.buttons.button.view :as button]
|
||||
[quo2.components.record-audio.record-audio.helpers :as helpers]))
|
||||
|
||||
(defn f-record-button
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
(ns quo2.components.settings.accounts.view
|
||||
(:require [quo2.components.avatars.account-avatar :as account-avatar]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.buttons.button.view :as button]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.settings.accounts.style :as style]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
@@ -26,4 +26,4 @@
|
||||
{:data [{:id 1
|
||||
:label "Item 1"}
|
||||
]} types/tab])
|
||||
(h/is-truthy (h/get-by-text "Item 1"))))
|
||||
(h/is-truthy (h/get-by-text "Item 1"))))
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
(:require [quo2.components.settings.settings-list.style :as style]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.selectors.selectors.view :as selectors]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.buttons.button.view :as button]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.tags.status-tags :as status-tag]
|
||||
[quo2.foundations.colors :as colors]
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
[react-native.blur :as blur]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.buttons.button.view :as button]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn view
|
||||
|
||||
@@ -41,8 +41,8 @@
|
||||
:margin-right 8})
|
||||
|
||||
(defn get-color-by-type
|
||||
[type key]
|
||||
(get-in themes [(theme/get-theme) type key]))
|
||||
[type k]
|
||||
(get-in themes [(theme/get-theme) type k]))
|
||||
|
||||
(defn account-selector
|
||||
"[account-selector opts]
|
||||
@@ -73,4 +73,3 @@
|
||||
:size :paragraph-1
|
||||
:style {:color account-text-color}}
|
||||
account-text]]]))
|
||||
|
||||
|
||||
+34
-18
@@ -2,21 +2,24 @@
|
||||
(:refer-clojure :exclude [filter])
|
||||
(:require
|
||||
quo2.components.avatars.account-avatar
|
||||
quo2.components.avatars.channel-avatar
|
||||
quo2.components.avatars.channel-avatar.view
|
||||
quo2.components.avatars.group-avatar
|
||||
quo2.components.avatars.icon-avatar
|
||||
quo2.components.avatars.user-avatar.view
|
||||
quo2.components.avatars.wallet-user-avatar
|
||||
quo2.components.banners.banner.view
|
||||
quo2.components.buttons.button
|
||||
quo2.components.buttons.button.view
|
||||
quo2.components.buttons.dynamic-button
|
||||
quo2.components.buttons.predictive-keyboard.view
|
||||
quo2.components.buttons.slide-button.view
|
||||
quo2.components.code.snippet
|
||||
quo2.components.colors.color-picker.view
|
||||
quo2.components.common.separator.view
|
||||
quo2.components.community.banner.view
|
||||
quo2.components.community.channel-actions
|
||||
quo2.components.community.community-card-view
|
||||
quo2.components.community.community-list-view
|
||||
quo2.components.community.community-view
|
||||
quo2.components.community.banner.view
|
||||
quo2.components.community.icon
|
||||
quo2.components.community.token-gating
|
||||
quo2.components.counter.counter
|
||||
@@ -30,8 +33,8 @@
|
||||
quo2.components.drawers.drawer-buttons.view
|
||||
quo2.components.drawers.permission-context.view
|
||||
quo2.components.dropdowns.dropdown
|
||||
quo2.components.header
|
||||
quo2.components.empty-state.empty-state.view
|
||||
quo2.components.header
|
||||
quo2.components.icon
|
||||
quo2.components.info.info-message
|
||||
quo2.components.info.information-box.view
|
||||
@@ -41,14 +44,16 @@
|
||||
quo2.components.inputs.search-input.view
|
||||
quo2.components.inputs.title-input.view
|
||||
quo2.components.keycard.view
|
||||
quo2.components.links.link-preview.view
|
||||
quo2.components.links.url-preview-list.view
|
||||
quo2.components.links.url-preview.view
|
||||
quo2.components.links.link-preview.view
|
||||
quo2.components.list-items.channel
|
||||
quo2.components.list-items.menu-item
|
||||
quo2.components.list-items.preview-list
|
||||
quo2.components.list-items.user-list
|
||||
quo2.components.loaders.skeleton
|
||||
quo2.components.loaders.skeleton.view
|
||||
quo2.components.markdown.list.view
|
||||
quo2.components.markdown.text
|
||||
quo2.components.messages.author.view
|
||||
quo2.components.messages.gap
|
||||
@@ -66,15 +71,16 @@
|
||||
quo2.components.profile.profile-card.view
|
||||
quo2.components.profile.select-profile.view
|
||||
quo2.components.reactions.reaction
|
||||
quo2.components.selectors.reactions.view
|
||||
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.selectors.view
|
||||
quo2.components.separator
|
||||
quo2.components.settings.accounts.view
|
||||
quo2.components.settings.privacy-option
|
||||
quo2.components.settings.reorder-item.view
|
||||
quo2.components.settings.settings-list.view
|
||||
quo2.components.share.qr-code.view
|
||||
quo2.components.share.share-qr-code.view
|
||||
quo2.components.tabs.account-selector
|
||||
@@ -86,14 +92,10 @@
|
||||
quo2.components.tags.tag
|
||||
quo2.components.tags.tags
|
||||
quo2.components.tags.token-tag
|
||||
quo2.components.text-combinations.title.view
|
||||
quo2.components.settings.settings-list.view
|
||||
quo2.components.settings.reorder-item.view
|
||||
quo2.components.community.channel-actions))
|
||||
quo2.components.text-combinations.title.view))
|
||||
|
||||
(def text quo2.components.markdown.text/text)
|
||||
(def icon quo2.components.icon/icon)
|
||||
(def separator quo2.components.separator/separator)
|
||||
(def separator quo2.components.common.separator.view/separator)
|
||||
(def header quo2.components.header/header)
|
||||
(def dropdown quo2.components.dropdowns.dropdown/dropdown)
|
||||
(def info-message quo2.components.info.info-message/info-message)
|
||||
@@ -107,12 +109,11 @@
|
||||
(def group-avatar-tag quo2.components.tags.context-tag.view/group-avatar-tag)
|
||||
(def audio-tag quo2.components.tags.context-tag.view/audio-tag)
|
||||
(def community-tag quo2.components.tags.context-tag.view/community-tag)
|
||||
(def floating-shell-button quo2.components.navigation.floating-shell-button/floating-shell-button)
|
||||
(def page-nav quo2.components.navigation.page-nav/page-nav)
|
||||
|
||||
|
||||
(def disclaimer quo2.components.selectors.disclaimer.view/view)
|
||||
(def checkbox quo2.components.selectors.selectors.view/checkbox)
|
||||
(def filter quo2.components.selectors.filter.view/view)
|
||||
(def skeleton quo2.components.loaders.skeleton/skeleton)
|
||||
(def author quo2.components.messages.author.view/author)
|
||||
|
||||
;;;; SELECTORS
|
||||
@@ -120,7 +121,7 @@
|
||||
|
||||
;;;; AVATAR
|
||||
(def account-avatar quo2.components.avatars.account-avatar/account-avatar)
|
||||
(def channel-avatar quo2.components.avatars.channel-avatar/channel-avatar)
|
||||
(def channel-avatar quo2.components.avatars.channel-avatar.view/view)
|
||||
(def group-avatar quo2.components.avatars.group-avatar/group-avatar)
|
||||
(def icon-avatar quo2.components.avatars.icon-avatar/icon-avatar)
|
||||
(def user-avatar quo2.components.avatars.user-avatar.view/user-avatar)
|
||||
@@ -130,11 +131,14 @@
|
||||
(def banner quo2.components.banners.banner.view/banner)
|
||||
|
||||
;;;; BUTTONS
|
||||
(def button quo2.components.buttons.button/button)
|
||||
(def button quo2.components.buttons.button.view/button)
|
||||
(def dynamic-button quo2.components.buttons.dynamic-button/dynamic-button)
|
||||
(def predictive-keyboard quo2.components.buttons.predictive-keyboard.view/view)
|
||||
(def slide-button quo2.components.buttons.slide-button.view/view)
|
||||
|
||||
;;;; CODE
|
||||
(def snippet quo2.components.code.snippet/snippet)
|
||||
|
||||
;;;; CARDS
|
||||
(def small-option-card quo2.components.onboarding.small-option-card.view/small-option-card)
|
||||
(def keycard quo2.components.keycard.view/keycard)
|
||||
@@ -190,6 +194,18 @@
|
||||
(def preview-list quo2.components.list-items.preview-list/preview-list)
|
||||
(def user-list quo2.components.list-items.user-list/user-list)
|
||||
|
||||
;;;; LOADERS
|
||||
(def skeleton quo2.components.loaders.skeleton/skeleton)
|
||||
(def static-skeleton quo2.components.loaders.skeleton.view/view)
|
||||
|
||||
;;;; NAVIGATION
|
||||
(def floating-shell-button quo2.components.navigation.floating-shell-button/floating-shell-button)
|
||||
(def page-nav quo2.components.navigation.page-nav/page-nav)
|
||||
|
||||
;;;; MARKDOWN
|
||||
(def markdown-list quo2.components.markdown.list.view/view)
|
||||
(def text quo2.components.markdown.text/text)
|
||||
|
||||
;;;; NOTIFICATIONS
|
||||
(def activity-log quo2.components.notifications.activity-log.view/view)
|
||||
(def info-count quo2.components.notifications.info-count/info-count)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
(:require
|
||||
[quo2.components.avatars.user-avatar.component-spec]
|
||||
[quo2.components.banners.banner.component-spec]
|
||||
[quo2.components.buttons.--tests--.buttons-component-spec]
|
||||
[quo2.components.buttons.button.component-spec]
|
||||
[quo2.components.buttons.predictive-keyboard.component-spec]
|
||||
[quo2.components.buttons.slide-button.component-spec]
|
||||
[quo2.components.colors.color-picker.component-spec]
|
||||
@@ -23,6 +23,7 @@
|
||||
[quo2.components.links.url-preview-list.component-spec]
|
||||
[quo2.components.links.url-preview.component-spec]
|
||||
[quo2.components.markdown.--tests--.text-component-spec]
|
||||
[quo2.components.markdown.list.component-spec]
|
||||
[quo2.components.notifications.notification.component-spec]
|
||||
[quo2.components.onboarding.small-option-card.component-spec]
|
||||
[quo2.components.password.tips.component-spec]
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
(def neutral-100-opa-5 (alpha neutral-100 0.05))
|
||||
(def neutral-100-opa-10 (alpha neutral-100 0.1))
|
||||
(def neutral-100-opa-30 (alpha neutral-100 0.3))
|
||||
(def neutral-100-opa-50 (alpha neutral-100 0.5))
|
||||
(def neutral-100-opa-60 (alpha neutral-100 0.6))
|
||||
(def neutral-100-opa-70 (alpha neutral-100 0.7))
|
||||
(def neutral-100-opa-80 (alpha neutral-100 0.8))
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
(defn on-finalize [gesture handler] (.onFinalize ^js gesture handler))
|
||||
|
||||
(defn max-pointers [gesture count] (.maxPointers ^js gesture count))
|
||||
(defn max-pointers [gesture amount] (.maxPointers ^js gesture amount))
|
||||
|
||||
(defn min-distance [gesture dist] (.minDistance ^js gesture dist))
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
(defn hit-slop [gesture settings] (.hitSlop ^js gesture settings))
|
||||
|
||||
(defn number-of-taps [gesture count] (.numberOfTaps ^js gesture count))
|
||||
(defn number-of-taps [gesture amount] (.numberOfTaps ^js gesture amount))
|
||||
|
||||
(defn enabled [gesture enabled?] (.enabled ^js gesture enabled?))
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
(ns react-native.keychain
|
||||
(:require ["react-native-keychain" :as react-native-keychain]
|
||||
[clojure.string :as string]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
;; ********************************************************************************
|
||||
;; Storing / Retrieving a user password to/from Keychain
|
||||
;; ********************************************************************************
|
||||
;;
|
||||
;; We are using set/get/reset internet credentials there because they are bound
|
||||
;; to an address (`server`) property.
|
||||
|
||||
(defn enum-val
|
||||
[enum-name value-name]
|
||||
(get-in (js->clj ^js react-native-keychain) [enum-name value-name]))
|
||||
|
||||
;; We need a more strict access mode for keychain entries that save user password.
|
||||
;; iOS
|
||||
;; see this article for more details:
|
||||
;; https://developer.apple.com/documentation/security/keychain_services/keychain_items/restricting_keychain_item_accessibility?language=objc
|
||||
(def keychain-restricted-availability
|
||||
;; From Apple's documentation:
|
||||
;; > The kSecAttrAccessible attribute enables you to control item availability
|
||||
;; > relative to the lock state of the device.
|
||||
;; > It also lets you specify eligibility for restoration to a new device.
|
||||
;; > If the attribute ends with the string ThisDeviceOnly,
|
||||
;; > the item can be restored to the same device that created a backup,
|
||||
;; > but it isn’t migrated when restoring another device’s backup data.
|
||||
;; > ...
|
||||
;; > For extremely sensitive data
|
||||
;; > THAT YOU NEVER WANT STORED IN iCloud,
|
||||
;; > you might choose kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly.
|
||||
;; That is exactly what we use there.
|
||||
;; Note that the password won't be stored if the device isn't locked by a passcode.
|
||||
#js {:accessible (enum-val "ACCESSIBLE" "WHEN_PASSCODE_SET_THIS_DEVICE_ONLY")})
|
||||
|
||||
(def keychain-secure-hardware
|
||||
;; (Android) Requires storing the encryption key for the entry in secure hardware
|
||||
;; or StrongBox (see https://developer.android.com/training/articles/keystore#ExtractionPrevention)
|
||||
"SECURE_HARDWARE")
|
||||
|
||||
;; Android only
|
||||
(defn secure-hardware-available?
|
||||
[callback]
|
||||
(-> (.getSecurityLevel ^js react-native-keychain)
|
||||
(.then (fn [level] (callback (= level keychain-secure-hardware))))))
|
||||
|
||||
;; iOS only
|
||||
(defn device-encrypted?
|
||||
[callback]
|
||||
(-> (.canImplyAuthentication
|
||||
^js react-native-keychain
|
||||
(clj->js
|
||||
{:authenticationType
|
||||
(enum-val "ACCESS_CONTROL" "BIOMETRY_ANY_OR_DEVICE_PASSCODE")}))
|
||||
(.then callback)))
|
||||
|
||||
(defn save-credentials
|
||||
"Stores the credentials for the address to the Keychain"
|
||||
[server username password callback]
|
||||
(-> (.setInternetCredentials ^js react-native-keychain
|
||||
(string/lower-case server)
|
||||
username
|
||||
password
|
||||
keychain-secure-hardware
|
||||
keychain-restricted-availability)
|
||||
(.then callback)))
|
||||
|
||||
(defn get-credentials
|
||||
"Gets the credentials for a specified server from the Keychain"
|
||||
[server callback]
|
||||
(-> (.getInternetCredentials ^js react-native-keychain (string/lower-case server))
|
||||
(.then callback)))
|
||||
|
||||
(defn reset-credentials
|
||||
[server]
|
||||
(-> (.resetInternetCredentials ^js react-native-keychain (string/lower-case server))
|
||||
(.then #(when-not % (log/error (str "Error while clearing saved password."))))))
|
||||
@@ -81,7 +81,8 @@
|
||||
{:linear (bezier 0 0 1 1)
|
||||
:easing1 (bezier 0.25 0.1 0.25 1)
|
||||
:easing2 (bezier 0 0.3 0.6 0.9)
|
||||
:easing3 (bezier 0.3 0.3 0.3 0.9)})
|
||||
:easing3 (bezier 0.3 0.3 0.3 0.9)
|
||||
:easing4 (bezier 0.3 0.3 1 1)})
|
||||
|
||||
;; Helper functions
|
||||
(defn get-shared-value
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
|
||||
(defn- get-static-bottom
|
||||
[]
|
||||
(oops/oget StaticSafeAreaInsets "safeAreaInsetsBottom"))
|
||||
(some-> StaticSafeAreaInsets
|
||||
(oops/oget "safeAreaInsetsBottom")))
|
||||
|
||||
(defn get-top
|
||||
[]
|
||||
@@ -20,8 +21,8 @@
|
||||
|
||||
(defn get-bottom
|
||||
[]
|
||||
(if platform/ios?
|
||||
(get-static-bottom)
|
||||
(if-let [bottom (and platform/ios? (get-static-bottom))]
|
||||
bottom
|
||||
0))
|
||||
|
||||
(defn get-insets
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
(ns react-native.touch-id
|
||||
(:require ["react-native-touch-id" :default touchid]))
|
||||
|
||||
;; currently, for android, react-native-touch-id
|
||||
;; is not returning supported biometric type
|
||||
;; defaulting to :fingerprint
|
||||
(def android-default-support :fingerprint)
|
||||
|
||||
(defn get-supported-type
|
||||
[callback]
|
||||
(-> (.isSupported ^js touchid)
|
||||
(.then #(callback (or (keyword %) android-default-support)))
|
||||
(.catch #(callback nil))))
|
||||
|
||||
(defn authenticate
|
||||
[{:keys [on-success on-fail reason options]}]
|
||||
(-> (.authenticate ^js touchid reason (clj->js options))
|
||||
(.then #(when on-success (on-success)))
|
||||
(.catch #(when on-fail (on-fail (aget % "code"))))))
|
||||
@@ -10,9 +10,9 @@
|
||||
(def key->string str)
|
||||
|
||||
(defn set-item!
|
||||
[key value]
|
||||
[k value]
|
||||
(-> ^js async-storage
|
||||
(.setItem (key->string key)
|
||||
(.setItem (key->string k)
|
||||
(clj->transit value))
|
||||
(.catch (fn [error]
|
||||
(log/error "[async-storage]" error)))))
|
||||
|
||||
@@ -619,3 +619,40 @@
|
||||
bookmarks)
|
||||
stored-bookmarks (get-in db [:bookmarks/bookmarks])]
|
||||
{:db (assoc-in db [:bookmarks/bookmarks] (merge stored-bookmarks changed-bookmarks))}))
|
||||
|
||||
(rf/defn initialize-dapp-permissions
|
||||
{:events [::initialize-dapp-permissions]}
|
||||
[{:keys [db]} all-dapp-permissions]
|
||||
(let [dapp-permissions (reduce (fn [acc {:keys [dapp] :as dapp-permissions}]
|
||||
(assoc acc dapp dapp-permissions))
|
||||
{}
|
||||
all-dapp-permissions)]
|
||||
{:db (assoc db :dapps/permissions dapp-permissions)}))
|
||||
|
||||
(rf/defn initialize-browsers
|
||||
{:events [::initialize-browsers]}
|
||||
[{:keys [db]} all-stored-browsers]
|
||||
(let [browsers (reduce (fn [acc {:keys [browser-id] :as browser}]
|
||||
(assoc acc browser-id browser))
|
||||
{}
|
||||
all-stored-browsers)]
|
||||
{:db (assoc db :browser/browsers browsers)}))
|
||||
|
||||
(rf/defn initialize-bookmarks
|
||||
{:events [::initialize-bookmarks]}
|
||||
[{:keys [db]} stored-bookmarks]
|
||||
(let [bookmarks (reduce (fn [acc {:keys [url] :as bookmark}]
|
||||
(assoc acc url bookmark))
|
||||
{}
|
||||
stored-bookmarks)]
|
||||
{:db (assoc db :bookmarks/bookmarks bookmarks)}))
|
||||
|
||||
(rf/defn initialize-browser
|
||||
[_]
|
||||
{:json-rpc/call
|
||||
[{:method "wakuext_getBrowsers"
|
||||
:on-success #(re-frame/dispatch [::initialize-browsers %])}
|
||||
{:method "browsers_getBookmarks"
|
||||
:on-success #(re-frame/dispatch [::initialize-bookmarks %])}
|
||||
{:method "permissions_getDappPermissions"
|
||||
:on-success #(re-frame/dispatch [::initialize-dapp-permissions %])}]})
|
||||
|
||||
@@ -284,9 +284,10 @@
|
||||
:params [community-id]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::left %])
|
||||
:on-error (fn []
|
||||
:on-error (fn [response]
|
||||
(log/error "failed to leave community"
|
||||
community-id)
|
||||
community-id
|
||||
response)
|
||||
(re-frame/dispatch [::failed-to-leave]))}]}))
|
||||
|
||||
(rf/defn status-tag-pressed
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
rpc->type
|
||||
unmarshal-members))
|
||||
|
||||
(rf/defn fetch-chats-rpc
|
||||
(rf/defn fetch-chats-preview
|
||||
[_ {:keys [on-success]}]
|
||||
{:json-rpc/call [{:method "wakuext_chatsPreview"
|
||||
:params []
|
||||
|
||||
@@ -6,4 +6,4 @@
|
||||
(-> message
|
||||
(clojure.set/rename-keys {:chatId :chat-id
|
||||
:introductionMessage :introduction-message
|
||||
:messageType :message-type})))
|
||||
:messageType :message-type})))
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
(ns status-im.data-store.settings
|
||||
(:require [status-im.data-store.visibility-status-updates :as visibility-status-updates]
|
||||
[status-im.ethereum.eip55 :as eip55]
|
||||
[status-im2.config :as config]))
|
||||
[status-im2.config :as config]
|
||||
[clojure.set :as set]))
|
||||
|
||||
(defn rpc->networks
|
||||
[networks]
|
||||
@@ -33,27 +34,19 @@
|
||||
{}
|
||||
custom-bootnodes))
|
||||
|
||||
(defn rpc->stickers-packs
|
||||
[stickers-packs]
|
||||
(reduce-kv (fn [acc pack-id stickers-pack]
|
||||
(assoc acc (js/parseInt (name pack-id)) stickers-pack))
|
||||
{}
|
||||
stickers-packs))
|
||||
|
||||
(defn rpc->settings
|
||||
[settings]
|
||||
(-> settings
|
||||
(update :dapps-address eip55/address->checksum)
|
||||
(update :address eip55/address->checksum)
|
||||
(update :networks/networks rpc->networks)
|
||||
(update :networks/current-network
|
||||
#(if (seq %)
|
||||
%
|
||||
config/default-network))
|
||||
(update :networks/current-network #(if (seq %) % config/default-network))
|
||||
(update :wallet/visible-tokens rpc->visible-tokens)
|
||||
(update :pinned-mailservers rpc->pinned-mailservers)
|
||||
(update :link-previews-enabled-sites set)
|
||||
(update :custom-bootnodes rpc->custom-bootnodes)
|
||||
(update :custom-bootnodes-enabled? rpc->custom-bootnodes)
|
||||
(update :currency keyword)
|
||||
(visibility-status-updates/<-rpc-settings)))
|
||||
(visibility-status-updates/<-rpc-settings)
|
||||
(set/rename-keys {:compressedKey :compressed-key
|
||||
:emojiHash :emoji-hash})))
|
||||
|
||||
+16
-81
@@ -23,7 +23,6 @@
|
||||
status-im.log-level.core
|
||||
status-im.mailserver.constants
|
||||
[status-im.mailserver.core :as mailserver]
|
||||
[status-im.multiaccounts.biometric.core :as biometric]
|
||||
status-im.multiaccounts.login.core
|
||||
status-im.multiaccounts.logout.core
|
||||
[status-im.multiaccounts.model :as multiaccounts.model]
|
||||
@@ -63,7 +62,8 @@
|
||||
[react-native.platform :as platform]
|
||||
status-im2.contexts.chat.home.events
|
||||
status-im2.contexts.communities.home.events
|
||||
status-im.ui.components.invite.events))
|
||||
status-im.ui.components.invite.events
|
||||
[status-im2.common.biometric.events :as biometric]))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:dismiss-keyboard
|
||||
@@ -124,33 +124,26 @@
|
||||
[(get-in db [:profile/profile :appearance])
|
||||
(:view-id db) true]})))
|
||||
|
||||
(def authentication-options
|
||||
{:reason (i18n/label :t/biometric-auth-reason-login)})
|
||||
|
||||
(defn- on-biometric-auth-result
|
||||
[{:keys [bioauth-success bioauth-code bioauth-message]}]
|
||||
(when-not bioauth-success
|
||||
(if (= bioauth-code "USER_FALLBACK")
|
||||
(re-frame/dispatch [:multiaccounts.logout.ui/logout-confirmed])
|
||||
(utils/show-confirmation
|
||||
{:title (i18n/label :t/biometric-auth-confirm-title)
|
||||
:content (or bioauth-message (i18n/label :t/biometric-auth-confirm-message))
|
||||
:confirm-button-text (i18n/label :t/biometric-auth-confirm-try-again)
|
||||
:cancel-button-text (i18n/label :t/biometric-auth-confirm-logout)
|
||||
:on-accept #(biometric/authenticate nil
|
||||
on-biometric-auth-result
|
||||
authentication-options)
|
||||
:on-cancel #(re-frame/dispatch [:multiaccounts.logout.ui/logout-confirmed])}))))
|
||||
(defn- on-biometric-auth-fail
|
||||
[{:keys [code]}]
|
||||
(if (= code "USER_FALLBACK")
|
||||
(re-frame/dispatch [:multiaccounts.logout.ui/logout-confirmed])
|
||||
(utils/show-confirmation
|
||||
{:title (i18n/label :t/biometric-auth-confirm-title)
|
||||
:content (i18n/label :t/biometric-auth-confirm-message)
|
||||
:confirm-button-text (i18n/label :t/biometric-auth-confirm-try-again)
|
||||
:cancel-button-text (i18n/label :t/biometric-auth-confirm-logout)
|
||||
:on-accept #(biometric/authenticate nil {:on-fail on-biometric-auth-fail})
|
||||
:on-cancel #(re-frame/dispatch [:multiaccounts.logout.ui/logout-confirmed])})))
|
||||
|
||||
(rf/defn on-return-from-background
|
||||
[{:keys [db now] :as cofx}]
|
||||
(let [new-account? (get db :onboarding-2/new-account?)
|
||||
app-in-background-since (get db :app-in-background-since)
|
||||
signed-up? (get-in db [:profile/profile :signed-up?])
|
||||
biometric-auth? (= (:auth-method db) "biometric")
|
||||
requires-bio-auth (and
|
||||
signed-up?
|
||||
biometric-auth?
|
||||
(= (:auth-method db) "biometric")
|
||||
(some? app-in-background-since)
|
||||
(>= (- now app-in-background-since)
|
||||
constants/ms-in-bg-for-require-bioauth))]
|
||||
@@ -163,7 +156,7 @@
|
||||
#(when-let [chat-id (:current-chat-id db)]
|
||||
{:dispatch [:chat/mark-all-as-read chat-id]})
|
||||
#(when requires-bio-auth
|
||||
(biometric/authenticate % on-biometric-auth-result authentication-options)))))
|
||||
(biometric/authenticate % {:on-fail on-biometric-auth-fail})))))
|
||||
|
||||
(rf/defn on-going-in-background
|
||||
[{:keys [db now]}]
|
||||
@@ -205,16 +198,8 @@
|
||||
:key-uid (get-in cofx [:db :profile/profile :key-uid])}
|
||||
:db (assoc db :screens/was-focused-once? true)}
|
||||
|
||||
(= :login view-id)
|
||||
{}
|
||||
|
||||
(not (get db :screens/was-focused-once?))
|
||||
{:db (assoc db :screens/was-focused-once? true)}
|
||||
|
||||
:else
|
||||
{::async-storage/set! {:chat-id nil
|
||||
:key-uid nil}
|
||||
:db (assoc db :screens/was-focused-once? true)})
|
||||
{:db (assoc db :screens/was-focused-once? true)})
|
||||
#(case view-id
|
||||
:keycard-settings (keycard/settings-screen-did-load %)
|
||||
:reset-card (keycard/reset-card-screen-did-load %)
|
||||
@@ -274,53 +259,3 @@
|
||||
cofx
|
||||
(navigation/open-modal :buy-crypto nil)
|
||||
(wallet/keep-watching-history)))
|
||||
|
||||
;; Information Box
|
||||
|
||||
(def closable-information-boxes
|
||||
"[{:id information box id
|
||||
:global? true/false (close information box across all profiles)}]"
|
||||
[])
|
||||
|
||||
(defn information-box-id-hash
|
||||
[id public-key global?]
|
||||
(if global?
|
||||
(hash id)
|
||||
(hash (str public-key id))))
|
||||
|
||||
(rf/defn close-information-box
|
||||
{:events [:close-information-box]}
|
||||
[{:keys [db]} id global?]
|
||||
(let [public-key (get-in db [:profile/profile :public-key])
|
||||
hash (information-box-id-hash id public-key global?)]
|
||||
{::async-storage/set! {hash true}
|
||||
:db (assoc-in db [:information-box-states id] true)}))
|
||||
|
||||
(rf/defn information-box-states-loaded
|
||||
{:events [:information-box-states-loaded]}
|
||||
[{:keys [db]} hashes states]
|
||||
{:db (assoc db
|
||||
:information-box-states
|
||||
(reduce
|
||||
(fn [acc [id hash]]
|
||||
(assoc acc id (get states hash)))
|
||||
{}
|
||||
hashes))})
|
||||
|
||||
(rf/defn load-information-box-states
|
||||
{:events [:load-information-box-states]}
|
||||
[{:keys [db]}]
|
||||
(let [public-key (get-in db [:profile/profile :public-key])
|
||||
{:keys [keys hashes]} (reduce (fn [acc {:keys [id global?]}]
|
||||
(let [hash (information-box-id-hash
|
||||
id
|
||||
public-key
|
||||
global?)]
|
||||
(-> acc
|
||||
(assoc-in [:hashes id] hash)
|
||||
(update :keys #(conj % hash)))))
|
||||
{}
|
||||
closable-information-boxes)]
|
||||
{::async-storage/get {:keys keys
|
||||
:cb #(re-frame/dispatch
|
||||
[:information-box-states-loaded hashes %])}}))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
(ns status-im.fleet.default-fleet (:require-macros [status-im.utils.slurp :refer [slurp]]))
|
||||
|
||||
(def default-fleets
|
||||
(slurp "resources/config/fleets.json"))
|
||||
(slurp "resources/config/fleets.json"))
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.contexts.shell.activity-center.events :as activity-center]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[utils.re-frame :as rf]))
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.data-store.invitations :as data-store.invitations]))
|
||||
|
||||
(rf/defn navigate-chat-updated
|
||||
{:events [:navigate-chat-updated]}
|
||||
@@ -258,3 +259,19 @@
|
||||
:on-accept #(do
|
||||
(re-frame/dispatch [:bottom-sheet/hide-old])
|
||||
(re-frame/dispatch [:group-chats.ui/leave-chat-confirmed chat-id]))}}))
|
||||
|
||||
(rf/defn initialize-invitations
|
||||
{:events [::initialize-invitations]}
|
||||
[{:keys [db]} invitations]
|
||||
{:db (assoc db
|
||||
:group-chat/invitations
|
||||
(reduce (fn [acc {:keys [id] :as inv}]
|
||||
(assoc acc id (data-store.invitations/<-rpc inv)))
|
||||
{}
|
||||
invitations))})
|
||||
|
||||
(rf/defn get-group-chat-invitations
|
||||
[_]
|
||||
{:json-rpc/call
|
||||
[{:method "wakuext_getGroupChatInvitations"
|
||||
:on-success #(re-frame/dispatch [::initialize-invitations %])}]})
|
||||
|
||||
+104
-131
@@ -26,13 +26,10 @@
|
||||
[]
|
||||
(rf/dispatch [:app-started]))
|
||||
|
||||
(defn generate-and-derive-addresses!
|
||||
[]
|
||||
(rf/dispatch [:generate-and-derive-addresses]))
|
||||
|
||||
(defn create-multiaccount!
|
||||
[]
|
||||
(rf/dispatch [:create-multiaccount password]))
|
||||
(rf/dispatch [:profile.create/create-and-login
|
||||
{:display-name account-name :password password :color "blue"}]))
|
||||
|
||||
(defn assert-app-initialized
|
||||
[]
|
||||
@@ -82,15 +79,12 @@
|
||||
(initialize-app!) ; initialize app
|
||||
(rf-test/wait-for
|
||||
[:profile/get-profiles-overview-success]
|
||||
(generate-and-derive-addresses!) ; generate 5 new keys
|
||||
(rf-test/wait-for
|
||||
[:multiaccount-generate-and-derive-addresses-success] ; wait for the keys
|
||||
(create-multiaccount!) ; create a multiaccount
|
||||
(rf-test/wait-for ; wait for login
|
||||
[::transport/messenger-started]
|
||||
(assert-messenger-started)
|
||||
(logout!)
|
||||
(rf-test/wait-for [::logout/logout-method]))))))
|
||||
(create-multiaccount!) ; create a multiaccount
|
||||
(rf-test/wait-for ; wait for login
|
||||
[::transport/messenger-started]
|
||||
(assert-messenger-started)
|
||||
(logout!)
|
||||
(rf-test/wait-for [::logout/logout-method])))))
|
||||
|
||||
(deftest create-community-test
|
||||
(log/info "====== create-community-test ==================")
|
||||
@@ -98,22 +92,19 @@
|
||||
(initialize-app!) ; initialize app
|
||||
(rf-test/wait-for
|
||||
[:profile/get-profiles-overview-success]
|
||||
(generate-and-derive-addresses!) ; generate 5 new keys
|
||||
(rf-test/wait-for
|
||||
[:multiaccount-generate-and-derive-addresses-success]
|
||||
(create-multiaccount!) ; create a multiaccount
|
||||
(rf-test/wait-for ; wait for login
|
||||
[::transport/messenger-started]
|
||||
(assert-messenger-started)
|
||||
(rf/dispatch-sync [:legacy-only-for-e2e/open-create-community])
|
||||
(doseq [[k v] (dissoc community :membership)]
|
||||
(rf/dispatch-sync [:status-im.communities.core/create-field k v]))
|
||||
(rf/dispatch [:status-im.communities.core/create-confirmation-pressed])
|
||||
(rf-test/wait-for
|
||||
[:status-im.communities.core/community-created]
|
||||
(assert-community-created)
|
||||
(logout!)
|
||||
(rf-test/wait-for [::logout/logout-method])))))))
|
||||
(create-multiaccount!) ; create a multiaccount
|
||||
(rf-test/wait-for ; wait for login
|
||||
[::transport/messenger-started]
|
||||
(assert-messenger-started)
|
||||
(rf/dispatch-sync [:legacy-only-for-e2e/open-create-community])
|
||||
(doseq [[k v] (dissoc community :membership)]
|
||||
(rf/dispatch-sync [:status-im.communities.core/create-field k v]))
|
||||
(rf/dispatch [:status-im.communities.core/create-confirmation-pressed])
|
||||
(rf-test/wait-for
|
||||
[:status-im.communities.core/community-created]
|
||||
(assert-community-created)
|
||||
(logout!)
|
||||
(rf-test/wait-for [::logout/logout-method]))))))
|
||||
|
||||
(deftest create-wallet-account-test
|
||||
(log/info "====== create-wallet-account-test ==================")
|
||||
@@ -121,19 +112,16 @@
|
||||
(initialize-app!)
|
||||
(rf-test/wait-for
|
||||
[:profile/get-profiles-overview-success]
|
||||
(generate-and-derive-addresses!) ; generate 5 new keys
|
||||
(rf-test/wait-for
|
||||
[:multiaccount-generate-and-derive-addresses-success]
|
||||
(create-multiaccount!) ; create a multiaccount
|
||||
(rf-test/wait-for ; wait for login
|
||||
[::transport/messenger-started]
|
||||
(assert-messenger-started)
|
||||
(create-new-account!) ; create a new account
|
||||
(rf-test/wait-for
|
||||
[:wallet.accounts/account-stored]
|
||||
(assert-new-account-created) ; assert account was created
|
||||
(logout!)
|
||||
(rf-test/wait-for [::logout/logout-method])))))))
|
||||
(create-multiaccount!) ; create a multiaccount
|
||||
(rf-test/wait-for ; wait for login
|
||||
[::transport/messenger-started]
|
||||
(assert-messenger-started)
|
||||
(create-new-account!) ; create a new account
|
||||
(rf-test/wait-for
|
||||
[:wallet.accounts/account-stored]
|
||||
(assert-new-account-created) ; assert account was created
|
||||
(logout!)
|
||||
(rf-test/wait-for [::logout/logout-method]))))))
|
||||
|
||||
(deftest back-up-seed-phrase-test
|
||||
(log/info "========= back-up-seed-phrase-test ==================")
|
||||
@@ -141,30 +129,27 @@
|
||||
(initialize-app!)
|
||||
(rf-test/wait-for
|
||||
[:profile/get-profiles-overview-success]
|
||||
(generate-and-derive-addresses!)
|
||||
(create-multiaccount!)
|
||||
(rf-test/wait-for
|
||||
[:multiaccount-generate-and-derive-addresses-success]
|
||||
(create-multiaccount!)
|
||||
(rf-test/wait-for
|
||||
[::transport/messenger-started]
|
||||
(assert-messenger-started)
|
||||
(rf/dispatch-sync [:set-in [:my-profile/seed :step] :12-words]) ; display seed phrase to user
|
||||
(rf/dispatch-sync [:my-profile/enter-two-random-words]) ; begin prompting user for seed words
|
||||
(let [{:keys [mnemonic]} @(rf/subscribe [:profile/profile])
|
||||
seed @(rf/subscribe [:my-profile/seed])
|
||||
word1 (second (:first-word seed))
|
||||
word2 (second (:second-word seed))]
|
||||
(is (= 12 (count (string/split mnemonic #" ")))) ; assert 12-word seed phrase
|
||||
(rf/dispatch-sync [:set-in [:my-profile/seed :word] word1])
|
||||
(rf/dispatch-sync [:my-profile/set-step :second-word])
|
||||
(rf/dispatch-sync [:set-in [:my-profile/seed :word] word2])
|
||||
;; TODO: refactor (defn next-handler) & (defn enter-word) to improve test coverage?
|
||||
(rf/dispatch [:my-profile/finish])
|
||||
(rf-test/wait-for
|
||||
[:my-profile/finish-success]
|
||||
(is (nil? @(rf/subscribe [:mnemonic]))) ; assert seed phrase has been removed
|
||||
(logout!)
|
||||
(rf-test/wait-for [::logout/logout-method]))))))))
|
||||
[::transport/messenger-started]
|
||||
(assert-messenger-started)
|
||||
(rf/dispatch-sync [:set-in [:my-profile/seed :step] :12-words]) ; display seed phrase to user
|
||||
(rf/dispatch-sync [:my-profile/enter-two-random-words]) ; begin prompting user for seed words
|
||||
(let [{:keys [mnemonic]} @(rf/subscribe [:profile/profile])
|
||||
seed @(rf/subscribe [:my-profile/seed])
|
||||
word1 (second (:first-word seed))
|
||||
word2 (second (:second-word seed))]
|
||||
(is (= 12 (count (string/split mnemonic #" ")))) ; assert 12-word seed phrase
|
||||
(rf/dispatch-sync [:set-in [:my-profile/seed :word] word1])
|
||||
(rf/dispatch-sync [:my-profile/set-step :second-word])
|
||||
(rf/dispatch-sync [:set-in [:my-profile/seed :word] word2])
|
||||
;; TODO: refactor (defn next-handler) & (defn enter-word) to improve test coverage?
|
||||
(rf/dispatch [:my-profile/finish])
|
||||
(rf-test/wait-for
|
||||
[:my-profile/finish-success]
|
||||
(is (nil? @(rf/subscribe [:mnemonic]))) ; assert seed phrase has been removed
|
||||
(logout!)
|
||||
(rf-test/wait-for [::logout/logout-method])))))))
|
||||
|
||||
(def multiaccount-name "Narrow Frail Lemming")
|
||||
(def multiaccount-mnemonic
|
||||
@@ -180,20 +165,17 @@
|
||||
(initialize-app!)
|
||||
(rf-test/wait-for
|
||||
[:profile/get-profiles-overview-success]
|
||||
(generate-and-derive-addresses!)
|
||||
(create-multiaccount!)
|
||||
(rf-test/wait-for
|
||||
[:multiaccount-generate-and-derive-addresses-success] ; wait for the keys
|
||||
(create-multiaccount!)
|
||||
[::transport/messenger-started]
|
||||
(assert-messenger-started)
|
||||
(rf/dispatch-sync [:chat.ui/start-chat chat-id]) ;; start a new chat
|
||||
(rf-test/wait-for
|
||||
[::transport/messenger-started]
|
||||
(assert-messenger-started)
|
||||
(rf/dispatch-sync [:chat.ui/start-chat chat-id]) ;; start a new chat
|
||||
(rf-test/wait-for
|
||||
[:chat/one-to-one-chat-created]
|
||||
(rf/dispatch-sync [:chat/navigate-to-chat chat-id])
|
||||
(is (= chat-id @(rf/subscribe [:chats/current-chat-id])))
|
||||
(logout!)
|
||||
(rf-test/wait-for [::logout/logout-method])))))))
|
||||
[:chat/one-to-one-chat-created]
|
||||
(rf/dispatch-sync [:chat/navigate-to-chat chat-id])
|
||||
(is (= chat-id @(rf/subscribe [:chats/current-chat-id])))
|
||||
(logout!)
|
||||
(rf-test/wait-for [::logout/logout-method]))))))
|
||||
|
||||
(deftest delete-chat-test
|
||||
(log/info "========= delete-chat-test ==================")
|
||||
@@ -201,23 +183,20 @@
|
||||
(initialize-app!)
|
||||
(rf-test/wait-for
|
||||
[:profile/get-profiles-overview-success]
|
||||
(generate-and-derive-addresses!)
|
||||
(create-multiaccount!)
|
||||
(rf-test/wait-for
|
||||
[:multiaccount-generate-and-derive-addresses-success] ; wait for the keys
|
||||
(create-multiaccount!)
|
||||
[::transport/messenger-started]
|
||||
(assert-messenger-started)
|
||||
(rf/dispatch-sync [:chat.ui/start-chat chat-id]) ;; start a new chat
|
||||
(rf-test/wait-for
|
||||
[::transport/messenger-started]
|
||||
(assert-messenger-started)
|
||||
(rf/dispatch-sync [:chat.ui/start-chat chat-id]) ;; start a new chat
|
||||
(rf-test/wait-for
|
||||
[:chat/one-to-one-chat-created]
|
||||
(rf/dispatch-sync [:chat/navigate-to-chat chat-id])
|
||||
(is (= chat-id @(rf/subscribe [:chats/current-chat-id])))
|
||||
(is @(rf/subscribe [:chats/chat chat-id]))
|
||||
(rf/dispatch-sync [:chat.ui/show-remove-confirmation chat-id])
|
||||
(rf/dispatch-sync [:chat.ui/remove-chat chat-id])
|
||||
(logout!)
|
||||
(rf-test/wait-for [::logout/logout-method])))))))
|
||||
[:chat/one-to-one-chat-created]
|
||||
(rf/dispatch-sync [:chat/navigate-to-chat chat-id])
|
||||
(is (= chat-id @(rf/subscribe [:chats/current-chat-id])))
|
||||
(is @(rf/subscribe [:chats/chat chat-id]))
|
||||
(rf/dispatch-sync [:chat.ui/show-remove-confirmation chat-id])
|
||||
(rf/dispatch-sync [:chat.ui/remove-chat chat-id])
|
||||
(logout!)
|
||||
(rf-test/wait-for [::logout/logout-method]))))))
|
||||
|
||||
(deftest mute-chat-test
|
||||
(log/info "========= mute-chat-test ==================")
|
||||
@@ -225,29 +204,26 @@
|
||||
(initialize-app!)
|
||||
(rf-test/wait-for
|
||||
[:profile/get-profiles-overview-success]
|
||||
(generate-and-derive-addresses!)
|
||||
(create-multiaccount!)
|
||||
(rf-test/wait-for
|
||||
[:multiaccount-generate-and-derive-addresses-success] ; wait for the keys
|
||||
(create-multiaccount!)
|
||||
[::transport/messenger-started]
|
||||
(assert-messenger-started)
|
||||
(rf/dispatch-sync [:chat.ui/start-chat chat-id]) ;; start a new chat
|
||||
(rf-test/wait-for
|
||||
[::transport/messenger-started]
|
||||
(assert-messenger-started)
|
||||
(rf/dispatch-sync [:chat.ui/start-chat chat-id]) ;; start a new chat
|
||||
[:chat/one-to-one-chat-created]
|
||||
(rf/dispatch-sync [:chat/navigate-to-chat chat-id])
|
||||
(is (= chat-id @(rf/subscribe [:chats/current-chat-id])))
|
||||
(is @(rf/subscribe [:chats/chat chat-id]))
|
||||
(rf/dispatch-sync [:chat.ui/mute chat-id true constants/mute-till-unmuted])
|
||||
(rf-test/wait-for
|
||||
[:chat/one-to-one-chat-created]
|
||||
(rf/dispatch-sync [:chat/navigate-to-chat chat-id])
|
||||
(is (= chat-id @(rf/subscribe [:chats/current-chat-id])))
|
||||
(is @(rf/subscribe [:chats/chat chat-id]))
|
||||
(rf/dispatch-sync [:chat.ui/mute chat-id true constants/mute-till-unmuted])
|
||||
[:chat/mute-successfully]
|
||||
(is @(rf/subscribe [:chats/muted chat-id]))
|
||||
(rf/dispatch-sync [:chat.ui/mute chat-id false])
|
||||
(rf-test/wait-for
|
||||
[:chat/mute-successfully]
|
||||
(is @(rf/subscribe [:chats/muted chat-id]))
|
||||
(rf/dispatch-sync [:chat.ui/mute chat-id false])
|
||||
(rf-test/wait-for
|
||||
[:chat/mute-successfully]
|
||||
(is (not @(rf/subscribe [:chats/muted chat-id])))
|
||||
(logout!)
|
||||
(rf-test/wait-for [::logout/logout-method])))))))))
|
||||
(is (not @(rf/subscribe [:chats/muted chat-id])))
|
||||
(logout!)
|
||||
(rf-test/wait-for [::logout/logout-method]))))))))
|
||||
|
||||
(deftest add-contact-test
|
||||
(log/info "========= add-contact-test ==================")
|
||||
@@ -260,27 +236,24 @@
|
||||
(initialize-app!)
|
||||
(rf-test/wait-for
|
||||
[:profile/get-profiles-overview-success]
|
||||
(generate-and-derive-addresses!)
|
||||
(create-multiaccount!)
|
||||
(rf-test/wait-for
|
||||
[:multiaccount-generate-and-derive-addresses-success]
|
||||
(create-multiaccount!)
|
||||
[::transport/messenger-started]
|
||||
(assert-messenger-started)
|
||||
;; search for contact using compressed key
|
||||
(rf/dispatch [:contacts/set-new-identity compressed-key])
|
||||
(rf-test/wait-for
|
||||
[::transport/messenger-started]
|
||||
(assert-messenger-started)
|
||||
;; search for contact using compressed key
|
||||
(rf/dispatch [:contacts/set-new-identity compressed-key])
|
||||
[:contacts/set-new-identity-success]
|
||||
(let [new-identity @(rf/subscribe [:contacts/new-identity])]
|
||||
(is (= public-key (:public-key new-identity)))
|
||||
(is (= :valid (:state new-identity))))
|
||||
;; click 'view profile' button
|
||||
(rf/dispatch [:chat.ui/show-profile public-key])
|
||||
(rf-test/wait-for
|
||||
[:contacts/set-new-identity-success]
|
||||
(let [new-identity @(rf/subscribe [:contacts/new-identity])]
|
||||
(is (= public-key (:public-key new-identity)))
|
||||
(is (= :valid (:state new-identity))))
|
||||
;; click 'view profile' button
|
||||
(rf/dispatch [:chat.ui/show-profile public-key])
|
||||
[:contacts/build-contact]
|
||||
(rf-test/wait-for
|
||||
[:contacts/build-contact]
|
||||
(rf-test/wait-for
|
||||
[:contacts/contact-built]
|
||||
(let [contact @(rf/subscribe [:contacts/current-contact])]
|
||||
(is (= three-words-name (:primary-name contact))))
|
||||
(logout!)
|
||||
(rf-test/wait-for [::logout/logout-method]))))))))))
|
||||
[:contacts/contact-built]
|
||||
(let [contact @(rf/subscribe [:contacts/current-contact])]
|
||||
(is (= three-words-name (:primary-name contact))))
|
||||
(logout!)
|
||||
(rf-test/wait-for [::logout/logout-method])))))))))
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
[status-im.keycard.sign :as sign]
|
||||
status-im.keycard.unpair
|
||||
[status-im.keycard.wallet :as wallet]
|
||||
[status-im.multiaccounts.recover.core :as multiaccounts.recover]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.datetime :as datetime]
|
||||
@@ -589,7 +588,8 @@
|
||||
(when (and (= card-state :profile/profile)
|
||||
(= flow :import))
|
||||
(if (common/find-multiaccount-by-key-uid db key-uid)
|
||||
(multiaccounts.recover/show-existing-multiaccount-alert key-uid)
|
||||
;; reimplement
|
||||
;;(multiaccounts.recover/show-existing-multiaccount-alert key-uid)
|
||||
(if paired?
|
||||
(load-recovery-pin-screen)
|
||||
(recovery/load-pair-screen))))
|
||||
@@ -681,3 +681,11 @@
|
||||
{:events [:keycard.callback/stop-nfc-failure]}
|
||||
[{:keys [db]} _]
|
||||
(log/debug "[keycard] nfc failed stopping")) ;; leave current value on :nfc-running
|
||||
|
||||
(rf/defn init
|
||||
{:events [:keycard/init]}
|
||||
[_]
|
||||
{:keycard/register-card-events nil
|
||||
:keycard/check-nfc-support nil
|
||||
:keycard/check-nfc-enabled nil
|
||||
:keycard/retrieve-pairings nil})
|
||||
|
||||
@@ -139,7 +139,6 @@
|
||||
{:db (-> db
|
||||
(update :keycard dissoc :flow)
|
||||
(dissoc :restored-account?))}
|
||||
(multiaccounts.create/prepare-intro-wizard)
|
||||
(if (pos? (count accs))
|
||||
(navigation/navigate-to :get-your-keys nil)
|
||||
(navigation/set-stack-root :onboarding [:get-your-keys])))))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user