Compare commits
50
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8a84e91d4 | ||
|
|
9a0cb79a2e | ||
|
|
cc665a8683 | ||
|
|
30bf4a2d92 | ||
|
|
c04cb79085 | ||
|
|
fd747614f9 | ||
|
|
faaecfaa95 | ||
|
|
f201ebc09f | ||
|
|
9c0361adef | ||
|
|
9d8e6aa224 | ||
|
|
599d293f9a | ||
|
|
915b8ebd9a | ||
|
|
6280a6c4d5 | ||
|
|
b45261f2e5 | ||
|
|
4ce71e4d29 | ||
|
|
9ded8bfe97 | ||
|
|
aca8c9250f | ||
|
|
99f7788c22 | ||
|
|
9c7b69a2cd | ||
|
|
a39e0f6fbd | ||
|
|
a8d392e4de | ||
|
|
d9e8fea14b | ||
|
|
8ff32f4fc3 | ||
|
|
e21b8d4396 | ||
|
|
1af6d925d2 | ||
|
|
9937914594 | ||
|
|
e9252f5025 | ||
|
|
2610f27190 | ||
|
|
3dda878742 | ||
|
|
1fb41b2ca0 | ||
|
|
7c2d76d00f | ||
|
|
270acefcf1 | ||
|
|
45e05b3f2b | ||
|
|
9f1af8a9c2 | ||
|
|
69c90c25ab | ||
|
|
388e5fae22 | ||
|
|
0a8993bbf1 | ||
|
|
39e29cfb5a | ||
|
|
37909c2d81 | ||
|
|
01660765b7 | ||
|
|
c0c0742687 | ||
|
|
b074e9c58e | ||
|
|
8cf95cdb30 | ||
|
|
ba41d4b271 | ||
|
|
003b0ffb1e | ||
|
|
dbd61a34a0 | ||
|
|
cbb6571954 | ||
|
|
7b72391e60 | ||
|
|
269d13e2f8 | ||
|
|
fc07fbf787 |
+21
-20
@@ -1,20 +1,21 @@
|
||||
{:lint-as {status-im.utils.views/defview clojure.core/defn
|
||||
status-im.utils.views/letsubs clojure.core/let
|
||||
reagent.core/with-let clojure.core/let
|
||||
status-im.utils.fx/defn clj-kondo.lint-as/def-catch-all
|
||||
utils.re-frame/defn clj-kondo.lint-as/def-catch-all
|
||||
quo.react/with-deps-check clojure.core/fn
|
||||
quo.previews.preview/list-comp clojure.core/for
|
||||
status-im.utils.styles/def clojure.core/def
|
||||
status-im.utils.styles/defn clojure.core/defn
|
||||
status-im.test-helpers/deftest-sub clojure.core/defn
|
||||
taoensso.tufte/defnp clojure.core/defn}
|
||||
:linters {:consistent-alias {:level :error
|
||||
:aliases {clojure.string string
|
||||
taoensso.timbre log}}
|
||||
: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
|
||||
:unresolved-symbol {:exclude [PersistentPriorityMap.EMPTY
|
||||
number
|
||||
status-im.test-helpers/restore-app-db]}}}
|
||||
{:lint-as {status-im.utils.views/defview clojure.core/defn
|
||||
status-im.utils.views/letsubs clojure.core/let
|
||||
reagent.core/with-let clojure.core/let
|
||||
status-im.utils.fx/defn clj-kondo.lint-as/def-catch-all
|
||||
utils.re-frame/defn clj-kondo.lint-as/def-catch-all
|
||||
quo.react/with-deps-check clojure.core/fn
|
||||
quo.previews.preview/list-comp clojure.core/for
|
||||
status-im.utils.styles/def clojure.core/def
|
||||
status-im.utils.styles/defn clojure.core/defn
|
||||
status-im.test-helpers/deftest-sub clojure.core/defn
|
||||
taoensso.tufte/defnp clojure.core/defn}
|
||||
:linters {:consistent-alias {:level :error
|
||||
:aliases {clojure.string string
|
||||
taoensso.timbre log}}
|
||||
: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
|
||||
:unresolved-symbol {:exclude [PersistentPriorityMap.EMPTY
|
||||
number
|
||||
status-im.test-helpers/restore-app-db]}}
|
||||
:config-in-ns {mocks.js-dependencies {:linters {:clojure-lsp/unused-public-var {:level :off}}}}}
|
||||
|
||||
@@ -32,3 +32,4 @@ COMMANDS_ENABLED=1
|
||||
TWO_MINUTES_SYNCING=1
|
||||
SWAP_ENABLED=1
|
||||
STICKERS_TEST_ENABLED=1
|
||||
LOCAL_PAIRING_ENABLED=1
|
||||
|
||||
@@ -32,3 +32,4 @@ COMMUNITIES_MANAGEMENT_ENABLED=1
|
||||
DELETE_MESSAGE_ENABLED=1
|
||||
TWO_MINUTES_SYNCING=1
|
||||
STICKERS_TEST_ENABLED=1
|
||||
LOCAL_PAIRING_ENABLED=1
|
||||
|
||||
@@ -34,3 +34,4 @@ DELETE_MESSAGE_ENABLED=1
|
||||
TWO_MINUTES_SYNCING=1
|
||||
ENABLE_QUO_PREVIEW=1
|
||||
STICKERS_TEST_ENABLED=1
|
||||
LOCAL_PAIRING_ENABLED=1
|
||||
|
||||
@@ -19,15 +19,17 @@
|
||||
:respect-bl]
|
||||
:fn-map
|
||||
{"reg-sub" :arg1-pair
|
||||
"h/describe" :arg1-body
|
||||
"h/test" :arg1-body
|
||||
"global.describe" :arg1-body
|
||||
"global.test" :arg1-body
|
||||
"list-comp" :binding
|
||||
"defview" :arg1-body
|
||||
"letsubs" :binding
|
||||
"testing" :arg1-body
|
||||
"deftest-sub" :arg1-body
|
||||
"wait-for" :arg1-body
|
||||
"with-deps-check" :arg1-body
|
||||
"ns" [:arg1-body
|
||||
{:list {:respect-nl? false}
|
||||
:vector {:respect-nl? false}}]
|
||||
"->" [:noarg1-body
|
||||
{:list {:constant-pair? false :force-nl? false}
|
||||
:next-inner-restore [[:list :constant-pair?]]}]
|
||||
@@ -39,7 +41,6 @@
|
||||
:remove {:fn-force-nl #{:noarg1-body}}
|
||||
:style-map
|
||||
{:no-comma {:map {:comma? false}}
|
||||
:rj-var {:pair {:justify {:max-variance 1000}}}
|
||||
:custom-justify
|
||||
{:doc "Justify everything using pre-1.1.2 approach"
|
||||
:binding {:justify? true :justify {:max-variance 1000}}
|
||||
|
||||
@@ -289,15 +289,14 @@ lint: export TARGET := default
|
||||
lint: ##@test Run code style checks
|
||||
sh scripts/lint-re-frame-in-quo-components.sh && \
|
||||
clj-kondo --config .clj-kondo/config.edn --cache false --lint src && \
|
||||
TARGETS=$$(git diff --diff-filter=d --cached --name-only | grep -e \.clj$$ -e \.cljs$$ -e \.cljc$$ -e \.edn$$ || echo shadow-cljs.edn) && \
|
||||
zprint '{:search-config? true}' -fc $$TARGETS
|
||||
ALL_CLOJURE_FILE=$$(git ls-files | grep -e \.clj$$ -e \.cljs$$ -e \.cljc$$ -e \.edn$$) && \
|
||||
zprint '{:search-config? true}' -sfc $$ALL_CLOJURE_FILE
|
||||
|
||||
lint-fix: export TARGET := default
|
||||
lint-fix: ##@test Run code style checks and fix issues
|
||||
TARGETS=$$(git diff --diff-filter=d --cached --name-only | grep -e \.clj$$ -e \.cljs$$ -e \.cljc$$ -e \.edn$$ || echo shadow-cljs.edn) && \
|
||||
clojure-lsp clean-ns --filenames $$(echo $$TARGETS | xargs | sed -e 's/ /,/g') && \
|
||||
zprint '{:search-config? true}' -fw $$TARGETS && \
|
||||
zprint '{:search-config? true}' -fw $$TARGETS
|
||||
ALL_CLOJURE_FILE=$$(git ls-files | grep -e \.clj$$ -e \.cljs$$ -e \.cljc$$ -e \.edn$$) && \
|
||||
zprint '{:search-config? true}' -sw $$ALL_CLOJURE_FILE && \
|
||||
zprint '{:search-config? true}' -sw $$ALL_CLOJURE_FILE
|
||||
|
||||
|
||||
shadow-server: export TARGET := clojure
|
||||
@@ -309,6 +308,14 @@ test-watch: ##@ Watch tests and re-run no changes to cljs files
|
||||
yarn install
|
||||
nodemon --exec 'yarn shadow-cljs compile mocks && yarn shadow-cljs compile test && node --require ./test-resources/override.js target/test/test.js' -e cljs
|
||||
|
||||
test-watch-for-repl: export TARGET := clojure
|
||||
test-watch-for-repl: ##@ Watch tests and support REPL connections
|
||||
yarn install
|
||||
rm -f target/test/test.js
|
||||
concurrently --kill-others --prefix-colors 'auto' --names 'build,repl' \
|
||||
'yarn shadow-cljs compile mocks && yarn shadow-cljs watch test --verbose' \
|
||||
'until [ -f ./target/test/test.js ] ; do sleep 1 ; done ; node --require ./test-resources/override.js ./target/test/test.js --repl'
|
||||
|
||||
test: export TARGET := clojure
|
||||
test: ##@test Run tests once in NodeJS
|
||||
# Here we create the gyp bindings for nodejs
|
||||
@@ -323,7 +330,7 @@ run-visual-test-ios: XCODE_DERIVED_DATA := $(HOME)/Library/Developer/Xcode/Deriv
|
||||
run-visual-test-ios: APPLICATION_NAME := StatusIm-brfnruzfrkkycpbndmdoeyrigthc
|
||||
run-visual-test-ios: export TEST_BINARY_PATH := $(XCODE_DERIVED_DATA)/$(APPLICATION_NAME)/Build/Products/Debug-iphonesimulator/StatusIm.app
|
||||
run-visual-test-ios: ##@test Run tests once in NodeJS
|
||||
detox test --configuration ios.sim.debug
|
||||
detox test --configuration ios.sim.debug
|
||||
|
||||
component-test-watch: export TARGET := clojure
|
||||
component-test-watch: export COMPONENT_TEST := true
|
||||
|
||||
@@ -20,6 +20,8 @@ printed out by mistake in a log entry (see https://github.com/status-im/status-m
|
||||
To minimize the risk of leaking passwords through logs, we should not pass
|
||||
passwords as strings in our codebase. We introduced a new type `MaskedData` in
|
||||
`status-im.utils.security`.
|
||||
update (16-Dec-2022) `status-im.utils.security` is now moved over to `utils.security.core`
|
||||
|
||||
We use `(security/mask-data <data to hide>` to wrap sensitive data into this
|
||||
type and then use `(security/unmask <masked-data>)` to get the plaintext back.
|
||||
|
||||
|
||||
+27
-11
@@ -399,13 +399,15 @@ src
|
||||
├── react_native
|
||||
│ ├── gesture.cljs
|
||||
│ └── platform.cljs
|
||||
├── status_im
|
||||
├── status_im/
|
||||
├── status_im2
|
||||
│ ├── common
|
||||
│ │ └── components
|
||||
│ │ └── bottom_sheet.cljs
|
||||
│ ├── contexts/
|
||||
│ ├── setup/
|
||||
│ └── subs/
|
||||
├── test_helpers/
|
||||
└── utils.cljs
|
||||
```
|
||||
|
||||
@@ -414,17 +416,23 @@ src
|
||||
- `src/quo2/`: The component library for Status Mobile.
|
||||
- `src/react_native/`: Contains only low-level constructs to help React Native
|
||||
work in tandem with Clojure(Script).
|
||||
- `src/status_im/common/`: Directories named `common` can appear at any level of
|
||||
the directory tree. Just like directories named `utils`, their directory
|
||||
- `src/status_im2/`: Directory where we try to be as strict as possible about
|
||||
our guidelines and where we prefer to write code for the new, redesigned
|
||||
mobile app.
|
||||
- `src/status_im/`: Directory containing what we call "old code", not yet
|
||||
migrated to new guidelines for the new mobile app.
|
||||
- `src/status_im2/common/`: Directories named `common` can appear at any level
|
||||
of the directory tree. Just like directories named `utils`, their directory
|
||||
nesting level communicates their applicable limits.
|
||||
- `src/status_im/common/components/`: Contains reusable components that are not
|
||||
- `src/status_im2/common/components/`: Contains reusable components that are not
|
||||
part of the design system (quo2).
|
||||
- `src/status_im/contexts/`: Contains [bounded contexts](#glossary), like
|
||||
- `src/status_im2/contexts/`: Contains [bounded contexts](#glossary), like
|
||||
`browser/`, `messaging/`, etc. As much as possible, _bounded contexts_ should
|
||||
not directly require each other's namespaces.
|
||||
- `src/status_im/setup/`: Contains namespaces that are mostly used to initialize
|
||||
the application, configure test runners, etc. In general, such namespaces
|
||||
should not be required from the outside.
|
||||
- `src/status_im2/setup/`: Contains namespaces that are mostly used to
|
||||
initialize the application, configure test runners, etc. In general, such
|
||||
namespaces should not be required from the outside.
|
||||
- `src/test_helpers/`: Reusable utilities for writing all kinds of tests.
|
||||
- `src/status_im/subs/`: All subscriptions should live inside it.
|
||||
|
||||
Directories named `utils/` can appear at any level of the directory tree. The
|
||||
@@ -485,18 +493,26 @@ src
|
||||
[Unit tests](#glossary) should be created alongside their respective source
|
||||
implementation. We prefer them colocated with the source and not like most
|
||||
Clojure (JVM) codebases which mirror the sources in a top-level test directory.
|
||||
Component tests should be created in a separate directory `__tests__`. Example:
|
||||
|
||||
```
|
||||
├── models
|
||||
│ ├── message.cljs
|
||||
│ └── message_test.cljs
|
||||
├── __tests__
|
||||
│ └── input_bla_test.cljs
|
||||
├── models.cljs
|
||||
└── models_test.cljs
|
||||
```
|
||||
|
||||
Component tests should be created in a separate directory `__tests__`, colocated
|
||||
with the source. When the entire component implementation is isolated under a
|
||||
single directory, create a test file named `component_spec.cljs` instead.
|
||||
|
||||
```
|
||||
└── filter
|
||||
├── component_spec.cljs
|
||||
├── style.cljs
|
||||
└── view.cljs
|
||||
```
|
||||
|
||||
There's no hard rule on how integration test namespaces should be split, but
|
||||
we're at least striving to define them under appropriate bounded contexts that
|
||||
mirror the source code.
|
||||
|
||||
+46
@@ -940,6 +940,52 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void getConnectionStringForBootstrappingAnotherDevice(final String configJSON, final Callback callback) throws JSONException {
|
||||
final JSONObject jsonConfig = new JSONObject(configJSON);
|
||||
final String keyUID = jsonConfig.getString("keyUID");
|
||||
final String keyStorePath = this.getKeyStorePath(keyUID);
|
||||
jsonConfig.put("keystorePath", keyStorePath);
|
||||
|
||||
if (!checkAvailability()) {
|
||||
callback.invoke(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Runnable runnableTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String res = Statusgo.getConnectionStringForBootstrappingAnotherDevice(jsonConfig.toString());
|
||||
callback.invoke(res);
|
||||
}
|
||||
};
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(runnableTask);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void inputConnectionStringForBootstrapping(final String connectionString, final String configJSON, final Callback callback) throws JSONException {
|
||||
final JSONObject jsonConfig = new JSONObject(configJSON);
|
||||
final String keyStorePath = pathCombine(this.getNoBackupDirectory(), "/keystore");
|
||||
jsonConfig.put("keystorePath", keyStorePath);
|
||||
|
||||
if (!checkAvailability()) {
|
||||
callback.invoke(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Runnable runnableTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String res = Statusgo.inputConnectionStringForBootstrapping(connectionString,jsonConfig.toString());
|
||||
callback.invoke(res);
|
||||
}
|
||||
};
|
||||
|
||||
StatusThreadPoolExecutor.getInstance().execute(runnableTask);
|
||||
}
|
||||
|
||||
|
||||
@ReactMethod
|
||||
public void hashTypedData(final String data, final Callback callback) {
|
||||
Log.d(TAG, "hashTypedData");
|
||||
|
||||
@@ -90,26 +90,25 @@ static RCTBridge *bridge;
|
||||
|
||||
RCT_EXPORT_MODULE();
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#pragma mark - shouldMoveToInternalStorage
|
||||
//////////////////////////////////////////////////////////////////// shouldMoveToInternalStorage
|
||||
|
||||
RCT_EXPORT_METHOD(shouldMoveToInternalStorage:(RCTResponseSenderBlock)onResultCallback) {
|
||||
// Android only
|
||||
onResultCallback(@[[NSNull null]]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma mark - moveToInternalStorage
|
||||
//////////////////////////////////////////////////////////////////// moveToInternalStorage
|
||||
|
||||
RCT_EXPORT_METHOD(moveToInternalStorage:(RCTResponseSenderBlock)onResultCallback) {
|
||||
// Android only
|
||||
onResultCallback(@[[NSNull null]]);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma mark - InitKeystore method
|
||||
//////////////////////////////////////////////////////////////////// StopNode
|
||||
|
||||
RCT_EXPORT_METHOD(initKeystore:(NSString *)keyUID
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
@@ -132,9 +131,9 @@ RCT_EXPORT_METHOD(initKeystore:(NSString *)keyUID
|
||||
});
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma mark - SendLogs method
|
||||
//////////////////////////////////////////////////////////////////// sendLogs
|
||||
|
||||
RCT_EXPORT_METHOD(sendLogs:(NSString *)dbJson
|
||||
jsLogs:(NSString *)jsLogs
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
@@ -196,7 +195,6 @@ RCT_EXPORT_METHOD(sendLogs:(NSString *)dbJson
|
||||
callback(@[zipFile.absoluteString]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// addPeer
|
||||
RCT_EXPORT_METHOD(exportLogs:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
NSLog(@"exportLogs() method called");
|
||||
@@ -205,7 +203,6 @@ RCT_EXPORT_METHOD(exportLogs:(RCTResponseSenderBlock)callback) {
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// addPeer
|
||||
RCT_EXPORT_METHOD(addPeer:(NSString *)enode
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
NSString *result = StatusgoAddPeer(enode);
|
||||
@@ -215,7 +212,6 @@ RCT_EXPORT_METHOD(addPeer:(NSString *)enode
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// multiAccountImportPrivateKey
|
||||
RCT_EXPORT_METHOD(deleteMultiaccount:(NSString *)keyUID
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
@@ -226,7 +222,6 @@ RCT_EXPORT_METHOD(deleteMultiaccount:(NSString *)keyUID
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
////////////////////////////////////verify//////////////////////////////// multiAccountImportPrivateKey
|
||||
RCT_EXPORT_METHOD(deleteImportedKey:(NSString *)keyUID
|
||||
address:(NSString *)address
|
||||
password:(NSString *)password
|
||||
@@ -239,7 +234,6 @@ RCT_EXPORT_METHOD(deleteImportedKey:(NSString *)keyUID
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// multiAccountGenerateAndDeriveAddresses
|
||||
RCT_EXPORT_METHOD(multiAccountGenerateAndDeriveAddresses:(NSString *)json
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
@@ -249,7 +243,6 @@ RCT_EXPORT_METHOD(multiAccountGenerateAndDeriveAddresses:(NSString *)json
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// MultiAccountStoreAccount
|
||||
RCT_EXPORT_METHOD(multiAccountStoreAccount:(NSString *)json
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
@@ -259,7 +252,6 @@ RCT_EXPORT_METHOD(multiAccountStoreAccount:(NSString *)json
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// MultiAccountLoadAccount
|
||||
RCT_EXPORT_METHOD(multiAccountLoadAccount:(NSString *)json
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
@@ -269,7 +261,6 @@ RCT_EXPORT_METHOD(multiAccountLoadAccount:(NSString *)json
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// MultiAccountReset
|
||||
RCT_EXPORT_METHOD(multiAccountReset:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
NSLog(@"MultiAccountReset() method called");
|
||||
@@ -278,7 +269,6 @@ RCT_EXPORT_METHOD(multiAccountReset:(RCTResponseSenderBlock)callback) {
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// multiAccountStoreDerived
|
||||
RCT_EXPORT_METHOD(multiAccountStoreDerived:(NSString *)json
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
@@ -288,7 +278,6 @@ RCT_EXPORT_METHOD(multiAccountStoreDerived:(NSString *)json
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// multiAccountImportPrivateKey
|
||||
RCT_EXPORT_METHOD(multiAccountImportPrivateKey:(NSString *)json
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
@@ -298,7 +287,6 @@ RCT_EXPORT_METHOD(multiAccountImportPrivateKey:(NSString *)json
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// hashTransaction
|
||||
RCT_EXPORT_METHOD(hashTransaction:(NSString *)txArgsJSON
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
@@ -308,7 +296,6 @@ RCT_EXPORT_METHOD(hashTransaction:(NSString *)txArgsJSON
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// hashMessage
|
||||
RCT_EXPORT_METHOD(hashMessage:(NSString *)message
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
@@ -318,7 +305,40 @@ RCT_EXPORT_METHOD(hashMessage:(NSString *)message
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// hashTypedData
|
||||
RCT_EXPORT_METHOD(getConnectionStringForBootstrappingAnotherDevice:(NSString *)configJSON
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
|
||||
NSData *configData = [configJSON dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSDictionary *configDict = [NSJSONSerialization JSONObjectWithData:configData options:NSJSONReadingMutableContainers error:nil];
|
||||
NSString *keyUID = [configDict objectForKey:@"keyUID"];
|
||||
NSURL *multiaccountKeystoreDir = [self getKeyStoreDir:keyUID];
|
||||
NSString *keystoreDir = multiaccountKeystoreDir.path;
|
||||
|
||||
[configDict setValue:keystoreDir forKey:@"keystorePath"];
|
||||
NSString *modifiedConfigJSON = [configDict bv_jsonStringWithPrettyPrint:NO];
|
||||
|
||||
NSString *result = StatusgoGetConnectionStringForBootstrappingAnotherDevice(modifiedConfigJSON);
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(inputConnectionStringForBootstrapping:(NSString *)cs
|
||||
configJSON:(NSString *)configJSON
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
|
||||
NSData *configData = [configJSON dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSDictionary *configDict = [NSJSONSerialization JSONObjectWithData:configData options:NSJSONReadingMutableContainers error:nil];
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSURL *rootUrl =[[fileManager URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject];
|
||||
NSURL *multiaccountKeystoreDir = [rootUrl URLByAppendingPathComponent:@"keystore"];
|
||||
NSString *keystoreDir = multiaccountKeystoreDir.path;
|
||||
|
||||
[configDict setValue:keystoreDir forKey:@"keystorePath"];
|
||||
NSString *modifiedConfigJSON = [configDict bv_jsonStringWithPrettyPrint:NO];
|
||||
|
||||
NSString *result = StatusgoInputConnectionStringForBootstrapping(cs,modifiedConfigJSON);
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(hashTypedData:(NSString *)data
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
@@ -328,7 +348,6 @@ RCT_EXPORT_METHOD(hashTypedData:(NSString *)data
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// hashTypedDataV4
|
||||
RCT_EXPORT_METHOD(hashTypedDataV4:(NSString *)data
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
@@ -338,7 +357,6 @@ RCT_EXPORT_METHOD(hashTypedDataV4:(NSString *)data
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// sendTransactionWithSignature
|
||||
RCT_EXPORT_METHOD(sendTransactionWithSignature:(NSString *)txArgsJSON
|
||||
signature:(NSString *)signature
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
@@ -349,7 +367,6 @@ RCT_EXPORT_METHOD(sendTransactionWithSignature:(NSString *)txArgsJSON
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// multiAccountImportMnemonic
|
||||
RCT_EXPORT_METHOD(multiAccountImportMnemonic:(NSString *)json
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
@@ -359,7 +376,6 @@ RCT_EXPORT_METHOD(multiAccountImportMnemonic:(NSString *)json
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// multiAccountDeriveAddresses
|
||||
RCT_EXPORT_METHOD(multiAccountDeriveAddresses:(NSString *)json
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
@@ -379,7 +395,6 @@ RCT_EXPORT_METHOD(multiAccountDeriveAddresses:(NSString *)json
|
||||
return [json valueForKey:@"key-uid"];
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// prepareDirAndUpdateConfig
|
||||
-(NSString *) prepareDirAndUpdateConfig:(NSString *)config
|
||||
withKeyUID:(NSString *)keyUID {
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
@@ -452,7 +467,6 @@ RCT_EXPORT_METHOD(multiAccountDeriveAddresses:(NSString *)json
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////// prepareDirAndUpdateConfig
|
||||
RCT_EXPORT_METHOD(prepareDirAndUpdateConfig:(NSString *)keyUID
|
||||
config:(NSString *)config
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
@@ -464,7 +478,6 @@ RCT_EXPORT_METHOD(prepareDirAndUpdateConfig:(NSString *)keyUID
|
||||
callback(@[updatedConfig]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// saveAccountAndLogin
|
||||
RCT_EXPORT_METHOD(saveAccountAndLogin:(NSString *)multiaccountData
|
||||
password:(NSString *)password
|
||||
settings:(NSString *)settings
|
||||
@@ -481,7 +494,6 @@ RCT_EXPORT_METHOD(saveAccountAndLogin:(NSString *)multiaccountData
|
||||
NSLog(@"%@", result);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// saveAccountAndLoginWithKeycard
|
||||
RCT_EXPORT_METHOD(saveAccountAndLoginWithKeycard:(NSString *)multiaccountData
|
||||
password:(NSString *)password
|
||||
settings:(NSString *)settings
|
||||
@@ -502,11 +514,11 @@ RCT_EXPORT_METHOD(saveAccountAndLoginWithKeycard:(NSString *)multiaccountData
|
||||
- (NSString *) getExportDbFilePath {
|
||||
NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"export.db"];
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
|
||||
|
||||
if ([fileManager fileExistsAtPath:filePath]) {
|
||||
[fileManager removeItemAtPath:filePath error:nil];
|
||||
}
|
||||
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
@@ -543,7 +555,6 @@ RCT_EXPORT_METHOD(saveAccountAndLoginWithKeycard:(NSString *)multiaccountData
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// login
|
||||
RCT_EXPORT_METHOD(login:(NSString *)accountData
|
||||
password:(NSString *)password) {
|
||||
#if DEBUG
|
||||
@@ -555,7 +566,6 @@ RCT_EXPORT_METHOD(login:(NSString *)accountData
|
||||
NSLog(@"%@", result);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// loginWithConfig
|
||||
RCT_EXPORT_METHOD(loginWithConfig:(NSString *)accountData
|
||||
password:(NSString *)password
|
||||
configJSON:(NSString *)configJSON) {
|
||||
@@ -568,7 +578,6 @@ RCT_EXPORT_METHOD(loginWithConfig:(NSString *)accountData
|
||||
NSLog(@"%@", result);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// loginWithKeycard
|
||||
RCT_EXPORT_METHOD(loginWithKeycard:(NSString *)accountData
|
||||
password:(NSString *)password
|
||||
chatKey:(NSString *)chatKey) {
|
||||
@@ -583,7 +592,6 @@ RCT_EXPORT_METHOD(loginWithKeycard:(NSString *)accountData
|
||||
NSLog(@"%@", result);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// logout
|
||||
RCT_EXPORT_METHOD(logout) {
|
||||
#if DEBUG
|
||||
NSLog(@"Logout() method called");
|
||||
@@ -593,7 +601,6 @@ RCT_EXPORT_METHOD(logout) {
|
||||
NSLog(@"%@", result);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// openAccounts
|
||||
RCT_EXPORT_METHOD(openAccounts:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
NSLog(@"OpenAccounts() method called");
|
||||
@@ -607,7 +614,6 @@ RCT_EXPORT_METHOD(openAccounts:(RCTResponseSenderBlock)callback) {
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// verityAccountPassword
|
||||
RCT_EXPORT_METHOD(verify:(NSString *)address
|
||||
password:(NSString *)password
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
@@ -624,7 +630,6 @@ RCT_EXPORT_METHOD(verify:(NSString *)address
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// verifyDatabasePassword
|
||||
RCT_EXPORT_METHOD(verifyDatabasePassword:(NSString *)keyUID
|
||||
password:(NSString *)password
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
@@ -635,7 +640,6 @@ RCT_EXPORT_METHOD(verifyDatabasePassword:(NSString *)keyUID
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// changeDatabasePassword
|
||||
RCT_EXPORT_METHOD(reEncryptDbAndKeystore:(NSString *)keyUID
|
||||
currentPassword:(NSString *)currentPassword
|
||||
newPassword:(NSString *)newPassword
|
||||
@@ -648,7 +652,6 @@ RCT_EXPORT_METHOD(reEncryptDbAndKeystore:(NSString *)keyUID
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////// convertToKeycardAccount
|
||||
RCT_EXPORT_METHOD(convertToKeycardAccount:(NSString *)keyUID
|
||||
accountData:(NSString *)accountData
|
||||
settings:(NSString *)settings
|
||||
@@ -663,9 +666,9 @@ RCT_EXPORT_METHOD(convertToKeycardAccount:(NSString *)keyUID
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma mark - SendTransaction
|
||||
//////////////////////////////////////////////////////////////////// sendTransaction
|
||||
|
||||
RCT_EXPORT_METHOD(sendTransaction:(NSString *)txArgsJSON
|
||||
password:(NSString *)password
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
@@ -676,9 +679,9 @@ RCT_EXPORT_METHOD(sendTransaction:(NSString *)txArgsJSON
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma mark - SignMessage
|
||||
//////////////////////////////////////////////////////////////////// signMessage
|
||||
|
||||
RCT_EXPORT_METHOD(signMessage:(NSString *)message
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
@@ -688,9 +691,9 @@ RCT_EXPORT_METHOD(signMessage:(NSString *)message
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma mark - Recover
|
||||
//////////////////////////////////////////////////////////////////// recover
|
||||
|
||||
RCT_EXPORT_METHOD(recover:(NSString *)message
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
@@ -700,9 +703,9 @@ RCT_EXPORT_METHOD(recover:(NSString *)message
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma mark - SignTypedData
|
||||
//////////////////////////////////////////////////////////////////// signTypedData
|
||||
|
||||
RCT_EXPORT_METHOD(signTypedData:(NSString *)data
|
||||
account:(NSString *)account
|
||||
password:(NSString *)password
|
||||
@@ -714,9 +717,9 @@ RCT_EXPORT_METHOD(signTypedData:(NSString *)data
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma mark - SignTypedDataV4
|
||||
//////////////////////////////////////////////////////////////////// signTypedDataV4
|
||||
|
||||
RCT_EXPORT_METHOD(signTypedDataV4:(NSString *)data
|
||||
account:(NSString *)account
|
||||
password:(NSString *)password
|
||||
@@ -728,9 +731,9 @@ RCT_EXPORT_METHOD(signTypedDataV4:(NSString *)data
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma mark - SignGroupMembership
|
||||
//////////////////////////////////////////////////////////////////// signGroupMembership
|
||||
|
||||
RCT_EXPORT_METHOD(signGroupMembership:(NSString *)content
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
@@ -740,9 +743,9 @@ RCT_EXPORT_METHOD(signGroupMembership:(NSString *)content
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma mark - ExtractGroupMembershipSignatures
|
||||
//////////////////////////////////////////////////////////////////// extractGroupMembershipSignatures
|
||||
|
||||
RCT_EXPORT_METHOD(extractGroupMembershipSignatures:(NSString *)content
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
@@ -752,9 +755,9 @@ RCT_EXPORT_METHOD(extractGroupMembershipSignatures:(NSString *)content
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma mark - GetNodeConfig
|
||||
//////////////////////////////////////////////////////////////////// getNodeConfig
|
||||
|
||||
RCT_EXPORT_METHOD(getNodeConfig:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
NSLog(@"GetNodeConfig() method called");
|
||||
@@ -764,9 +767,9 @@ RCT_EXPORT_METHOD(getNodeConfig:(RCTResponseSenderBlock)callback) {
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma mark - only android methods
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
RCT_EXPORT_METHOD(setAdjustResize) {
|
||||
#if DEBUG
|
||||
NSLog(@"setAdjustResize() works only on Android");
|
||||
@@ -957,10 +960,10 @@ RCT_EXPORT_METHOD(exportUnencryptedDatabase:(NSString *)accountData
|
||||
#if DEBUG
|
||||
NSLog(@"exportUnencryptedDatabase() method called");
|
||||
#endif
|
||||
|
||||
|
||||
NSString *filePath = [self getExportDbFilePath];
|
||||
StatusgoExportUnencryptedDatabase(accountData, password, filePath);
|
||||
|
||||
|
||||
callback(@[filePath]);
|
||||
}
|
||||
|
||||
@@ -995,7 +998,7 @@ RCT_EXPORT_METHOD(deactivateKeepAwake)
|
||||
});
|
||||
}
|
||||
|
||||
//// deviceinfo
|
||||
#pragma mark - deviceinfo
|
||||
|
||||
- (bool) is24Hour
|
||||
{
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ in mkShell {
|
||||
# build specific utilities
|
||||
clojure maven watchman
|
||||
# lint specific utilities
|
||||
clj-kondo zprint clojure-lsp
|
||||
clj-kondo zprint
|
||||
# other nice to have stuff
|
||||
yarn nodejs python27
|
||||
] # and some special cases
|
||||
|
||||
@@ -89,6 +89,7 @@
|
||||
"@testing-library/jest-native": "^5.0.0",
|
||||
"@testing-library/react-native": "^11.2.0",
|
||||
"@types/jest": "^28.1.6",
|
||||
"concurrently": "^7.6.0",
|
||||
"detox": "^19.9.1",
|
||||
"jest": "^25.1.0",
|
||||
"jest-circus": "^26.0.0",
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 377 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 738 KiB |
+16
-10
@@ -19,6 +19,7 @@
|
||||
;; routing
|
||||
[bidi "2.1.6"]
|
||||
;; test dependencies
|
||||
[camel-snake-kebab "0.4.3"]
|
||||
[day8.re-frame/test "0.1.5"]
|
||||
[com.taoensso/tufte "2.1.0"]]
|
||||
|
||||
@@ -81,20 +82,25 @@
|
||||
:output-dir "target/test"
|
||||
:optimizations :simple
|
||||
:target :node-test
|
||||
:main status-im.test-runner/main
|
||||
;; When running tests without a REPL you can uncomment below line to `make test-watch` a specific file
|
||||
;; :ns-regexp "status-im.chat.models-test$"
|
||||
:main
|
||||
status-im.test-runner/main
|
||||
;; set :ui-driven to true to let shadow-cljs inject node-repl
|
||||
:ui-driven true
|
||||
:ui-driven
|
||||
true
|
||||
:closure-defines
|
||||
{status-im.utils.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
|
||||
status-im.utils.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"}
|
||||
:compiler-options {;; needed because we override require and it
|
||||
;; messes with source-map which reports callstack
|
||||
;; exceeded exceptions instead of real issues
|
||||
:source-map false
|
||||
;; needed because we use deref in tests
|
||||
:static-fns false
|
||||
:optimizations :simple
|
||||
:infer-externs true}}
|
||||
:compiler-options
|
||||
{;; needed because we override require and it
|
||||
;; messes with source-map which reports callstack
|
||||
;; exceeded exceptions instead of real issues
|
||||
:source-map false
|
||||
;; needed because we use deref in tests
|
||||
:static-fns false
|
||||
:optimizations :simple
|
||||
:infer-externs true}}
|
||||
|
||||
;; mock.js-dependencies is mocking the react-native libraries
|
||||
;; we build it as a node library so that it can be required by
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import {useDerivedValue, runOnJS as reaRunOnJS, runOnJS} from "react-native-reanimated";
|
||||
|
||||
export function useTranslateY(initialTranslationY, bottomSheetDy, panY) {
|
||||
return useDerivedValue(() => {
|
||||
return initialTranslationY - (bottomSheetDy.value - panY.value)
|
||||
})
|
||||
}
|
||||
|
||||
export function useBackgroundOpacity(translateY, backgroundHeight, windowHeight) {
|
||||
return useDerivedValue(() => {
|
||||
const opacity = ((translateY.value - windowHeight) / -backgroundHeight) * 0.5
|
||||
|
||||
return Math.max(Math.min(opacity, 0.5), 0)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { useDerivedValue } from 'react-native-reanimated';
|
||||
|
||||
const MAX_SCALE = 1.8;
|
||||
|
||||
export function ringScale(scale, subtract) {
|
||||
return useDerivedValue(
|
||||
function () {
|
||||
'worklet'
|
||||
const value = scale.value;
|
||||
const maxDelta = MAX_SCALE - 1;
|
||||
const maxDeltaDiff = 1 - maxDelta;
|
||||
const maxVirtualScale = MAX_SCALE + maxDelta;
|
||||
const decimals = value - Math.floor(value);
|
||||
const normalizedValue = value >= maxVirtualScale ? (decimals + ((parseInt(value) - 1) * maxDeltaDiff) + 1) : value;
|
||||
return (((normalizedValue - subtract) > MAX_SCALE ? normalizedValue - maxDelta : normalizedValue) - subtract);
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import { useDerivedValue, interpolate } from 'react-native-reanimated';
|
||||
|
||||
// Generic Worklets
|
||||
|
||||
export function applyAnimationsToStyle(animations, style) {
|
||||
@@ -27,3 +29,12 @@ export function applyAnimationsToStyle(animations, style) {
|
||||
return Object.assign(animatedStyle, style);
|
||||
};
|
||||
};
|
||||
|
||||
export function interpolateValue(sharedValue, inputRange, outputRange) {
|
||||
return useDerivedValue(
|
||||
function () {
|
||||
'worklet'
|
||||
return interpolate(sharedValue.value, inputRange, outputRange);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,22 @@
|
||||
(:require [status-im.utils.test :as utils.test])
|
||||
(:require [status-im.chat.default-chats :refer (default-chats)]))
|
||||
|
||||
;; to generate a js Proxy at js/__STATUS_MOBILE_JS_IDENTITY_PROXY__ that accept any (.xxx) call and
|
||||
;; return itself
|
||||
;; For the convenience to mock eg.
|
||||
;; (-> reanimated/slide-out-up-animation .springify (.damping 20) (.stiffness 300))
|
||||
;; (-> reanimated/slide-out-up-animation (.damping 20) .springify (.stiffness 300))
|
||||
(js/eval
|
||||
"
|
||||
var globalThis
|
||||
if (typeof window === \"undefined\") {
|
||||
globalThis = global
|
||||
} else {
|
||||
globalThis = window
|
||||
}
|
||||
globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return () => globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__}})
|
||||
")
|
||||
|
||||
(def action-button #js {:default #js {:Item #js {}}})
|
||||
(def config #js {:default #js {}})
|
||||
(def camera #js {:RNCamera #js {:Constants #js {}}})
|
||||
@@ -122,8 +138,10 @@
|
||||
(def react-native-share #js {:default {}})
|
||||
(def react-native-svg
|
||||
#js
|
||||
{:SvgUri #js {:render identity}
|
||||
:SvgXml #js {:render identity}})
|
||||
{:SvgUri #js {:render identity}
|
||||
:SvgXml #js {:render identity}
|
||||
:default #js {:render identity}
|
||||
:Path #js {:render identity}})
|
||||
(def react-native-webview #js {:default {}})
|
||||
(def react-native-audio-toolkit #js {:MediaStates {}})
|
||||
(def net-info #js {})
|
||||
@@ -236,7 +254,10 @@
|
||||
:withTiming (fn [])
|
||||
:withDelay (fn [])
|
||||
:Easing #js {:bezier identity}
|
||||
:Keyframe (fn [])})
|
||||
:Keyframe (fn [])
|
||||
:SlideOutUp js/__STATUS_MOBILE_JS_IDENTITY_PROXY__
|
||||
:SlideInUp js/__STATUS_MOBILE_JS_IDENTITY_PROXY__
|
||||
:LinearTransition js/__STATUS_MOBILE_JS_IDENTITY_PROXY__})
|
||||
(def react-native-gesture-handler
|
||||
#js
|
||||
{:default #js {}
|
||||
@@ -321,6 +342,9 @@
|
||||
|
||||
(def shell-worklets #js {})
|
||||
|
||||
(def bottom-sheet #js {})
|
||||
(def record-audio-worklets #js {})
|
||||
|
||||
;; Update i18n_resources.cljs
|
||||
(defn mock
|
||||
[module]
|
||||
@@ -369,6 +393,8 @@
|
||||
"react-native-svg" react-native-svg
|
||||
"../src/js/worklet_factory.js" worklet-factory
|
||||
"../src/js/shell_worklets.js" shell-worklets
|
||||
"../src/js/bottom_sheet.js" bottom-sheet
|
||||
"../src/js/record_audio_worklets.js" record-audio-worklets
|
||||
"./fleets.js" default-fleets
|
||||
"./chats.js" default-chats
|
||||
"@walletconnect/client" wallet-connect-client
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
(ns quo2.components.banners.--tests--.banner-component-spec
|
||||
(:require ["@testing-library/react-native" :as rtl]
|
||||
[quo2.components.banners.banner.view :as banner]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn render-banner
|
||||
[opts]
|
||||
(rtl/render (reagent/as-element [banner/banner opts])))
|
||||
|
||||
(js/global.test "basic render of banner component"
|
||||
(fn []
|
||||
(render-banner {:pins-count "5"
|
||||
:latest-pin-text "this message"})
|
||||
(-> (js/expect (rtl/screen.getByText "this message"))
|
||||
(.toBeTruthy))
|
||||
(-> (js/expect (rtl/screen.getByText "5"))
|
||||
(.toBeTruthy))))
|
||||
@@ -0,0 +1,19 @@
|
||||
(ns quo2.components.banners.banner.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
|
||||
(def container
|
||||
{:width "100%"
|
||||
:height 50
|
||||
:background-color colors/primary-50-opa-20
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:padding-horizontal 20
|
||||
:padding-vertical 10})
|
||||
|
||||
(def counter
|
||||
{:padding-right 22
|
||||
:height 20
|
||||
:width 20
|
||||
:justify-content :center
|
||||
:align-items :center})
|
||||
@@ -0,0 +1,24 @@
|
||||
(ns quo2.components.banners.banner.view
|
||||
(:require [quo2.components.banners.banner.style :as style]
|
||||
[quo2.components.counter.counter :as counter]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn banner
|
||||
[{:keys [show-pin? latest-pin-text pins-count on-press]}]
|
||||
[rn/touchable-opacity
|
||||
{:accessibility-label :pinned-banner
|
||||
:style style/container
|
||||
:active-opacity 1
|
||||
:on-press on-press}
|
||||
(when show-pin? [icons/icon :i/pin {:size 20}])
|
||||
[text/text
|
||||
{:number-of-lines 1
|
||||
:size :paragraph-2
|
||||
:style {:margin-left 10 :margin-right 50}}
|
||||
latest-pin-text]
|
||||
[rn/view
|
||||
{:accessibility-label :pins-count
|
||||
:style style/counter}
|
||||
(when (pos? pins-count) [counter/counter {:type :secondary} pins-count])]])
|
||||
@@ -0,0 +1,28 @@
|
||||
(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)))))
|
||||
@@ -1,12 +1,15 @@
|
||||
(ns quo2.components.community.community-card-view
|
||||
(:require [quo2.components.community.community-view :as community-view]
|
||||
[quo2.components.community.icon :as icon]
|
||||
[quo2.components.community.style :as style]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn community-card-view-item
|
||||
[{:keys [name description locked
|
||||
[{:keys [name description locked images
|
||||
status tokens cover tags width]} on-press]
|
||||
[rn/touchable-opacity {:on-press on-press}
|
||||
[rn/touchable-opacity
|
||||
{:accessibility-label :community-card-item
|
||||
:on-press on-press}
|
||||
[rn/view {:style (style/community-card 20)}
|
||||
[rn/view
|
||||
{:style {:width width
|
||||
@@ -22,9 +25,9 @@
|
||||
{:flex 1
|
||||
:border-radius 20}}]]
|
||||
[rn/view (style/card-view-content-container 12)
|
||||
[rn/view (style/card-view-chat-icon 48)]
|
||||
;;TODO new pure component based on quo2 should be implemented without status-im usage
|
||||
;[communities.icon/community-icon-redesign community 48]]
|
||||
[rn/view (style/card-view-chat-icon 48)
|
||||
[icon/community-icon {:images images} 48]]
|
||||
|
||||
(when (= status :gated)
|
||||
[rn/view (style/permission-tag-styles)
|
||||
[community-view/permission-tag-container
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
(ns quo2.components.community.icon
|
||||
(:require [react-native.core :as rn]))
|
||||
|
||||
(defn community-icon
|
||||
[{:keys [images]} size]
|
||||
(let [thumbnail-image (get-in images [:thumbnail :uri])]
|
||||
[rn/image
|
||||
{:source {:uri thumbnail-image}
|
||||
:style {:border-radius 50
|
||||
:border-width 0
|
||||
:border-color :transparent
|
||||
:width size
|
||||
:height size}}]))
|
||||
@@ -10,25 +10,25 @@
|
||||
(rtl/render (reagent/as-element [counter/counter opts value]))))
|
||||
|
||||
(js/global.test "default render of counter component"
|
||||
(fn []
|
||||
(render-counter)
|
||||
(-> (js/expect (rtl/screen.getByTestId "counter-component"))
|
||||
(.toBeTruthy))))
|
||||
(fn []
|
||||
(render-counter)
|
||||
(-> (js/expect (rtl/screen.getByTestId "counter-component"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "renders counter with a string value"
|
||||
(fn []
|
||||
(render-counter {} "1")
|
||||
(-> (js/expect (rtl/screen.getByText "1"))
|
||||
(.toBeTruthy))))
|
||||
(fn []
|
||||
(render-counter {} "1")
|
||||
(-> (js/expect (rtl/screen.getByText "1"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "renders counter with an integer value"
|
||||
(fn []
|
||||
(render-counter {} 1)
|
||||
(-> (js/expect (rtl/screen.getByText "1"))
|
||||
(.toBeTruthy))))
|
||||
(fn []
|
||||
(render-counter {} 1)
|
||||
(-> (js/expect (rtl/screen.getByText "1"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "renders counter with value 99+ when the value is greater than 99"
|
||||
(fn []
|
||||
(render-counter {} "100")
|
||||
(-> (js/expect (rtl/screen.getByText "99+"))
|
||||
(.toBeTruthy))))
|
||||
(fn []
|
||||
(render-counter {} "100")
|
||||
(-> (js/expect (rtl/screen.getByText "99+"))
|
||||
(.toBeTruthy))))
|
||||
@@ -0,0 +1,45 @@
|
||||
(ns quo2.components.dividers.--tests--.divider-label-component-spec
|
||||
(:require ["@testing-library/react-native" :as rtl]
|
||||
[quo2.components.dividers.divider-label :as divider-label]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn render-divider-label
|
||||
([]
|
||||
(render-divider-label {}))
|
||||
([opts]
|
||||
(rtl/render (reagent/as-element [divider-label/divider-label opts]))))
|
||||
|
||||
(js/global.test "default render of divider-label component"
|
||||
(fn []
|
||||
(render-divider-label)
|
||||
(-> (js/expect (rtl/screen.getByLabelText "divider-label"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "render divider-label component with a label"
|
||||
(fn []
|
||||
(render-divider-label {:label :hello})
|
||||
(-> (js/expect (rtl/screen.getByText "hello"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "render divider-label component with a counter-value"
|
||||
(fn []
|
||||
(render-divider-label {:label :hello
|
||||
:counter-value "1"})
|
||||
(-> (js/expect (rtl/screen.getByText "1"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "divider-label chevron icon renders to the left when set"
|
||||
(fn []
|
||||
(render-divider-label {:label :hello
|
||||
:counter-value "1"
|
||||
:chevron-position :left})
|
||||
(-> (js/expect (rtl/screen.getByTestId "divider-label-icon-left"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "divider-label chevron icon renders to the right when set"
|
||||
(fn []
|
||||
(render-divider-label {:label :hello
|
||||
:counter-value "1"
|
||||
:chevron-position :right})
|
||||
(-> (js/expect (rtl/screen.getByTestId "divider-label-icon-right"))
|
||||
(.toBeTruthy))))
|
||||
@@ -7,9 +7,9 @@
|
||||
(defn date
|
||||
[value]
|
||||
[rn/view
|
||||
{:margin-vertical 16
|
||||
:padding-right 8
|
||||
:padding-left 62}
|
||||
{:margin-vertical 8
|
||||
:padding-right 20
|
||||
:padding-left 60}
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:accessibility-label :divider-date-text
|
||||
|
||||
@@ -23,14 +23,18 @@
|
||||
text-and-icon-color (if dark? colors/neutral-40 colors/neutral-50)
|
||||
counter-text-color (if dark? colors/white colors/neutral-100)]
|
||||
[rn/view
|
||||
{:style {:border-top-width 1
|
||||
:border-top-color border-and-counter-bg-color
|
||||
:padding-top padding-top
|
||||
:padding-horizontal 16
|
||||
:align-items :center
|
||||
:flex-direction :row}}
|
||||
{:accessible true
|
||||
:accessibility-label :divider-label
|
||||
:style {:border-top-width 1
|
||||
:border-top-color border-and-counter-bg-color
|
||||
:padding-top padding-top
|
||||
:padding-horizontal 16
|
||||
:align-items :center
|
||||
:flex-direction :row}}
|
||||
(when (= chevron-position :left)
|
||||
[rn/view {:style {:margin-right 4}}
|
||||
[rn/view
|
||||
{:test-ID :divider-label-icon-left
|
||||
:style {:margin-right 4}}
|
||||
[icons/icon
|
||||
:main-icons/chevron-down
|
||||
{:color text-and-icon-color
|
||||
@@ -43,10 +47,11 @@
|
||||
:flex 1}}
|
||||
label]
|
||||
(when (= chevron-position :right)
|
||||
[icons/icon
|
||||
:main-icons/chevron-down
|
||||
{:color text-and-icon-color
|
||||
:size chevron-icon-container-width}])
|
||||
[rn/view {:test-ID :divider-label-icon-right}
|
||||
[icons/icon
|
||||
:main-icons/chevron-down
|
||||
{:color text-and-icon-color
|
||||
:size chevron-icon-container-width}]])
|
||||
(when (pos? counter-value)
|
||||
[rn/view
|
||||
{:style {:border-radius 6
|
||||
|
||||
@@ -8,56 +8,46 @@
|
||||
(rtl/render (reagent/as-element [action-drawer/action-drawer options]))))
|
||||
|
||||
(js/global.test "action-drawer renders with elements label displaying"
|
||||
(fn []
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"}]])
|
||||
(-> (js/expect (rtl/screen.getByText "a sample label"))
|
||||
(.toBeTruthy))))
|
||||
(fn []
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"}]])
|
||||
(-> (js/expect (rtl/screen.getByText "a sample label"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "action-drawer renders with elements sub-label displaying"
|
||||
(fn []
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"
|
||||
:sub-label "a sample sub label"}]])
|
||||
(-> (js/expect (rtl/screen.getByText "a sample sub label"))
|
||||
(.toBeTruthy))))
|
||||
(fn []
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"
|
||||
:sub-label "a sample sub label"}]])
|
||||
(-> (js/expect (rtl/screen.getByText "a sample sub label"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "action-drawer on click action works on element"
|
||||
(let [event (js/jest.fn)]
|
||||
(fn []
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"
|
||||
:on-press event}]])
|
||||
(rtl/fireEvent.press (rtl/screen.getByText "a sample label"))
|
||||
(-> (js/expect event)
|
||||
(.toHaveBeenCalled)))))
|
||||
(let [event (js/jest.fn)]
|
||||
(fn []
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"
|
||||
:on-press event}]])
|
||||
(rtl/fireEvent.press (rtl/screen.getByText "a sample label"))
|
||||
(-> (js/expect event)
|
||||
(.toHaveBeenCalled)))))
|
||||
|
||||
(js/global.test "action-drawer renders two icons when set"
|
||||
(fn []
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"
|
||||
:right-icon :i/friend
|
||||
:accessibility-label :first-element}]])
|
||||
(-> (js/expect (rtl/screen.getByLabelText "right-icon-for-action"))
|
||||
(.toBeTruthy))
|
||||
(-> (js/expect (rtl/screen.queryByLabelText "left-icon-for-action"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "action-drawer does not render a divider when the add-divider? prop is false"
|
||||
(fn []
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"
|
||||
:add-divider? false
|
||||
:accessibility-label :first-element}]])
|
||||
(-> (js/expect (rtl/screen.getAllByLabelText "divider"))
|
||||
(.not)
|
||||
(.toBeTruthy))))
|
||||
(fn []
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"
|
||||
:right-icon :i/friend
|
||||
:accessibility-label :first-element}]])
|
||||
(-> (js/expect (rtl/screen.getByLabelText "right-icon-for-action"))
|
||||
(.toBeTruthy))
|
||||
(-> (js/expect (rtl/screen.queryByLabelText "left-icon-for-action"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "action-drawer renders a divider when the add-divider? prop is true"
|
||||
(fn []
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"
|
||||
:add-divider? true
|
||||
:accessibility-label :first-element}]])
|
||||
(-> (js/expect (rtl/screen.getAllByLabelText "divider"))
|
||||
(.toBeTruthy))))
|
||||
(fn []
|
||||
(render-action-drawer [[{:icon :i/friend
|
||||
:label "a sample label"
|
||||
:add-divider? true
|
||||
:accessibility-label :first-element}]])
|
||||
(-> (js/expect (rtl/screen.getAllByLabelText "divider"))
|
||||
(.toBeTruthy))))
|
||||
@@ -0,0 +1,14 @@
|
||||
(ns quo2.components.markdown.--tests--.text-component-spec
|
||||
(:require ["@testing-library/react-native" :as rtl]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn render-text
|
||||
([options value]
|
||||
(rtl/render (reagent/as-element [text/text options value]))))
|
||||
|
||||
(js/global.test "text renders with text"
|
||||
(fn []
|
||||
(render-text {} "hello")
|
||||
(-> (js/expect (rtl/screen.getByText "hello"))
|
||||
(.toBeTruthy))))
|
||||
@@ -4,7 +4,6 @@
|
||||
(def container
|
||||
{:flex 1
|
||||
:flex-wrap :wrap
|
||||
:height 18
|
||||
:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
@@ -40,4 +39,4 @@
|
||||
(defn time-text
|
||||
[ens?]
|
||||
{:color colors/neutral-50
|
||||
:margin-left (if ens? 8 4)})
|
||||
:margin-left (if ens? 8 4)})
|
||||
|
||||
@@ -93,7 +93,8 @@
|
||||
:style style/middle-dot-chat-key}
|
||||
middle-dot])
|
||||
[text/text
|
||||
{:monospace true
|
||||
:size :paragraph-2
|
||||
:style (style/time-text ens?)}
|
||||
{:monospace true
|
||||
:size :paragraph-2
|
||||
:accessibility-label :message-timestamp
|
||||
:style (style/time-text ens?)}
|
||||
time-str]]))])
|
||||
|
||||
@@ -146,12 +146,11 @@
|
||||
[rn/view
|
||||
{:style (assoc centrify-style
|
||||
:flex-direction :row
|
||||
:flex 1
|
||||
:justify-content :flex-end)}
|
||||
(let [last-icon-index (-> right-section-buttons count dec)]
|
||||
(map-indexed (fn [index {:keys [icon on-press type] :or {type :grey}}]
|
||||
(map-indexed (fn [index {:keys [icon on-press type style] :or {type :grey}}]
|
||||
^{:key index}
|
||||
[rn/view {:style {:margin-right (if (not= index last-icon-index) 8 0)}}
|
||||
[rn/view {:style (merge {:margin-right (if (not= index last-icon-index) 8 0)} style)}
|
||||
[button/button {:on-press on-press :icon true :type type :size 32}
|
||||
icon]])
|
||||
right-section-buttons))])
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
(ns quo2.components.notifications.count-down-circle
|
||||
(:require [goog.string :as gstring]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.svg :as svg]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn- get-path-props
|
||||
[size stroke-width rotation]
|
||||
(let [half-size (/ size 2)
|
||||
half-stroke-width (/ stroke-width 2)
|
||||
arc-radius (- half-size half-stroke-width)
|
||||
arc-diameter (* arc-radius 2)
|
||||
rotation-indicator (if (= rotation :clockwise) "1,0" "0,1")
|
||||
path-length (* js/Math.PI arc-diameter)
|
||||
path (gstring/format
|
||||
"m %s,%s a %s,%s 0 %s 0,%s a %s,%s 0 %s 0 ,-%s"
|
||||
half-size
|
||||
half-stroke-width
|
||||
arc-radius
|
||||
arc-radius
|
||||
rotation-indicator
|
||||
arc-diameter
|
||||
arc-radius
|
||||
arc-radius
|
||||
rotation-indicator
|
||||
arc-diameter)]
|
||||
{:path path
|
||||
:path-length path-length}))
|
||||
|
||||
(defn- linear-ease
|
||||
[time start goal duration]
|
||||
(if (zero? duration)
|
||||
start
|
||||
(-> time
|
||||
(/ duration)
|
||||
(* goal)
|
||||
(+ start))))
|
||||
|
||||
(defn- get-start-at
|
||||
[duration initial-remaining-time]
|
||||
(cond (or (zero? duration) (= duration initial-remaining-time)) 0
|
||||
(number? initial-remaining-time) (- duration initial-remaining-time)
|
||||
:else 0))
|
||||
|
||||
(def ^:private themes
|
||||
{:color {:light colors/neutral-80-opa-40
|
||||
:dark colors/white-opa-40}})
|
||||
|
||||
(defn circle-timer
|
||||
[{:keys [color duration size stroke-width trail-color rotation initial-remaining-time]}]
|
||||
(let [rotation (or rotation :clockwise)
|
||||
duration (or duration 4)
|
||||
stroke-width (or stroke-width 1)
|
||||
size (or size 9)
|
||||
max-stroke-width (max stroke-width 0)
|
||||
{:keys [path path-length]} (get-path-props size max-stroke-width rotation)
|
||||
start-at (get-start-at duration initial-remaining-time)
|
||||
elapsed-time (reagent/atom 0)
|
||||
prev-frame-time (reagent/atom nil)
|
||||
frame-request (reagent/atom nil)
|
||||
display-time (reagent/atom start-at)
|
||||
;; get elapsed frame time
|
||||
swap-elapsed-time-each-frame (fn swap-elapsed-time-each-frame [frame-time]
|
||||
(if (nil? @prev-frame-time)
|
||||
(do (reset! prev-frame-time frame-time)
|
||||
(reset! frame-request (js/requestAnimationFrame
|
||||
swap-elapsed-time-each-frame)))
|
||||
(let [delta (- (/ frame-time 1000)
|
||||
(/ @prev-frame-time 1000))
|
||||
current-elapsed (swap! elapsed-time + delta)
|
||||
current-display-time (+ start-at current-elapsed)
|
||||
completed? (>= current-display-time duration)]
|
||||
(reset! display-time (if completed?
|
||||
duration
|
||||
current-display-time))
|
||||
(when-not completed?
|
||||
(reset! prev-frame-time frame-time)
|
||||
(reset! frame-request (js/requestAnimationFrame
|
||||
swap-elapsed-time-each-frame))))))]
|
||||
(reagent/create-class
|
||||
{:component-will-unmount #(js/cancelAnimationFrame @frame-request)
|
||||
:reagent-render
|
||||
(fn []
|
||||
(reset! frame-request (js/requestAnimationFrame swap-elapsed-time-each-frame))
|
||||
[rn/view
|
||||
{:style {:position :relative
|
||||
:width size
|
||||
:height size}}
|
||||
[svg/svg
|
||||
{:view-box (str "0 0 " size " " size)
|
||||
:width size
|
||||
:height size}
|
||||
[svg/path
|
||||
{:d path :fill :none :stroke (or trail-color :transparent) :stroke-width stroke-width}]
|
||||
(when-not (= @display-time duration)
|
||||
[svg/path
|
||||
{:d path
|
||||
:fill :none
|
||||
:stroke (or color (get-in themes [:color (theme/get-theme)]))
|
||||
:stroke-linecap :square
|
||||
:stroke-width stroke-width
|
||||
:stroke-dasharray path-length
|
||||
:stroke-dashoffset (linear-ease @display-time 0 path-length duration)}])]])})))
|
||||
@@ -4,18 +4,23 @@
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn info-count
|
||||
[count style]
|
||||
(when (> count 0)
|
||||
[rn/view
|
||||
{:style (merge {:width 16
|
||||
:height 16
|
||||
:position :absolute
|
||||
:right 22
|
||||
:border-radius 6
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color (colors/theme-colors colors/primary-50 colors/primary-60)}
|
||||
style)}
|
||||
[rn/text
|
||||
{:style (merge typography/font-medium typography/label {:color colors/white :text-align :center})}
|
||||
count]]))
|
||||
([count]
|
||||
(info-count {} count))
|
||||
([props count]
|
||||
(when (> count 0)
|
||||
[rn/view
|
||||
(merge props
|
||||
{:style (merge {:width 16
|
||||
:height 16
|
||||
:position :absolute
|
||||
:right 22
|
||||
:border-radius 6
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color (colors/theme-colors colors/primary-50 colors/primary-60)}
|
||||
(:style props))})
|
||||
[rn/text
|
||||
{:style (merge typography/font-medium
|
||||
typography/label
|
||||
{:color colors/white :text-align :center})}
|
||||
count]])))
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
(ns quo2.components.notifications.toast
|
||||
(:require [i18n.i18n :as i18n]
|
||||
[quo2.components.icon :as icon]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.notifications.count-down-circle :as count-down-circle]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def ^:private themes
|
||||
{:container {:light {:background-color colors/white-opa-70}
|
||||
:dark {:background-color colors/neutral-80-opa-70}}
|
||||
:text {:light {:color colors/neutral-100}
|
||||
:dark {:color colors/white}}
|
||||
:icon {:light {:color colors/neutral-100}
|
||||
:dark {:color colors/white}}
|
||||
:action-container {:light {:background-color :colors/neutral-80-opa-5}
|
||||
:dark {:background-color :colors/white-opa-5}}})
|
||||
|
||||
(defn- merge-theme-style
|
||||
[component-key styles]
|
||||
(merge (get-in themes [component-key (theme/get-theme)]) styles))
|
||||
|
||||
(defn toast-action-container
|
||||
[{:keys [on-press style]} & children]
|
||||
[rn/touchable-highlight {:on-press on-press}
|
||||
[into
|
||||
[rn/view
|
||||
{:style (merge
|
||||
{:flex-direction :row
|
||||
:padding-vertical 3
|
||||
:padding-horizontal 8
|
||||
:align-items :center
|
||||
:border-radius 8
|
||||
:background-color (get-in themes
|
||||
[:action-container (theme/get-theme)
|
||||
:background-color])}
|
||||
style)}]
|
||||
children]])
|
||||
|
||||
(defn toast-undo-action
|
||||
[duration on-press]
|
||||
[toast-action-container {:on-press on-press}
|
||||
[rn/view {:style {:margin-right 5}}
|
||||
[count-down-circle/circle-timer {:duration duration}]]
|
||||
[text/text
|
||||
{:size :paragraph-2 :weight :medium :style (merge-theme-style :text {})}
|
||||
[i18n/label :t/undo]]])
|
||||
|
||||
(defn- toast-container
|
||||
[{:keys [left middle right]}]
|
||||
[rn/view {:style {:padding-left 12 :padding-right 12}}
|
||||
[rn/view
|
||||
{:style (merge-theme-style :container
|
||||
{:flex-direction :row
|
||||
:width "100%"
|
||||
:margin :auto
|
||||
:justify-content :space-between
|
||||
:padding-vertical 8
|
||||
:padding-left 10
|
||||
:padding-right 8
|
||||
:border-radius 12})}
|
||||
[rn/view {:style {:padding 2}} left]
|
||||
[rn/view {:style {:padding 4 :flex 1}}
|
||||
[text/text
|
||||
{:size :paragraph-2 :weight :medium :style (merge-theme-style :text {})}
|
||||
middle]]
|
||||
(when right right)]])
|
||||
|
||||
(defn toast
|
||||
[{:keys [icon icon-color text action undo-duration undo-on-press]}]
|
||||
[toast-container
|
||||
{:left (when icon
|
||||
[icon/icon icon
|
||||
{:container-style {:width 20 :height 20}
|
||||
:color (or icon-color
|
||||
(get-in themes [:icon (theme/get-theme) :color]))}])
|
||||
:middle text
|
||||
:right (if undo-duration
|
||||
[toast-undo-action undo-duration undo-on-press]
|
||||
action)}])
|
||||
@@ -1,31 +1,18 @@
|
||||
(ns quo2.components.reactions.reaction
|
||||
(:require [quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as quo2.text]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.reactions.style :as style]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(def reaction-styling
|
||||
{:flex-direction :row
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:padding-horizontal 8
|
||||
:border-radius 8
|
||||
:height 24})
|
||||
|
||||
(defn open-reactions-menu
|
||||
(defn add-reaction
|
||||
[{:keys [on-press]}]
|
||||
(let [dark? (theme/dark?)]
|
||||
[rn/touchable-opacity
|
||||
{:on-press on-press
|
||||
:accessibility-label :emoji-reaction-add
|
||||
:style (merge reaction-styling
|
||||
{:padding-horizontal 9
|
||||
:border-width 1
|
||||
:margin-top 5
|
||||
:border-color (if dark?
|
||||
colors/neutral-70
|
||||
colors/neutral-30)})}
|
||||
:style (style/add-reaction)}
|
||||
[icons/icon :i/add
|
||||
{:size 20
|
||||
:color (if dark?
|
||||
@@ -35,41 +22,19 @@
|
||||
(defn reaction
|
||||
"Add your emoji as a param here"
|
||||
[{:keys [emoji clicks neutral? on-press accessibility-label]}]
|
||||
(let [dark? (theme/dark?)
|
||||
text-color (if dark?
|
||||
colors/white
|
||||
colors/neutral-100)
|
||||
numeric-value (int clicks)
|
||||
clicks-positive? (pos? numeric-value)]
|
||||
(let [numeric-value (int clicks)]
|
||||
[rn/touchable-opacity
|
||||
{:on-press on-press
|
||||
:accessibility-label accessibility-label
|
||||
:style (merge reaction-styling
|
||||
(cond->
|
||||
{:background-color
|
||||
(if dark?
|
||||
(if neutral?
|
||||
colors/neutral-70
|
||||
:transparent)
|
||||
(if neutral?
|
||||
colors/neutral-30
|
||||
:transparent))}
|
||||
(and dark? (not neutral?))
|
||||
(assoc :border-color colors/neutral-70
|
||||
:border-width 1)
|
||||
(and (not dark?) (not neutral?))
|
||||
(assoc :border-color colors/neutral-30
|
||||
:border-width 1)))}
|
||||
:style (style/reaction neutral?)}
|
||||
[icons/icon emoji
|
||||
{:no-color true
|
||||
:size 16}]
|
||||
[quo2.text/text
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :semi-bold
|
||||
:color text-color
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
(if clicks-positive?
|
||||
(str " " numeric-value)
|
||||
"")]]))
|
||||
(when (pos? numeric-value)
|
||||
(str " " numeric-value))]]))
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
(ns quo2.components.reactions.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def reaction-styling
|
||||
{:flex-direction :row
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:padding-horizontal 8
|
||||
:border-radius 8
|
||||
:height 24})
|
||||
|
||||
(defn add-reaction
|
||||
[]
|
||||
(merge reaction-styling
|
||||
{:padding-horizontal 9
|
||||
:border-width 1
|
||||
:border-color (colors/theme-colors colors/neutral-30 colors/neutral-70)}))
|
||||
|
||||
(defn reaction
|
||||
[neutral?]
|
||||
(merge reaction-styling
|
||||
(cond->
|
||||
{:background-color (colors/theme-colors (if neutral?
|
||||
colors/neutral-30
|
||||
:transparent)
|
||||
(if neutral?
|
||||
colors/neutral-70
|
||||
:transparent))}
|
||||
(and (colors/dark?) (not neutral?))
|
||||
(assoc :border-color colors/neutral-70
|
||||
:border-width 1)
|
||||
(and (not (colors/dark?)) (not neutral?))
|
||||
(assoc :border-color colors/neutral-30
|
||||
:border-width 1))))
|
||||
@@ -0,0 +1,228 @@
|
||||
(ns quo2.components.record-audio.record-audio.style
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[react-native.reanimated :as reanimated]))
|
||||
|
||||
(defn animated-circle
|
||||
[scale opacity color]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:transform [{:scale scale}]
|
||||
:opacity opacity}
|
||||
{:width 56
|
||||
:height 56
|
||||
:border-width 1
|
||||
:border-color color
|
||||
:border-radius 28
|
||||
:position :absolute
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:z-index 0}))
|
||||
|
||||
(defn record-button-big-container
|
||||
[translate-x translate-y opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:transform [{:translateY translate-y}
|
||||
{:translateX translate-x}]
|
||||
:opacity opacity}
|
||||
{:position :absolute
|
||||
:bottom 0
|
||||
:right 0
|
||||
:width 96
|
||||
:height 96
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:z-index 0}))
|
||||
|
||||
(defn record-button-big-body
|
||||
[button-color]
|
||||
{:width 56
|
||||
:height 56
|
||||
:border-radius 28
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color button-color
|
||||
:overflow :hidden})
|
||||
|
||||
(defn record-button-big-red-overlay
|
||||
[red-overlay-opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity red-overlay-opacity}
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 0
|
||||
:background-color colors/danger-50}))
|
||||
|
||||
(defn record-button-big-gray-overlay
|
||||
[gray-overlay-opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity gray-overlay-opacity}
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 0
|
||||
:background-color (colors/theme-colors colors/neutral-80-opa-5-opaque colors/neutral-80)}))
|
||||
|
||||
(defn record-button-big-icon-container
|
||||
[icon-opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity icon-opacity}
|
||||
{}))
|
||||
|
||||
(def stop-icon
|
||||
{:width 13
|
||||
:height 13
|
||||
:border-radius 4
|
||||
:background-color colors/white})
|
||||
|
||||
(defn send-button-container
|
||||
[opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity opacity}
|
||||
{:justify-content :center
|
||||
:align-items :center
|
||||
:position :absolute
|
||||
:width 56
|
||||
:height 56
|
||||
:top 0
|
||||
:right 20}))
|
||||
|
||||
(defn send-button-connector
|
||||
[opacity width height border-radius-first-half border-radius-second-half]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity opacity
|
||||
:width width
|
||||
:height height
|
||||
:border-bottom-left-radius border-radius-second-half
|
||||
:border-top-left-radius border-radius-first-half
|
||||
:border-top-right-radius border-radius-first-half
|
||||
:border-bottom-right-radius border-radius-second-half}
|
||||
{:justify-content :center
|
||||
:align-items :center
|
||||
:align-self :center
|
||||
:background-color colors/primary-50
|
||||
:z-index 0}))
|
||||
|
||||
(defn send-button
|
||||
[translate-y opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:transform [{:translateY translate-y}]
|
||||
:opacity opacity}
|
||||
{:justify-content :center
|
||||
:align-items :center
|
||||
:background-color colors/primary-50
|
||||
:width 32
|
||||
:height 32
|
||||
:border-radius 16
|
||||
:position :absolute
|
||||
:top 0
|
||||
:right 32
|
||||
:z-index 10}))
|
||||
|
||||
(def send-icon-container
|
||||
{:z-index 10})
|
||||
|
||||
(defn lock-button-container
|
||||
[opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity opacity}
|
||||
{:transform [{:rotate "45deg"}]
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:position :absolute
|
||||
:width 56
|
||||
:height 56
|
||||
:top 20
|
||||
:left 20}))
|
||||
|
||||
(defn lock-button-connector
|
||||
[opacity width height border-radius-first-half border-radius-second-half]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity opacity
|
||||
:width width
|
||||
:height height
|
||||
:border-bottom-left-radius border-radius-first-half
|
||||
:border-top-left-radius border-radius-first-half
|
||||
:border-top-right-radius border-radius-second-half
|
||||
:border-bottom-right-radius border-radius-second-half}
|
||||
{:justify-content :center
|
||||
:align-items :center
|
||||
:align-self :center
|
||||
:background-color (colors/theme-colors colors/neutral-80-opa-5-opaque colors/neutral-80)
|
||||
:overflow :hidden}))
|
||||
|
||||
(defn lock-button
|
||||
[translate-x-y opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:transform [{:translateX translate-x-y}
|
||||
{:translateY translate-x-y}]
|
||||
:opacity opacity}
|
||||
{:width 32
|
||||
:height 32
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color (colors/theme-colors colors/neutral-80-opa-5-opaque colors/neutral-80)
|
||||
:border-radius 16
|
||||
:position :absolute
|
||||
:top 24
|
||||
:left 24
|
||||
:overflow :hidden
|
||||
:z-index 12}))
|
||||
|
||||
(defn delete-button-container
|
||||
[opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity opacity}
|
||||
{:justify-content :center
|
||||
:align-items :center
|
||||
:position :absolute
|
||||
:width 56
|
||||
:height 56
|
||||
:bottom 20
|
||||
:left 0}))
|
||||
|
||||
(defn delete-button-connector
|
||||
[opacity width height border-radius-first-half border-radius-second-half]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity opacity
|
||||
:width width
|
||||
:height height
|
||||
:border-bottom-left-radius border-radius-first-half
|
||||
:border-top-left-radius border-radius-first-half
|
||||
:border-top-right-radius border-radius-second-half
|
||||
:border-bottom-right-radius border-radius-second-half}
|
||||
{:justify-content :center
|
||||
:align-items :center
|
||||
:align-self :center
|
||||
:background-color colors/danger-50
|
||||
:z-index 0}))
|
||||
|
||||
(defn delete-button
|
||||
[translate-x opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:transform [{:translateX translate-x}]
|
||||
:opacity opacity}
|
||||
{:width 32
|
||||
:height 32
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color colors/danger-50
|
||||
:border-radius 16
|
||||
:position :absolute
|
||||
:top 76
|
||||
:left 0
|
||||
:z-index 11}))
|
||||
|
||||
(defn record-button-container
|
||||
[opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity opacity}
|
||||
{:margin-bottom 32
|
||||
:margin-right 32}))
|
||||
|
||||
(def input-container
|
||||
{:width 140
|
||||
:height 140
|
||||
:align-items :flex-end
|
||||
:justify-content :flex-end})
|
||||
@@ -0,0 +1,767 @@
|
||||
(ns quo2.components.record-audio.record-audio.view
|
||||
(:require [cljs-bean.core :as bean]
|
||||
[oops.core :as oops]
|
||||
[quo.react :refer [effect! memo]]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.record-audio.record-audio.style :as style]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.utils.utils :as utils]))
|
||||
|
||||
(def ^:private scale-to-each 1.8)
|
||||
(def ^:private scale-to-total 2.6)
|
||||
(def ^:private scale-padding 0.16)
|
||||
(def ^:private opacity-from-lock 1)
|
||||
(def ^:private opacity-from-default 0.5)
|
||||
(def ^:private signal-anim-duration 3900)
|
||||
(def ^:private signal-anim-duration-2 1950)
|
||||
|
||||
(def ^:private animated-ring
|
||||
(reagent/adapt-react-class
|
||||
(memo
|
||||
(fn [props]
|
||||
(let [{:keys [scale opacity color]} (bean/bean props)]
|
||||
(reagent/as-element
|
||||
[reanimated/view {:style (style/animated-circle scale opacity color)}]))))))
|
||||
|
||||
(def ^:private record-button-area-big
|
||||
{:width 56
|
||||
:height 56
|
||||
:x 64
|
||||
:y 64})
|
||||
|
||||
(def ^:private record-button-area
|
||||
{:width 48
|
||||
:height 48
|
||||
:x 68
|
||||
:y 68})
|
||||
|
||||
(defn- delete-button-area
|
||||
[active?]
|
||||
{:width (if active? 72 82)
|
||||
:height 56
|
||||
:x (if active? -16 -32)
|
||||
:y (if active? 64 70)})
|
||||
|
||||
(defn- lock-button-area
|
||||
[active?]
|
||||
{:width (if active? 72 100)
|
||||
:height (if active? 72 102)
|
||||
:x -32
|
||||
:y -32})
|
||||
|
||||
(defn- send-button-area
|
||||
[active?]
|
||||
{:width 56
|
||||
:height (if active? 72 92)
|
||||
:x 68
|
||||
:y (if active? -16 -32)})
|
||||
|
||||
(defn- touch-inside-area?
|
||||
[{:keys [location-x location-y ignore-min-y? ignore-max-y? ignore-min-x? ignore-max-x?]}
|
||||
{:keys [width height x y]}]
|
||||
(let [max-x (+ x width)
|
||||
max-y (+ y height)]
|
||||
(and
|
||||
(and
|
||||
(or ignore-min-x? (>= location-x x))
|
||||
(or ignore-max-x? (<= location-x max-x)))
|
||||
(and
|
||||
(or ignore-min-y? (>= location-y y))
|
||||
(or ignore-max-y? (<= location-y max-y))))))
|
||||
|
||||
(def record-audio-worklets (js/require "../src/js/record_audio_worklets.js"))
|
||||
|
||||
(defn- ring-scale
|
||||
[scale substract]
|
||||
(.ringScale ^js record-audio-worklets
|
||||
scale
|
||||
substract))
|
||||
|
||||
(defn- record-button-big
|
||||
[recording? ready-to-send? ready-to-lock? ready-to-delete? record-button-is-animating?
|
||||
record-button-at-initial-position? locked? reviewing-audio? recording-timer recording-length-ms
|
||||
clear-timeout touch-active?]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [scale (reanimated/use-shared-value 1)
|
||||
opacity (reanimated/use-shared-value 0)
|
||||
opacity-from (if @ready-to-lock? opacity-from-lock opacity-from-default)
|
||||
animations (map
|
||||
(fn [index]
|
||||
(let [ring-scale (ring-scale scale (* scale-padding index))]
|
||||
{:scale ring-scale
|
||||
:opacity (reanimated/interpolate ring-scale
|
||||
[1 scale-to-each]
|
||||
[opacity-from 0])}))
|
||||
(range 0 5))
|
||||
rings-color (cond
|
||||
@ready-to-lock? (colors/theme-colors colors/neutral-80-opa-5-opaque
|
||||
colors/neutral-80)
|
||||
@ready-to-delete? colors/danger-50
|
||||
:else colors/primary-50)
|
||||
translate-y (reanimated/use-shared-value 0)
|
||||
translate-x (reanimated/use-shared-value 0)
|
||||
button-color colors/primary-50
|
||||
icon-color (if (and (not (colors/dark?)) @ready-to-lock?) colors/black colors/white)
|
||||
icon-opacity (reanimated/use-shared-value 1)
|
||||
red-overlay-opacity (reanimated/use-shared-value 0)
|
||||
gray-overlay-opacity (reanimated/use-shared-value 0)
|
||||
complete-animation (fn []
|
||||
(cond
|
||||
(and @ready-to-lock? (not @record-button-is-animating?))
|
||||
(do
|
||||
(reset! locked? true)
|
||||
(reset! ready-to-lock? false))
|
||||
(and (not @locked?) (not @reviewing-audio?))
|
||||
(do
|
||||
(reset! recording? false)
|
||||
(reset! ready-to-send? false)
|
||||
(reset! ready-to-delete? false)
|
||||
(reset! ready-to-lock? false)
|
||||
(utils/clear-interval @recording-timer)
|
||||
(reset! recording-length-ms 0))))
|
||||
start-animation (fn []
|
||||
(reanimated/set-shared-value opacity 1)
|
||||
(reanimated/animate-shared-value-with-timing scale
|
||||
2.6
|
||||
signal-anim-duration
|
||||
:linear)
|
||||
;; TODO: Research if we can implement this with withSequence method
|
||||
;; from Reanimated 2
|
||||
;; GitHub issue [#14561]:
|
||||
;; https://github.com/status-im/status-mobile/issues/14561
|
||||
(reset! clear-timeout
|
||||
(utils/set-timeout
|
||||
#(do (reanimated/set-shared-value scale scale-to-each)
|
||||
(reanimated/animate-shared-value-with-delay-repeat
|
||||
scale
|
||||
scale-to-total
|
||||
signal-anim-duration-2
|
||||
:linear
|
||||
0
|
||||
-1))
|
||||
signal-anim-duration)))
|
||||
stop-animation (fn []
|
||||
(reanimated/set-shared-value opacity 0)
|
||||
(reanimated/cancel-animation scale)
|
||||
(reanimated/set-shared-value scale 1)
|
||||
(when @clear-timeout (utils/clear-timeout @clear-timeout)))
|
||||
start-y-animation (fn []
|
||||
(reset! record-button-at-initial-position? false)
|
||||
(reset! record-button-is-animating? true)
|
||||
(reanimated/animate-shared-value-with-timing translate-y
|
||||
-64
|
||||
250
|
||||
:easing1)
|
||||
(reanimated/animate-shared-value-with-delay icon-opacity
|
||||
0 33.33
|
||||
:linear 76.66)
|
||||
(utils/set-timeout (fn []
|
||||
(reset! record-button-is-animating? false)
|
||||
(when-not @touch-active? (complete-animation)))
|
||||
250))
|
||||
reset-y-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-y
|
||||
0
|
||||
300
|
||||
:easing1)
|
||||
(reanimated/animate-shared-value-with-timing icon-opacity
|
||||
1
|
||||
500
|
||||
:linear)
|
||||
(utils/set-timeout (fn []
|
||||
(reset! record-button-at-initial-position? true))
|
||||
500))
|
||||
start-x-animation (fn []
|
||||
(reset! record-button-at-initial-position? false)
|
||||
(reset! record-button-is-animating? true)
|
||||
(reanimated/animate-shared-value-with-timing translate-x
|
||||
-64
|
||||
250
|
||||
:easing1)
|
||||
(reanimated/animate-shared-value-with-delay icon-opacity
|
||||
0 33.33
|
||||
:linear 76.66)
|
||||
(reanimated/animate-shared-value-with-timing red-overlay-opacity
|
||||
1
|
||||
33.33
|
||||
:linear)
|
||||
(utils/set-timeout (fn []
|
||||
(reset! record-button-is-animating? false)
|
||||
(when-not @touch-active? (complete-animation)))
|
||||
250))
|
||||
reset-x-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-x
|
||||
0
|
||||
300
|
||||
:easing1)
|
||||
(reanimated/animate-shared-value-with-timing icon-opacity
|
||||
1
|
||||
500
|
||||
:linear)
|
||||
(reanimated/animate-shared-value-with-timing red-overlay-opacity
|
||||
0
|
||||
100
|
||||
:linear)
|
||||
(utils/set-timeout (fn []
|
||||
(reset! record-button-at-initial-position? true))
|
||||
500))
|
||||
start-x-y-animation (fn []
|
||||
(reset! record-button-at-initial-position? false)
|
||||
(reset! record-button-is-animating? true)
|
||||
(reanimated/animate-shared-value-with-timing translate-y
|
||||
-44
|
||||
200
|
||||
:easing1)
|
||||
(reanimated/animate-shared-value-with-timing translate-x
|
||||
-44
|
||||
200
|
||||
:easing1)
|
||||
(reanimated/animate-shared-value-with-delay icon-opacity
|
||||
0 33.33
|
||||
:linear 33.33)
|
||||
(reanimated/animate-shared-value-with-timing gray-overlay-opacity
|
||||
1
|
||||
33.33
|
||||
:linear)
|
||||
(utils/set-timeout (fn []
|
||||
(reset! record-button-is-animating? false)
|
||||
(when-not @touch-active? (complete-animation)))
|
||||
200))
|
||||
reset-x-y-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-y
|
||||
0
|
||||
300
|
||||
:easing1)
|
||||
(reanimated/animate-shared-value-with-timing translate-x
|
||||
0
|
||||
300
|
||||
:easing1)
|
||||
(reanimated/animate-shared-value-with-timing icon-opacity
|
||||
1
|
||||
500
|
||||
:linear)
|
||||
(reanimated/animate-shared-value-with-timing gray-overlay-opacity
|
||||
0
|
||||
800
|
||||
:linear)
|
||||
(utils/set-timeout (fn []
|
||||
(reset! record-button-at-initial-position? true))
|
||||
800))]
|
||||
(effect! #(cond
|
||||
@recording?
|
||||
(start-animation)
|
||||
(not @ready-to-lock?)
|
||||
(stop-animation))
|
||||
[@recording?])
|
||||
(effect! #(if @ready-to-lock?
|
||||
(start-x-y-animation)
|
||||
(reset-x-y-animation))
|
||||
[@ready-to-lock?])
|
||||
(effect! #(if @ready-to-send?
|
||||
(start-y-animation)
|
||||
(reset-y-animation))
|
||||
[@ready-to-send?])
|
||||
(effect! #(if @ready-to-delete?
|
||||
(start-x-animation)
|
||||
(reset-x-animation))
|
||||
[@ready-to-delete?])
|
||||
[reanimated/view
|
||||
{:style (style/record-button-big-container translate-x translate-y opacity)
|
||||
:pointer-events :none}
|
||||
[:<>
|
||||
(map-indexed
|
||||
(fn [id animation]
|
||||
^{:key id}
|
||||
[animated-ring
|
||||
{:scale (:scale animation)
|
||||
:opacity (:opacity animation)
|
||||
:color rings-color}])
|
||||
animations)]
|
||||
[rn/view {:style (style/record-button-big-body button-color)}
|
||||
[reanimated/view {:style (style/record-button-big-red-overlay red-overlay-opacity)}]
|
||||
[reanimated/view {:style (style/record-button-big-gray-overlay gray-overlay-opacity)}]
|
||||
[reanimated/view {:style (style/record-button-big-icon-container icon-opacity)}
|
||||
(if @locked?
|
||||
[rn/view {:style style/stop-icon}]
|
||||
[icons/icon :i/audio {:color icon-color}])]]]))])
|
||||
|
||||
(defn- send-button
|
||||
[recording? ready-to-send? reviewing-audio?]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [opacity (reanimated/use-shared-value 0)
|
||||
translate-y (reanimated/use-shared-value 20)
|
||||
connector-opacity (reanimated/use-shared-value 0)
|
||||
width (reanimated/use-shared-value 12)
|
||||
height (reanimated/use-shared-value 24)
|
||||
border-radius-first-half (reanimated/use-shared-value 16)
|
||||
border-radius-second-half (reanimated/use-shared-value 8)
|
||||
start-y-animation (fn []
|
||||
(reanimated/animate-shared-value-with-delay translate-y
|
||||
12 50
|
||||
:linear 133.33)
|
||||
(reanimated/animate-shared-value-with-delay connector-opacity
|
||||
1 0
|
||||
:easing1 93.33)
|
||||
(reanimated/animate-shared-value-with-delay width
|
||||
56 83.33
|
||||
:easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay height
|
||||
56 83.33
|
||||
:easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay
|
||||
border-radius-first-half
|
||||
28 83.33
|
||||
:easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay
|
||||
border-radius-second-half
|
||||
28 83.33
|
||||
:easing1 80))
|
||||
reset-y-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-y
|
||||
0
|
||||
100
|
||||
:linear)
|
||||
(reanimated/set-shared-value connector-opacity 0)
|
||||
(reanimated/set-shared-value width 12)
|
||||
(reanimated/set-shared-value height 24)
|
||||
(reanimated/set-shared-value border-radius-first-half 16)
|
||||
(reanimated/set-shared-value border-radius-second-half 8))
|
||||
fade-in-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-y
|
||||
0
|
||||
200
|
||||
:linear)
|
||||
(reanimated/animate-shared-value-with-timing opacity
|
||||
1
|
||||
200
|
||||
:linear))
|
||||
fade-out-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-y
|
||||
(if @reviewing-audio?
|
||||
76
|
||||
20)
|
||||
200
|
||||
:linear)
|
||||
(when-not @reviewing-audio?
|
||||
(reanimated/animate-shared-value-with-timing opacity
|
||||
0
|
||||
200
|
||||
:linear))
|
||||
(reanimated/set-shared-value connector-opacity 0)
|
||||
(reanimated/set-shared-value width 24)
|
||||
(reanimated/set-shared-value height 12)
|
||||
(reanimated/set-shared-value border-radius-first-half 8)
|
||||
(reanimated/set-shared-value border-radius-second-half 16))
|
||||
fade-out-reset-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing opacity
|
||||
0
|
||||
200
|
||||
:linear)
|
||||
(reanimated/animate-shared-value-with-delay translate-y
|
||||
20 0
|
||||
:linear 200)
|
||||
(reanimated/set-shared-value connector-opacity 0)
|
||||
(reanimated/set-shared-value width 24)
|
||||
(reanimated/set-shared-value height 12)
|
||||
(reanimated/set-shared-value border-radius-first-half 8)
|
||||
(reanimated/set-shared-value border-radius-second-half 16))]
|
||||
(effect! #(if @recording?
|
||||
(fade-in-animation)
|
||||
(fade-out-animation))
|
||||
[@recording?])
|
||||
(effect! #(when-not @reviewing-audio?
|
||||
(fade-out-reset-animation))
|
||||
[@reviewing-audio?])
|
||||
(effect! #(cond
|
||||
@ready-to-send?
|
||||
(start-y-animation)
|
||||
@recording? (reset-y-animation))
|
||||
[@ready-to-send?])
|
||||
[:<>
|
||||
[reanimated/view {:style (style/send-button-container opacity)}
|
||||
[reanimated/view
|
||||
{:style (style/send-button-connector connector-opacity
|
||||
width
|
||||
height
|
||||
border-radius-first-half
|
||||
border-radius-second-half)}]]
|
||||
[reanimated/view
|
||||
{:style (style/send-button translate-y opacity)
|
||||
:pointer-events :none}
|
||||
[icons/icon :i/arrow-up
|
||||
{:color colors/white
|
||||
:size 20
|
||||
:container-style style/send-icon-container}]]]))])
|
||||
|
||||
(defn- lock-button
|
||||
[recording? ready-to-lock? locked?]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [translate-x-y (reanimated/use-shared-value 20)
|
||||
opacity (reanimated/use-shared-value 0)
|
||||
connector-opacity (reanimated/use-shared-value 0)
|
||||
width (reanimated/use-shared-value 24)
|
||||
height (reanimated/use-shared-value 12)
|
||||
border-radius-first-half (reanimated/use-shared-value 8)
|
||||
border-radius-second-half (reanimated/use-shared-value 8)
|
||||
start-x-y-animation (fn []
|
||||
(reanimated/animate-shared-value-with-delay translate-x-y
|
||||
8 50
|
||||
:linear 116.66)
|
||||
(reanimated/animate-shared-value-with-delay connector-opacity
|
||||
1 0
|
||||
:easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay width
|
||||
56 83.33
|
||||
:easing1 63.33)
|
||||
(reanimated/animate-shared-value-with-delay height
|
||||
56 83.33
|
||||
:easing1 63.33)
|
||||
(reanimated/animate-shared-value-with-delay
|
||||
border-radius-first-half
|
||||
28 83.33
|
||||
:easing1 63.33)
|
||||
(reanimated/animate-shared-value-with-delay
|
||||
border-radius-second-half
|
||||
28 83.33
|
||||
:easing1 63.33))
|
||||
reset-x-y-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-x-y
|
||||
0
|
||||
100
|
||||
:linear)
|
||||
(reanimated/set-shared-value connector-opacity 0)
|
||||
(reanimated/set-shared-value width 24)
|
||||
(reanimated/set-shared-value height 12)
|
||||
(reanimated/set-shared-value border-radius-first-half 8)
|
||||
(reanimated/set-shared-value border-radius-second-half 16))
|
||||
fade-in-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-x-y
|
||||
0
|
||||
220
|
||||
:linear)
|
||||
(reanimated/animate-shared-value-with-timing opacity
|
||||
1
|
||||
220
|
||||
:linear))
|
||||
fade-out-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-x-y
|
||||
20
|
||||
200
|
||||
:linear)
|
||||
(reanimated/animate-shared-value-with-timing opacity
|
||||
0
|
||||
200
|
||||
:linear)
|
||||
(reanimated/set-shared-value connector-opacity 0)
|
||||
(reanimated/set-shared-value width 24)
|
||||
(reanimated/set-shared-value height 12)
|
||||
(reanimated/set-shared-value border-radius-first-half 8)
|
||||
(reanimated/set-shared-value border-radius-second-half 16))]
|
||||
(effect! #(if @recording?
|
||||
(fade-in-animation)
|
||||
(fade-out-animation))
|
||||
[@recording?])
|
||||
(effect! #(cond
|
||||
@ready-to-lock?
|
||||
(start-x-y-animation)
|
||||
(and @recording? (not @locked?))
|
||||
(reset-x-y-animation))
|
||||
[@ready-to-lock?])
|
||||
(effect! #(if @locked?
|
||||
(fade-out-animation)
|
||||
(reset-x-y-animation))
|
||||
[@locked?])
|
||||
[:<>
|
||||
[reanimated/view {:style (style/lock-button-container opacity)}
|
||||
[reanimated/view
|
||||
{:style (style/lock-button-connector connector-opacity
|
||||
width
|
||||
height
|
||||
border-radius-first-half
|
||||
border-radius-second-half)}]]
|
||||
[reanimated/view
|
||||
{:style (style/lock-button translate-x-y opacity)
|
||||
:pointer-events :none}
|
||||
[icons/icon (if @ready-to-lock? :i/locked :i/unlocked)
|
||||
{:color (colors/theme-colors colors/black colors/white)
|
||||
:size 20}]]]))])
|
||||
|
||||
(defn- delete-button
|
||||
[recording? ready-to-delete?]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [opacity (reanimated/use-shared-value 0)
|
||||
translate-x (reanimated/use-shared-value 20)
|
||||
connector-opacity (reanimated/use-shared-value 0)
|
||||
width (reanimated/use-shared-value 24)
|
||||
height (reanimated/use-shared-value 12)
|
||||
border-radius-first-half (reanimated/use-shared-value 8)
|
||||
border-radius-second-half (reanimated/use-shared-value 8)
|
||||
start-x-animation (fn []
|
||||
(reanimated/animate-shared-value-with-delay translate-x
|
||||
12 50
|
||||
:linear 133.33)
|
||||
(reanimated/animate-shared-value-with-delay connector-opacity
|
||||
1 0
|
||||
:easing1 93.33)
|
||||
(reanimated/animate-shared-value-with-delay width
|
||||
56 83.33
|
||||
:easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay height
|
||||
56 83.33
|
||||
:easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay
|
||||
border-radius-first-half
|
||||
28 83.33
|
||||
:easing1 80)
|
||||
(reanimated/animate-shared-value-with-delay
|
||||
border-radius-second-half
|
||||
28 83.33
|
||||
:easing1 80))
|
||||
reset-x-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-x
|
||||
0
|
||||
100
|
||||
:linear)
|
||||
(reanimated/set-shared-value connector-opacity 0)
|
||||
(reanimated/set-shared-value width 24)
|
||||
(reanimated/set-shared-value height 12)
|
||||
(reanimated/set-shared-value border-radius-first-half 8)
|
||||
(reanimated/set-shared-value border-radius-second-half 16))
|
||||
fade-in-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-x
|
||||
0
|
||||
200
|
||||
:linear)
|
||||
(reanimated/animate-shared-value-with-timing opacity
|
||||
1
|
||||
200
|
||||
:linear))
|
||||
fade-out-animation (fn []
|
||||
(reanimated/animate-shared-value-with-timing translate-x
|
||||
20
|
||||
200
|
||||
:linear)
|
||||
(reanimated/animate-shared-value-with-timing opacity
|
||||
0
|
||||
200
|
||||
:linear)
|
||||
(reanimated/set-shared-value connector-opacity 0)
|
||||
(reanimated/set-shared-value width 24)
|
||||
(reanimated/set-shared-value height 12)
|
||||
(reanimated/set-shared-value border-radius-first-half 8)
|
||||
(reanimated/set-shared-value border-radius-second-half 16))]
|
||||
(effect! #(if @recording?
|
||||
(fade-in-animation)
|
||||
(fade-out-animation))
|
||||
[@recording?])
|
||||
(effect! #(cond
|
||||
@ready-to-delete?
|
||||
(start-x-animation)
|
||||
@recording?
|
||||
(reset-x-animation))
|
||||
[@ready-to-delete?])
|
||||
[:<>
|
||||
[reanimated/view {:style (style/delete-button-container opacity)}
|
||||
[reanimated/view
|
||||
{:style (style/delete-button-connector connector-opacity
|
||||
width
|
||||
height
|
||||
border-radius-first-half
|
||||
border-radius-second-half)}]]
|
||||
[reanimated/view
|
||||
{:style (style/delete-button translate-x opacity)
|
||||
:pointer-events :none}
|
||||
[icons/icon :i/delete
|
||||
{:color colors/white
|
||||
:size 20}]]]))])
|
||||
|
||||
(defn- record-button
|
||||
[recording? reviewing-audio?]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [opacity (reanimated/use-shared-value 1)
|
||||
show-animation #(reanimated/set-shared-value opacity 1)
|
||||
hide-animation #(reanimated/set-shared-value opacity 0)]
|
||||
(effect! #(if (or @recording? @reviewing-audio?)
|
||||
(hide-animation)
|
||||
(show-animation))
|
||||
[@recording? @reviewing-audio?])
|
||||
[reanimated/view {:style (style/record-button-container opacity)}
|
||||
[button/button
|
||||
{:type :outline
|
||||
:size 32
|
||||
:width 32
|
||||
:accessibility-label :mic-button}
|
||||
[icons/icon :i/audio {:color (colors/theme-colors colors/neutral-100 colors/white)}]]]))])
|
||||
|
||||
(defn input-view
|
||||
[]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [recording? (reagent/atom false)
|
||||
locked? (reagent/atom false)
|
||||
ready-to-send? (reagent/atom false)
|
||||
ready-to-lock? (reagent/atom false)
|
||||
ready-to-delete? (reagent/atom false)
|
||||
reviewing-audio? (reagent/atom false)
|
||||
clear-timeout (atom nil)
|
||||
record-button-at-initial-position? (atom true)
|
||||
record-button-is-animating? (atom false)
|
||||
touch-active? (atom false)
|
||||
recording-timer (atom nil)
|
||||
recording-length-ms (atom 0)
|
||||
on-start-should-set-responder
|
||||
(fn [^js e]
|
||||
(when-not @locked?
|
||||
(let [pressed-record-button? (touch-inside-area?
|
||||
{:location-x (oops/oget e "nativeEvent.locationX")
|
||||
:location-y (oops/oget e "nativeEvent.locationY")
|
||||
:ignore-min-y? false
|
||||
:ignore-max-y? false
|
||||
:ignore-min-x? false
|
||||
:ignore-max-x? false}
|
||||
record-button-area)]
|
||||
(when-not @reviewing-audio?
|
||||
(reset! recording? pressed-record-button?)
|
||||
(when pressed-record-button?
|
||||
;; TODO: By now we just track recording length, we need to add actual audio
|
||||
;; recording logic
|
||||
;; GitHub issue [#14558]: https://github.com/status-im/status-mobile/issues/14558
|
||||
(reset! recording-timer (utils/set-interval #(reset! recording-length-ms
|
||||
(+ @recording-length-ms 500))
|
||||
500))))
|
||||
(reset! touch-active? true)))
|
||||
true)
|
||||
on-responder-move
|
||||
(fn [^js e]
|
||||
(when-not @locked?
|
||||
(let [location-x (oops/oget e "nativeEvent.locationX")
|
||||
location-y (oops/oget e "nativeEvent.locationY")
|
||||
page-x (oops/oget e "nativeEvent.pageX")
|
||||
page-y (oops/oget e "nativeEvent.pageY")
|
||||
moved-to-send-button? (touch-inside-area?
|
||||
{:location-x location-x
|
||||
:location-y location-y
|
||||
:ignore-min-y? true
|
||||
:ignore-max-y? false
|
||||
:ignore-min-x? false
|
||||
:ignore-max-x? true}
|
||||
(send-button-area @ready-to-send?))
|
||||
moved-to-delete-button? (touch-inside-area?
|
||||
{:location-x location-x
|
||||
:location-y location-y
|
||||
:ignore-min-y? false
|
||||
:ignore-max-y? true
|
||||
:ignore-min-x? true
|
||||
:ignore-max-x? false}
|
||||
(delete-button-area @ready-to-delete?))
|
||||
moved-to-lock-button? (touch-inside-area?
|
||||
{:location-x location-x
|
||||
:location-y location-y
|
||||
:ignore-min-y? false
|
||||
:ignore-max-y? false
|
||||
:ignore-min-x? false
|
||||
:ignore-max-x? false}
|
||||
(lock-button-area @ready-to-lock?))
|
||||
moved-to-record-button? (and
|
||||
(touch-inside-area?
|
||||
{:location-x location-x
|
||||
:location-y location-y
|
||||
:ignore-min-y? false
|
||||
:ignore-max-y? false
|
||||
:ignore-min-x? false
|
||||
:ignore-max-x? false}
|
||||
record-button-area-big)
|
||||
(not= location-x page-x)
|
||||
(not= location-y page-y))]
|
||||
(cond
|
||||
(and
|
||||
(or
|
||||
(and moved-to-record-button? @ready-to-lock?)
|
||||
(and (not @locked?) moved-to-lock-button? @record-button-at-initial-position?))
|
||||
(not @ready-to-delete?)
|
||||
(not @ready-to-send?)
|
||||
@recording?)
|
||||
(reset! ready-to-lock? moved-to-lock-button?)
|
||||
(and
|
||||
(or
|
||||
(and moved-to-record-button? @ready-to-delete?)
|
||||
(and moved-to-delete-button? @record-button-at-initial-position?))
|
||||
(not @ready-to-lock?)
|
||||
(not @ready-to-send?)
|
||||
@recording?)
|
||||
(reset! ready-to-delete? moved-to-delete-button?)
|
||||
(and
|
||||
(or
|
||||
(and moved-to-record-button? @ready-to-send?)
|
||||
(and moved-to-send-button? @record-button-at-initial-position?))
|
||||
(not @ready-to-lock?)
|
||||
(not @ready-to-delete?)
|
||||
@recording?)
|
||||
(reset! ready-to-send? moved-to-send-button?)))))
|
||||
on-responder-release
|
||||
(fn [^js e]
|
||||
(let [on-record-button? (touch-inside-area?
|
||||
{:location-x (oops/oget e "nativeEvent.locationX")
|
||||
:location-y (oops/oget e "nativeEvent.locationY")
|
||||
:ignore-min-y? false
|
||||
:ignore-max-y? false
|
||||
:ignore-min-x? false
|
||||
:ignore-max-x? false}
|
||||
(if @reviewing-audio? record-button-area record-button-area-big))]
|
||||
(cond
|
||||
(and @reviewing-audio? on-record-button?)
|
||||
(reset! reviewing-audio? false)
|
||||
(and @ready-to-lock? (not @record-button-is-animating?))
|
||||
(do
|
||||
(reset! locked? true)
|
||||
(reset! ready-to-lock? false))
|
||||
(and (not @reviewing-audio?) on-record-button?)
|
||||
(do
|
||||
(when (>= @recording-length-ms 500) (reset! reviewing-audio? true))
|
||||
(reset! locked? false)
|
||||
(reset! recording? false)
|
||||
(reset! ready-to-lock? false)
|
||||
(utils/clear-interval @recording-timer)
|
||||
(reset! recording-length-ms 0))
|
||||
(and (not @locked?) (not @reviewing-audio?) (not @record-button-is-animating?))
|
||||
(do
|
||||
(reset! recording? false)
|
||||
(reset! ready-to-send? false)
|
||||
(reset! ready-to-delete? false)
|
||||
(reset! ready-to-lock? false)
|
||||
(utils/clear-interval @recording-timer)
|
||||
(reset! recording-length-ms 0))))
|
||||
(reset! touch-active? false))]
|
||||
(fn []
|
||||
[rn/view
|
||||
{:style style/input-container
|
||||
:pointer-events :box-only
|
||||
:on-start-should-set-responder on-start-should-set-responder
|
||||
:on-responder-move on-responder-move
|
||||
:on-responder-release on-responder-release}
|
||||
[delete-button recording? ready-to-delete?]
|
||||
[lock-button recording? ready-to-lock? locked?]
|
||||
[send-button recording? ready-to-send? reviewing-audio?]
|
||||
[record-button-big
|
||||
recording?
|
||||
ready-to-send?
|
||||
ready-to-lock?
|
||||
ready-to-delete?
|
||||
record-button-is-animating?
|
||||
record-button-at-initial-position?
|
||||
locked?
|
||||
reviewing-audio?
|
||||
recording-timer
|
||||
recording-length-ms
|
||||
clear-timeout
|
||||
touch-active?]
|
||||
[record-button recording? reviewing-audio?]])))])
|
||||
@@ -28,57 +28,57 @@
|
||||
(rtl/render (reagent/as-element [selectors/radio opts]))))
|
||||
|
||||
(js/global.test "default render of toggle component"
|
||||
(fn []
|
||||
(render-toggle)
|
||||
(-> (js/expect (rtl/screen.getByTestId "toggle-component"))
|
||||
(.toBeTruthy))))
|
||||
(fn []
|
||||
(render-toggle)
|
||||
(-> (js/expect (rtl/screen.getByTestId "toggle-component"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "toggle component on change is working"
|
||||
(let [mock-fn (js/jest.fn)]
|
||||
(fn []
|
||||
(render-toggle {:on-change mock-fn})
|
||||
(rtl/fireEvent.press (rtl/screen.getByTestId "toggle-component"))
|
||||
(-> (js/expect mock-fn)
|
||||
(.toHaveBeenCalledTimes 1)))))
|
||||
(let [mock-fn (js/jest.fn)]
|
||||
(fn []
|
||||
(render-toggle {:on-change mock-fn})
|
||||
(rtl/fireEvent.press (rtl/screen.getByTestId "toggle-component"))
|
||||
(-> (js/expect mock-fn)
|
||||
(.toHaveBeenCalledTimes 1)))))
|
||||
|
||||
(js/global.test "default render of radio component"
|
||||
(fn []
|
||||
(render-radio)
|
||||
(-> (js/expect (rtl/screen.getByTestId "radio-component"))
|
||||
(.toBeTruthy))))
|
||||
(fn []
|
||||
(render-radio)
|
||||
(-> (js/expect (rtl/screen.getByTestId "radio-component"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "radio component on change is working"
|
||||
(let [mock-fn (js/jest.fn)]
|
||||
(fn []
|
||||
(render-radio {:on-change mock-fn})
|
||||
(rtl/fireEvent.press (rtl/screen.getByTestId "radio-component"))
|
||||
(-> (js/expect mock-fn)
|
||||
(.toHaveBeenCalledTimes 1)))))
|
||||
(let [mock-fn (js/jest.fn)]
|
||||
(fn []
|
||||
(render-radio {:on-change mock-fn})
|
||||
(rtl/fireEvent.press (rtl/screen.getByTestId "radio-component"))
|
||||
(-> (js/expect mock-fn)
|
||||
(.toHaveBeenCalledTimes 1)))))
|
||||
|
||||
(js/global.test "default render of checkbox component"
|
||||
(fn []
|
||||
(render-checkbox)
|
||||
(-> (js/expect (rtl/screen.getByTestId "checkbox-component"))
|
||||
(.toBeTruthy))))
|
||||
(fn []
|
||||
(render-checkbox)
|
||||
(-> (js/expect (rtl/screen.getByTestId "checkbox-component"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "checkbox component on change is working"
|
||||
(let [mock-fn (js/jest.fn)]
|
||||
(fn []
|
||||
(render-checkbox {:on-change mock-fn})
|
||||
(rtl/fireEvent.press (rtl/screen.getByTestId "checkbox-component"))
|
||||
(-> (js/expect mock-fn)
|
||||
(.toHaveBeenCalledTimes 1)))))
|
||||
(let [mock-fn (js/jest.fn)]
|
||||
(fn []
|
||||
(render-checkbox {:on-change mock-fn})
|
||||
(rtl/fireEvent.press (rtl/screen.getByTestId "checkbox-component"))
|
||||
(-> (js/expect mock-fn)
|
||||
(.toHaveBeenCalledTimes 1)))))
|
||||
|
||||
(js/global.test "default render of checkbox-prefill component"
|
||||
(fn []
|
||||
(render-checkbox-prefill)
|
||||
(-> (js/expect (rtl/screen.getByTestId "checkbox-prefill-component"))
|
||||
(.toBeTruthy))))
|
||||
(fn []
|
||||
(render-checkbox-prefill)
|
||||
(-> (js/expect (rtl/screen.getByTestId "checkbox-prefill-component"))
|
||||
(.toBeTruthy))))
|
||||
|
||||
(js/global.test "checkbox-prefill component on change is working"
|
||||
(let [mock-fn (js/jest.fn)]
|
||||
(fn []
|
||||
(render-checkbox-prefill {:on-change mock-fn})
|
||||
(rtl/fireEvent.press (rtl/screen.getByTestId "checkbox-prefill-component"))
|
||||
(-> (js/expect mock-fn)
|
||||
(.toHaveBeenCalledTimes 1)))))
|
||||
(let [mock-fn (js/jest.fn)]
|
||||
(fn []
|
||||
(render-checkbox-prefill {:on-change mock-fn})
|
||||
(rtl/fireEvent.press (rtl/screen.getByTestId "checkbox-prefill-component"))
|
||||
(-> (js/expect mock-fn)
|
||||
(.toHaveBeenCalledTimes 1)))))
|
||||
@@ -1,32 +0,0 @@
|
||||
(ns quo2.components.selectors.disclaimer
|
||||
(:require [quo2.components.markdown.text :as text]
|
||||
[quo2.components.selectors.selectors :as selectors]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn disclaimer
|
||||
[{:keys [on-change accessibility-label container-style]} label]
|
||||
[rn/view
|
||||
{:style
|
||||
(merge
|
||||
container-style
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:background-color (colors/theme-colors
|
||||
colors/neutral-5
|
||||
colors/neutral-80-opa-40)
|
||||
:padding 11
|
||||
:align-self :stretch
|
||||
:border-radius 12
|
||||
:border-width 1
|
||||
:border-color (colors/theme-colors
|
||||
colors/neutral-20
|
||||
colors/neutral-70)})}
|
||||
[selectors/checkbox
|
||||
{:on-change on-change}]
|
||||
[text/text
|
||||
{:accessibility-label accessibility-label
|
||||
:size :paragraph-2
|
||||
:style {:margin-left 8}}
|
||||
label]])
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
(ns quo2.components.selectors.disclaimer.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(defn container
|
||||
[]
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-80-opa-40)
|
||||
:padding 11
|
||||
:align-self :stretch
|
||||
:border-radius 12
|
||||
:border-width 1
|
||||
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-70)})
|
||||
|
||||
(def text
|
||||
{:margin-left 8})
|
||||
@@ -0,0 +1,17 @@
|
||||
(ns quo2.components.selectors.disclaimer.view
|
||||
(:require [quo2.components.markdown.text :as text]
|
||||
[quo2.components.selectors.disclaimer.style :as style]
|
||||
[quo2.components.selectors.selectors :as selectors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn view
|
||||
[{:keys [on-change accessibility-label container-style]} label]
|
||||
[rn/view
|
||||
{:style (merge container-style (style/container))}
|
||||
[selectors/checkbox
|
||||
{:accessibility-label accessibility-label
|
||||
:on-change on-change}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style style/text}
|
||||
label]])
|
||||
@@ -0,0 +1,16 @@
|
||||
(ns quo2.components.selectors.filter.component-spec
|
||||
(:require [quo2.components.selectors.filter.view :as quo]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "selector filter component"
|
||||
(h/test "renders component"
|
||||
(h/render [quo/view])
|
||||
(-> (js/expect (h/get-by-label-text :selector-filter))
|
||||
(.toBeTruthy)))
|
||||
|
||||
(h/test "calls custom event handler when on-press-out is triggered"
|
||||
(let [on-press-out-mock (js/jest.fn)]
|
||||
(h/render [quo/view {:on-press-out on-press-out-mock}])
|
||||
(h/fire-event :press-out (h/get-by-label-text :selector-filter))
|
||||
(-> (js/expect on-press-out-mock)
|
||||
(.toHaveBeenCalledTimes 1)))))
|
||||
@@ -0,0 +1,60 @@
|
||||
(ns quo2.components.selectors.filter.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def container-default
|
||||
{:width 32
|
||||
:height 32
|
||||
:border-radius 10
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:padding 6})
|
||||
|
||||
(defn container-border-color
|
||||
[pressed? blur? override-theme]
|
||||
(let [dark? (= :dark override-theme)]
|
||||
(cond
|
||||
(and (not pressed?) (not dark?) (not blur?))
|
||||
colors/neutral-20
|
||||
|
||||
(and (not pressed?) dark? (not blur?))
|
||||
colors/neutral-80
|
||||
|
||||
(and pressed? (not dark?) blur?)
|
||||
colors/neutral-80-opa-20
|
||||
|
||||
(or (and pressed? (not dark?) (not blur?))
|
||||
(and (not pressed?) (not dark?) blur?))
|
||||
colors/neutral-80-opa-10
|
||||
|
||||
(or (and pressed? dark? (not blur?))
|
||||
(and (not pressed?) dark? blur?)
|
||||
(and pressed? dark? blur?))
|
||||
colors/white-opa-10
|
||||
|
||||
:else
|
||||
nil)))
|
||||
|
||||
(defn container-background-color
|
||||
[pressed? override-theme]
|
||||
(when pressed?
|
||||
(if (= :dark override-theme)
|
||||
colors/primary-60
|
||||
colors/primary-50)))
|
||||
|
||||
(defn container-outer
|
||||
[pressed? override-theme]
|
||||
(merge container-default
|
||||
{:background-color (container-background-color pressed? override-theme)}))
|
||||
|
||||
(defn container-inner
|
||||
[pressed? blur? override-theme]
|
||||
(merge container-default
|
||||
{:border-width 1
|
||||
:border-color (container-border-color pressed? blur? override-theme)}))
|
||||
|
||||
(defn icon-color
|
||||
[pressed? override-theme]
|
||||
(if (and (not pressed?)
|
||||
(= :light override-theme))
|
||||
colors/neutral-100
|
||||
colors/white))
|
||||
@@ -0,0 +1,23 @@
|
||||
(ns quo2.components.selectors.filter.view
|
||||
(:require [quo2.components.icon :as icon]
|
||||
[quo2.components.selectors.filter.style :as style]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn view
|
||||
[initial-props]
|
||||
(let [pressed? (reagent/atom (:pressed? initial-props))]
|
||||
(fn [{:keys [blur? override-theme on-press-out]
|
||||
:or {override-theme (theme/get-theme)}}]
|
||||
[rn/touchable-without-feedback
|
||||
{:accessibility-label :selector-filter
|
||||
:on-press-out (fn []
|
||||
(swap! pressed? not)
|
||||
(when on-press-out
|
||||
(on-press-out @pressed?)))}
|
||||
[rn/view {:style (style/container-outer @pressed? override-theme)}
|
||||
[rn/view {:style (style/container-inner @pressed? blur? override-theme)}
|
||||
[icon/icon :i/unread
|
||||
{:color (style/icon-color @pressed? override-theme)
|
||||
:size 20}]]]])))
|
||||
@@ -69,9 +69,10 @@
|
||||
(defn checkbox
|
||||
[{:keys [default-checked?]}]
|
||||
(let [checked? (reagent/atom (or default-checked? false))]
|
||||
(fn [{:keys [on-change disabled? blurred-background? container-style]}]
|
||||
(fn [{:keys [on-change disabled? blurred-background? container-style accessibility-label]}]
|
||||
[rn/touchable-without-feedback
|
||||
{:on-press (handle-press disabled? on-change checked?)}
|
||||
{:accessibility-label accessibility-label
|
||||
:on-press (handle-press disabled? on-change checked?)}
|
||||
[rn/view
|
||||
{:style (merge
|
||||
container-style
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
(ns quo2.components.settings.privacy-option
|
||||
(:require [quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.selectors.selectors :as selectors]
|
||||
[quo2.components.settings.style :as style]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]))
|
||||
|
||||
(defn- bullet
|
||||
[]
|
||||
[rn/view {:style style/bullet-container}
|
||||
[rn/view {:style (style/bullet)}]])
|
||||
|
||||
(defn- unordered-list
|
||||
[container-style list-items]
|
||||
[rn/view {:style (merge style/list-container container-style)}
|
||||
(for [item list-items]
|
||||
^{:key (hash item)}
|
||||
[rn/view {:style style/list-item}
|
||||
[bullet]
|
||||
[text/text {:size :paragraph-2} item]])])
|
||||
|
||||
(defn- card-footer
|
||||
[{:keys [active? label on-toggle]}]
|
||||
[rn/touchable-without-feedback
|
||||
[rn/view {:style (style/card-footer)}
|
||||
[rn/view {:style style/card-footer-label-container}
|
||||
[text/text {:size :paragraph-2} label]]
|
||||
[rn/view {:style style/card-footer-toggle-container}
|
||||
[selectors/toggle
|
||||
{:disabled? (not active?)
|
||||
:on-change on-toggle}]]]])
|
||||
|
||||
(defn- selection-indicator
|
||||
[active?]
|
||||
[rn/view {:style (style/selection-indicator-container active?)}
|
||||
[rn/view {:style (style/selection-indicator active?)}]])
|
||||
|
||||
(defn- card-header
|
||||
[{:keys [icon label active?]}]
|
||||
[rn/view {:style style/card-header-container}
|
||||
[icons/icon icon
|
||||
{:size 20
|
||||
:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]
|
||||
[rn/view {:style style/card-header-label-container}
|
||||
[text/text {:weight :semi-bold} label]]
|
||||
[selection-indicator active?]])
|
||||
|
||||
(defn card
|
||||
[{:keys [active? header footer list-items icon on-select on-toggle]
|
||||
:or {icon :i/world
|
||||
active? false}}]
|
||||
[rn/touchable-without-feedback
|
||||
{:on-press on-select
|
||||
:accessibility-label :privacy-option-card
|
||||
:testID :privacy-option-card}
|
||||
[rn/view (style/privacy-option-card active?)
|
||||
[card-header
|
||||
{:active? active?
|
||||
:icon icon
|
||||
:label header}]
|
||||
[unordered-list (when-not footer {:margin-bottom 8}) list-items]
|
||||
(when footer
|
||||
[card-footer
|
||||
{:active? active?
|
||||
:label footer
|
||||
:on-toggle on-toggle}])]])
|
||||
@@ -0,0 +1,93 @@
|
||||
(ns quo2.components.settings.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def bullet-container
|
||||
{:width 20
|
||||
:height 20
|
||||
:margin-right 8
|
||||
:align-self :flex-start})
|
||||
|
||||
(defn bullet
|
||||
[]
|
||||
{:background-color (colors/theme-colors colors/neutral-40 colors/neutral-50)
|
||||
:border-radius 100
|
||||
:width 8
|
||||
:height 8
|
||||
:position :absolute
|
||||
:left 6
|
||||
:top 6})
|
||||
|
||||
(def list-container
|
||||
{:margin-right 12})
|
||||
|
||||
(def list-item
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:padding-vertical 6
|
||||
:padding-horizontal 12})
|
||||
|
||||
(defn selection-indicator-container
|
||||
[active?]
|
||||
{:height 20
|
||||
:width 20
|
||||
:border-radius 20
|
||||
:border-width 1
|
||||
:border-color (if active?
|
||||
(colors/theme-colors colors/primary-50 colors/primary-60)
|
||||
(colors/theme-colors colors/neutral-20 colors/neutral-80))})
|
||||
|
||||
(defn selection-indicator
|
||||
[active?]
|
||||
{:margin-left :auto
|
||||
:height 14
|
||||
:width 14
|
||||
:background-color (if active?
|
||||
(colors/theme-colors colors/primary-50 colors/primary-60)
|
||||
(colors/theme-colors colors/white-opa-40 colors/neutral-80-opa-40))
|
||||
:border-radius 20
|
||||
:margin-right :auto
|
||||
:margin-top :auto
|
||||
:margin-bottom :auto})
|
||||
|
||||
(def card-footer-label-container
|
||||
{:flex 0.9
|
||||
:margin-left 16})
|
||||
|
||||
(def card-footer-toggle-container
|
||||
{:flex 0.1
|
||||
:margin-horizontal 12
|
||||
:align-self :center})
|
||||
|
||||
(defn card-footer
|
||||
[]
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:margin-horizontal 12
|
||||
:margin-top 8
|
||||
:margin-bottom 12
|
||||
:padding-vertical 12
|
||||
:border-radius 12
|
||||
:border-width 1
|
||||
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-90)
|
||||
:border-color (colors/theme-colors colors/neutral-10 colors/neutral-80)})
|
||||
|
||||
(def card-header-container
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:padding-top 12
|
||||
:padding-bottom 8
|
||||
:padding-horizontal 12})
|
||||
|
||||
(def card-header-label-container
|
||||
{:flex 1
|
||||
:margin-left 4})
|
||||
|
||||
(defn privacy-option-card
|
||||
[active?]
|
||||
{:border-radius 16
|
||||
:border-width 1
|
||||
:border-color (if active?
|
||||
(colors/theme-colors colors/primary-50 colors/primary-60)
|
||||
(colors/theme-colors colors/neutral-10 colors/neutral-80))})
|
||||
@@ -15,16 +15,17 @@
|
||||
(defn indicator
|
||||
[]
|
||||
[rn/view
|
||||
{:position :absolute
|
||||
:z-index 1
|
||||
:right -2
|
||||
:top -2
|
||||
:width 10
|
||||
:height 10
|
||||
:border-radius 5
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)}
|
||||
{:accessibility-label :notification-dot
|
||||
:style {:position :absolute
|
||||
:z-index 1
|
||||
:right -2
|
||||
:top -2
|
||||
:width 10
|
||||
:height 10
|
||||
:border-radius 5
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)}}
|
||||
[notification-dot]])
|
||||
|
||||
(defn tabs
|
||||
@@ -138,6 +139,7 @@
|
||||
:shows-horizontal-scroll-indicator false
|
||||
:data data
|
||||
:key-fn (comp str :id)
|
||||
:on-scroll-to-index-failed identity
|
||||
:on-scroll (fn [^js e]
|
||||
(when fade-end?
|
||||
(let [offset-x (oget
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns quo2.components.tags.context-tags
|
||||
(:require [quo2.components.avatars.group-avatar :as group-avatar]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as quo2.theme]
|
||||
@@ -57,20 +58,31 @@
|
||||
(trim-public-key public-key)]]))
|
||||
|
||||
(defn context-tag
|
||||
[params photo name]
|
||||
(let [text-style (params :text-style)]
|
||||
[base-tag (assoc-in params [:style :padding-left] 3)
|
||||
[rn/image
|
||||
{:style {:width 20
|
||||
:border-radius 10
|
||||
:background-color :white
|
||||
:height 20}
|
||||
:source photo}]
|
||||
[text/text
|
||||
(merge {:weight :medium
|
||||
:size :paragraph-2}
|
||||
{:style text-style})
|
||||
(str " " name)]]))
|
||||
[_ _]
|
||||
(fn [params photo name channel-name]
|
||||
(let [text-style (:text-style params)
|
||||
text-params {:weight :medium
|
||||
:size :paragraph-2
|
||||
:style (assoc text-style :justify-content :center)}
|
||||
icon-color (colors/theme-colors colors/neutral-50 colors/neutral-40)]
|
||||
[base-tag (assoc-in params [:style :padding-left] 3)
|
||||
[rn/image
|
||||
{:style {:width 20
|
||||
:border-radius 10
|
||||
:background-color :white
|
||||
:height 20}
|
||||
:source photo}]
|
||||
[rn/view
|
||||
{:style {:align-items :center
|
||||
:flex-direction :row}}
|
||||
[text/text text-params (str " " name)]
|
||||
(when channel-name
|
||||
[:<>
|
||||
[icons/icon
|
||||
:i/chevron-right
|
||||
{:color icon-color
|
||||
:size 16}]
|
||||
[text/text text-params (str "# " channel-name)]])]])))
|
||||
|
||||
(defn user-avatar-tag
|
||||
[]
|
||||
|
||||
+66
-45
@@ -1,49 +1,59 @@
|
||||
(ns quo2.core
|
||||
(:require quo2.components.avatars.account-avatar
|
||||
quo2.components.avatars.channel-avatar
|
||||
quo2.components.avatars.group-avatar
|
||||
quo2.components.avatars.icon-avatar
|
||||
quo2.components.avatars.user-avatar
|
||||
quo2.components.avatars.wallet-user-avatar
|
||||
quo2.components.buttons.button
|
||||
quo2.components.buttons.dynamic-button
|
||||
quo2.components.community.community-card-view
|
||||
quo2.components.community.community-list-view
|
||||
quo2.components.community.community-view
|
||||
quo2.components.community.discover-card
|
||||
quo2.components.community.token-gating
|
||||
quo2.components.counter.counter
|
||||
quo2.components.dividers.date
|
||||
quo2.components.dividers.divider-label
|
||||
quo2.components.dividers.new-messages
|
||||
quo2.components.drawers.action-drawers
|
||||
quo2.components.dropdowns.dropdown
|
||||
quo2.components.header
|
||||
quo2.components.icon
|
||||
quo2.components.info.info-message
|
||||
quo2.components.info.information-box
|
||||
quo2.components.list-items.channel
|
||||
quo2.components.list-items.menu-item
|
||||
quo2.components.list-items.preview-list
|
||||
quo2.components.loaders.skeleton
|
||||
quo2.components.markdown.text
|
||||
quo2.components.messages.gap
|
||||
quo2.components.messages.system-message
|
||||
quo2.components.navigation.floating-shell-button
|
||||
quo2.components.navigation.page-nav
|
||||
quo2.components.notifications.activity-log.view
|
||||
quo2.components.notifications.info-count
|
||||
quo2.components.notifications.notification-dot
|
||||
quo2.components.reactions.reaction
|
||||
quo2.components.selectors.disclaimer
|
||||
quo2.components.selectors.selectors
|
||||
quo2.components.separator
|
||||
quo2.components.tabs.account-selector
|
||||
quo2.components.tabs.tabs
|
||||
quo2.components.tags.context-tags
|
||||
quo2.components.tags.status-tags
|
||||
quo2.components.tags.tags))
|
||||
(:refer-clojure :exclude [filter])
|
||||
(:require
|
||||
quo2.components.avatars.account-avatar
|
||||
quo2.components.avatars.channel-avatar
|
||||
quo2.components.avatars.group-avatar
|
||||
quo2.components.avatars.icon-avatar
|
||||
quo2.components.avatars.user-avatar
|
||||
quo2.components.avatars.wallet-user-avatar
|
||||
quo2.components.banners.banner.view
|
||||
quo2.components.buttons.button
|
||||
quo2.components.buttons.dynamic-button
|
||||
quo2.components.community.community-card-view
|
||||
quo2.components.community.community-list-view
|
||||
quo2.components.community.community-view
|
||||
quo2.components.community.discover-card
|
||||
quo2.components.community.icon
|
||||
quo2.components.community.token-gating
|
||||
quo2.components.counter.counter
|
||||
quo2.components.dividers.date
|
||||
quo2.components.dividers.divider-label
|
||||
quo2.components.dividers.new-messages
|
||||
quo2.components.drawers.action-drawers
|
||||
quo2.components.dropdowns.dropdown
|
||||
quo2.components.header
|
||||
quo2.components.icon
|
||||
quo2.components.info.info-message
|
||||
quo2.components.info.information-box
|
||||
quo2.components.list-items.channel
|
||||
quo2.components.list-items.menu-item
|
||||
quo2.components.list-items.preview-list
|
||||
quo2.components.loaders.skeleton
|
||||
quo2.components.markdown.text
|
||||
quo2.components.messages.author.view
|
||||
quo2.components.messages.gap
|
||||
quo2.components.messages.system-message
|
||||
quo2.components.navigation.floating-shell-button
|
||||
quo2.components.navigation.page-nav
|
||||
quo2.components.notifications.activity-log.view
|
||||
quo2.components.notifications.count-down-circle
|
||||
quo2.components.notifications.info-count
|
||||
quo2.components.notifications.notification-dot
|
||||
quo2.components.notifications.toast
|
||||
quo2.components.reactions.reaction
|
||||
quo2.components.selectors.disclaimer.view
|
||||
quo2.components.selectors.filter.view
|
||||
quo2.components.selectors.selectors
|
||||
quo2.components.separator
|
||||
quo2.components.settings.privacy-option
|
||||
quo2.components.tabs.account-selector
|
||||
quo2.components.tabs.tabs
|
||||
quo2.components.tags.context-tags
|
||||
quo2.components.tags.status-tags
|
||||
quo2.components.tags.tags))
|
||||
|
||||
(def toast quo2.components.notifications.toast/toast)
|
||||
(def button quo2.components.buttons.button/button)
|
||||
(def dynamic-button quo2.components.buttons.dynamic-button/dynamic-button)
|
||||
(def text quo2.components.markdown.text/text)
|
||||
@@ -58,6 +68,7 @@
|
||||
(def gap quo2.components.messages.gap/gap)
|
||||
(def system-message quo2.components.messages.system-message/system-message)
|
||||
(def reaction quo2.components.reactions.reaction/reaction)
|
||||
(def add-reaction quo2.components.reactions.reaction/add-reaction)
|
||||
(def tags quo2.components.tags.tags/tags)
|
||||
(def user-avatar-tag quo2.components.tags.context-tags/user-avatar-tag)
|
||||
(def context-tag quo2.components.tags.context-tags/context-tag)
|
||||
@@ -68,9 +79,11 @@
|
||||
(def floating-shell-button quo2.components.navigation.floating-shell-button/floating-shell-button)
|
||||
(def status-tag quo2.components.tags.status-tags/status-tag)
|
||||
(def page-nav quo2.components.navigation.page-nav/page-nav)
|
||||
(def disclaimer quo2.components.selectors.disclaimer/disclaimer)
|
||||
(def disclaimer quo2.components.selectors.disclaimer.view/view)
|
||||
(def checkbox quo2.components.selectors.selectors/checkbox)
|
||||
(def filter quo2.components.selectors.filter.view/view)
|
||||
(def skeleton quo2.components.loaders.skeleton/skeleton)
|
||||
(def author quo2.components.messages.author.view/author)
|
||||
|
||||
;;;; AVATAR
|
||||
(def account-avatar quo2.components.avatars.account-avatar/account-avatar)
|
||||
@@ -80,6 +93,9 @@
|
||||
(def user-avatar quo2.components.avatars.user-avatar/user-avatar)
|
||||
(def wallet-user-avatar quo2.components.avatars.wallet-user-avatar/wallet-user-avatar)
|
||||
|
||||
;;;; BANNER
|
||||
(def banner quo2.components.banners.banner.view/banner)
|
||||
|
||||
;;;; COMMUNITY
|
||||
(def community-card-view-item quo2.components.community.community-card-view/community-card-view-item)
|
||||
(def communities-list-view-item quo2.components.community.community-list-view/communities-list-view-item)
|
||||
@@ -92,6 +108,7 @@
|
||||
(def permission-tag-container quo2.components.community.community-view/permission-tag-container)
|
||||
(def discover-card quo2.components.community.discover-card/discover-card)
|
||||
(def token-gating quo2.components.community.token-gating/token-gating)
|
||||
(def community-icon quo2.components.community.icon/community-icon)
|
||||
|
||||
;;;; DIVIDERS
|
||||
(def divider-label quo2.components.dividers.divider-label/divider-label)
|
||||
@@ -107,3 +124,7 @@
|
||||
(def activity-log quo2.components.notifications.activity-log.view/view)
|
||||
(def info-count quo2.components.notifications.info-count/info-count)
|
||||
(def notification-dot quo2.components.notifications.notification-dot/notification-dot)
|
||||
(def count-down-circle quo2.components.notifications.count-down-circle/circle-timer)
|
||||
|
||||
;;;; SETTINGS
|
||||
(def privacy-option quo2.components.settings.privacy-option/card)
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
(ns quo2.core-spec
|
||||
(:require [quo2.components.counter.--tests--.counter-component-spec]
|
||||
(:require [quo2.components.banners.--tests--.banner-component-spec]
|
||||
[quo2.components.buttons.--tests--.buttons-component-spec]
|
||||
[quo2.components.counter.--tests--.counter-component-spec]
|
||||
[quo2.components.dividers.--tests--.divider-label-component-spec]
|
||||
[quo2.components.drawers.--tests--.action-drawers-component-spec]
|
||||
[quo2.components.selectors.--tests--.selectors-component-spec]))
|
||||
[quo2.components.markdown.--tests--.text-component-spec]
|
||||
[quo2.components.selectors.--tests--.selectors-component-spec]
|
||||
[quo2.components.selectors.filter.component-spec]))
|
||||
|
||||
@@ -14,6 +14,21 @@
|
||||
(let [rgb (string/split value #",")]
|
||||
(str (string/join "," (butlast rgb)) "," opacity ")")))))
|
||||
|
||||
(defn- alpha-opaque
|
||||
[value opacity]
|
||||
(when value
|
||||
(if (string/starts-with? value "#")
|
||||
(let [hex (string/replace value #"#" "")
|
||||
r (- 255 (* opacity (- 255 (js/parseInt (subs hex 0 2) 16))))
|
||||
g (- 255 (* opacity (- 255 (js/parseInt (subs hex 2 4) 16))))
|
||||
b (- 255 (* opacity (- 255 (js/parseInt (subs hex 4 6) 16))))]
|
||||
(str "rgb(" r "," g "," b ")"))
|
||||
(let [rgb (string/split value #",")
|
||||
r (- 255 (* opacity (- 255 (get rgb 0))))
|
||||
g (- 255 (* opacity (- 255 (get rgb 1))))
|
||||
b (- 255 (* opacity (- 255 (get rgb 2))))]
|
||||
(str "rgb(" r "," g "," b ")")))))
|
||||
|
||||
(def theme-alpha
|
||||
(memoize
|
||||
(fn
|
||||
@@ -50,6 +65,7 @@
|
||||
;;80 with transparency
|
||||
(def neutral-80-opa-5 (alpha neutral-80 0.05))
|
||||
(def neutral-80-opa-10 (alpha neutral-80 0.1))
|
||||
(def neutral-80-opa-15 (alpha neutral-80 0.15))
|
||||
(def neutral-80-opa-20 (alpha neutral-80 0.2))
|
||||
(def neutral-80-opa-30 (alpha neutral-80 0.3))
|
||||
(def neutral-80-opa-40 (alpha neutral-80 0.4))
|
||||
@@ -68,11 +84,17 @@
|
||||
(def neutral-95-opa-95 (alpha neutral-95 0.95))
|
||||
|
||||
;;100 with transparency
|
||||
(def neutral-100-opa-0 (alpha neutral-100 0))
|
||||
(def neutral-100-opa-10 (alpha neutral-100 0.1))
|
||||
(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))
|
||||
(def neutral-100-opa-90 (alpha neutral-100 0.9))
|
||||
(def neutral-100-opa-95 (alpha neutral-100 0.95))
|
||||
(def neutral-100-opa-100 (alpha neutral-100 1))
|
||||
|
||||
;;80 with transparency opaque
|
||||
(def neutral-80-opa-5-opaque (alpha-opaque neutral-80 0.05))
|
||||
|
||||
;;;;White
|
||||
|
||||
@@ -92,6 +114,11 @@
|
||||
(def white-opa-90 (alpha white 0.9))
|
||||
(def white-opa-95 (alpha white 0.95))
|
||||
|
||||
;;;;Black
|
||||
|
||||
;;Solid
|
||||
(def black "#000000")
|
||||
|
||||
;;;;Primary
|
||||
|
||||
;;Solid
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
(ns react-native.core
|
||||
(:require ["@react-native-community/blur" :as blur]
|
||||
["react" :as react]
|
||||
["react-native" :as react-native]
|
||||
[cljs-bean.core :as bean]
|
||||
[oops.core :as oops]
|
||||
[react-native.flat-list :as flat-list]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.section-list :as section-list]
|
||||
@@ -64,6 +67,12 @@
|
||||
|
||||
(def status-bar (.-StatusBar ^js react-native))
|
||||
|
||||
(def style-sheet (.-StyleSheet ^js react-native))
|
||||
|
||||
(defn status-bar-height
|
||||
[]
|
||||
(.-currentHeight ^js status-bar))
|
||||
|
||||
(defn hw-back-add-listener
|
||||
[callback]
|
||||
(.addEventListener (.-BackHandler ^js react-native) "hardwareBackPress" callback))
|
||||
@@ -80,3 +89,16 @@
|
||||
(merge (when platform/ios? {:behavior :padding})
|
||||
props)]
|
||||
children))
|
||||
|
||||
(defn use-effect
|
||||
([effect] (use-effect effect []))
|
||||
([effect deps]
|
||||
(react/useEffect effect (bean/->js deps))))
|
||||
|
||||
(def use-ref react/useRef)
|
||||
(defn use-effect-once [effect] (use-effect effect))
|
||||
(defn use-unmount
|
||||
[f]
|
||||
(let [fn-ref (use-ref f)]
|
||||
(oops/oset! fn-ref "current" f)
|
||||
(use-effect-once (fn [] #((oops/oget fn-ref "current"))))))
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
(ns react-native.hooks
|
||||
(:require ["@react-native-community/hooks" :as hooks]))
|
||||
|
||||
(defn use-keyboard
|
||||
[]
|
||||
(let [kb (.useKeyboard hooks)]
|
||||
{:keyboard-shown (.-keyboardShown ^js kb)
|
||||
:keyboard-height (.-keyboardHeight ^js kb)}))
|
||||
@@ -1,11 +1,25 @@
|
||||
(ns react-native.reanimated
|
||||
(:require
|
||||
["react-native" :as rn]
|
||||
["react-native-linear-gradient" :default LinearGradient]
|
||||
["react-native-reanimated" :default reanimated :refer
|
||||
(useSharedValue useAnimatedStyle withTiming withDelay withSpring withRepeat Easing Keyframe)]
|
||||
[clojure.string :as string]
|
||||
[reagent.core :as reagent]))
|
||||
(:require ["react-native" :as rn]
|
||||
["react-native-linear-gradient" :default LinearGradient]
|
||||
["react-native-reanimated" :default reanimated :refer
|
||||
(useSharedValue useAnimatedStyle
|
||||
withTiming
|
||||
withDelay
|
||||
withSpring
|
||||
withRepeat
|
||||
Easing
|
||||
Keyframe
|
||||
cancelAnimation
|
||||
SlideInUp
|
||||
SlideOutUp
|
||||
LinearTransition)]
|
||||
[clojure.string :as string]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
;; Animations
|
||||
(def slide-in-up-animation SlideInUp)
|
||||
(def slide-out-up-animation SlideOutUp)
|
||||
(def linear-transition LinearTransition)
|
||||
|
||||
;; Animated Components
|
||||
(def create-animated-component (comp reagent/adapt-react-class (.-createAnimatedComponent reanimated)))
|
||||
@@ -26,6 +40,7 @@
|
||||
(def with-spring withSpring)
|
||||
(def key-frame Keyframe)
|
||||
(def with-repeat withRepeat)
|
||||
(def cancel-animation cancelAnimation)
|
||||
|
||||
;; Easings
|
||||
(def bezier (.-bezier ^js Easing))
|
||||
@@ -60,6 +75,13 @@
|
||||
;; Worklets
|
||||
(def worklet-factory (js/require "../src/js/worklet_factory.js"))
|
||||
|
||||
(defn interpolate
|
||||
[shared-value input-range output-range]
|
||||
(.interpolateValue ^js worklet-factory
|
||||
shared-value
|
||||
(clj->js input-range)
|
||||
(clj->js output-range)))
|
||||
|
||||
;;;; Component Animations
|
||||
|
||||
;; kebab-case styles are not working for worklets
|
||||
@@ -94,4 +116,26 @@
|
||||
(js-obj "duration" duration
|
||||
"easing" (get easings easing)))
|
||||
number-of-repetitions
|
||||
reverse?)))
|
||||
reverse?)))
|
||||
|
||||
(defn animate-shared-value-with-delay-repeat
|
||||
([anim val duration easing delay number-of-repetitions]
|
||||
(animate-shared-value-with-delay-repeat anim val duration easing delay number-of-repetitions false))
|
||||
([anim val duration easing delay number-of-repetitions reverse?]
|
||||
(set-shared-value anim
|
||||
(with-delay delay
|
||||
(with-repeat
|
||||
(with-timing val
|
||||
#js
|
||||
{:duration duration
|
||||
:easing (get easings easing)})
|
||||
number-of-repetitions
|
||||
reverse?)))))
|
||||
|
||||
(defn animate-shared-value-with-spring
|
||||
[anim val {:keys [mass stiffness damping]}]
|
||||
(set-shared-value anim
|
||||
(with-spring val
|
||||
(js-obj "mass" mass
|
||||
"damping" damping
|
||||
"stiffness" stiffness))))
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
(defn consumer
|
||||
[component]
|
||||
[consumer-raw
|
||||
(fn [insets]
|
||||
(fn [^js insets]
|
||||
(reagent/as-element
|
||||
[component (js->clj insets :keywordize-keys true)]))])
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
(ns react-native.svg
|
||||
(:require ["react-native-svg" :as Svg]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def svg (reagent/adapt-react-class Svg/default))
|
||||
(def path (reagent/adapt-react-class Svg/Path))
|
||||
@@ -10,7 +10,7 @@
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.router.core :as router]
|
||||
[status-im.utils.db :as utils.db]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im2.navigation.events :as navigation]))
|
||||
@@ -24,7 +24,7 @@
|
||||
;;NOTE we want to handle only last resolve
|
||||
(def resolve-last-id (atom nil))
|
||||
|
||||
(fx/defn new-chat-set-new-identity
|
||||
(rf/defn new-chat-set-new-identity
|
||||
{:events [:new-chat/set-new-identity]}
|
||||
[{db :db} new-identity-raw new-ens-name id]
|
||||
(let [ens-error (and (= new-identity-raw "0x") (not (string/blank? new-ens-name)))]
|
||||
@@ -61,12 +61,12 @@
|
||||
new-identity
|
||||
@resolve-last-id])}})))))))
|
||||
|
||||
(fx/defn clear-new-identity
|
||||
(rf/defn clear-new-identity
|
||||
{:events [::clear-new-identity ::new-chat-focus]}
|
||||
[{:keys [db]}]
|
||||
{:db (dissoc db :contacts/new-identity)})
|
||||
|
||||
(fx/defn qr-code-handled
|
||||
(rf/defn qr-code-handled
|
||||
{:events [::qr-code-handled]}
|
||||
[{:keys [db] :as cofx} {:keys [type public-key chat-id data ens-name]}
|
||||
{:keys [new-contact? nickname] :as opts}]
|
||||
@@ -81,7 +81,7 @@
|
||||
validation-result (db/validate-pub-key db chat-key)]
|
||||
(if-not validation-result
|
||||
(if new-contact?
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(contact/add-contact chat-key nickname ens-name)
|
||||
(navigation/navigate-to-cofx :contacts-list {}))
|
||||
(chat/start-chat cofx chat-key ens-name))
|
||||
@@ -93,7 +93,7 @@
|
||||
(i18n/label :t/can-not-add-yourself))
|
||||
:on-dismiss #(re-frame/dispatch [:pop-to-root-tab :chat-stack])}})))
|
||||
|
||||
(fx/defn qr-code-scanned
|
||||
(rf/defn qr-code-scanned
|
||||
{:events [:contact/qr-code-scanned]}
|
||||
[{:keys [db]} data opts]
|
||||
{::router/handle-uri {:chain (ethereum/chain-keyword db)
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
(ns status-im.backup.core
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(fx/defn handle-backup-failed
|
||||
(rf/defn handle-backup-failed
|
||||
{:events [::backup-failed]}
|
||||
[{:keys [db]}]
|
||||
{:db (dissoc db :backup/performing-backup)})
|
||||
|
||||
(fx/defn handle-backup-perfomed
|
||||
(rf/defn handle-backup-perfomed
|
||||
{:events [::backup-performed]}
|
||||
[{:keys [db]}]
|
||||
{:db (dissoc db :backup/performing-backup)})
|
||||
|
||||
(fx/defn handle-perform-backup-pressed
|
||||
(rf/defn handle-perform-backup-pressed
|
||||
{:events [:multiaccounts.ui/perform-backup-pressed]}
|
||||
[{:keys [db]}]
|
||||
{:db (assoc db :backup/performing-backup true)
|
||||
::json-rpc/call [{:method "wakuext_backupData"
|
||||
:params []
|
||||
:on-error #(do
|
||||
(log/error "failed to perfom backup" %)
|
||||
(re-frame/dispatch [::backup-failed %]))
|
||||
:on-success #(re-frame/dispatch [::backup-performed %])}]})
|
||||
{:db (assoc db :backup/performing-backup true)
|
||||
:json-rpc/call [{:method "wakuext_backupData"
|
||||
:params []
|
||||
:on-error #(do
|
||||
(log/error "failed to perfom backup" %)
|
||||
(re-frame/dispatch [::backup-failed %]))
|
||||
:on-success #(re-frame/dispatch [::backup-performed %])}]})
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im2.navigation.events :as navigation]))
|
||||
|
||||
(def address-regex #"enode://[a-zA-Z0-9]+:?(.*)\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})")
|
||||
@@ -19,12 +19,12 @@
|
||||
:id (string/replace id "-" "")
|
||||
:name bootnode-name})
|
||||
|
||||
(fx/defn fetch
|
||||
(rf/defn fetch
|
||||
[cofx id]
|
||||
(let [network (get-in cofx [:db :networks/current-network])]
|
||||
(get-in cofx [:db :multiaccount :custom-bootnodes network id])))
|
||||
|
||||
(fx/defn set-input
|
||||
(rf/defn set-input
|
||||
{:events [:bootnodes.ui/input-changed]}
|
||||
[{:keys [db]} input-key value]
|
||||
{:db (update
|
||||
@@ -38,14 +38,14 @@
|
||||
:name (string/blank? value)
|
||||
:url (not (valid-address? value)))})})
|
||||
|
||||
(fx/defn edit
|
||||
(rf/defn edit
|
||||
{:events [:bootnodes.ui/add-bootnode-pressed]}
|
||||
[{:keys [db] :as cofx} id]
|
||||
(let [{:keys [id
|
||||
address
|
||||
name]}
|
||||
(fetch cofx id)
|
||||
fxs (fx/merge cofx
|
||||
fxs (rf/merge cofx
|
||||
(set-input :id id)
|
||||
(set-input :url (str address))
|
||||
(set-input :name (str name)))]
|
||||
@@ -56,11 +56,11 @@
|
||||
(let [network (:networks/current-network db)]
|
||||
(get-in db [:multiaccount :custom-bootnodes-enabled? network])))
|
||||
|
||||
(fx/defn delete
|
||||
(rf/defn delete
|
||||
[{{:keys [multiaccount] :as db} :db :as cofx} id]
|
||||
(let [network (:networks/current-network db)
|
||||
new-multiaccount (update-in multiaccount [:custom-bootnodes network] dissoc id)]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc db :multiaccount new-multiaccount)}
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:custom-bootnodes
|
||||
@@ -68,7 +68,7 @@
|
||||
{:success-event (when (custom-bootnodes-in-use? cofx)
|
||||
[:multiaccounts.update.callback/save-settings-success])}))))
|
||||
|
||||
(fx/defn upsert
|
||||
(rf/defn upsert
|
||||
{:events [:bootnodes.ui/save-pressed]
|
||||
:interceptors [(re-frame/inject-cofx :random-id-generator)]}
|
||||
[{{:bootnodes/keys [manage] :keys [multiaccount] :as db} :db
|
||||
@@ -86,7 +86,7 @@
|
||||
[network (:id bootnode)]
|
||||
bootnode)]
|
||||
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (dissoc db :bootnodes/manage)
|
||||
:dispatch [:navigate-back]}
|
||||
(multiaccounts.update/multiaccount-update
|
||||
@@ -95,7 +95,7 @@
|
||||
{:success-event (when (custom-bootnodes-in-use? cofx)
|
||||
[:multiaccounts.update.callback/save-settings-success])}))))
|
||||
|
||||
(fx/defn toggle-custom-bootnodes
|
||||
(rf/defn toggle-custom-bootnodes
|
||||
{:events [:bootnodes.ui/custom-bootnodes-switch-toggled]}
|
||||
[{:keys [db] :as cofx} value]
|
||||
(let [current-network (:networks/current-network db)
|
||||
@@ -106,14 +106,14 @@
|
||||
(assoc bootnodes-settings current-network value)
|
||||
{:success-event [:multiaccounts.update.callback/save-settings-success]})))
|
||||
|
||||
(fx/defn set-bootnodes-from-qr
|
||||
(rf/defn set-bootnodes-from-qr
|
||||
{:events [:bootnodes.callback/qr-code-scanned]}
|
||||
[cofx url]
|
||||
(assoc (set-input cofx :url (string/trim url))
|
||||
:dispatch
|
||||
[:navigate-back]))
|
||||
|
||||
(fx/defn show-delete-bootnode-confirmation
|
||||
(rf/defn show-delete-bootnode-confirmation
|
||||
{:events [:bootnodes.ui/delete-pressed]}
|
||||
[_ bootnode-id]
|
||||
{:ui/show-confirmation {:title (i18n/label :t/delete-bootnode-title)
|
||||
@@ -122,9 +122,9 @@
|
||||
:on-accept #(re-frame/dispatch [:bootnodes.ui/delete-confirmed
|
||||
bootnode-id])}})
|
||||
|
||||
(fx/defn delete-bootnode
|
||||
(rf/defn delete-bootnode
|
||||
{:events [:bootnodes.ui/delete-confirmed]}
|
||||
[cofx bootnode-id]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(delete bootnode-id)
|
||||
(navigation/navigate-back)))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(ns status-im.bottom-sheet.core
|
||||
(:require [status-im.utils.fx :as fx]))
|
||||
(:require [utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn show-bottom-sheet
|
||||
(rf/defn show-bottom-sheet
|
||||
[{:keys [db]} {:keys [view options]}]
|
||||
{:show-bottom-sheet nil
|
||||
:db (assoc db
|
||||
@@ -9,7 +9,7 @@
|
||||
:bottom-sheet/view view
|
||||
:bottom-sheet/options options)})
|
||||
|
||||
(fx/defn show-bottom-sheet-event
|
||||
(rf/defn show-bottom-sheet-event
|
||||
{:events [:bottom-sheet/show-sheet]}
|
||||
[cofx view options]
|
||||
(show-bottom-sheet
|
||||
@@ -17,8 +17,12 @@
|
||||
{:view view
|
||||
:options options}))
|
||||
|
||||
(fx/defn hide-bottom-sheet
|
||||
(rf/defn hide-bottom-sheet
|
||||
{:events [:bottom-sheet/hide]}
|
||||
[{:keys [db]}]
|
||||
{:hide-bottom-sheet nil
|
||||
:db (assoc db :bottom-sheet/show? false)})
|
||||
{:db (assoc db :bottom-sheet/show? false)})
|
||||
|
||||
(rf/defn hide-bottom-sheet-navigation-overlay
|
||||
{:events [:bottom-sheet/hide-navigation-overlay]}
|
||||
[{}]
|
||||
{:hide-bottom-sheet nil})
|
||||
|
||||
+116
-114
@@ -1,36 +1,37 @@
|
||||
(ns status-im.browser.core
|
||||
(:require ["eth-phishing-detect" :as eth-phishing-detect]
|
||||
[clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.browser.eip3085 :as eip3085]
|
||||
[status-im.browser.eip3326 :as eip3326]
|
||||
[status-im.browser.permissions :as browser.permissions]
|
||||
[status-im.browser.webview-ref :as webview-ref]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.signing.core :as signing]
|
||||
[status-im.ui.components.list-selection :as list-selection]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.http :as http]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.utils.universal-links.utils :as links]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.debounce :as debounce]))
|
||||
(:require
|
||||
["eth-phishing-detect" :as eth-phishing-detect]
|
||||
[clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.browser.eip3085 :as eip3085]
|
||||
[status-im.browser.eip3326 :as eip3326]
|
||||
[status-im.browser.permissions :as browser.permissions]
|
||||
[status-im.browser.webview-ref :as webview-ref]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.signing.core :as signing]
|
||||
[status-im.ui.components.list-selection :as list-selection]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.http :as http]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.utils.universal-links.utils :as links]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(fx/defn update-browser-option
|
||||
(rf/defn update-browser-option
|
||||
[{:keys [db]} option-key option-value]
|
||||
{:db (assoc-in db [:browser/options option-key] option-value)})
|
||||
|
||||
(fx/defn update-browser-options
|
||||
(rf/defn update-browser-options
|
||||
[{:keys [db]} options]
|
||||
{:db (update db :browser/options merge options)})
|
||||
|
||||
@@ -51,22 +52,22 @@
|
||||
(when url
|
||||
(string/starts-with? url "https://")))))
|
||||
|
||||
(fx/defn remove-browser
|
||||
(rf/defn remove-browser
|
||||
{:events [:browser.ui/remove-browser-pressed]}
|
||||
[{:keys [db]} browser-id]
|
||||
{:db (update-in db [:browser/browsers] dissoc browser-id)
|
||||
::json-rpc/call [{:method "wakuext_deleteBrowser"
|
||||
:params [browser-id]
|
||||
:on-success #()}]})
|
||||
{:db (update-in db [:browser/browsers] dissoc browser-id)
|
||||
:json-rpc/call [{:method "wakuext_deleteBrowser"
|
||||
:params [browser-id]
|
||||
:on-success #()}]})
|
||||
|
||||
(fx/defn clear-all-browsers
|
||||
(rf/defn clear-all-browsers
|
||||
{:events [:browser.ui/clear-all-browsers-pressed]}
|
||||
[{:keys [db]}]
|
||||
{:db (dissoc db :browser/browsers)
|
||||
::json-rpc/call (for [browser-id (keys (get db :browser/browsers))]
|
||||
{:method "wakuext_deleteBrowser"
|
||||
:params [browser-id]
|
||||
:on-success #()})})
|
||||
{:db (dissoc db :browser/browsers)
|
||||
:json-rpc/call (for [browser-id (keys (get db :browser/browsers))]
|
||||
{:method "wakuext_deleteBrowser"
|
||||
:params [browser-id]
|
||||
:on-success #()})})
|
||||
|
||||
(defn update-dapp-name
|
||||
[{:keys [name] :as browser}]
|
||||
@@ -83,7 +84,7 @@
|
||||
(re-frame/dispatch [:browser.callback/resolve-ens-multihash-success url])
|
||||
(re-frame/dispatch [:browser.callback/resolve-ens-multihash-error])))
|
||||
|
||||
(fx/defn resolve-url
|
||||
(rf/defn resolve-url
|
||||
[{:keys [db]} {:keys [error? resolved-url]}]
|
||||
(when (not error?)
|
||||
(let [current-url (get-current-url (get-current-browser db))
|
||||
@@ -95,69 +96,69 @@
|
||||
:cb resolve-ens-contenthash-callback}}
|
||||
{:db (update db :browser/options assoc :url (or resolved-url current-url) :resolving? false)}))))
|
||||
|
||||
(fx/defn update-browser
|
||||
(rf/defn update-browser
|
||||
[{:keys [db]}
|
||||
{:keys [browser-id] :as browser}]
|
||||
(let [updated-browser (-> browser
|
||||
(update-dapp-name)
|
||||
(check-if-phishing-url))]
|
||||
{:db (update-in db
|
||||
[:browser/browsers browser-id]
|
||||
merge
|
||||
updated-browser)
|
||||
::json-rpc/call [{:method "wakuext_addBrowser"
|
||||
:params [(select-keys updated-browser
|
||||
[:browser-id :timestamp :name :dapp? :history
|
||||
:history-index])]
|
||||
:on-success #()}]}))
|
||||
{:db (update-in db
|
||||
[:browser/browsers browser-id]
|
||||
merge
|
||||
updated-browser)
|
||||
:json-rpc/call [{:method "wakuext_addBrowser"
|
||||
:params [(select-keys updated-browser
|
||||
[:browser-id :timestamp :name :dapp? :history
|
||||
:history-index])]
|
||||
:on-success #()}]}))
|
||||
|
||||
(fx/defn store-bookmark
|
||||
(rf/defn store-bookmark
|
||||
{:events [:browser/store-bookmark]}
|
||||
[{:keys [db]}
|
||||
{:keys [url] :as bookmark}]
|
||||
{:db (assoc-in db [:bookmarks/bookmarks url] bookmark)
|
||||
::json-rpc/call [{:method "wakuext_addBookmark"
|
||||
:params [bookmark]
|
||||
:on-success #()}]})
|
||||
{:db (assoc-in db [:bookmarks/bookmarks url] bookmark)
|
||||
:json-rpc/call [{:method "wakuext_addBookmark"
|
||||
:params [bookmark]
|
||||
:on-success #()}]})
|
||||
|
||||
(fx/defn update-bookmark
|
||||
(rf/defn update-bookmark
|
||||
{:events [:browser/update-bookmark]}
|
||||
[{:keys [db] :as cofx}
|
||||
{:keys [url] :as bookmark}]
|
||||
(let [old-bookmark (get-in db [:bookmarks/bookmarks url])
|
||||
new-bookmark (merge old-bookmark bookmark)]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:bookmarks/bookmarks url] new-bookmark)
|
||||
::json-rpc/call [{:method "wakuext_updateBookmark"
|
||||
:params [url bookmark]
|
||||
:on-success #()}]})))
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:bookmarks/bookmarks url] new-bookmark)
|
||||
:json-rpc/call [{:method "wakuext_updateBookmark"
|
||||
:params [url bookmark]
|
||||
:on-success #()}]})))
|
||||
|
||||
(fx/defn delete-bookmark
|
||||
(rf/defn delete-bookmark
|
||||
{:events [:browser/delete-bookmark]}
|
||||
[{:keys [db] :as cofx}
|
||||
url]
|
||||
(let [old-bookmark (get-in db [:bookmarks/bookmarks url])
|
||||
removed-bookmark (merge old-bookmark {:removed true})]
|
||||
(fx/merge cofx
|
||||
{:db (update db :bookmarks/bookmarks dissoc url)
|
||||
::json-rpc/call [{:method "wakuext_removeBookmark"
|
||||
:params [url]
|
||||
:on-success #()}]})))
|
||||
(rf/merge cofx
|
||||
{:db (update db :bookmarks/bookmarks dissoc url)
|
||||
:json-rpc/call [{:method "wakuext_removeBookmark"
|
||||
:params [url]
|
||||
:on-success #()}]})))
|
||||
|
||||
(defn can-go-back?
|
||||
[{:keys [history-index]}]
|
||||
(pos? history-index))
|
||||
|
||||
(fx/defn navigate-to-previous-page
|
||||
(rf/defn navigate-to-previous-page
|
||||
{:events [:browser.ui/previous-page-button-pressed]}
|
||||
[cofx]
|
||||
(let [{:keys [history-index] :as browser} (get-current-browser (:db cofx))]
|
||||
(when (can-go-back? browser)
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(update-browser (assoc browser :history-index (dec history-index)))
|
||||
(resolve-url nil)))))
|
||||
|
||||
(fx/defn ignore-unsafe
|
||||
(rf/defn ignore-unsafe
|
||||
{:events [:browser/ignore-unsafe]}
|
||||
[cofx]
|
||||
(let [browser (get-current-browser (:db cofx))
|
||||
@@ -168,16 +169,16 @@
|
||||
[{:keys [history-index history]}]
|
||||
(< history-index (dec (count history))))
|
||||
|
||||
(fx/defn navigate-to-next-page
|
||||
(rf/defn navigate-to-next-page
|
||||
{:events [:browser.ui/next-page-button-pressed]}
|
||||
[cofx]
|
||||
(let [{:keys [history-index] :as browser} (get-current-browser (:db cofx))]
|
||||
(when (can-go-forward? browser)
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(update-browser (assoc browser :history-index (inc history-index)))
|
||||
(resolve-url nil)))))
|
||||
|
||||
(fx/defn update-browser-history
|
||||
(rf/defn update-browser-history
|
||||
[cofx browser url]
|
||||
(let [history-index (:history-index browser)
|
||||
history (:history browser)]
|
||||
@@ -189,14 +190,14 @@
|
||||
:history new-history
|
||||
:history-index new-index))))))
|
||||
|
||||
(fx/defn resolve-ens-multihash-success
|
||||
(rf/defn resolve-ens-multihash-success
|
||||
{:events [:browser.callback/resolve-ens-multihash-success]}
|
||||
[{:keys [db] :as cofx} url]
|
||||
(let [current-url (get-current-url (get-current-browser db))
|
||||
host (http/url-host current-url)
|
||||
path (subs current-url (+ (.indexOf ^js current-url host) (count host)))
|
||||
gateway url]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> (update db
|
||||
:browser/options
|
||||
assoc
|
||||
@@ -204,7 +205,7 @@
|
||||
:resolving? false)
|
||||
(assoc-in [:browser/options :resolved-ens host] gateway))})))
|
||||
|
||||
(fx/defn resolve-ens-multihash-error
|
||||
(rf/defn resolve-ens-multihash-error
|
||||
{:events [:browser.callback/resolve-ens-multihash-error]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(update-browser-options cofx
|
||||
@@ -212,26 +213,27 @@
|
||||
:resolving? false
|
||||
:error? true}))
|
||||
|
||||
(fx/defn handle-browser-error
|
||||
(rf/defn handle-browser-error
|
||||
{:events [:browser/error-occured]}
|
||||
[cofx]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(update-browser-option :error? true)
|
||||
(update-browser-option :loading? false)))
|
||||
|
||||
(fx/defn handle-pdf
|
||||
(rf/defn handle-pdf
|
||||
[_ url]
|
||||
(when (and platform/android? (string/ends-with? url ".pdf"))
|
||||
{:browser/show-web-browser-selection url}))
|
||||
|
||||
(fx/defn handle-message-link
|
||||
(rf/defn handle-message-link
|
||||
{:events [:browser.ui/message-link-pressed]}
|
||||
[_ link]
|
||||
(if (links/universal-link? link)
|
||||
{:dispatch [:universal-links/handle-url link]}
|
||||
{:browser/show-browser-selection link}))
|
||||
(when (security/safe-link? link)
|
||||
(if (links/universal-link? link)
|
||||
{:dispatch [:universal-links/handle-url link]}
|
||||
{:browser/show-browser-selection link})))
|
||||
|
||||
(fx/defn update-browser-on-nav-change
|
||||
(rf/defn update-browser-on-nav-change
|
||||
[cofx url error?]
|
||||
(let [browser (get-current-browser (:db cofx))
|
||||
options (get-in cofx [:db :browser/options])
|
||||
@@ -249,18 +251,18 @@
|
||||
(second resolved-ens)
|
||||
(first resolved-ens)))
|
||||
url)]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(update-browser-history browser resolved-url)
|
||||
(handle-pdf url)
|
||||
(resolve-url {:error? error? :resolved-url (when resolved-ens url)}))))))
|
||||
|
||||
(fx/defn update-browser-name
|
||||
(rf/defn update-browser-name
|
||||
[cofx title]
|
||||
(let [browser (get-current-browser (:db cofx))]
|
||||
(when (and browser (not (:dapp? browser)) title (not (string/blank? title)))
|
||||
(update-browser cofx (assoc browser :name title)))))
|
||||
|
||||
(fx/defn navigation-state-changed
|
||||
(rf/defn navigation-state-changed
|
||||
{:events [:browser/navigation-state-changed]}
|
||||
[cofx event error?]
|
||||
(let [{:strs [url loading title]} (js->clj event)
|
||||
@@ -268,12 +270,12 @@
|
||||
(if (links/universal-link? url)
|
||||
(when-not (and deep-link? platform/ios?) ;; ios webview handles this
|
||||
{:dispatch [:universal-links/handle-url url]})
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(update-browser-option :loading? loading)
|
||||
(update-browser-name title)
|
||||
(update-browser-on-nav-change url error?)))))
|
||||
|
||||
(fx/defn open-url-in-current-browser
|
||||
(rf/defn open-url-in-current-browser
|
||||
"Opens a url in the current browser, which mean no new entry is added to the home page
|
||||
and history of the current browser is updated so that the user can navigate back to the
|
||||
origin url"
|
||||
@@ -283,12 +285,12 @@
|
||||
normalized-url (http/normalize-and-decode-url url)]
|
||||
(if (links/universal-link? normalized-url)
|
||||
{:dispatch [:universal-links/handle-url normalized-url]}
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(update-browser-option :url-editing? false)
|
||||
(update-browser-history browser normalized-url)
|
||||
(resolve-url nil)))))
|
||||
|
||||
(fx/defn open-url
|
||||
(rf/defn open-url
|
||||
"Opens a url in the browser. If a host can be extracted from the url and
|
||||
there is already a browser for this host, this browser is reused
|
||||
If the browser is reused, the history is flushed"
|
||||
@@ -300,7 +302,7 @@
|
||||
:history [normalized-url]}]
|
||||
(if (links/universal-link? normalized-url)
|
||||
{:dispatch [:universal-links/handle-url normalized-url]}
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc db
|
||||
:browser/options
|
||||
{:browser-id (:browser-id browser)})}
|
||||
@@ -309,12 +311,12 @@
|
||||
(update-browser browser)
|
||||
(resolve-url nil)))))
|
||||
|
||||
(fx/defn open-existing-browser
|
||||
(rf/defn open-existing-browser
|
||||
"Opens an existing browser with it's history"
|
||||
{:events [:browser.ui/browser-item-selected]}
|
||||
[{:keys [db] :as cofx} browser-id]
|
||||
(let [browser (get-in db [:browser/browsers browser-id])]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc db
|
||||
:browser/options
|
||||
{:browser-id browser-id})}
|
||||
@@ -322,7 +324,7 @@
|
||||
(navigation/set-stack-root :browser-stack :browser)
|
||||
(resolve-url nil))))
|
||||
|
||||
(fx/defn web3-error-callback
|
||||
(rf/defn web3-error-callback
|
||||
{:events [:browser.dapp/transaction-on-error]}
|
||||
[_ message-id message]
|
||||
{:browser/send-to-bridge
|
||||
@@ -330,7 +332,7 @@
|
||||
:messageId message-id
|
||||
:error message}})
|
||||
|
||||
(fx/defn dapp-complete-transaction
|
||||
(rf/defn dapp-complete-transaction
|
||||
{:events [:browser.dapp/transaction-on-result]}
|
||||
[_ message-id id result]
|
||||
;;TODO check and test id
|
||||
@@ -359,7 +361,7 @@
|
||||
(ethereum/address? second-param)
|
||||
[second-param (if typed? first-param (normalize-message first-param))]))))
|
||||
|
||||
(fx/defn send-to-bridge
|
||||
(rf/defn send-to-bridge
|
||||
{:events [:browser.callback/call-rpc]}
|
||||
[_ message]
|
||||
{:browser/send-to-bridge message})
|
||||
@@ -371,7 +373,7 @@
|
||||
constants/web3-eth-sign constants/web3-keycard-sign-typed-data}
|
||||
method))
|
||||
|
||||
(fx/defn web3-send-async
|
||||
(rf/defn web3-send-async
|
||||
[cofx dapp-name {:keys [method params id] :as payload} message-id]
|
||||
(let [message? (web3-sign-message? method)
|
||||
dapps-address (get-in cofx [:db :multiaccount :dapps-address])
|
||||
@@ -431,7 +433,7 @@
|
||||
:error %1
|
||||
:result %2}])]}))))
|
||||
|
||||
(fx/defn handle-no-permissions
|
||||
(rf/defn handle-no-permissions
|
||||
[cofx {:keys [method id]} message-id]
|
||||
(if (= method "eth_accounts")
|
||||
;; eth_accounts returns empty array for compatibility with meta-mask
|
||||
@@ -457,28 +459,28 @@
|
||||
(and (permissioned-method method)
|
||||
(not (some #{constants/dapp-permission-web3} (get-in permissions [dapp-name :permissions]))))))
|
||||
|
||||
(fx/defn web3-send-async-read-only
|
||||
(rf/defn web3-send-async-read-only
|
||||
[{:keys [db] :as cofx} dapp-name {:keys [method] :as payload} message-id]
|
||||
(if (has-permissions? db dapp-name method)
|
||||
(handle-no-permissions cofx payload message-id)
|
||||
(web3-send-async cofx dapp-name payload message-id)))
|
||||
|
||||
(fx/defn handle-scanned-qr-code
|
||||
(rf/defn handle-scanned-qr-code
|
||||
{:events [:browser.bridge.callback/qr-code-scanned]}
|
||||
[cofx data {{:keys [dapp-name permission message-id]} :data}]
|
||||
(fx/merge (assoc-in cofx [:db :browser/options :yielding-control?] false)
|
||||
(rf/merge (assoc-in cofx [:db :browser/options :yielding-control?] false)
|
||||
(browser.permissions/send-response-to-bridge permission message-id true data)
|
||||
(browser.permissions/process-next-permission dapp-name)
|
||||
(navigation/navigate-back)))
|
||||
|
||||
(fx/defn handle-canceled-qr-code
|
||||
(rf/defn handle-canceled-qr-code
|
||||
{:events [:browser.bridge.callback/qr-code-canceled]}
|
||||
[cofx {{:keys [dapp-name permission message-id]} :data}]
|
||||
(fx/merge (assoc-in cofx [:db :browser/options :yielding-control?] false)
|
||||
(rf/merge (assoc-in cofx [:db :browser/options :yielding-control?] false)
|
||||
(browser.permissions/send-response-to-bridge permission message-id true nil)
|
||||
(browser.permissions/process-next-permission dapp-name)))
|
||||
|
||||
(fx/defn process-bridge-message
|
||||
(rf/defn process-bridge-message
|
||||
{:events [:browser/bridge-message-received]}
|
||||
[{:keys [db] :as cofx} message]
|
||||
(let [browser (get-current-browser
|
||||
@@ -555,10 +557,10 @@
|
||||
message (i18n/label :t/share-dapp-text {:link link})]
|
||||
(list-selection/open-share {:message message})))
|
||||
|
||||
(fx/defn dapps-account-selected
|
||||
(rf/defn dapps-account-selected
|
||||
{:events [:dapps-account-selected]}
|
||||
[{:keys [db] :as cofx} address]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:browser/clear-web-data nil}
|
||||
(bottom-sheet/hide-bottom-sheet)
|
||||
(browser.permissions/clear-dapps-permissions)
|
||||
@@ -568,38 +570,38 @@
|
||||
{:dispatch [:browser.ui/browser-item-selected
|
||||
(get-in db [:browser/options :browser-id])]}))))
|
||||
|
||||
(fx/defn open-empty-tab
|
||||
(rf/defn open-empty-tab
|
||||
{:events [:browser.ui/open-empty-tab]}
|
||||
[cofx]
|
||||
(debounce/clear :browser/navigation-state-changed)
|
||||
(navigation/set-stack-root cofx :browser-stack :empty-tab))
|
||||
|
||||
(fx/defn url-input-pressed
|
||||
(rf/defn url-input-pressed
|
||||
{:events [:browser.ui/url-input-pressed]}
|
||||
[cofx _]
|
||||
(update-browser-option cofx :url-editing? true))
|
||||
|
||||
(fx/defn url-input-blured
|
||||
(rf/defn url-input-blured
|
||||
{:events [:browser.ui/url-input-blured]}
|
||||
[cofx]
|
||||
(update-browser-option cofx :url-editing? false))
|
||||
|
||||
(fx/defn lock-pressed
|
||||
(rf/defn lock-pressed
|
||||
{:events [:browser.ui/lock-pressed]}
|
||||
[cofx secure?]
|
||||
(update-browser-option cofx :show-tooltip (if secure? :secure :not-secure)))
|
||||
|
||||
(fx/defn close-tooltip-pressed
|
||||
(rf/defn close-tooltip-pressed
|
||||
{:events [:browser.ui/close-tooltip-pressed]}
|
||||
[cofx]
|
||||
(update-browser-option cofx :show-tooltip nil))
|
||||
|
||||
(fx/defn loading-started
|
||||
(rf/defn loading-started
|
||||
{:events [:browser/loading-started]}
|
||||
[cofx]
|
||||
(update-browser-options cofx {:error? false :loading? true}))
|
||||
|
||||
(fx/defn handle-bookmarks
|
||||
(rf/defn handle-bookmarks
|
||||
[{:keys [db]} bookmarks]
|
||||
(let [changed-bookmarks (reduce (fn [acc {:keys [url] :as bookmark}]
|
||||
(assoc acc url bookmark))
|
||||
|
||||
@@ -4,14 +4,13 @@
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.network.core :as network]
|
||||
[status-im.ui.screens.browser.eip3085.sheet :as sheet]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.random :as random]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(fx/defn send-success-call-to-bridge
|
||||
(rf/defn send-success-call-to-bridge
|
||||
{:events [:eip3085/send-success-call-to-bridge]}
|
||||
[_ id messageId]
|
||||
{:browser/send-to-bridge {:type constants/web3-send-async-callback
|
||||
@@ -20,18 +19,18 @@
|
||||
:id (int id)
|
||||
:result nil}}})
|
||||
|
||||
(fx/defn allow-permission
|
||||
(rf/defn allow-permission
|
||||
{:events [:eip3085.ui/dapp-permission-allowed]}
|
||||
[{:keys [db] :as cofx} message-id {:keys [new-networks id]}]
|
||||
{:db (assoc db :networks/networks new-networks)
|
||||
::json-rpc/call [{:method "settings_saveSetting"
|
||||
:params [:networks/networks (vals new-networks)]
|
||||
:on-success #(re-frame/dispatch [:eip3085/send-success-call-to-bridge cofx id
|
||||
message-id])
|
||||
:on-error #(log/error "failed to perform settings_saveSetting" %)}]
|
||||
:dispatch [:bottom-sheet/hide]})
|
||||
{:db (assoc db :networks/networks new-networks)
|
||||
:json-rpc/call [{:method "settings_saveSetting"
|
||||
:params [:networks/networks (vals new-networks)]
|
||||
:on-success #(re-frame/dispatch [:eip3085/send-success-call-to-bridge cofx id
|
||||
message-id])
|
||||
:on-error #(log/error "failed to perform settings_saveSetting" %)}]
|
||||
:dispatch [:bottom-sheet/hide]})
|
||||
|
||||
(fx/defn deny-permission
|
||||
(rf/defn deny-permission
|
||||
{:events [:eip3085.ui/dapp-permission-denied]}
|
||||
[_ message-id _]
|
||||
{:browser/send-to-bridge {:type constants/web3-send-async-callback
|
||||
@@ -40,7 +39,7 @@
|
||||
:message "User rejected the request."}}
|
||||
:dispatch [:bottom-sheet/hide]})
|
||||
|
||||
(fx/defn handle-add-ethereum-chain
|
||||
(rf/defn handle-add-ethereum-chain
|
||||
{:events [:eip3085/handle-add-ethereum-chain]}
|
||||
[{{:networks/keys [networks] :as db} :db :as cofx}
|
||||
dapp-name id message-id
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
(:require [status-im.constants :as constants]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ui.screens.browser.eip3326.sheet :as sheet]
|
||||
[status-im.utils.fx :as fx]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn deny-permission
|
||||
(rf/defn deny-permission
|
||||
{:events [:eip3326.ui/dapp-permission-denied]}
|
||||
[{:keys [db] :as cofx} message-id _]
|
||||
{:browser/send-to-bridge {:type constants/web3-send-async-callback
|
||||
@@ -15,7 +15,7 @@
|
||||
:message "User rejected the request."}}
|
||||
:dispatch [:bottom-sheet/hide]})
|
||||
|
||||
(fx/defn handle-switch-ethereum-chain
|
||||
(rf/defn handle-switch-ethereum-chain
|
||||
{:events [:eip3326/handle-switch-ethereum-chain]}
|
||||
[{:keys [db] :as cofx} dapp-name id message-id {:keys [chainId] :as params}]
|
||||
(let [target-chain-id (js/parseInt chainId 16)
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
(ns status-im.browser.permissions
|
||||
(:require [status-im.constants :as constants]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.qr-scanner.core :as qr-scanner]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im2.navigation.events :as navigation]))
|
||||
|
||||
(declare process-next-permission)
|
||||
@@ -21,18 +20,18 @@
|
||||
:description (i18n/label :t/allowing-authorizes-this-dapp)
|
||||
:icon :main-icons/wallet}})
|
||||
|
||||
(fx/defn permission-yield-control
|
||||
(rf/defn permission-yield-control
|
||||
[{:keys [db] :as cofx} dapp-name permission message-id params]
|
||||
(cond
|
||||
(= permission constants/dapp-permission-qr-code)
|
||||
(fx/merge (assoc-in cofx [:db :browser/options :yielding-control?] true)
|
||||
(rf/merge (assoc-in cofx [:db :browser/options :yielding-control?] true)
|
||||
(qr-scanner/scan-qr-code {:handler :browser.bridge.callback/qr-code-scanned
|
||||
:cancel-handler :browser.bridge.callback/qr-code-canceled
|
||||
:data {:dapp-name dapp-name
|
||||
:permission permission
|
||||
:message-id message-id}}))))
|
||||
|
||||
(fx/defn permission-show-permission
|
||||
(rf/defn permission-show-permission
|
||||
[{:keys [db] :as cofx} dapp-name permission message-id yield-control?]
|
||||
{:db (assoc-in db
|
||||
[:browser/options :show-permission]
|
||||
@@ -48,7 +47,7 @@
|
||||
constants/dapp-permission-web3 [(:dapps-address multiaccount)]}
|
||||
allowed-permission)))
|
||||
|
||||
(fx/defn send-response-to-bridge
|
||||
(rf/defn send-response-to-bridge
|
||||
"Send response to the bridge. If the permission is allowed, send data associated
|
||||
with the permission"
|
||||
[{:keys [db] :as cofx} permission message-id allowed? data]
|
||||
@@ -59,7 +58,7 @@
|
||||
allowed?
|
||||
(assoc :data data))})
|
||||
|
||||
(fx/defn update-dapp-permissions
|
||||
(rf/defn update-dapp-permissions
|
||||
[{:keys [db]} dapp-name permission allowed?]
|
||||
(let [dapp-permissions-set (set (get-in db [:dapps/permissions dapp-name :permissions]))
|
||||
allowed-permissions-set (if allowed?
|
||||
@@ -67,37 +66,37 @@
|
||||
(disj dapp-permissions-set permission))
|
||||
allowed-permissions {:dapp dapp-name
|
||||
:permissions (vec allowed-permissions-set)}]
|
||||
{:db (assoc-in db [:dapps/permissions dapp-name] allowed-permissions)
|
||||
::json-rpc/call [{:method "permissions_addDappPermissions"
|
||||
:params [allowed-permissions]
|
||||
:on-success #()}]}))
|
||||
{:db (assoc-in db [:dapps/permissions dapp-name] allowed-permissions)
|
||||
:json-rpc/call [{:method "permissions_addDappPermissions"
|
||||
:params [allowed-permissions]
|
||||
:on-success #()}]}))
|
||||
|
||||
(fx/defn revoke-permissions
|
||||
(rf/defn revoke-permissions
|
||||
{:events [:browser/revoke-dapp-permissions]}
|
||||
[{:keys [db] :as cofx} dapp]
|
||||
(fx/merge cofx
|
||||
{:db (update-in db [:dapps/permissions] dissoc dapp)
|
||||
::json-rpc/call [{:method "permissions_deleteDappPermissions"
|
||||
:params [dapp]
|
||||
:on-success #()}]}))
|
||||
(rf/merge cofx
|
||||
{:db (update-in db [:dapps/permissions] dissoc dapp)
|
||||
:json-rpc/call [{:method "permissions_deleteDappPermissions"
|
||||
:params [dapp]
|
||||
:on-success #()}]}))
|
||||
|
||||
(fx/defn revoke-dapp-permissions
|
||||
(rf/defn revoke-dapp-permissions
|
||||
{:events [:dapps/revoke-access]}
|
||||
[cofx dapp]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(revoke-permissions dapp)
|
||||
(navigation/navigate-back)))
|
||||
|
||||
(fx/defn clear-dapps-permissions
|
||||
(rf/defn clear-dapps-permissions
|
||||
[{:keys [db]}]
|
||||
(let [dapp-permissions (keys (:dapps/permissions db))]
|
||||
{:db (dissoc db :dapps/permissions)
|
||||
::json-rpc/call (for [dapp dapp-permissions]
|
||||
{:method "permissions_deleteDappPermissions"
|
||||
:params [dapp]
|
||||
:on-success #()})}))
|
||||
{:db (dissoc db :dapps/permissions)
|
||||
:json-rpc/call (for [dapp dapp-permissions]
|
||||
{:method "permissions_deleteDappPermissions"
|
||||
:params [dapp]
|
||||
:on-success #()})}))
|
||||
|
||||
(fx/defn process-next-permission
|
||||
(rf/defn process-next-permission
|
||||
"Process next permission by removing it from pending permissions and prompting user
|
||||
if there is no pending permissions left, save all granted permissions
|
||||
and return the result to the bridge"
|
||||
@@ -113,41 +112,41 @@
|
||||
(permission-yield-control new-cofx dapp-name permission message-id params)
|
||||
(permission-show-permission new-cofx dapp-name permission message-id yield-control?)))))))
|
||||
|
||||
(fx/defn send-response-and-process-next-permission
|
||||
(rf/defn send-response-and-process-next-permission
|
||||
[{:keys [db] :as cofx} dapp-name requested-permission message-id]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(send-response-to-bridge requested-permission
|
||||
message-id
|
||||
true
|
||||
(get-permission-data cofx requested-permission))
|
||||
(process-next-permission dapp-name)))
|
||||
|
||||
(fx/defn allow-permission
|
||||
(rf/defn allow-permission
|
||||
"Add permission to set of allowed permission and process next permission"
|
||||
{:events [:browser.permissions.ui/dapp-permission-allowed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [requested-permission message-id dapp-name yield-control? params]}
|
||||
(get-in db [:browser/options :show-permission])]
|
||||
(fx/merge (assoc-in cofx [:db :browser/options :show-permission] nil)
|
||||
(rf/merge (assoc-in cofx [:db :browser/options :show-permission] nil)
|
||||
(update-dapp-permissions dapp-name requested-permission true)
|
||||
(if yield-control?
|
||||
(permission-yield-control dapp-name requested-permission message-id params)
|
||||
(send-response-and-process-next-permission dapp-name requested-permission message-id)))))
|
||||
|
||||
(fx/defn deny-permission
|
||||
(rf/defn deny-permission
|
||||
"Add permission to set of allowed permission and process next permission"
|
||||
{:events [:browser.permissions.ui/dapp-permission-denied]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [requested-permission message-id dapp-name]} (get-in db
|
||||
[:browser/options :show-permission])]
|
||||
(fx/merge (assoc-in cofx [:db :browser/options :show-permission] nil)
|
||||
(rf/merge (assoc-in cofx [:db :browser/options :show-permission] nil)
|
||||
(send-response-to-bridge requested-permission
|
||||
message-id
|
||||
false
|
||||
(get-permission-data cofx requested-permission))
|
||||
(process-next-permission dapp-name))))
|
||||
|
||||
(fx/defn process-permission
|
||||
(rf/defn process-permission
|
||||
"Process the permission requested by a dapp
|
||||
If supported permission is already granted, return the result immediatly to the bridge
|
||||
Otherwise process the first permission which will prompt user"
|
||||
|
||||
@@ -3,22 +3,21 @@
|
||||
[quo.design-system.colors :as colors]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.add-new.db :as new-public-chat.db]
|
||||
[status-im.chat.models.delete-message :as delete-message]
|
||||
[status-im.chat.models.delete-message-for-me :as delete-for-me]
|
||||
[status-im.chat.models.loading :as loading]
|
||||
[status-im.chat.models.message-list :as message-list]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.data-store.chats :as chats-store]
|
||||
[status-im.data-store.contacts :as contacts-store]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.mailserver.core :as mailserver]
|
||||
[status-im.multiaccounts.model :as multiaccounts.model]
|
||||
[status-im.ui.screens.chat.state :as chat.state]
|
||||
[status-im.utils.clocks :as utils.clocks]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im2.contexts.chat.messages.delete-message-for-me.events :as delete-for-me]
|
||||
[status-im2.contexts.chat.messages.delete-message.events :as delete-message]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
@@ -113,14 +112,14 @@
|
||||
(fn [val]
|
||||
(and (not (get-in db [:chats (:chat-id val)])) (:public? val))))
|
||||
|
||||
(fx/defn leave-removed-chat
|
||||
(rf/defn leave-removed-chat
|
||||
[{{:keys [view-id current-chat-id chats]} :db
|
||||
:as cofx}]
|
||||
(when (and (= view-id :chat)
|
||||
(not (contains? chats current-chat-id)))
|
||||
(navigation/navigate-back cofx)))
|
||||
|
||||
(fx/defn ensure-chats
|
||||
(rf/defn ensure-chats
|
||||
"Add chats to db and update"
|
||||
[{:keys [db] :as cofx} chats]
|
||||
(let [{:keys [all-chats chats-home-list removed-chats]}
|
||||
@@ -137,7 +136,7 @@
|
||||
:chats-home-list #{}
|
||||
:removed-chats #{}}
|
||||
(map (map-chats cofx) chats))]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
(merge {:db (-> db
|
||||
(update :chats merge all-chats)
|
||||
@@ -150,7 +149,7 @@
|
||||
(get-in db [:multiaccount :remote-push-notifications-enabled?])]}))
|
||||
leave-removed-chat)))
|
||||
|
||||
(fx/defn clear-history
|
||||
(rf/defn clear-history
|
||||
"Clears history of the particular chat"
|
||||
[{:keys [db] :as cofx} chat-id remove-chat?]
|
||||
(let [{:keys [last-message public?
|
||||
@@ -176,40 +175,40 @@
|
||||
:deleted-at-clock-value last-message-clock-value})
|
||||
chats))))}))
|
||||
|
||||
(fx/defn clear-history-handler
|
||||
(rf/defn clear-history-handler
|
||||
"Clears history of the particular chat"
|
||||
{:events [:chat.ui/clear-history]}
|
||||
[{:keys [db] :as cofx} chat-id remove-chat?]
|
||||
(fx/merge cofx
|
||||
{:db db
|
||||
::json-rpc/call [{:method "wakuext_clearHistory"
|
||||
:params [{:id chat-id}]
|
||||
:on-success #(re-frame/dispatch [::history-cleared chat-id %])
|
||||
:on-error #(log/error "failed to clear history " chat-id %)}]}
|
||||
(rf/merge cofx
|
||||
{:db db
|
||||
:json-rpc/call [{:method "wakuext_clearHistory"
|
||||
:params [{:id chat-id}]
|
||||
:on-success #(re-frame/dispatch [::history-cleared chat-id %])
|
||||
:on-error #(log/error "failed to clear history " chat-id %)}]}
|
||||
(clear-history chat-id remove-chat?)))
|
||||
|
||||
(fx/defn chat-deactivated
|
||||
(rf/defn chat-deactivated
|
||||
{:events [::chat-deactivated]}
|
||||
[_ chat-id]
|
||||
(log/debug "chat deactivated" chat-id))
|
||||
|
||||
(fx/defn deactivate-chat
|
||||
(rf/defn deactivate-chat
|
||||
"Deactivate chat in db, no side effects"
|
||||
[{:keys [db now] :as cofx} chat-id]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> (if (get-in db [:chats chat-id :muted])
|
||||
(assoc-in db [:chats chat-id :active] false)
|
||||
(update db :chats dissoc chat-id))
|
||||
(update :chats-home-list disj chat-id)
|
||||
(assoc :current-chat-id nil))
|
||||
::json-rpc/call [{:method "wakuext_deactivateChat"
|
||||
:params [{:id chat-id}]
|
||||
:on-success #(re-frame/dispatch [::chat-deactivated chat-id])
|
||||
:on-error #(log/error "failed to create public chat" chat-id %)}]}
|
||||
{:db (-> (if (get-in db [:chats chat-id :muted])
|
||||
(assoc-in db [:chats chat-id :active] false)
|
||||
(update db :chats dissoc chat-id))
|
||||
(update :chats-home-list disj chat-id)
|
||||
(assoc :current-chat-id nil))
|
||||
:json-rpc/call [{:method "wakuext_deactivateChat"
|
||||
:params [{:id chat-id}]
|
||||
:on-success #(re-frame/dispatch [::chat-deactivated chat-id])
|
||||
:on-error #(log/error "failed to create public chat" chat-id %)}]}
|
||||
(clear-history chat-id true)))
|
||||
|
||||
(fx/defn offload-messages
|
||||
(rf/defn offload-messages
|
||||
{:events [:offload-messages]}
|
||||
[{:keys [db]} chat-id]
|
||||
(merge {:db (-> db
|
||||
@@ -219,52 +218,52 @@
|
||||
(when (and (= chat-id constants/timeline-chat-id) (= (:view-id db) :status))
|
||||
{:dispatch [:init-timeline-chat]})))
|
||||
|
||||
(fx/defn close-chat
|
||||
(rf/defn close-chat
|
||||
{:events [:close-chat]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(when-let [chat-id (:current-chat-id db)]
|
||||
(chat.state/reset-visible-item)
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (dissoc db :current-chat-id)}
|
||||
(delete-for-me/sync-all)
|
||||
(delete-message/send-all)
|
||||
(offload-messages chat-id))))
|
||||
|
||||
(fx/defn force-close-chat
|
||||
(rf/defn force-close-chat
|
||||
[{:keys [db] :as cofx} chat-id]
|
||||
(do
|
||||
(chat.state/reset-visible-item)
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (dissoc db :current-chat-id)}
|
||||
(offload-messages chat-id))))
|
||||
|
||||
(fx/defn remove-chat
|
||||
(rf/defn remove-chat
|
||||
"Removes chat completely from app, producing all necessary effects for that"
|
||||
{:events [:chat.ui/remove-chat]}
|
||||
[{:keys [db now] :as cofx} chat-id]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:clear-message-notifications
|
||||
[[chat-id] (get-in db [:multiaccount :remote-push-notifications-enabled?])]}
|
||||
(deactivate-chat chat-id)
|
||||
(offload-messages chat-id)))
|
||||
|
||||
(fx/defn show-more-chats
|
||||
(rf/defn show-more-chats
|
||||
{:events [:chat.ui/show-more-chats]}
|
||||
[{:keys [db]}]
|
||||
(when (< (:home-items-show-number db) (count (:chats db)))
|
||||
{:db (update db :home-items-show-number + 40)}))
|
||||
|
||||
(fx/defn preload-chat-data
|
||||
(rf/defn preload-chat-data
|
||||
"Takes chat-id and coeffects map, returns effects necessary when navigating to chat"
|
||||
{:events [:chat.ui/preload-chat-data]}
|
||||
[cofx chat-id]
|
||||
(loading/load-messages cofx chat-id))
|
||||
|
||||
(fx/defn navigate-to-chat
|
||||
(rf/defn navigate-to-chat
|
||||
"Takes coeffects map and chat-id, returns effects necessary for navigation and preloading data"
|
||||
{:events [:chat.ui/navigate-to-chat]}
|
||||
[{db :db :as cofx} chat-id]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:dispatch [:navigate-to :chat]}
|
||||
(navigation/change-tab :chat)
|
||||
(when-not (= (:view-id db) :community)
|
||||
@@ -277,11 +276,11 @@
|
||||
#(when (group-chat? cofx chat-id)
|
||||
(loading/load-chat % chat-id))))
|
||||
|
||||
(fx/defn navigate-to-chat-nav2
|
||||
(rf/defn navigate-to-chat-nav2
|
||||
"Takes coeffects map and chat-id, returns effects necessary for navigation and preloading data"
|
||||
{:events [:chat.ui/navigate-to-chat-nav2]}
|
||||
[{db :db :as cofx} chat-id from-shell?]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:dispatch [:navigate-to-nav2 :chat chat-id from-shell?]}
|
||||
(when-not (= (:view-id db) :community)
|
||||
(navigation/pop-to-root-tab :shell-stack))
|
||||
@@ -293,13 +292,13 @@
|
||||
#(when (group-chat? cofx chat-id)
|
||||
(loading/load-chat % chat-id))))
|
||||
|
||||
(fx/defn handle-clear-history-response
|
||||
(rf/defn handle-clear-history-response
|
||||
{:events [::history-cleared]}
|
||||
[{:keys [db]} chat-id response]
|
||||
(let [chat (chats-store/<-rpc (first (:chats response)))]
|
||||
{:db (assoc-in db [:chats chat-id] chat)}))
|
||||
|
||||
(fx/defn handle-one-to-one-chat-created
|
||||
(rf/defn handle-one-to-one-chat-created
|
||||
{:events [::one-to-one-chat-created]}
|
||||
[{:keys [db]} chat-id response]
|
||||
(let [chat (chats-store/<-rpc (first (:chats response)))
|
||||
@@ -314,22 +313,22 @@
|
||||
(update :chats-home-list conj chat-id))
|
||||
:dispatch [:chat.ui/navigate-to-chat chat-id]}))
|
||||
|
||||
(fx/defn navigate-to-user-pinned-messages
|
||||
(rf/defn navigate-to-user-pinned-messages
|
||||
"Takes coeffects map and chat-id, returns effects necessary for navigation and preloading data"
|
||||
{:events [:chat.ui/navigate-to-pinned-messages]}
|
||||
[cofx chat-id]
|
||||
(navigation/navigate-to cofx :chat-pinned-messages {:chat-id chat-id}))
|
||||
|
||||
(fx/defn start-chat
|
||||
(rf/defn start-chat
|
||||
"Start a chat, making sure it exists"
|
||||
{:events [:chat.ui/start-chat]}
|
||||
[{:keys [db] :as cofx} chat-id ens-name]
|
||||
;; don't allow to open chat with yourself
|
||||
(when (not= (multiaccounts.model/current-public-key cofx) chat-id)
|
||||
{::json-rpc/call [{:method "wakuext_createOneToOneChat"
|
||||
:params [{:id chat-id :ensName ens-name}]
|
||||
:on-success #(re-frame/dispatch [::one-to-one-chat-created chat-id %])
|
||||
:on-error #(log/error "failed to create one-to-on chat" chat-id %)}]}))
|
||||
{:json-rpc/call [{:method "wakuext_createOneToOneChat"
|
||||
:params [{:id chat-id :ensName ens-name}]
|
||||
:on-success #(re-frame/dispatch [::one-to-one-chat-created chat-id %])
|
||||
:on-error #(log/error "failed to create one-to-on chat" chat-id %)}]}))
|
||||
|
||||
(defn profile-chat-topic
|
||||
[public-key]
|
||||
@@ -339,7 +338,7 @@
|
||||
[db]
|
||||
(profile-chat-topic (get-in db [:multiaccount :public-key])))
|
||||
|
||||
(fx/defn handle-public-chat-created
|
||||
(rf/defn handle-public-chat-created
|
||||
{:events [::public-chat-created]}
|
||||
[{:keys [db]} chat-id response]
|
||||
{:db (-> db
|
||||
@@ -347,14 +346,14 @@
|
||||
(update :chats-home-list conj chat-id))
|
||||
:dispatch [:chat.ui/navigate-to-chat chat-id]})
|
||||
|
||||
(fx/defn create-public-chat-go
|
||||
(rf/defn create-public-chat-go
|
||||
[_ chat-id]
|
||||
{::json-rpc/call [{:method "wakuext_createPublicChat"
|
||||
:params [{:id chat-id}]
|
||||
:on-success #(re-frame/dispatch [::public-chat-created chat-id %])
|
||||
:on-error #(log/error "failed to create public chat" chat-id %)}]})
|
||||
{:json-rpc/call [{:method "wakuext_createPublicChat"
|
||||
:params [{:id chat-id}]
|
||||
:on-success #(re-frame/dispatch [::public-chat-created chat-id %])
|
||||
:on-error #(log/error "failed to create public chat" chat-id %)}]})
|
||||
|
||||
(fx/defn start-public-chat
|
||||
(rf/defn start-public-chat
|
||||
"Starts a new public chat"
|
||||
{:events [:chat.ui/start-public-chat]}
|
||||
[cofx topic]
|
||||
@@ -367,10 +366,10 @@
|
||||
{:utils/show-popup {:title (i18n/label :t/cant-open-public-chat)
|
||||
:content (i18n/label :t/invalid-public-chat-topic)}}))
|
||||
|
||||
(fx/defn profile-chat-created
|
||||
(rf/defn profile-chat-created
|
||||
{:events [::profile-chat-created]}
|
||||
[{:keys [db] :as cofx} chat-id response navigate-to?]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db db}
|
||||
#(when response
|
||||
@@ -380,19 +379,19 @@
|
||||
{:dispatch-n [[:chat.ui/preload-chat-data chat-id]
|
||||
[:open-modal :profile]]})))
|
||||
|
||||
(fx/defn start-profile-chat
|
||||
(rf/defn start-profile-chat
|
||||
"Starts a new profile chat"
|
||||
{:events [:start-profile-chat]}
|
||||
[cofx profile-public-key navigate-to?]
|
||||
(let [chat-id (profile-chat-topic profile-public-key)]
|
||||
(if (active-chat? cofx chat-id)
|
||||
{:dispatch [::profile-chat-created chat-id nil navigate-to?]}
|
||||
{::json-rpc/call [{:method "wakuext_createProfileChat"
|
||||
:params [{:id profile-public-key}]
|
||||
:on-success #(re-frame/dispatch [::profile-chat-created chat-id % navigate-to?])
|
||||
:on-error #(log/error "failed to create profile chat" chat-id %)}]})))
|
||||
{:json-rpc/call [{:method "wakuext_createProfileChat"
|
||||
:params [{:id profile-public-key}]
|
||||
:on-success #(re-frame/dispatch [::profile-chat-created chat-id % navigate-to?])
|
||||
:on-error #(log/error "failed to create profile chat" chat-id %)}]})))
|
||||
|
||||
(fx/defn disable-chat-cooldown
|
||||
(rf/defn disable-chat-cooldown
|
||||
"Turns off chat cooldown (protection against message spamming)"
|
||||
{:events [:chat/disable-cooldown]}
|
||||
[{:keys [db]}]
|
||||
@@ -406,40 +405,40 @@
|
||||
(i18n/label :cooldown/warning-message)
|
||||
#())))
|
||||
|
||||
(fx/defn mute-chat-failed
|
||||
(rf/defn mute-chat-failed
|
||||
{:events [::mute-chat-failed]}
|
||||
[{:keys [db] :as cofx} chat-id muted? error]
|
||||
(log/error "mute chat failed" chat-id error)
|
||||
{:db (assoc-in db [:chats chat-id :muted] (not muted?))})
|
||||
|
||||
(fx/defn mute-chat-toggled-successfully
|
||||
(rf/defn mute-chat-toggled-successfully
|
||||
{:events [::mute-chat-toggled-successfully]}
|
||||
[_ chat-id]
|
||||
(log/debug "muted chat successfully" chat-id))
|
||||
|
||||
(fx/defn mute-chat
|
||||
(rf/defn mute-chat
|
||||
{:events [::mute-chat-toggled]}
|
||||
[{:keys [db] :as cofx} chat-id muted?]
|
||||
(let [method (if muted? "wakuext_muteChat" "wakuext_unmuteChat")]
|
||||
{:db (assoc-in db [:chats chat-id :muted] muted?)
|
||||
::json-rpc/call [{:method method
|
||||
:params [chat-id]
|
||||
:on-error #(re-frame/dispatch [::mute-chat-failed chat-id muted? %])
|
||||
:on-success #(re-frame/dispatch [::mute-chat-toggled-successfully chat-id])}]}))
|
||||
{:db (assoc-in db [:chats chat-id :muted] muted?)
|
||||
:json-rpc/call [{:method method
|
||||
:params [chat-id]
|
||||
:on-error #(re-frame/dispatch [::mute-chat-failed chat-id muted? %])
|
||||
:on-success #(re-frame/dispatch [::mute-chat-toggled-successfully chat-id])}]}))
|
||||
|
||||
(fx/defn show-profile
|
||||
(rf/defn show-profile
|
||||
{:events [:chat.ui/show-profile]}
|
||||
[{:keys [db] :as cofx} identity ens-name]
|
||||
(let [my-public-key (get-in db [:multiaccount :public-key])]
|
||||
(when (not= my-public-key identity)
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(assoc :contacts/identity identity)
|
||||
(assoc :contacts/ens-name ens-name))}
|
||||
(start-profile-chat identity true)))))
|
||||
|
||||
(fx/defn clear-history-pressed
|
||||
(rf/defn clear-history-pressed
|
||||
{:events [:chat.ui/clear-history-pressed]}
|
||||
[_ chat-id]
|
||||
{:ui/show-confirmation
|
||||
@@ -450,19 +449,19 @@
|
||||
(re-frame/dispatch [:bottom-sheet/hide])
|
||||
(re-frame/dispatch [:chat.ui/clear-history chat-id false]))}})
|
||||
|
||||
(fx/defn gaps-failed
|
||||
(rf/defn gaps-failed
|
||||
{:events [::gaps-failed]}
|
||||
[{:keys [db]} chat-id gap-ids error]
|
||||
(log/error "failed to fetch gaps" chat-id gap-ids error)
|
||||
{:db (dissoc db :mailserver/fetching-gaps-in-progress)})
|
||||
|
||||
(fx/defn sync-chat-from-sync-from-failed
|
||||
(rf/defn sync-chat-from-sync-from-failed
|
||||
{:events [::sync-chat-from-sync-from-failed]}
|
||||
[{:keys [db]} chat-id error]
|
||||
(log/error "failed to sync chat" chat-id error)
|
||||
{:db (dissoc db :mailserver/fetching-gaps-in-progress)})
|
||||
|
||||
(fx/defn sync-chat-from-sync-from-success
|
||||
(rf/defn sync-chat-from-sync-from-success
|
||||
{:events [::sync-chat-from-sync-from-success]}
|
||||
[{:keys [db] :as cofx} chat-id synced-from]
|
||||
(log/debug "synced success" chat-id synced-from)
|
||||
@@ -471,44 +470,44 @@
|
||||
(assoc-in [:chats chat-id :synced-from] synced-from)
|
||||
(dissoc :mailserver/fetching-gaps-in-progress))})
|
||||
|
||||
(fx/defn gaps-filled
|
||||
(rf/defn gaps-filled
|
||||
{:events [::gaps-filled]}
|
||||
[{:keys [db] :as cofx} chat-id message-ids]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(update-in [:messages chat-id] (fn [messages] (apply dissoc messages message-ids)))
|
||||
(dissoc :mailserver/fetching-gaps-in-progress))}
|
||||
(message-list/rebuild-message-list chat-id)))
|
||||
|
||||
(fx/defn fill-gaps
|
||||
(rf/defn fill-gaps
|
||||
[cofx chat-id gap-ids]
|
||||
{::json-rpc/call [{:method "wakuext_fillGaps"
|
||||
:params [chat-id gap-ids]
|
||||
:on-success #(re-frame/dispatch [::gaps-filled chat-id gap-ids %])
|
||||
:on-error #(re-frame/dispatch [::gaps-failed chat-id gap-ids %])}]})
|
||||
{:json-rpc/call [{:method "wakuext_fillGaps"
|
||||
:params [chat-id gap-ids]
|
||||
:on-success #(re-frame/dispatch [::gaps-filled chat-id gap-ids %])
|
||||
:on-error #(re-frame/dispatch [::gaps-failed chat-id gap-ids %])}]})
|
||||
|
||||
(fx/defn sync-chat-from-sync-from
|
||||
(rf/defn sync-chat-from-sync-from
|
||||
[cofx chat-id]
|
||||
(log/debug "syncing chat from sync from")
|
||||
{::json-rpc/call [{:method "wakuext_syncChatFromSyncedFrom"
|
||||
:params [chat-id]
|
||||
:on-success #(re-frame/dispatch [::sync-chat-from-sync-from-success chat-id %])
|
||||
:on-error #(re-frame/dispatch [::sync-chat-from-sync-from-failed chat-id %])}]})
|
||||
{:json-rpc/call [{:method "wakuext_syncChatFromSyncedFrom"
|
||||
:params [chat-id]
|
||||
:on-success #(re-frame/dispatch [::sync-chat-from-sync-from-success chat-id %])
|
||||
:on-error #(re-frame/dispatch [::sync-chat-from-sync-from-failed chat-id %])}]})
|
||||
|
||||
(fx/defn chat-ui-fill-gaps
|
||||
(rf/defn chat-ui-fill-gaps
|
||||
{:events [:chat.ui/fill-gaps]}
|
||||
[{:keys [db] :as cofx} chat-id gap-ids]
|
||||
(let [use-status-nodes? (mailserver/fetch-use-mailservers? {:db db})]
|
||||
(log/info "filling gaps if use-status-nodes = true" chat-id gap-ids)
|
||||
(when use-status-nodes?
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc db :mailserver/fetching-gaps-in-progress gap-ids)}
|
||||
(if (= gap-ids #{:first-gap})
|
||||
(sync-chat-from-sync-from chat-id)
|
||||
(fill-gaps chat-id gap-ids))))))
|
||||
|
||||
(fx/defn chat-ui-remove-chat-pressed
|
||||
(rf/defn chat-ui-remove-chat-pressed
|
||||
{:events [:chat.ui/remove-chat-pressed]}
|
||||
[_ chat-id]
|
||||
{:ui/show-confirmation
|
||||
@@ -519,7 +518,7 @@
|
||||
(re-frame/dispatch [:bottom-sheet/hide])
|
||||
(re-frame/dispatch [:chat.ui/remove-chat chat-id]))}})
|
||||
|
||||
(fx/defn decrease-unviewed-count
|
||||
(rf/defn decrease-unviewed-count
|
||||
{:events [:chat/decrease-unviewed-count]}
|
||||
[{:keys [db]} chat-id {:keys [count countWithMentions]}]
|
||||
{:db (-> db
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.utils.fs :as fs]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.image-processing :as image-processing]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.types :as types]
|
||||
@@ -105,16 +105,22 @@
|
||||
|
||||
(re-frame/reg-fx
|
||||
::camera-roll-get-photos
|
||||
(fn [num]
|
||||
(fn [[num end-cursor]]
|
||||
(permissions/request-permissions
|
||||
{:permissions [:read-external-storage]
|
||||
:on-allowed (fn []
|
||||
(-> (.getPhotos CameraRoll #js {:first num :assetType "Photos" :groupTypes "All"})
|
||||
(.then #(re-frame/dispatch [:on-camera-roll-get-photos
|
||||
(:edges (types/js->clj %))]))
|
||||
(.catch #(log/warn "could not get cameraroll photos"))))})))
|
||||
(-> (if end-cursor
|
||||
(.getPhotos
|
||||
CameraRoll
|
||||
#js {:first num :after end-cursor :assetType "Photos" :groupTypes "All"})
|
||||
(.getPhotos CameraRoll
|
||||
#js {:first num :assetType "Photos" :groupTypes "All"}))
|
||||
(.then #(let [response (types/js->clj %)]
|
||||
(re-frame/dispatch [:on-camera-roll-get-photos (:edges response)
|
||||
(:page_info response) end-cursor])))
|
||||
(.catch #(log/warn "could not get camera roll photos"))))})))
|
||||
|
||||
(fx/defn image-captured
|
||||
(rf/defn image-captured
|
||||
{:events [:chat.ui/image-captured]}
|
||||
[{:keys [db]} chat-id uri]
|
||||
(let [current-chat-id (or chat-id (:current-chat-id db))
|
||||
@@ -123,44 +129,61 @@
|
||||
(not (get images uri)))
|
||||
{::image-selected [uri current-chat-id]})))
|
||||
|
||||
(fx/defn camera-roll-get-photos
|
||||
(rf/defn on-end-reached
|
||||
{:events [:camera-roll/on-end-reached]}
|
||||
[_ end-cursor loading? has-next-page?]
|
||||
(when (and (not loading?) has-next-page?)
|
||||
(re-frame/dispatch [:chat.ui/camera-roll-loading-more true])
|
||||
(re-frame/dispatch [:chat.ui/camera-roll-get-photos 20 end-cursor])))
|
||||
|
||||
(rf/defn camera-roll-get-photos
|
||||
{:events [:chat.ui/camera-roll-get-photos]}
|
||||
[_ num]
|
||||
{::camera-roll-get-photos num})
|
||||
[_ num end-cursor]
|
||||
{::camera-roll-get-photos [num end-cursor]})
|
||||
|
||||
(fx/defn on-camera-roll-get-photos
|
||||
(rf/defn camera-roll-loading-more
|
||||
{:events [:chat.ui/camera-roll-loading-more]}
|
||||
[{:keys [db]} is-loading]
|
||||
{:db (assoc db :camera-roll/loading-more is-loading)})
|
||||
|
||||
(rf/defn on-camera-roll-get-photos
|
||||
{:events [:on-camera-roll-get-photos]}
|
||||
[{db :db} photos]
|
||||
{:db (assoc db :camera-roll-photos (mapv #(get-in % [:node :image :uri]) photos))})
|
||||
[{:keys [db] :as cofx} photos page-info end-cursor]
|
||||
(let [photos_x (when end-cursor (:camera-roll/photos db))]
|
||||
{:db (-> db
|
||||
(assoc :camera-roll/photos (concat photos_x (map #(get-in % [:node :image :uri]) photos)))
|
||||
(assoc :camera-roll/end-cursor (:end_cursor page-info))
|
||||
(assoc :camera-roll/has-next-page (:has_next_page page-info))
|
||||
(assoc :camera-roll/loading-more false))}))
|
||||
|
||||
(fx/defn clear-sending-images
|
||||
(rf/defn clear-sending-images
|
||||
{:events [:chat.ui/clear-sending-images]}
|
||||
[{:keys [db]} current-chat-id]
|
||||
{:db (update-in db [:chat/inputs current-chat-id :metadata] assoc :sending-image {})})
|
||||
|
||||
(fx/defn cancel-sending-image
|
||||
(rf/defn cancel-sending-image
|
||||
{:events [:chat.ui/cancel-sending-image]}
|
||||
[{:keys [db] :as cofx} chat-id]
|
||||
(let [current-chat-id (or chat-id (:current-chat-id db))]
|
||||
(clear-sending-images cofx current-chat-id)))
|
||||
|
||||
(fx/defn cancel-sending-image-timeline
|
||||
(rf/defn cancel-sending-image-timeline
|
||||
{:events [:chat.ui/cancel-sending-image-timeline]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(cancel-sending-image cofx (chat/my-profile-chat-topic db)))
|
||||
|
||||
(fx/defn image-selected
|
||||
(rf/defn image-selected
|
||||
{:events [:chat.ui/image-selected]}
|
||||
[{:keys [db]} current-chat-id original uri]
|
||||
{:db (update-in db [:chat/inputs current-chat-id :metadata :sending-image original] merge {:uri uri})})
|
||||
|
||||
(fx/defn image-unselected
|
||||
(rf/defn image-unselected
|
||||
{:events [:chat.ui/image-unselected]}
|
||||
[{:keys [db]} original]
|
||||
(let [current-chat-id (:current-chat-id db)]
|
||||
{:db (update-in db [:chat/inputs current-chat-id :metadata :sending-image] dissoc original)}))
|
||||
|
||||
(fx/defn chat-open-image-picker
|
||||
(rf/defn chat-open-image-picker
|
||||
{:events [:chat.ui/open-image-picker]}
|
||||
[{:keys [db]} chat-id]
|
||||
(let [current-chat-id (or chat-id (:current-chat-id db))
|
||||
@@ -168,12 +191,12 @@
|
||||
(when (< (count images) config/max-images-batch)
|
||||
{::chat-open-image-picker current-chat-id})))
|
||||
|
||||
(fx/defn chat-open-image-picker-timeline
|
||||
(rf/defn chat-open-image-picker-timeline
|
||||
{:events [:chat.ui/open-image-picker-timeline]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(chat-open-image-picker cofx (chat/my-profile-chat-topic db)))
|
||||
|
||||
(fx/defn chat-show-image-picker-camera
|
||||
(rf/defn chat-show-image-picker-camera
|
||||
{:events [:chat.ui/show-image-picker-camera]}
|
||||
[{:keys [db]} chat-id]
|
||||
(let [current-chat-id (or chat-id (:current-chat-id db))
|
||||
@@ -181,12 +204,12 @@
|
||||
(when (< (count images) config/max-images-batch)
|
||||
{::chat-open-image-picker-camera current-chat-id})))
|
||||
|
||||
(fx/defn chat-show-image-picker-camera-timeline
|
||||
(rf/defn chat-show-image-picker-camera-timeline
|
||||
{:events [:chat.ui/show-image-picker-camera-timeline]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(chat-show-image-picker-camera cofx (chat/my-profile-chat-topic db)))
|
||||
|
||||
(fx/defn camera-roll-pick
|
||||
(rf/defn camera-roll-pick
|
||||
{:events [:chat.ui/camera-roll-pick]}
|
||||
[{:keys [db]} uri chat-id]
|
||||
(let [current-chat-id (or chat-id (:current-chat-id db))
|
||||
@@ -198,12 +221,12 @@
|
||||
(not (get images uri)))
|
||||
{::image-selected [uri current-chat-id]}))))
|
||||
|
||||
(fx/defn camera-roll-pick-timeline
|
||||
(rf/defn camera-roll-pick-timeline
|
||||
{:events [:chat.ui/camera-roll-pick-timeline]}
|
||||
[{:keys [db] :as cofx} uri]
|
||||
(camera-roll-pick cofx uri (chat/my-profile-chat-topic db)))
|
||||
|
||||
(fx/defn save-image-to-gallery
|
||||
(rf/defn save-image-to-gallery
|
||||
{:events [:chat.ui/save-image-to-gallery]}
|
||||
[_ base64-uri]
|
||||
{::save-image-to-gallery base64-uri})
|
||||
|
||||
@@ -9,10 +9,9 @@
|
||||
[status-im.chat.models.message :as chat.message]
|
||||
[status-im.chat.models.message-content :as message-content]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.utils.datetime :as datetime]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.utils :as utils]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
@@ -26,7 +25,7 @@
|
||||
(.-char ^js emoji-map)
|
||||
original))))
|
||||
|
||||
(fx/defn set-chat-input-text
|
||||
(rf/defn set-chat-input-text
|
||||
"Set input text for current-chat. Takes db and input text and cofx
|
||||
as arguments and returns new fx. Always clear all validation messages."
|
||||
{:events [:chat.ui/set-chat-input-text]}
|
||||
@@ -34,21 +33,21 @@
|
||||
(let [current-chat-id (or chat-id (:current-chat-id db))]
|
||||
{:db (assoc-in db [:chat/inputs current-chat-id :input-text] (text->emoji new-input))}))
|
||||
|
||||
(fx/defn set-timeline-input-text
|
||||
(rf/defn set-timeline-input-text
|
||||
{:events [:chat.ui/set-timeline-input-text]}
|
||||
[{db :db} new-input]
|
||||
{:db (assoc-in db
|
||||
[:chat/inputs (chat/my-profile-chat-topic db) :input-text]
|
||||
(text->emoji new-input))})
|
||||
|
||||
(fx/defn select-mention
|
||||
(rf/defn select-mention
|
||||
{:events [:chat.ui/select-mention]}
|
||||
[{:keys [db] :as cofx} text-input-ref {:keys [alias name searched-text match] :as user}]
|
||||
(let [chat-id (:current-chat-id db)
|
||||
new-text (mentions/new-input-text-with-mention cofx user)
|
||||
at-sign-idx (get-in db [:chats/mentions chat-id :mentions :at-sign-idx])
|
||||
cursor (+ at-sign-idx (count name) 2)]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:chats/cursor chat-id] cursor)
|
||||
@@ -92,7 +91,7 @@
|
||||
:chat/spam-messages-frequency 0
|
||||
:chat/cooldown-enabled? true)})
|
||||
|
||||
(fx/defn process-cooldown
|
||||
(rf/defn process-cooldown
|
||||
"Process cooldown to protect against message spammers"
|
||||
[{{:keys [chat/last-outgoing-message-sent-at
|
||||
chat/cooldowns
|
||||
@@ -115,12 +114,12 @@
|
||||
(and spamming-fast? spamming-frequently?)
|
||||
(start-cooldown (inc cooldowns))))))
|
||||
|
||||
(fx/defn reply-to-message
|
||||
(rf/defn reply-to-message
|
||||
"Sets reference to previous chat message and focuses on input"
|
||||
{:events [:chat.ui/reply-to-message]}
|
||||
[{:keys [db] :as cofx} message]
|
||||
(let [current-chat-id (:current-chat-id db)]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message]
|
||||
message)
|
||||
@@ -129,7 +128,7 @@
|
||||
dissoc
|
||||
:sending-image))})))
|
||||
|
||||
(fx/defn edit-message
|
||||
(rf/defn edit-message
|
||||
"Sets reference to previous chat message and focuses on input"
|
||||
{:events [:chat.ui/edit-message]}
|
||||
[{:keys [db] :as cofx} message]
|
||||
@@ -145,7 +144,7 @@
|
||||
dissoc
|
||||
:sending-image))}))
|
||||
|
||||
(fx/defn show-contact-request-input
|
||||
(rf/defn show-contact-request-input
|
||||
"Sets reference to previous chat message and focuses on input"
|
||||
{:events [:chat.ui/send-contact-request]}
|
||||
[{:keys [db] :as cofx}]
|
||||
@@ -160,7 +159,7 @@
|
||||
dissoc
|
||||
:sending-image))}))
|
||||
|
||||
(fx/defn cancel-message-reply
|
||||
(rf/defn cancel-message-reply
|
||||
"Cancels stage message reply"
|
||||
{:events [:chat.ui/cancel-message-reply]}
|
||||
[{:keys [db]}]
|
||||
@@ -185,17 +184,19 @@
|
||||
|
||||
(defn build-image-messages
|
||||
[{db :db} chat-id]
|
||||
(let [images (get-in db [:chat/inputs chat-id :metadata :sending-image])]
|
||||
(let [images (get-in db [:chat/inputs chat-id :metadata :sending-image])
|
||||
album-id (str (random-uuid))]
|
||||
(mapv (fn [[_ {:keys [uri]}]]
|
||||
{:chat-id chat-id
|
||||
:album-id album-id
|
||||
:content-type constants/content-type-image
|
||||
:image-path (utils/safe-replace uri #"file://" "")
|
||||
:text (i18n/label :t/update-to-see-image {"locale" "en"})})
|
||||
images)))
|
||||
|
||||
(fx/defn clean-input
|
||||
(rf/defn clean-input
|
||||
[{:keys [db] :as cofx} current-chat-id]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:chat/inputs current-chat-id :metadata :sending-contact-request] nil)
|
||||
(assoc-in [:chat/inputs current-chat-id :metadata :sending-image] nil)
|
||||
@@ -203,29 +204,29 @@
|
||||
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message] nil))}
|
||||
(set-chat-input-text nil current-chat-id)))
|
||||
|
||||
(fx/defn cancel-message-edit
|
||||
(rf/defn cancel-message-edit
|
||||
"Cancels stage message edit"
|
||||
{:events [:chat.ui/cancel-message-edit]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [current-chat-id (:current-chat-id db)]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:set-text-input-value [current-chat-id ""]}
|
||||
(clean-input current-chat-id)
|
||||
(mentions/clear-mentions)
|
||||
(mentions/clear-cursor))))
|
||||
|
||||
(fx/defn send-messages
|
||||
(rf/defn send-messages
|
||||
[{:keys [db] :as cofx} input-text current-chat-id]
|
||||
(let [image-messages (build-image-messages cofx current-chat-id)
|
||||
text-message (build-text-message cofx input-text current-chat-id)
|
||||
messages (keep identity (conj image-messages text-message))]
|
||||
(when (seq messages)
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(clean-input (:current-chat-id db))
|
||||
(process-cooldown)
|
||||
(chat.message/send-messages messages)))))
|
||||
|
||||
(fx/defn send-my-status-message
|
||||
(rf/defn send-my-status-message
|
||||
"when not empty, proceed by sending text message with public key topic"
|
||||
{:events [:profile.ui/send-my-status-message]}
|
||||
[{db :db :as cofx}]
|
||||
@@ -235,11 +236,11 @@
|
||||
text-message (build-text-message cofx input-text current-chat-id)
|
||||
messages (keep identity (conj image-messages text-message))]
|
||||
(when (seq messages)
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(clean-input current-chat-id)
|
||||
(chat.message/send-messages messages)))))
|
||||
|
||||
(fx/defn send-audio-message
|
||||
(rf/defn send-audio-message
|
||||
[cofx audio-path duration current-chat-id]
|
||||
(when-not (string/blank? audio-path)
|
||||
(chat.message/send-message
|
||||
@@ -250,7 +251,7 @@
|
||||
:audio-duration-ms duration
|
||||
:text (i18n/label :t/update-to-listen-audio {"locale" "en"})})))
|
||||
|
||||
(fx/defn send-sticker-message
|
||||
(rf/defn send-sticker-message
|
||||
[cofx {:keys [hash packID pack]} current-chat-id]
|
||||
(when-not (or (string/blank? hash) (and (string/blank? packID) (string/blank? pack)))
|
||||
(chat.message/send-message cofx
|
||||
@@ -260,44 +261,44 @@
|
||||
:pack (int (if (string/blank? packID) pack packID))}
|
||||
:text (i18n/label :t/update-to-see-sticker {"locale" "en"})})))
|
||||
|
||||
(fx/defn send-edited-message
|
||||
(rf/defn send-edited-message
|
||||
[{:keys [db] :as cofx} text {:keys [message-id quoted-message]}]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{::json-rpc/call [{:method "wakuext_editMessage"
|
||||
:params [{:id message-id
|
||||
:text text
|
||||
:content-type (if (message-content/emoji-only-content?
|
||||
{:text text :response-to quoted-message})
|
||||
constants/content-type-emoji
|
||||
constants/content-type-text)}]
|
||||
:js-response true
|
||||
:on-error #(log/error "failed to edit message " %)
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]}
|
||||
{:json-rpc/call [{:method "wakuext_editMessage"
|
||||
:params [{:id message-id
|
||||
:text text
|
||||
:content-type (if (message-content/emoji-only-content?
|
||||
{:text text :response-to quoted-message})
|
||||
constants/content-type-emoji
|
||||
constants/content-type-text)}]
|
||||
:js-response true
|
||||
:on-error #(log/error "failed to edit message " %)
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]}
|
||||
(cancel-message-edit)
|
||||
(process-cooldown)))
|
||||
|
||||
(fx/defn send-current-message
|
||||
(rf/defn send-current-message
|
||||
"Sends message from current chat input"
|
||||
{:events [:chat.ui/send-current-message]}
|
||||
[{{:keys [current-chat-id] :as db} :db :as cofx}]
|
||||
(let [{:keys [input-text metadata]} (get-in db [:chat/inputs current-chat-id])
|
||||
editing-message (:editing-message metadata)
|
||||
input-text-with-mentions (mentions/check-mentions cofx input-text)]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(if editing-message
|
||||
(send-edited-message input-text-with-mentions editing-message)
|
||||
(send-messages input-text-with-mentions current-chat-id))
|
||||
(mentions/clear-mentions)
|
||||
(mentions/clear-cursor))))
|
||||
|
||||
(fx/defn send-contact-request
|
||||
(rf/defn send-contact-request
|
||||
{:events [:contacts/send-contact-request]}
|
||||
[{:keys [db] :as cofx} public-key message]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:chat.ui/clear-inputs nil
|
||||
:chat.ui/clear-inputs-old nil
|
||||
::json-rpc/call [{:method "wakuext_sendContactRequest"
|
||||
:json-rpc/call [{:method "wakuext_sendContactRequest"
|
||||
:js-response true
|
||||
:params [{:id public-key :message message}]
|
||||
:on-error #(log/warn "failed to send a contact request" %)
|
||||
@@ -307,33 +308,33 @@
|
||||
(clean-input (:current-chat-id db))
|
||||
(process-cooldown)))
|
||||
|
||||
(fx/defn cancel-contact-request
|
||||
(rf/defn cancel-contact-request
|
||||
"Cancels contact request"
|
||||
{:events [:chat.ui/cancel-contact-request]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [current-chat-id (:current-chat-id db)]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:chat/inputs current-chat-id :metadata :sending-contact-request] nil)}
|
||||
(mentions/clear-mentions)
|
||||
(mentions/clear-cursor)
|
||||
(clean-input (:current-chat-id db))
|
||||
(process-cooldown))))
|
||||
|
||||
(fx/defn chat-send-sticker
|
||||
(rf/defn chat-send-sticker
|
||||
{:events [:chat/send-sticker]}
|
||||
[{{:keys [current-chat-id] :as db} :db :as cofx} {:keys [hash packID pack] :as sticker}]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (update db
|
||||
:stickers/recent-stickers
|
||||
(fn [recent]
|
||||
(conj (remove #(= hash (:hash %)) recent) sticker)))
|
||||
::json-rpc/call [{:method "stickers_addRecent"
|
||||
:params [(int (if (string/blank? packID) pack packID)) hash]
|
||||
:on-success #()}]}
|
||||
{:db (update db
|
||||
:stickers/recent-stickers
|
||||
(fn [recent]
|
||||
(conj (remove #(= hash (:hash %)) recent) sticker)))
|
||||
:json-rpc/call [{:method "stickers_addRecent"
|
||||
:params [(int (if (string/blank? packID) pack packID)) hash]
|
||||
:on-success #()}]}
|
||||
(send-sticker-message sticker current-chat-id)))
|
||||
|
||||
(fx/defn chat-send-audio
|
||||
(rf/defn chat-send-audio
|
||||
{:events [:chat/send-audio]}
|
||||
[{{:keys [current-chat-id]} :db :as cofx} audio-path duration]
|
||||
(send-audio-message cofx audio-path duration current-chat-id))
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
(ns status-im.chat.models.link-preview
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.communities.core :as models.communities]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(fx/defn enable
|
||||
(rf/defn enable
|
||||
{:events [::enable]}
|
||||
[{{:keys [multiaccount]} :db :as cofx} site enabled?]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:link-previews-enabled-sites
|
||||
(if enabled?
|
||||
@@ -17,10 +16,10 @@
|
||||
(disj (get multiaccount :link-previews-enabled-sites #{}) site))
|
||||
{})))
|
||||
|
||||
(fx/defn enable-all
|
||||
(rf/defn enable-all
|
||||
{:events [::enable-all]}
|
||||
[{{:keys [multiaccount]} :db :as cofx} link-previews-whitelist enabled?]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:link-previews-enabled-sites
|
||||
(if enabled?
|
||||
@@ -40,7 +39,7 @@
|
||||
[db community-id]
|
||||
(assoc-in db [:communities/resolve-community-info community-id] true))
|
||||
|
||||
(fx/defn handle-community-failed-to-resolve
|
||||
(rf/defn handle-community-failed-to-resolve
|
||||
{:events [::community-failed-to-resolve]}
|
||||
[{:keys [db]} community-id]
|
||||
{:db (community-failed-to-resolve db community-id)})
|
||||
@@ -49,10 +48,10 @@
|
||||
[id]
|
||||
(str "https://join.status.im/c/" id))
|
||||
|
||||
(fx/defn handle-community-resolved
|
||||
(rf/defn handle-community-resolved
|
||||
{:events [::community-resolved]}
|
||||
[{:keys [db] :as cofx} community-id community]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(cond-> {:db (community-resolved db community-id)}
|
||||
(some? community)
|
||||
(assoc :dispatch
|
||||
@@ -60,29 +59,29 @@
|
||||
(community-link community-id) community]))
|
||||
(models.communities/handle-community community)))
|
||||
|
||||
(fx/defn resolve-community-info
|
||||
(rf/defn resolve-community-info
|
||||
{:events [::resolve-community-info]}
|
||||
[{:keys [db]} community-id]
|
||||
{:db (community-resolving db community-id)
|
||||
::json-rpc/call [{:method "wakuext_requestCommunityInfoFromMailserver"
|
||||
:params [community-id]
|
||||
:on-success #(re-frame/dispatch [::community-resolved community-id %])
|
||||
:on-error #(do
|
||||
(re-frame/dispatch [::community-failed-to-resolve community-id])
|
||||
(log/error "Failed to request community info from mailserver"))}]})
|
||||
{:db (community-resolving db community-id)
|
||||
:json-rpc/call [{:method "wakuext_requestCommunityInfoFromMailserver"
|
||||
:params [community-id]
|
||||
:on-success #(re-frame/dispatch [::community-resolved community-id %])
|
||||
:on-error #(do
|
||||
(re-frame/dispatch [::community-failed-to-resolve community-id])
|
||||
(log/error "Failed to request community info from mailserver"))}]})
|
||||
|
||||
(fx/defn load-link-preview-data
|
||||
(rf/defn load-link-preview-data
|
||||
{:events [::load-link-preview-data]}
|
||||
[cofx link]
|
||||
{::json-rpc/call [{:method "wakuext_getLinkPreviewData"
|
||||
:params [link]
|
||||
:on-success #(re-frame/dispatch [::cache-link-preview-data link %])
|
||||
:on-error #(re-frame/dispatch
|
||||
[::cache-link-preview-data
|
||||
link
|
||||
{:error (str "Can't get preview data for " link)}])}]})
|
||||
{:json-rpc/call [{:method "wakuext_getLinkPreviewData"
|
||||
:params [link]
|
||||
:on-success #(re-frame/dispatch [::cache-link-preview-data link %])
|
||||
:on-error #(re-frame/dispatch
|
||||
[::cache-link-preview-data
|
||||
link
|
||||
{:error (str "Can't get preview data for " link)}])}]})
|
||||
|
||||
(fx/defn cache-link-preview-data
|
||||
(rf/defn cache-link-preview-data
|
||||
{:events [::cache-link-preview-data]}
|
||||
[{{:keys [multiaccount]} :db :as cofx} site data]
|
||||
(multiaccounts.update/optimistic
|
||||
@@ -96,7 +95,7 @@
|
||||
(community-link id)
|
||||
community]))
|
||||
|
||||
(fx/defn should-suggest-link-preview
|
||||
(rf/defn should-suggest-link-preview
|
||||
{:events [::should-suggest-link-preview]}
|
||||
[{:keys [db] :as cofx} enabled?]
|
||||
(multiaccounts.update/multiaccount-update
|
||||
@@ -105,14 +104,14 @@
|
||||
(boolean enabled?)
|
||||
{}))
|
||||
|
||||
(fx/defn request-link-preview-whitelist
|
||||
(rf/defn request-link-preview-whitelist
|
||||
[_]
|
||||
{::json-rpc/call [{:method "wakuext_getLinkPreviewWhitelist"
|
||||
:params []
|
||||
:on-success #(re-frame/dispatch [::link-preview-whitelist-received %])
|
||||
:on-error #(log/error "Failed to get link preview whitelist")}]})
|
||||
{:json-rpc/call [{:method "wakuext_getLinkPreviewWhitelist"
|
||||
:params []
|
||||
:on-success #(re-frame/dispatch [::link-preview-whitelist-received %])
|
||||
:on-error #(log/error "Failed to get link preview whitelist")}]})
|
||||
|
||||
(fx/defn save-link-preview-whitelist
|
||||
(rf/defn save-link-preview-whitelist
|
||||
{:events [::link-preview-whitelist-received]}
|
||||
[{:keys [db]} whitelist]
|
||||
{:db (assoc db
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
(ns status-im.chat.models.loading
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.activity-center.core :as activity-center]
|
||||
[status-im.chat.models.message-list :as message-list]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.data-store.chats :as data-store.chats]
|
||||
[status-im.data-store.messages :as data-store.messages]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.utils.fx :as fx]
|
||||
[taoensso.timbre :as log]))
|
||||
[status-im2.contexts.activity-center.events :as activity-center]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn cursor->clock-value
|
||||
[^js cursor]
|
||||
@@ -19,7 +18,7 @@
|
||||
clock-value
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000"))
|
||||
|
||||
(fx/defn update-chats-in-app-db
|
||||
(rf/defn update-chats-in-app-db
|
||||
{:events [:chats-list/load-success]}
|
||||
[{:keys [db]} ^js new-chats-js]
|
||||
(let [{:keys [all-chats chats-home-list]}
|
||||
@@ -39,20 +38,20 @@
|
||||
:chats-home-list chats-home-list
|
||||
:chats/loading? false)}))
|
||||
|
||||
(fx/defn load-chat-success
|
||||
(rf/defn load-chat-success
|
||||
{:events [:chats-list/load-chat-success]}
|
||||
[{:keys [db]} ^js chat]
|
||||
(let [{:keys [chat-id] :as chat} (data-store.chats/<-rpc chat)]
|
||||
{:db (update-in db [:chats chat-id] merge chat)}))
|
||||
|
||||
(fx/defn load-chat
|
||||
(rf/defn load-chat
|
||||
[_ chat-id]
|
||||
{::json-rpc/call [{:method "wakuext_chat"
|
||||
:params [chat-id]
|
||||
:on-success #(re-frame/dispatch [:chats-list/load-chat-success %])
|
||||
:on-error #(log/error "failed to fetch chats" 0 -1 %)}]})
|
||||
{:json-rpc/call [{:method "wakuext_chat"
|
||||
:params [chat-id]
|
||||
:on-success #(re-frame/dispatch [:chats-list/load-chat-success %])
|
||||
:on-error #(log/error "failed to fetch chats" 0 -1 %)}]})
|
||||
|
||||
(fx/defn handle-failed-loading-messages
|
||||
(rf/defn handle-failed-loading-messages
|
||||
{:events [::failed-loading-messages]}
|
||||
[{:keys [db]} current-chat-id _ err]
|
||||
(log/error "failed loading messages" current-chat-id err)
|
||||
@@ -68,41 +67,47 @@
|
||||
:unviewed-mentions-count 0
|
||||
:highlight false))
|
||||
|
||||
(fx/defn handle-mark-all-read-successful
|
||||
(rf/defn handle-mark-all-read-successful
|
||||
{:events [::mark-all-read-successful]}
|
||||
[cofx]
|
||||
(activity-center/notifications-fetch-unread-count cofx))
|
||||
|
||||
(fx/defn handle-mark-all-read-in-community-successful
|
||||
(rf/defn handle-mark-all-read-in-community-successful
|
||||
{:events [::mark-all-read-in-community-successful]}
|
||||
[{:keys [db] :as cofx} chat-ids]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (reduce mark-chat-all-read db chat-ids)}
|
||||
(activity-center/notifications-fetch-unread-count)))
|
||||
|
||||
(fx/defn handle-mark-all-read
|
||||
(rf/defn handle-mark-all-read
|
||||
{:events [:chat.ui/mark-all-read-pressed :chat/mark-all-as-read]}
|
||||
[{db :db} chat-id]
|
||||
{:db (mark-chat-all-read db chat-id)
|
||||
:clear-message-notifications [[chat-id]
|
||||
(get-in db [:multiaccount :remote-push-notifications-enabled?])]
|
||||
::json-rpc/call [{:method "wakuext_markAllRead"
|
||||
:json-rpc/call [{:method "wakuext_markAllRead"
|
||||
:params [chat-id]
|
||||
:on-success #(re-frame/dispatch [::mark-all-read-successful])}]})
|
||||
|
||||
(fx/defn handle-mark-mark-all-read-in-community
|
||||
(rf/defn handle-mark-mark-all-read-in-community
|
||||
{:events [:chat.ui/mark-all-read-in-community-pressed]}
|
||||
[{db :db} community-id]
|
||||
(let [community-chat-ids (map #(str community-id %)
|
||||
(keys (get-in db [:communities community-id :chats])))]
|
||||
{:clear-message-notifications [community-chat-ids
|
||||
(get-in db [:multiaccount :remote-push-notifications-enabled?])]
|
||||
::json-rpc/call [{:method "wakuext_markAllReadInCommunity"
|
||||
:json-rpc/call [{:method "wakuext_markAllReadInCommunity"
|
||||
:params [community-id]
|
||||
:on-success #(re-frame/dispatch
|
||||
[::mark-all-read-in-community-successful %])}]}))
|
||||
|
||||
(fx/defn messages-loaded
|
||||
(defn mark-album
|
||||
[message]
|
||||
(if (:album-id message)
|
||||
(assoc message :albumize? true)
|
||||
message))
|
||||
|
||||
(rf/defn messages-loaded
|
||||
"Loads more messages for current chat"
|
||||
{:events [::messages-loaded]}
|
||||
[{db :db} chat-id session-id {:keys [cursor messages]}]
|
||||
@@ -132,8 +137,8 @@
|
||||
current-clock-value (get-in db
|
||||
[:pagination-info chat-id
|
||||
:cursor-clock-value])
|
||||
clock-value (when cursor
|
||||
(cursor->clock-value cursor))]
|
||||
clock-value (when cursor (cursor->clock-value cursor))
|
||||
new-messages (map mark-album new-messages)]
|
||||
{:dispatch [:chat/add-senders-to-chat-users (vals senders)]
|
||||
:db (-> db
|
||||
(update-in [:pagination-info chat-id :cursor-clock-value]
|
||||
@@ -154,7 +159,7 @@
|
||||
(empty? cursor))
|
||||
(update :contacts/contacts merge contacts))})))
|
||||
|
||||
(fx/defn load-more-messages
|
||||
(rf/defn load-more-messages
|
||||
{:events [:chat.ui/load-more-messages]}
|
||||
[{:keys [db]} chat-id first-request]
|
||||
(when-let [session-id (get-in db [:pagination-info chat-id :messages-initialized?])]
|
||||
@@ -173,15 +178,15 @@
|
||||
#(re-frame/dispatch [::messages-loaded chat-id session-id %])
|
||||
#(re-frame/dispatch [::failed-loading-messages chat-id session-id %]))))))))
|
||||
|
||||
(fx/defn load-more-messages-for-current-chat
|
||||
(rf/defn load-more-messages-for-current-chat
|
||||
{:events [:chat.ui/load-more-messages-for-current-chat]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(load-more-messages cofx (:current-chat-id db) false))
|
||||
|
||||
(fx/defn load-messages
|
||||
(rf/defn load-messages
|
||||
[{:keys [db now] :as cofx} chat-id]
|
||||
(when-not (get-in db [:pagination-info chat-id :messages-initialized?])
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:pagination-info chat-id :messages-initialized?] now)
|
||||
:utils/dispatch-later [{:ms 50 :dispatch [:chat.ui/mark-all-read-pressed chat-id]}
|
||||
(when-not (get-in cofx [:db :chats chat-id :public?])
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
[status-im.contact.db :as contact.db]
|
||||
[status-im.multiaccounts.core :as multiaccounts]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.utils :as utils]
|
||||
[taoensso.timbre :as log]))
|
||||
@@ -526,7 +526,7 @@
|
||||
(assoc-in [last-idx :to] (dec (count text)))
|
||||
(assoc-in [last-idx :checked?] false)))))))
|
||||
|
||||
(fx/defn on-text-input
|
||||
(rf/defn on-text-input
|
||||
{:events [::on-text-input]}
|
||||
[{:keys [db]} {:keys [previous-text start end] :as args}]
|
||||
(log/debug "[mentions] on-text-input args" args)
|
||||
@@ -573,7 +573,7 @@
|
||||
[[:text (subs text 0 first-from)]]))
|
||||
idxs))))
|
||||
|
||||
(fx/defn recheck-at-idxs
|
||||
(rf/defn recheck-at-idxs
|
||||
[{:keys [db]} mentionable-users]
|
||||
(let [chat-id (:current-chat-id db)
|
||||
text (get-in db [:chat/inputs chat-id :input-text])
|
||||
@@ -592,7 +592,7 @@
|
||||
new-at-idxs)
|
||||
(assoc-in [:chat/inputs-with-mentions chat-id] calculated-input))}))
|
||||
|
||||
(fx/defn calculate-suggestions
|
||||
(rf/defn calculate-suggestions
|
||||
{:events [::calculate-suggestions]}
|
||||
[{:keys [db]} mentionable-users]
|
||||
(let [chat-id (:current-chat-id db)
|
||||
@@ -600,9 +600,9 @@
|
||||
{:keys [new-text at-idxs start end] :as state}
|
||||
(get-in db [:chats/mentions chat-id :mentions])
|
||||
new-text (or new-text text)]
|
||||
(log/info "[mentions] calculate suggestions"
|
||||
"state"
|
||||
state)
|
||||
(log/debug "[mentions] calculate suggestions"
|
||||
"state"
|
||||
state)
|
||||
(if-not (seq at-idxs)
|
||||
{:db (-> db
|
||||
(assoc-in [:chats/mention-suggestions chat-id] nil)
|
||||
@@ -659,31 +659,31 @@
|
||||
" "))
|
||||
(subs text mention-end)])))
|
||||
|
||||
(fx/defn clear-suggestions
|
||||
(rf/defn clear-suggestions
|
||||
[{:keys [db]}]
|
||||
(log/debug "[mentions] clear suggestions")
|
||||
(let [chat-id (:current-chat-id db)]
|
||||
{:db (update db :chats/mention-suggestions dissoc chat-id)}))
|
||||
|
||||
(fx/defn clear-mentions
|
||||
(rf/defn clear-mentions
|
||||
[{:keys [db] :as cofx}]
|
||||
(log/debug "[mentions] clear mentions")
|
||||
(let [chat-id (:current-chat-id db)]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(update-in [:chats/mentions chat-id] dissoc :mentions)
|
||||
(update :chat/inputs-with-mentions dissoc chat-id))}
|
||||
(clear-suggestions))))
|
||||
|
||||
(fx/defn clear-cursor
|
||||
(rf/defn clear-cursor
|
||||
{:events [::clear-cursor]}
|
||||
[{:keys [db]}]
|
||||
(log/debug "[mentions] clear cursor")
|
||||
{:db
|
||||
(update db :chats/cursor dissoc (:current-chat-id db))})
|
||||
|
||||
(fx/defn check-selection
|
||||
(rf/defn check-selection
|
||||
{:events [::on-selection-change]}
|
||||
[{:keys [db] :as cofx}
|
||||
{:keys [start end] :as selection}
|
||||
@@ -698,7 +698,7 @@
|
||||
(<= (dec end) to))
|
||||
idx))
|
||||
at-idxs)
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (update-in db
|
||||
[:chats/mentions chat-id :mentions]
|
||||
@@ -717,7 +717,7 @@
|
||||
(rn/find-node-handle (react/current-ref ref))
|
||||
cursor))))
|
||||
|
||||
(fx/defn reset-text-input-cursor
|
||||
(rf/defn reset-text-input-cursor
|
||||
[_ ref cursor]
|
||||
{::reset-text-input-cursor [ref cursor]})
|
||||
|
||||
|
||||
@@ -2,19 +2,18 @@
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.chat.models :as chat-model]
|
||||
[status-im.chat.models.delete-message :as delete-message]
|
||||
[status-im.chat.models.loading :as chat.loading]
|
||||
[status-im.chat.models.mentions :as mentions]
|
||||
[status-im.chat.models.message-list :as message-list]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.data-store.messages :as data-store.messages]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.transport.message.protocol :as protocol]
|
||||
[status-im.ui.screens.chat.state :as view.state]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.gfycat.core :as gfycat]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im2.contexts.chat.messages.delete-message.events :as delete-message]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn- message-loaded?
|
||||
@@ -37,7 +36,7 @@
|
||||
;; TODO this is too expensive, probably we could mark message somehow and just hide it in the UI
|
||||
(message-list/rebuild-message-list {:db (update-in db [:messages chat-id] dissoc message-id)} chat-id))
|
||||
|
||||
(fx/defn add-senders-to-chat-users
|
||||
(rf/defn add-senders-to-chat-users
|
||||
{:events [:chat/add-senders-to-chat-users]}
|
||||
[{:keys [db]} messages]
|
||||
(reduce (fn [acc {:keys [chat-id alias name identicon from]}]
|
||||
@@ -168,42 +167,42 @@
|
||||
(update-in [:message-lists constants/timeline-chat-id] message-list/add message)))
|
||||
db)))
|
||||
|
||||
(fx/defn process-statuses
|
||||
(rf/defn process-statuses
|
||||
{:events [:process-statuses]}
|
||||
[{:keys [db]} statuses]
|
||||
{:db (reduce reduce-js-statuses db statuses)})
|
||||
|
||||
(fx/defn update-db-message-status
|
||||
(rf/defn update-db-message-status
|
||||
[{:keys [db] :as cofx} chat-id message-id status]
|
||||
(when (get-in db [:messages chat-id message-id])
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:messages chat-id message-id :outgoing-status]
|
||||
status)})))
|
||||
|
||||
(fx/defn update-message-status
|
||||
(rf/defn update-message-status
|
||||
[{:keys [db] :as cofx} chat-id message-id status]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(update-db-message-status chat-id message-id status)))
|
||||
|
||||
(fx/defn resend-message
|
||||
(rf/defn resend-message
|
||||
[{:keys [db] :as cofx} chat-id message-id]
|
||||
(fx/merge cofx
|
||||
{::json-rpc/call [{:method "wakuext_reSendChatMessage"
|
||||
:params [message-id]
|
||||
:on-success #(log/debug "re-sent message successfully")
|
||||
:on-error #(log/error "failed to re-send message" %)}]}
|
||||
(rf/merge cofx
|
||||
{:json-rpc/call [{:method "wakuext_reSendChatMessage"
|
||||
:params [message-id]
|
||||
:on-success #(log/debug "re-sent message successfully")
|
||||
:on-error #(log/error "failed to re-send message" %)}]}
|
||||
(update-message-status chat-id message-id :sending)))
|
||||
|
||||
(fx/defn send-message
|
||||
(rf/defn send-message
|
||||
[cofx message]
|
||||
(protocol/send-chat-messages cofx [message]))
|
||||
|
||||
(fx/defn send-messages
|
||||
(rf/defn send-messages
|
||||
[cofx messages]
|
||||
(protocol/send-chat-messages cofx messages))
|
||||
|
||||
(fx/defn handle-removed-messages
|
||||
(rf/defn handle-removed-messages
|
||||
{:events [::handle-removed-messages]}
|
||||
[{:keys [db] :as cofx} removed-messages]
|
||||
(let [mark-as-deleted-fx (->> removed-messages
|
||||
@@ -223,7 +222,7 @@
|
||||
removed-messages)
|
||||
remove-messages-fx (fn [{:keys [db]}]
|
||||
{:dispatch [:activity-center.notifications/fetch-unread-count]})]
|
||||
(apply fx/merge
|
||||
(apply rf/merge
|
||||
cofx
|
||||
(-> mark-as-deleted-fx
|
||||
(concat mark-as-seen-fx)
|
||||
@@ -244,7 +243,7 @@
|
||||
(<= message-clock cleared-at))
|
||||
messages)))
|
||||
|
||||
(fx/defn handle-cleared-histories-messages
|
||||
(rf/defn handle-cleared-histories-messages
|
||||
{:events [::handle-cleared-hisotories-messages]}
|
||||
[{:keys [db]} cleared-histories]
|
||||
{:db (reduce (fn [acc current]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
(:require ["functional-red-black-tree" :as rb-tree]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.utils.fx :as fx]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- add-datemark
|
||||
[{:keys [whisper-timestamp] :as msg}]
|
||||
@@ -20,7 +20,8 @@
|
||||
from
|
||||
outgoing
|
||||
whisper-timestamp
|
||||
deleted-for-me?]}]
|
||||
deleted-for-me?
|
||||
albumize?]}]
|
||||
(-> {:whisper-timestamp whisper-timestamp
|
||||
:from from
|
||||
:one-to-one? (= constants/message-type-one-to-one message-type)
|
||||
@@ -32,7 +33,8 @@
|
||||
:clock-value clock-value
|
||||
:type :message
|
||||
:message-id message-id
|
||||
:outgoing (boolean outgoing)}
|
||||
:outgoing (boolean outgoing)
|
||||
:albumize? albumize?}
|
||||
add-datemark
|
||||
add-timestamp))
|
||||
|
||||
@@ -195,8 +197,9 @@
|
||||
(array-seq (.-values message-list))
|
||||
[]))
|
||||
|
||||
;;TODO this is too expensive, probably we could mark message somehow and just hide it in the UI
|
||||
(fx/defn rebuild-message-list
|
||||
;; NOTE(performance): this is too expensive, probably we could mark message somehow and just hide it in
|
||||
;; the UI
|
||||
(rf/defn rebuild-message-list
|
||||
[{:keys [db]} chat-id]
|
||||
{:db (assoc-in db
|
||||
[:message-lists chat-id]
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
[status-im.constants :as constants]
|
||||
[status-im.data-store.reactions :as data-store.reactions]
|
||||
[status-im.transport.message.protocol :as message.protocol]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn update-reaction
|
||||
@@ -40,12 +40,12 @@
|
||||
(get-in db [:chats chat-id])]
|
||||
(>= deleted-at-clock-value clock-value)))
|
||||
|
||||
(fx/defn receive-signal
|
||||
(rf/defn receive-signal
|
||||
[{:keys [db] :as cofx} reactions]
|
||||
(let [reactions (filter (partial earlier-than-deleted-at? cofx) reactions)]
|
||||
{:db (update db :reactions (process-reactions (:chats db)) reactions)}))
|
||||
|
||||
(fx/defn load-more-reactions
|
||||
(rf/defn load-more-reactions
|
||||
{:events [:load-more-reactions]}
|
||||
[{:keys [db]} cursor chat-id]
|
||||
(when-let [session-id (get-in db [:pagination-info chat-id :messages-initialized?])]
|
||||
@@ -56,7 +56,7 @@
|
||||
#(re-frame/dispatch [::reactions-loaded chat-id session-id %])
|
||||
#(log/error "failed loading reactions" chat-id %))))
|
||||
|
||||
(fx/defn reactions-loaded
|
||||
(rf/defn reactions-loaded
|
||||
{:events [::reactions-loaded]}
|
||||
[{db :db}
|
||||
chat-id
|
||||
@@ -72,19 +72,19 @@
|
||||
;; Send reactions
|
||||
|
||||
|
||||
(fx/defn send-emoji-reaction
|
||||
{:events [::send-emoji-reaction]}
|
||||
(rf/defn send-emoji-reaction
|
||||
{:events [:models.reactions/send-emoji-reaction]}
|
||||
[{{:keys [current-chat-id]} :db :as cofx} reaction]
|
||||
(message.protocol/send-reaction cofx
|
||||
(update reaction :chat-id #(or % current-chat-id))))
|
||||
|
||||
(fx/defn send-retract-emoji-reaction
|
||||
{:events [::send-emoji-reaction-retraction]}
|
||||
(rf/defn send-retract-emoji-reaction
|
||||
{:events [:models.reactions/send-emoji-reaction-retraction]}
|
||||
[{{:keys [current-chat-id]} :db :as cofx} reaction]
|
||||
(message.protocol/send-retract-reaction cofx
|
||||
(update reaction :chat-id #(or % current-chat-id))))
|
||||
|
||||
(fx/defn receive-one
|
||||
(rf/defn receive-one
|
||||
{:events [::receive-one]}
|
||||
[{:keys [db]} reaction]
|
||||
{:db (update db :reactions (process-reactions (:chats db)) [reaction])})
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
(ns status-im.chat.models.transport
|
||||
(:require [status-im.chat.models.message :as chat.message]
|
||||
[status-im.transport.message.core :as transport.message]
|
||||
[status-im.utils.fx :as fx]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn chat-ui-resend-message
|
||||
(rf/defn chat-ui-resend-message
|
||||
{:events [:chat.ui/resend-message]}
|
||||
[{:keys [db] :as cofx} chat-id message-id]
|
||||
(let [message (get-in db [:messages chat-id message-id])]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
(transport.message/set-message-envelope-hash chat-id message-id (:message-type message))
|
||||
(chat.message/resend-message chat-id message-id))))
|
||||
(chat.message/resend-message chat-id message-id))))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
(ns status-im.chat.models-test
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.chat.models :as chat]
|
||||
[status-im.chat.models.images :as images]
|
||||
[status-im.utils.clocks :as utils.clocks]))
|
||||
|
||||
(deftest clear-history-test
|
||||
@@ -92,3 +93,8 @@
|
||||
(testing "Pagination info should be reset on navigation"
|
||||
(let [res (chat/navigate-to-chat-nav2 {:db db} chat-id false)]
|
||||
(is (nil? (get-in res [:db :pagination-info chat-id :all-loaded?])))))))
|
||||
|
||||
(deftest camera-roll-loading-more-test
|
||||
(let [cofx {:db {:camera-roll/loading-more false}}]
|
||||
(is (= {:db {:camera-roll/loading-more true}}
|
||||
(images/camera-roll-loading-more cofx true)))))
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
(ns status-im.commands.core
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.utils.fx :as fx]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn handle-prepare-accept-request-address-for-transaction
|
||||
(rf/defn handle-prepare-accept-request-address-for-transaction
|
||||
{:events [::prepare-accept-request-address-for-transaction]}
|
||||
[{:keys [db]} message]
|
||||
{:db (assoc db
|
||||
@@ -13,33 +12,33 @@
|
||||
:from (ethereum/get-default-account (:multiaccount/accounts db))})
|
||||
:show-select-acc-sheet nil})
|
||||
|
||||
(fx/defn set-selected-account
|
||||
(rf/defn set-selected-account
|
||||
{:events [::set-selected-account]}
|
||||
[{:keys [db]} _ account]
|
||||
{:db (-> (assoc-in db [:commands/select-account :from] account)
|
||||
(assoc :bottom-sheet/show? false))})
|
||||
|
||||
(fx/defn handle-accept-request-address-for-transaction
|
||||
(rf/defn handle-accept-request-address-for-transaction
|
||||
{:events [::accept-request-address-for-transaction]}
|
||||
[{:keys [db]} message-id address]
|
||||
{:db (dissoc db :commands/select-account)
|
||||
::json-rpc/call [{:method "wakuext_acceptRequestAddressForTransaction"
|
||||
:params [message-id address]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:transport/message-sent %])}]})
|
||||
{:db (dissoc db :commands/select-account)
|
||||
:json-rpc/call [{:method "wakuext_acceptRequestAddressForTransaction"
|
||||
:params [message-id address]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:transport/message-sent %])}]})
|
||||
|
||||
(fx/defn handle-decline-request-address-for-transaction
|
||||
(rf/defn handle-decline-request-address-for-transaction
|
||||
{:events [::decline-request-address-for-transaction]}
|
||||
[_ message-id]
|
||||
{::json-rpc/call [{:method "wakuext_declineRequestAddressForTransaction"
|
||||
:params [message-id]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:transport/message-sent %])}]})
|
||||
{:json-rpc/call [{:method "wakuext_declineRequestAddressForTransaction"
|
||||
:params [message-id]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:transport/message-sent %])}]})
|
||||
|
||||
(fx/defn handle-decline-request-transaction
|
||||
(rf/defn handle-decline-request-transaction
|
||||
{:events [::decline-request-transaction]}
|
||||
[cofx message-id]
|
||||
{::json-rpc/call [{:method "wakuext_declineRequestTransaction"
|
||||
:params [message-id]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:transport/message-sent %])}]})
|
||||
{:json-rpc/call [{:method "wakuext_declineRequestTransaction"
|
||||
:params [message-id]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:transport/message-sent %])}]})
|
||||
|
||||
+313
-315
@@ -4,15 +4,13 @@
|
||||
[clojure.walk :as walk]
|
||||
[quo.design-system.colors :as colors]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.activity-center.core :as activity-center]
|
||||
[status-im.async-storage.core :as async-storage]
|
||||
[status-im.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.ui.components.emoji-thumbnail.styles :as emoji-thumbnail-styles]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.handlers :refer [>evt]]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.universal-links.core :as universal-links]
|
||||
[status-im2.contexts.activity-center.events :as activity-center]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
@@ -80,24 +78,24 @@
|
||||
[{:keys [db]}]
|
||||
(:communities/community-id-input db))
|
||||
|
||||
(fx/defn handle-request-to-join
|
||||
(rf/defn handle-request-to-join
|
||||
[{:keys [db]} r]
|
||||
(let [{:keys [id community-id] :as request} (<-request-to-join-community-rpc r)]
|
||||
{:db (assoc-in db [:communities/requests-to-join community-id id] request)}))
|
||||
|
||||
(fx/defn handle-removed-chats
|
||||
(rf/defn handle-removed-chats
|
||||
[{:keys [db]} chat-ids]
|
||||
{:db (reduce (fn [db chat-id]
|
||||
(update db :chats dissoc chat-id))
|
||||
db
|
||||
chat-ids)})
|
||||
|
||||
(fx/defn handle-community
|
||||
(rf/defn handle-community
|
||||
[{:keys [db]} {:keys [id] :as community}]
|
||||
(when id
|
||||
{:db (assoc-in db [:communities id] (<-rpc community))}))
|
||||
|
||||
(fx/defn handle-communities
|
||||
(rf/defn handle-communities
|
||||
{:events [::fetched]}
|
||||
[{:keys [db]} communities]
|
||||
{:db (reduce (fn [db {:keys [id] :as community}]
|
||||
@@ -105,76 +103,76 @@
|
||||
db
|
||||
communities)})
|
||||
|
||||
(fx/defn handle-response
|
||||
(rf/defn handle-response
|
||||
[_ response-js]
|
||||
{:dispatch [:sanitize-messages-and-process-response response-js]})
|
||||
|
||||
(fx/defn left
|
||||
(rf/defn left
|
||||
{:events [::left]}
|
||||
[cofx response-js]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(handle-response cofx response-js)
|
||||
(navigation/pop-to-root-tab :chat-stack)
|
||||
(activity-center/notifications-fetch-unread-count)))
|
||||
|
||||
(fx/defn joined
|
||||
(rf/defn joined
|
||||
{:events [::joined ::requested-to-join]}
|
||||
[cofx response-js]
|
||||
(handle-response cofx response-js))
|
||||
|
||||
(fx/defn export
|
||||
(rf/defn export
|
||||
{:events [::export-pressed]}
|
||||
[cofx community-id]
|
||||
{::json-rpc/call [{:method "wakuext_exportCommunity"
|
||||
:params [community-id]
|
||||
:on-success #(re-frame/dispatch [:show-popover
|
||||
{:view :export-community
|
||||
:community-key %}])
|
||||
:on-error #(do
|
||||
(log/error "failed to export community" community-id %)
|
||||
(re-frame/dispatch [::failed-to-export %]))}]})
|
||||
{:json-rpc/call [{:method "wakuext_exportCommunity"
|
||||
:params [community-id]
|
||||
:on-success #(re-frame/dispatch [:show-popover
|
||||
{:view :export-community
|
||||
:community-key %}])
|
||||
:on-error #(do
|
||||
(log/error "failed to export community" community-id %)
|
||||
(re-frame/dispatch [::failed-to-export %]))}]})
|
||||
|
||||
(fx/defn import-community
|
||||
(rf/defn import-community
|
||||
{:events [::import]}
|
||||
[cofx community-key]
|
||||
{::json-rpc/call [{:method "wakuext_importCommunity"
|
||||
:params [community-key]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::community-imported %])
|
||||
:on-error #(do
|
||||
(log/error "failed to import community" %)
|
||||
(re-frame/dispatch [::failed-to-import %]))}]})
|
||||
{:json-rpc/call [{:method "wakuext_importCommunity"
|
||||
:params [community-key]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::community-imported %])
|
||||
:on-error #(do
|
||||
(log/error "failed to import community" %)
|
||||
(re-frame/dispatch [::failed-to-import %]))}]})
|
||||
|
||||
(fx/defn join
|
||||
(rf/defn join
|
||||
{:events [:communities/join]}
|
||||
[cofx community-id]
|
||||
{::json-rpc/call [{:method "wakuext_joinCommunity"
|
||||
:params [community-id]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::joined %])
|
||||
:on-error #(do
|
||||
(log/error "failed to join community" community-id %)
|
||||
(re-frame/dispatch [::failed-to-join %]))}]})
|
||||
{:json-rpc/call [{:method "wakuext_joinCommunity"
|
||||
:params [community-id]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::joined %])
|
||||
:on-error #(do
|
||||
(log/error "failed to join community" community-id %)
|
||||
(re-frame/dispatch [::failed-to-join %]))}]})
|
||||
|
||||
(fx/defn request-to-join
|
||||
(rf/defn request-to-join
|
||||
{:events [::request-to-join]}
|
||||
[cofx community-id]
|
||||
{::json-rpc/call [{:method "wakuext_requestToJoinCommunity"
|
||||
:params [{:communityId community-id}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::requested-to-join %])
|
||||
:on-error #(do
|
||||
(log/error "failed to request to join community" community-id %)
|
||||
(re-frame/dispatch [::failed-to-request-to-join %]))}]})
|
||||
{:json-rpc/call [{:method "wakuext_requestToJoinCommunity"
|
||||
:params [{:communityId community-id}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::requested-to-join %])
|
||||
:on-error #(do
|
||||
(log/error "failed to request to join community" community-id %)
|
||||
(re-frame/dispatch [::failed-to-request-to-join %]))}]})
|
||||
|
||||
(fx/defn leave
|
||||
(rf/defn leave
|
||||
{:events [:communities/leave]}
|
||||
[{:keys [db]} community-id]
|
||||
(let [community-chat-ids (map #(str community-id %)
|
||||
(keys (get-in db [:communities community-id :chats])))]
|
||||
{:clear-message-notifications [community-chat-ids
|
||||
(get-in db [:multiaccount :remote-push-notifications-enabled?])]
|
||||
::json-rpc/call [{:method "wakuext_leaveCommunity"
|
||||
:json-rpc/call [{:method "wakuext_leaveCommunity"
|
||||
:params [community-id]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::left %])
|
||||
@@ -184,30 +182,30 @@
|
||||
%)
|
||||
(re-frame/dispatch [::failed-to-leave %]))}]}))
|
||||
|
||||
(fx/defn fetch
|
||||
(rf/defn fetch
|
||||
[_]
|
||||
{::json-rpc/call [{:method "wakuext_communities"
|
||||
:params []
|
||||
:on-success #(re-frame/dispatch [::fetched %])
|
||||
:on-error #(do
|
||||
(log/error "failed to fetch communities" %)
|
||||
(re-frame/dispatch [::failed-to-fetch %]))}]})
|
||||
{:json-rpc/call [{:method "wakuext_communities"
|
||||
:params []
|
||||
:on-success #(re-frame/dispatch [::fetched %])
|
||||
:on-error #(do
|
||||
(log/error "failed to fetch communities" %)
|
||||
(re-frame/dispatch [::failed-to-fetch %]))}]})
|
||||
|
||||
(fx/defn chat-created
|
||||
(rf/defn chat-created
|
||||
{:events [::chat-created]}
|
||||
[_ community-id user-pk]
|
||||
{::json-rpc/call [{:method "wakuext_sendChatMessage"
|
||||
:params [{:chatId user-pk
|
||||
:text "Upgrade here to see an invitation to community"
|
||||
:communityId community-id
|
||||
:contentType constants/content-type-community}]
|
||||
:js-response true
|
||||
:on-success
|
||||
#(re-frame/dispatch [:transport/message-sent %])
|
||||
:on-error
|
||||
#(log/error "failed to send a message" %)}]})
|
||||
{:json-rpc/call [{:method "wakuext_sendChatMessage"
|
||||
:params [{:chatId user-pk
|
||||
:text "Upgrade here to see an invitation to community"
|
||||
:communityId community-id
|
||||
:contentType constants/content-type-community}]
|
||||
:js-response true
|
||||
:on-success
|
||||
#(re-frame/dispatch [:transport/message-sent %])
|
||||
:on-error
|
||||
#(log/error "failed to send a message" %)}]})
|
||||
|
||||
(fx/defn invite-users
|
||||
(rf/defn invite-users
|
||||
{:events [::invite-people-confirmation-pressed]}
|
||||
[cofx user-pk contacts]
|
||||
(let [community-id (fetch-community-id-input cofx)
|
||||
@@ -215,15 +213,15 @@
|
||||
(conj contacts user-pk)
|
||||
contacts)]
|
||||
(when (seq pks)
|
||||
{::json-rpc/call [{:method "wakuext_inviteUsersToCommunity"
|
||||
:params [{:communityId community-id
|
||||
:users pks}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::people-invited %])
|
||||
:on-error #(do
|
||||
(log/error "failed to invite-user community" %)
|
||||
(re-frame/dispatch [::failed-to-invite-people %]))}]})))
|
||||
(fx/defn share-community
|
||||
{:json-rpc/call [{:method "wakuext_inviteUsersToCommunity"
|
||||
:params [{:communityId community-id
|
||||
:users pks}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::people-invited %])
|
||||
:on-error #(do
|
||||
(log/error "failed to invite-user community" %)
|
||||
(re-frame/dispatch [::failed-to-invite-people %]))}]})))
|
||||
(rf/defn share-community
|
||||
{:events [::share-community-confirmation-pressed]}
|
||||
[cofx user-pk contacts]
|
||||
(let [community-id (fetch-community-id-input cofx)
|
||||
@@ -231,16 +229,16 @@
|
||||
(conj contacts user-pk)
|
||||
contacts)]
|
||||
(when (seq pks)
|
||||
{::json-rpc/call [{:method "wakuext_shareCommunity"
|
||||
:params [{:communityId community-id
|
||||
:users pks}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::people-invited %])
|
||||
:on-error #(do
|
||||
(log/error "failed to invite-user community" %)
|
||||
(re-frame/dispatch [::failed-to-share-community %]))}]})))
|
||||
{:json-rpc/call [{:method "wakuext_shareCommunity"
|
||||
:params [{:communityId community-id
|
||||
:users pks}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::people-invited %])
|
||||
:on-error #(do
|
||||
(log/error "failed to invite-user community" %)
|
||||
(re-frame/dispatch [::failed-to-share-community %]))}]})))
|
||||
|
||||
(fx/defn create
|
||||
(rf/defn create
|
||||
{:events [::create-confirmation-pressed]}
|
||||
[{:keys [db]}]
|
||||
(let [{:keys [name description membership image]} (get db :communities/create)]
|
||||
@@ -254,52 +252,52 @@
|
||||
:imageBx crop-size
|
||||
:imageBy crop-size}]
|
||||
|
||||
{::json-rpc/call [{:method "wakuext_createCommunity"
|
||||
:params [params]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::community-created %])
|
||||
:on-error #(do
|
||||
(log/error "failed to create community" %)
|
||||
(re-frame/dispatch [::failed-to-create-community %]))}]})))
|
||||
{:json-rpc/call [{:method "wakuext_createCommunity"
|
||||
:params [params]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::community-created %])
|
||||
:on-error #(do
|
||||
(log/error "failed to create community" %)
|
||||
(re-frame/dispatch [::failed-to-create-community %]))}]})))
|
||||
|
||||
(fx/defn edit
|
||||
(rf/defn edit
|
||||
{:events [::edit-confirmation-pressed]}
|
||||
[{:keys [db]}]
|
||||
(let [{:keys [id name description membership new-image color]} (get db :communities/create)]
|
||||
{::json-rpc/call [{:method "wakuext_editCommunity"
|
||||
:params [{:communityID id
|
||||
:name name
|
||||
:description description
|
||||
:color color
|
||||
:image (string/replace-first (str new-image) #"file://" "")
|
||||
:imageAx 0
|
||||
:imageAy 0
|
||||
:imageBx crop-size
|
||||
:imageBy crop-size
|
||||
:membership membership}]
|
||||
:on-success #(re-frame/dispatch [::community-edited %])
|
||||
:on-error #(do
|
||||
(log/error "failed to edit community" %)
|
||||
(re-frame/dispatch [::failed-to-edit-community %]))}]}))
|
||||
{:json-rpc/call [{:method "wakuext_editCommunity"
|
||||
:params [{:communityID id
|
||||
:name name
|
||||
:description description
|
||||
:color color
|
||||
:image (string/replace-first (str new-image) #"file://" "")
|
||||
:imageAx 0
|
||||
:imageAy 0
|
||||
:imageBx crop-size
|
||||
:imageBy crop-size
|
||||
:membership membership}]
|
||||
:on-success #(re-frame/dispatch [::community-edited %])
|
||||
:on-error #(do
|
||||
(log/error "failed to edit community" %)
|
||||
(re-frame/dispatch [::failed-to-edit-community %]))}]}))
|
||||
|
||||
(fx/defn create-channel
|
||||
(rf/defn create-channel
|
||||
{:events [::create-channel-confirmation-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [community-id (fetch-community-id-input cofx)
|
||||
{:keys [name description color emoji]} (get db :communities/create-channel)]
|
||||
{::json-rpc/call [{:method "wakuext_createCommunityChat"
|
||||
:params [community-id
|
||||
{:identity {:display_name name
|
||||
:description description
|
||||
:color color
|
||||
:emoji emoji}
|
||||
:permissions {:access
|
||||
constants/community-channel-access-no-membership}}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::community-channel-created %])
|
||||
:on-error #(do
|
||||
(log/error "failed to create community channel" %)
|
||||
(re-frame/dispatch [::failed-to-create-community-channel %]))}]}))
|
||||
{:json-rpc/call [{:method "wakuext_createCommunityChat"
|
||||
:params [community-id
|
||||
{:identity {:display_name name
|
||||
:description description
|
||||
:color color
|
||||
:emoji emoji}
|
||||
:permissions {:access
|
||||
constants/community-channel-access-no-membership}}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::community-channel-created %])
|
||||
:on-error #(do
|
||||
(log/error "failed to create community channel" %)
|
||||
(re-frame/dispatch [::failed-to-create-community-channel %]))}]}))
|
||||
|
||||
(def community-chat-id-length 68)
|
||||
|
||||
@@ -307,27 +305,27 @@
|
||||
[chat-id]
|
||||
(subs chat-id community-chat-id-length))
|
||||
|
||||
(fx/defn edit-channel
|
||||
(rf/defn edit-channel
|
||||
{:events [::edit-channel-confirmation-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [name description color community-id emoji edit-channel-id category-id position]}
|
||||
(get db :communities/create-channel)]
|
||||
{::json-rpc/call [{:method "wakuext_editCommunityChat"
|
||||
:params [community-id
|
||||
edit-channel-id
|
||||
{:identity {:display_name name
|
||||
:description description
|
||||
:color color
|
||||
:emoji emoji}
|
||||
:category_id category-id
|
||||
:position position
|
||||
:permissions {:access
|
||||
constants/community-channel-access-no-membership}}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::community-channel-edited %])
|
||||
:on-error #(do
|
||||
(log/error "failed to edit community channel" %)
|
||||
(re-frame/dispatch [::failed-to-edit-community-channel %]))}]}))
|
||||
{:json-rpc/call [{:method "wakuext_editCommunityChat"
|
||||
:params [community-id
|
||||
edit-channel-id
|
||||
{:identity {:display_name name
|
||||
:description description
|
||||
:color color
|
||||
:emoji emoji}
|
||||
:category_id category-id
|
||||
:position position
|
||||
:permissions {:access
|
||||
constants/community-channel-access-no-membership}}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::community-channel-edited %])
|
||||
:on-error #(do
|
||||
(log/error "failed to edit community channel" %)
|
||||
(re-frame/dispatch [::failed-to-edit-community-channel %]))}]}))
|
||||
|
||||
(defn require-membership?
|
||||
[permissions]
|
||||
@@ -338,47 +336,47 @@
|
||||
(let [chat-id (to-community-chat-id local-chat-id)]
|
||||
(get-in community [:chats chat-id :can-post?])))
|
||||
|
||||
(fx/defn reset-community-id-input
|
||||
(rf/defn reset-community-id-input
|
||||
[{:keys [db]} id]
|
||||
{:db (assoc db :communities/community-id-input id)})
|
||||
|
||||
(fx/defn reset-channel-info
|
||||
(rf/defn reset-channel-info
|
||||
[{:keys [db]}]
|
||||
{:db (assoc db :communities/create-channel {})})
|
||||
|
||||
(fx/defn invite-people-pressed
|
||||
(rf/defn invite-people-pressed
|
||||
{:events [:communities/invite-people-pressed]}
|
||||
[cofx id]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(reset-community-id-input id)
|
||||
(bottom-sheet/hide-bottom-sheet)
|
||||
(navigation/open-modal :invite-people-community {:invite? true})))
|
||||
|
||||
(fx/defn share-community-pressed
|
||||
(rf/defn share-community-pressed
|
||||
{:events [:communities/share-community-pressed]}
|
||||
[cofx id]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(reset-community-id-input id)
|
||||
(bottom-sheet/hide-bottom-sheet)
|
||||
(navigation/open-modal :invite-people-community {})))
|
||||
|
||||
(fx/defn create-channel-pressed
|
||||
(rf/defn create-channel-pressed
|
||||
{:events [::create-channel-pressed]}
|
||||
[{:keys [db] :as cofx} id]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(reset-community-id-input id)
|
||||
(reset-channel-info)
|
||||
(>evt [::create-channel-fields
|
||||
(rand-nth emoji-thumbnail-styles/emoji-picker-default-thumbnails)])
|
||||
(rf/dispatch [::create-channel-fields
|
||||
(rand-nth emoji-thumbnail-styles/emoji-picker-default-thumbnails)])
|
||||
(navigation/open-modal :create-community-channel {:community-id id})))
|
||||
|
||||
(fx/defn edit-channel-pressed
|
||||
(rf/defn edit-channel-pressed
|
||||
{:events [::edit-channel-pressed]}
|
||||
[{:keys [db] :as cofx} community-id chat-name description color emoji chat-id category-id position]
|
||||
(let [{:keys [color emoji]} (if (string/blank? emoji)
|
||||
(rand-nth emoji-thumbnail-styles/emoji-picker-default-thumbnails)
|
||||
{:color color :emoji emoji})]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc db
|
||||
:communities/create-channel
|
||||
{:name chat-name
|
||||
@@ -391,33 +389,33 @@
|
||||
:position position})}
|
||||
(navigation/open-modal :edit-community-channel nil))))
|
||||
|
||||
(fx/defn community-created
|
||||
(rf/defn community-created
|
||||
{:events [::community-created]}
|
||||
[cofx response-js]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(navigation/navigate-back)
|
||||
(handle-response response-js)))
|
||||
|
||||
(fx/defn community-edited
|
||||
(rf/defn community-edited
|
||||
{:events [::community-edited]}
|
||||
[cofx response-js]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(navigation/navigate-back)
|
||||
(handle-response response-js)))
|
||||
|
||||
(fx/defn open-create-community
|
||||
(rf/defn open-create-community
|
||||
{:events [::open-create-community]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc db :communities/create {:membership constants/community-no-membership-access})}
|
||||
(navigation/navigate-to :community-create nil)))
|
||||
|
||||
(fx/defn open-edit-community
|
||||
(rf/defn open-edit-community
|
||||
{:events [::open-edit-community]}
|
||||
[{:keys [db] :as cofx} id]
|
||||
(let [{:keys [name description images permissions color]} (get-in db [:communities id])
|
||||
{:keys [access]} permissions]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc db
|
||||
:communities/create
|
||||
{:id id
|
||||
@@ -429,264 +427,264 @@
|
||||
:editing? true})}
|
||||
(navigation/navigate-to :community-edit nil))))
|
||||
|
||||
(fx/defn community-imported
|
||||
(rf/defn community-imported
|
||||
{:events [::community-imported]}
|
||||
[cofx response-js]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(navigation/navigate-back)
|
||||
(handle-response response-js)))
|
||||
|
||||
(fx/defn people-invited
|
||||
(rf/defn people-invited
|
||||
{:events [::people-invited]}
|
||||
[cofx response-js]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(navigation/navigate-back)
|
||||
(handle-response response-js)))
|
||||
|
||||
(fx/defn community-channel-created
|
||||
(rf/defn community-channel-created
|
||||
{:events [::community-channel-created]}
|
||||
[cofx response-js]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(navigation/navigate-back)
|
||||
(handle-response response-js)))
|
||||
|
||||
(fx/defn community-channel-edited
|
||||
(rf/defn community-channel-edited
|
||||
{:events [::community-channel-edited]}
|
||||
[cofx response-js]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(navigation/navigate-back)
|
||||
(handle-response response-js)))
|
||||
|
||||
(fx/defn create-field
|
||||
(rf/defn create-field
|
||||
{:events [::create-field]}
|
||||
[{:keys [db]} field value]
|
||||
{:db (assoc-in db [:communities/create field] value)})
|
||||
|
||||
(fx/defn remove-field
|
||||
(rf/defn remove-field
|
||||
{:events [::remove-field]}
|
||||
[{:keys [db]} field]
|
||||
{:db (update-in db [:communities/create] dissoc field)})
|
||||
|
||||
(fx/defn create-channel-field
|
||||
(rf/defn create-channel-field
|
||||
{:events [::create-channel-field]}
|
||||
[{:keys [db]} field value]
|
||||
{:db (assoc-in db [:communities/create-channel field] value)})
|
||||
|
||||
(fx/defn create-channel-fields
|
||||
(rf/defn create-channel-fields
|
||||
{:events [::create-channel-fields]}
|
||||
[{:keys [db]} field-values]
|
||||
{:db (update-in db [:communities/create-channel] merge field-values)})
|
||||
|
||||
(fx/defn member-banned
|
||||
(rf/defn member-banned
|
||||
{:events [::member-banned]}
|
||||
[cofx response-js]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(bottom-sheet/hide-bottom-sheet)
|
||||
(handle-response response-js)
|
||||
(activity-center/notifications-fetch-unread-count)))
|
||||
|
||||
(fx/defn member-ban
|
||||
(rf/defn member-ban
|
||||
{:events [::member-ban]}
|
||||
[cofx community-id public-key]
|
||||
{::json-rpc/call [{:method "wakuext_banUserFromCommunity"
|
||||
:params [{:communityId community-id
|
||||
:user public-key}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::member-banned %])
|
||||
:on-error #(log/error "failed to ban user from community"
|
||||
community-id
|
||||
public-key
|
||||
%)}]})
|
||||
{:json-rpc/call [{:method "wakuext_banUserFromCommunity"
|
||||
:params [{:communityId community-id
|
||||
:user public-key}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::member-banned %])
|
||||
:on-error #(log/error "failed to ban user from community"
|
||||
community-id
|
||||
public-key
|
||||
%)}]})
|
||||
|
||||
(fx/defn member-kicked
|
||||
(rf/defn member-kicked
|
||||
{:events [::member-kicked]}
|
||||
[cofx response-js]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(bottom-sheet/hide-bottom-sheet)
|
||||
(handle-response response-js)))
|
||||
|
||||
(fx/defn member-kick
|
||||
(rf/defn member-kick
|
||||
{:events [::member-kick]}
|
||||
[cofx community-id public-key]
|
||||
{::json-rpc/call [{:method "wakuext_removeUserFromCommunity"
|
||||
:params [community-id public-key]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::member-kicked %])
|
||||
:on-error #(log/error "failed to remove user from community"
|
||||
community-id
|
||||
public-key
|
||||
%)}]})
|
||||
{:json-rpc/call [{:method "wakuext_removeUserFromCommunity"
|
||||
:params [community-id public-key]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::member-kicked %])
|
||||
:on-error #(log/error "failed to remove user from community"
|
||||
community-id
|
||||
public-key
|
||||
%)}]})
|
||||
|
||||
(fx/defn delete-community
|
||||
(rf/defn delete-community
|
||||
{:events [::delete-community]}
|
||||
[cofx community-id]
|
||||
(log/error "Community delete is not yet implemented"))
|
||||
|
||||
(fx/defn requests-to-join-fetched
|
||||
(rf/defn requests-to-join-fetched
|
||||
{:events [::requests-to-join-fetched]}
|
||||
[{:keys [db]} community-id requests]
|
||||
{:db (assoc-in db
|
||||
[:communities/requests-to-join community-id]
|
||||
(<-requests-to-join-community-rpc requests))})
|
||||
|
||||
(fx/defn fetch-requests-to-join
|
||||
(rf/defn fetch-requests-to-join
|
||||
{:events [::fetch-requests-to-join]}
|
||||
[cofx community-id]
|
||||
{::json-rpc/call [{:method "wakuext_pendingRequestsToJoinForCommunity"
|
||||
:params [community-id]
|
||||
:on-success #(re-frame/dispatch [::requests-to-join-fetched community-id %])
|
||||
:on-error #(log/error "failed to fetch requests-to-join" community-id %)}]})
|
||||
{:json-rpc/call [{:method "wakuext_pendingRequestsToJoinForCommunity"
|
||||
:params [community-id]
|
||||
:on-success #(re-frame/dispatch [::requests-to-join-fetched community-id %])
|
||||
:on-error #(log/error "failed to fetch requests-to-join" community-id %)}]})
|
||||
|
||||
(defn fetch-requests-to-join!
|
||||
[community-id]
|
||||
(re-frame/dispatch [::fetch-requests-to-join community-id]))
|
||||
|
||||
(fx/defn request-to-join-accepted
|
||||
(rf/defn request-to-join-accepted
|
||||
{:events [::request-to-join-accepted]}
|
||||
[{:keys [db] :as cofx} community-id request-id response-js]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (update-in db [:communities/requests-to-join community-id] dissoc request-id)}
|
||||
(handle-response response-js)))
|
||||
|
||||
(fx/defn request-to-join-declined
|
||||
(rf/defn request-to-join-declined
|
||||
{:events [::request-to-join-declined]}
|
||||
[{:keys [db] :as cofx} community-id request-id response-js]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (update-in db [:communities/requests-to-join community-id] dissoc request-id)}
|
||||
(handle-response response-js)))
|
||||
|
||||
(fx/defn accept-request-to-join-pressed
|
||||
(rf/defn accept-request-to-join-pressed
|
||||
{:events [:communities.ui/accept-request-to-join-pressed]}
|
||||
[cofx community-id request-id]
|
||||
{::json-rpc/call [{:method "wakuext_acceptRequestToJoinCommunity"
|
||||
:params [{:id request-id}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::request-to-join-accepted community-id request-id
|
||||
%])
|
||||
:on-error #(log/error "failed to accept requests-to-join"
|
||||
community-id
|
||||
request-id
|
||||
%)}]})
|
||||
{:json-rpc/call [{:method "wakuext_acceptRequestToJoinCommunity"
|
||||
:params [{:id request-id}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::request-to-join-accepted community-id request-id
|
||||
%])
|
||||
:on-error #(log/error "failed to accept requests-to-join"
|
||||
community-id
|
||||
request-id
|
||||
%)}]})
|
||||
|
||||
(fx/defn decline-request-to-join-pressed
|
||||
(rf/defn decline-request-to-join-pressed
|
||||
{:events [:communities.ui/decline-request-to-join-pressed]}
|
||||
[cofx community-id request-id]
|
||||
{::json-rpc/call [{:method "wakuext_declineRequestToJoinCommunity"
|
||||
:params [{:id request-id}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::request-to-join-declined community-id request-id
|
||||
%])
|
||||
:on-error #(log/error "failed to decline requests-to-join"
|
||||
community-id
|
||||
request-id)}]})
|
||||
{:json-rpc/call [{:method "wakuext_declineRequestToJoinCommunity"
|
||||
:params [{:id request-id}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::request-to-join-declined community-id request-id
|
||||
%])
|
||||
:on-error #(log/error "failed to decline requests-to-join"
|
||||
community-id
|
||||
request-id)}]})
|
||||
|
||||
(fx/defn switch-communities-enabled
|
||||
(rf/defn switch-communities-enabled
|
||||
{:events [:multiaccounts.ui/switch-communities-enabled]}
|
||||
[{:keys [db]} enabled?]
|
||||
{::async-storage/set! {:communities-enabled? enabled?}
|
||||
:db (assoc db :communities/enabled? enabled?)})
|
||||
|
||||
(fx/defn create-category
|
||||
(rf/defn create-category
|
||||
{:events [::create-category-confirmation-pressed]}
|
||||
[_ community-id category-title chat-ids]
|
||||
{::json-rpc/call [{:method "wakuext_createCommunityCategory"
|
||||
:params [{:communityId community-id
|
||||
:categoryName category-title
|
||||
:chatIds (map #(string/replace % community-id "") chat-ids)}]
|
||||
:js-response true
|
||||
:on-success #(do
|
||||
(re-frame/dispatch [:navigate-back])
|
||||
(re-frame/dispatch [:sanitize-messages-and-process-response %]))
|
||||
:on-error #(log/error "failed to create community category" %)}]})
|
||||
{:json-rpc/call [{:method "wakuext_createCommunityCategory"
|
||||
:params [{:communityId community-id
|
||||
:categoryName category-title
|
||||
:chatIds (map #(string/replace % community-id "") chat-ids)}]
|
||||
:js-response true
|
||||
:on-success #(do
|
||||
(re-frame/dispatch [:navigate-back])
|
||||
(re-frame/dispatch [:sanitize-messages-and-process-response %]))
|
||||
:on-error #(log/error "failed to create community category" %)}]})
|
||||
|
||||
(fx/defn remove-chat-from-category
|
||||
(rf/defn remove-chat-from-category
|
||||
{:events [:remove-chat-from-community-category]}
|
||||
[{:keys [db]} community-id id categoryID]
|
||||
(let [category (get-in db [:communities community-id :categories categoryID])
|
||||
category-chats (map :id
|
||||
(filter #(and (= (:categoryID %) categoryID) (not= id (:id %)))
|
||||
(vals (get-in db [:communities community-id :chats]))))]
|
||||
{::json-rpc/call [{:method "wakuext_editCommunityCategory"
|
||||
:params [{:communityId community-id
|
||||
:categoryId categoryID
|
||||
:categoryName (:name category)
|
||||
:chatIds category-chats}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
|
||||
:on-error #(log/error "failed to remove chat from community" %)}]}))
|
||||
{:json-rpc/call [{:method "wakuext_editCommunityCategory"
|
||||
:params [{:communityId community-id
|
||||
:categoryId categoryID
|
||||
:categoryName (:name category)
|
||||
:chatIds category-chats}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
|
||||
:on-error #(log/error "failed to remove chat from community" %)}]}))
|
||||
|
||||
(fx/defn delete-community-chat
|
||||
(rf/defn delete-community-chat
|
||||
{:events [:delete-community-chat]}
|
||||
[_ community-id chat-id]
|
||||
{::json-rpc/call [{:method "wakuext_deleteCommunityChat"
|
||||
:params [community-id chat-id]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
|
||||
:on-error #(log/error "failed to delete community chat" %)}]})
|
||||
{:json-rpc/call [{:method "wakuext_deleteCommunityChat"
|
||||
:params [community-id chat-id]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
|
||||
:on-error #(log/error "failed to delete community chat" %)}]})
|
||||
|
||||
(fx/defn delete-category
|
||||
(rf/defn delete-category
|
||||
{:events [:delete-community-category]}
|
||||
[_ community-id category-id]
|
||||
{::json-rpc/call [{:method "wakuext_deleteCommunityCategory"
|
||||
:params [{:communityId community-id
|
||||
:categoryId category-id}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
|
||||
:on-error #(log/error "failed to delete community category" %)}]})
|
||||
{:json-rpc/call [{:method "wakuext_deleteCommunityCategory"
|
||||
:params [{:communityId community-id
|
||||
:categoryId category-id}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
|
||||
:on-error #(log/error "failed to delete community category" %)}]})
|
||||
|
||||
(fx/defn change-category
|
||||
(rf/defn change-category
|
||||
{:events [::change-category-confirmation-pressed]}
|
||||
[cofx community-id category-id {:keys [id position categoryID]}]
|
||||
(if (not (string/blank? category-id))
|
||||
{::json-rpc/call [{:method "wakuext_reorderCommunityChat"
|
||||
:params [{:communityId community-id
|
||||
:categoryId category-id
|
||||
:chatId id
|
||||
:position position}]
|
||||
:js-response true
|
||||
:on-success #(do
|
||||
(re-frame/dispatch [:navigate-back])
|
||||
(re-frame/dispatch [:sanitize-messages-and-process-response %]))
|
||||
:on-error #(log/error "failed to change community category" %)}]}
|
||||
(fx/merge cofx
|
||||
{:json-rpc/call [{:method "wakuext_reorderCommunityChat"
|
||||
:params [{:communityId community-id
|
||||
:categoryId category-id
|
||||
:chatId id
|
||||
:position position}]
|
||||
:js-response true
|
||||
:on-success #(do
|
||||
(re-frame/dispatch [:navigate-back])
|
||||
(re-frame/dispatch [:sanitize-messages-and-process-response %]))
|
||||
:on-error #(log/error "failed to change community category" %)}]}
|
||||
(rf/merge cofx
|
||||
(navigation/navigate-back)
|
||||
(remove-chat-from-category community-id id categoryID))))
|
||||
|
||||
(fx/defn reorder-category-chat
|
||||
(rf/defn reorder-category-chat
|
||||
{:events [::reorder-community-category-chat]}
|
||||
[_ community-id category-id chat-id new-position]
|
||||
{::json-rpc/call [{:method "wakuext_reorderCommunityChat"
|
||||
:params [{:communityId community-id
|
||||
:categoryId category-id
|
||||
:chatId chat-id
|
||||
:position new-position}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
|
||||
:on-error #(log/error "failed to reorder community category chat" %)}]})
|
||||
{:json-rpc/call [{:method "wakuext_reorderCommunityChat"
|
||||
:params [{:communityId community-id
|
||||
:categoryId category-id
|
||||
:chatId chat-id
|
||||
:position new-position}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
|
||||
:on-error #(log/error "failed to reorder community category chat" %)}]})
|
||||
|
||||
(fx/defn reorder-category
|
||||
(rf/defn reorder-category
|
||||
{:events [::reorder-community-category]}
|
||||
[_ community-id category-id new-position]
|
||||
{::json-rpc/call [{:method "wakuext_reorderCommunityCategories"
|
||||
:params [{:communityId community-id
|
||||
:categoryId category-id
|
||||
:position new-position}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
|
||||
:on-error #(log/error "failed to reorder community category" %)}]})
|
||||
{:json-rpc/call [{:method "wakuext_reorderCommunityCategories"
|
||||
:params [{:communityId community-id
|
||||
:categoryId category-id
|
||||
:position new-position}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])
|
||||
:on-error #(log/error "failed to reorder community category" %)}]})
|
||||
|
||||
(defn category-hash
|
||||
[public-key community-id category-id]
|
||||
(hash (str public-key community-id category-id)))
|
||||
|
||||
(fx/defn store-category-state
|
||||
(rf/defn store-category-state
|
||||
{:events [::store-category-state]}
|
||||
[{:keys [db]} community-id category-id state-open?]
|
||||
(let [public-key (get-in db [:multiaccount :public-key])
|
||||
hash (category-hash public-key community-id category-id)]
|
||||
{::async-storage/set! {hash state-open?}}))
|
||||
|
||||
(fx/defn update-category-states-in-db
|
||||
(rf/defn update-category-states-in-db
|
||||
{:events [::category-states-loaded]}
|
||||
[{:keys [db]} community-id hashes states]
|
||||
(let [public-key (get-in db [:multiaccount :public-key])
|
||||
@@ -700,7 +698,7 @@
|
||||
categories-old)]
|
||||
{:db (update-in db [:communities community-id :categories] merge categories)}))
|
||||
|
||||
(fx/defn load-category-states
|
||||
(rf/defn load-category-states
|
||||
{:events [:communities/load-category-states]}
|
||||
[{:keys [db]} community-id]
|
||||
(let [public-key (get-in db [:multiaccount :public-key])
|
||||
@@ -720,45 +718,45 @@
|
||||
:cb #(re-frame/dispatch
|
||||
[::category-states-loaded community-id hashes %])}}))
|
||||
|
||||
(fx/defn navigate-to-community
|
||||
(rf/defn navigate-to-community
|
||||
{:events [:communities/navigate-to-community]}
|
||||
[cofx community-id]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(navigation/pop-to-root-tab :shell-stack)
|
||||
(navigation/navigate-to-nav2 :community community-id true)))
|
||||
|
||||
(fx/defn member-role-updated
|
||||
(rf/defn member-role-updated
|
||||
{:events [:community.member/role-updated]}
|
||||
[cofx response-js]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(bottom-sheet/hide-bottom-sheet)
|
||||
(handle-response response-js)))
|
||||
|
||||
(fx/defn add-role-to-member
|
||||
(rf/defn add-role-to-member
|
||||
{:events [:community.member/add-role]}
|
||||
[cofx community-id public-key role-id]
|
||||
{::json-rpc/call [{:method "wakuext_addRoleToMember"
|
||||
:params [{:communityId community-id
|
||||
:user public-key
|
||||
:role role-id}]
|
||||
:on-success #(re-frame/dispatch [:community.member/role-updated %])
|
||||
:on-error #(log/error "failed to add role to member"
|
||||
{:error %
|
||||
:community-id community-id
|
||||
:public-key public-key
|
||||
:role-id role-id})}]})
|
||||
{:json-rpc/call [{:method "wakuext_addRoleToMember"
|
||||
:params [{:communityId community-id
|
||||
:user public-key
|
||||
:role role-id}]
|
||||
:on-success #(re-frame/dispatch [:community.member/role-updated %])
|
||||
:on-error #(log/error "failed to add role to member"
|
||||
{:error %
|
||||
:community-id community-id
|
||||
:public-key public-key
|
||||
:role-id role-id})}]})
|
||||
|
||||
(fx/defn remove-role-from-member
|
||||
(rf/defn remove-role-from-member
|
||||
{:events [:community.member/remove-role]}
|
||||
[_ community-id public-key role-id]
|
||||
{::json-rpc/call [{:method "wakuext_removeRoleFromMember"
|
||||
:params [{:communityId community-id
|
||||
:user public-key
|
||||
:role role-id}]}
|
||||
:on-success #(re-frame/dispatch [:community.member/role-updated %])
|
||||
:on-error
|
||||
#(log/error "failed to remove role from member"
|
||||
{:error %
|
||||
:community-id community-id
|
||||
:public-key public-key
|
||||
:role-id role-id})]})
|
||||
{:json-rpc/call [{:method "wakuext_removeRoleFromMember"
|
||||
:params [{:communityId community-id
|
||||
:user public-key
|
||||
:role role-id}]}
|
||||
:on-success #(re-frame/dispatch [:community.member/role-updated %])
|
||||
:on-error
|
||||
#(log/error "failed to remove role from member"
|
||||
{:error %
|
||||
:community-id community-id
|
||||
:public-key public-key
|
||||
:role-id role-id})]})
|
||||
|
||||
@@ -204,3 +204,10 @@
|
||||
(def ^:const community-member-role-all 1)
|
||||
(def ^:const community-member-role-manage-users 2)
|
||||
(def ^:const community-member-role-moderator 3)
|
||||
|
||||
(def local-pairing-connection-string-identifier
|
||||
"If any string begins with cs we know its a connection string.
|
||||
This is useful when we read QR codes we know it is a connection string if it begins with this identifier.
|
||||
An example of a connection string is -> cs2:5vd6J6:Jfc:27xMmHKEYwzRGXcvTtuiLZFfXscMx4Mz8d9wEHUxDj4p7:EG7Z13QScfWBJNJ5cprszzDQ5fBVsYMirXo8MaQFJvpF:3 "
|
||||
"cs")
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
(ns status-im.contact.block
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.activity-center.core :as activity-center]
|
||||
[status-im.chat.models.message-list :as message-list]
|
||||
[status-im.contact.db :as contact.db]
|
||||
[status-im.data-store.chats :as chats-store]
|
||||
[status-im.data-store.contacts :as contacts-store]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im2.contexts.activity-center.events :as activity-center]
|
||||
[status-im2.navigation.events :as navigation]))
|
||||
|
||||
(fx/defn clean-up-chat
|
||||
(rf/defn clean-up-chat
|
||||
[{:keys [db] :as cofx}
|
||||
public-key
|
||||
{:keys [chat-id
|
||||
@@ -34,14 +34,14 @@
|
||||
[:message-lists chat-id]
|
||||
(message-list/add-many nil (vals (get-in db [:messages chat-id]))))}))
|
||||
|
||||
(fx/defn contact-blocked
|
||||
(rf/defn contact-blocked
|
||||
{:events [::contact-blocked]}
|
||||
[{:keys [db] :as cofx} {:keys [public-key]} chats]
|
||||
(let [fxs (when chats
|
||||
(map #(->> (chats-store/<-rpc %)
|
||||
(clean-up-chat public-key))
|
||||
(types/js->clj chats)))]
|
||||
(apply fx/merge
|
||||
(apply rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(update :chats dissoc public-key)
|
||||
@@ -52,7 +52,7 @@
|
||||
(activity-center/notifications-fetch-unread-count)
|
||||
fxs)))
|
||||
|
||||
(fx/defn block-contact
|
||||
(rf/defn block-contact
|
||||
{:events [:contact.ui/block-contact-confirmed]}
|
||||
[{:keys [db] :as cofx} public-key]
|
||||
(let [contact (-> (contact.db/public-key->contact
|
||||
@@ -61,7 +61,7 @@
|
||||
(assoc :blocked true
|
||||
:added false))
|
||||
from-one-to-one-chat? (not (get-in db [:chats (:current-chat-id db) :group-chat]))]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
;; add the contact to blocked contacts
|
||||
(update :contacts/blocked (fnil conj #{}) public-key)
|
||||
@@ -77,7 +77,7 @@
|
||||
(navigation/pop-to-root-tab :chat-stack)
|
||||
(navigation/navigate-back)))))
|
||||
|
||||
(fx/defn contact-unblocked
|
||||
(rf/defn contact-unblocked
|
||||
{:events [::contact-unblocked]}
|
||||
[{:keys [db]} contact-id]
|
||||
(let [contact (-> (get-in db [:contacts/contacts contact-id])
|
||||
@@ -86,7 +86,7 @@
|
||||
(update :contacts/blocked disj contact-id)
|
||||
(assoc-in [:contacts/contacts contact-id] contact))}))
|
||||
|
||||
(fx/defn unblock-contact
|
||||
(rf/defn unblock-contact
|
||||
{:events [:contact.ui/unblock-contact-pressed]}
|
||||
[cofx contact-id]
|
||||
(contacts-store/unblock
|
||||
|
||||
@@ -2,28 +2,28 @@
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.chat.models :as chat]
|
||||
[status-im.contact.core :as contact]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im2.navigation.events :as navigation]))
|
||||
|
||||
(fx/defn send-message-pressed
|
||||
(rf/defn send-message-pressed
|
||||
{:events [:contact.ui/send-message-pressed]
|
||||
:interceptors [(re-frame/inject-cofx :random-id-generator)]}
|
||||
[cofx {:keys [public-key ens-name]}]
|
||||
(chat/start-chat cofx public-key ens-name))
|
||||
|
||||
(fx/defn contact-code-submitted
|
||||
(rf/defn contact-code-submitted
|
||||
{:events [:contact.ui/contact-code-submitted]
|
||||
:interceptors [(re-frame/inject-cofx :random-id-generator)]}
|
||||
[{{:contacts/keys [new-identity]} :db :as cofx} new-contact? nickname]
|
||||
(let [{:keys [public-key ens-name]} new-identity]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
#(if new-contact?
|
||||
(contact/add-contact % public-key nickname ens-name)
|
||||
(chat/start-chat % public-key ens-name))
|
||||
#(when new-contact?
|
||||
(navigation/navigate-back %)))))
|
||||
|
||||
(fx/defn pinned-messages-pressed
|
||||
(rf/defn pinned-messages-pressed
|
||||
{:events [:contact.ui/pinned-messages-pressed]}
|
||||
[cofx public-key]
|
||||
(chat/navigate-to-user-pinned-messages cofx public-key))
|
||||
|
||||
@@ -4,13 +4,12 @@
|
||||
[status-im.contact.block :as contact.block]
|
||||
[status-im.contact.db :as contact.db]
|
||||
[status-im.data-store.contacts :as contacts-store]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(fx/defn load-contacts
|
||||
(rf/defn load-contacts
|
||||
{:events [::contacts-loaded]}
|
||||
[{:keys [db] :as cofx} all-contacts]
|
||||
(let [contacts-list (map #(vector (:public-key %)
|
||||
@@ -31,7 +30,7 @@
|
||||
(= public-key (:public-key multiaccount))
|
||||
(assoc :name (:name multiaccount))))
|
||||
|
||||
(fx/defn ensure-contacts
|
||||
(rf/defn ensure-contacts
|
||||
[{:keys [db]} contacts chats]
|
||||
(let [events
|
||||
(reduce
|
||||
@@ -44,6 +43,10 @@
|
||||
(and added (not was-added))
|
||||
(conj [:start-profile-chat public-key])
|
||||
|
||||
(and (not (:has-added-us contact))
|
||||
(= constants/contact-request-state-none (:contact-request-state contact)))
|
||||
(conj [:activity-center/remove-pending-contact-request (:public-key contact)])
|
||||
|
||||
(and was-added (not added))
|
||||
(conj nil)
|
||||
|
||||
@@ -71,15 +74,15 @@
|
||||
:profile-image identicon
|
||||
:address address}))
|
||||
|
||||
(fx/defn send-contact-request
|
||||
(rf/defn send-contact-request
|
||||
{:events [::send-contact-request]}
|
||||
[{:keys [db] :as cofx} public-key]
|
||||
(let [{:keys [name profile-image]} (own-info db)]
|
||||
{::json-rpc/call [{:method "wakuext_sendContactUpdate"
|
||||
:params [public-key name profile-image]
|
||||
:on-success #(log/debug "contact request sent" public-key)}]}))
|
||||
{:json-rpc/call [{:method "wakuext_sendContactUpdate"
|
||||
:params [public-key name profile-image]
|
||||
:on-success #(log/debug "contact request sent" public-key)}]}))
|
||||
|
||||
(fx/defn add-contact
|
||||
(rf/defn add-contact
|
||||
"Add a contact and set pending to false"
|
||||
{:events [:contact.ui/add-to-contact-pressed]}
|
||||
[{:keys [db] :as cofx} public-key nickname ens-name]
|
||||
@@ -93,62 +96,62 @@
|
||||
(re-frame/dispatch [:sanitize-messages-and-process-response %])
|
||||
(re-frame/dispatch [:offload-messages constants/timeline-chat-id])))))
|
||||
|
||||
(fx/defn remove-contact
|
||||
(rf/defn remove-contact
|
||||
"Remove a contact from current account's contact list"
|
||||
{:events [:contact.ui/remove-contact-pressed]}
|
||||
[{:keys [db]} {:keys [public-key]}]
|
||||
{:db (-> db
|
||||
(assoc-in [:contacts/contacts public-key :added] false)
|
||||
(assoc-in [:contacts/contacts public-key :contact-request-state]
|
||||
constants/contact-request-state-none))
|
||||
::json-rpc/call [{:method "wakuext_removeContact"
|
||||
:params [public-key]
|
||||
:on-success #(log/debug "contact removed successfully")}
|
||||
{:method "wakuext_retractContactRequest"
|
||||
:params [{:contactId public-key}]
|
||||
:on-success #(log/debug "contact removed successfully")}]
|
||||
:dispatch [:offload-messages constants/timeline-chat-id]})
|
||||
{:db (-> db
|
||||
(assoc-in [:contacts/contacts public-key :added] false)
|
||||
(assoc-in [:contacts/contacts public-key :contact-request-state]
|
||||
constants/contact-request-state-none))
|
||||
:json-rpc/call [{:method "wakuext_removeContact"
|
||||
:params [public-key]
|
||||
:on-success #(log/debug "contact removed successfully")}
|
||||
{:method "wakuext_retractContactRequest"
|
||||
:params [{:contactId public-key}]
|
||||
:on-success #(log/debug "contact removed successfully")}]
|
||||
:dispatch [:offload-messages constants/timeline-chat-id]})
|
||||
|
||||
(fx/defn accept-contact-request
|
||||
(rf/defn accept-contact-request
|
||||
{:events [:contact-requests.ui/accept-request]}
|
||||
[{:keys [db]} id]
|
||||
{::json-rpc/call [{:method "wakuext_acceptContactRequest"
|
||||
:params [{:id id}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]})
|
||||
{:json-rpc/call [{:method "wakuext_acceptContactRequest"
|
||||
:params [{:id id}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]})
|
||||
|
||||
(fx/defn decline-contact-request
|
||||
(rf/defn decline-contact-request
|
||||
{:events [:contact-requests.ui/decline-request]}
|
||||
[{:keys [db]} id]
|
||||
{::json-rpc/call [{:method "wakuext_dismissContactRequest"
|
||||
:params [{:id id}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]})
|
||||
{:json-rpc/call [{:method "wakuext_dismissContactRequest"
|
||||
:params [{:id id}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]})
|
||||
|
||||
(fx/defn initialize-contacts
|
||||
(rf/defn initialize-contacts
|
||||
[cofx]
|
||||
(contacts-store/fetch-contacts-rpc cofx #(re-frame/dispatch [::contacts-loaded %])))
|
||||
|
||||
(fx/defn open-contact-toggle-list
|
||||
(rf/defn open-contact-toggle-list
|
||||
{:events [:contact.ui/start-group-chat-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc db
|
||||
:group/selected-contacts #{}
|
||||
:new-chat-name "")}
|
||||
(navigation/navigate-to-cofx :contact-toggle-list nil)))
|
||||
|
||||
(fx/defn update-nickname
|
||||
(rf/defn update-nickname
|
||||
{:events [:contacts/update-nickname]}
|
||||
[{:keys [db] :as cofx} public-key nickname]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(contacts-store/set-nickname
|
||||
public-key
|
||||
nickname
|
||||
#(re-frame/dispatch [:sanitize-messages-and-process-response %]))
|
||||
(navigation/navigate-back)))
|
||||
|
||||
(fx/defn switch-mutual-contact-requests-enabled
|
||||
(rf/defn switch-mutual-contact-requests-enabled
|
||||
{:events [:multiaccounts.ui/switch-mutual-contact-requests-enabled]}
|
||||
[cofx enabled?]
|
||||
(multiaccounts.update/multiaccount-update
|
||||
@@ -157,7 +160,7 @@
|
||||
enabled?
|
||||
nil))
|
||||
|
||||
(fx/defn set-search-query
|
||||
(rf/defn set-search-query
|
||||
{:events [:contacts/set-search-query]}
|
||||
[{:keys [db] :as cofx} value]
|
||||
{:db (assoc db :contacts/search-query value)})
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
(ns status-im.currency.core
|
||||
(:require [status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.wallet.prices :as prices]))
|
||||
|
||||
(defn get-currency
|
||||
[db]
|
||||
(get-in db [:multiaccount :currency] :usd))
|
||||
|
||||
(fx/defn set-currency
|
||||
(rf/defn set-currency
|
||||
{:events [:wallet.settings.ui/currency-selected]}
|
||||
[{:keys [db] :as cofx} currency]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:currency
|
||||
currency
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
(ns status-im.data-store.activities
|
||||
(:require [clojure.set :as set]
|
||||
[status-im.activity-center.notification-types :as notification-types]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.data-store.messages :as messages]))
|
||||
[status-im.data-store.messages :as messages]
|
||||
[status-im2.contexts.activity-center.notification-types :as notification-types]))
|
||||
|
||||
(defn- rpc->type
|
||||
[{:keys [type name] :as chat}]
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
(ns status-im.data-store.activities-test
|
||||
(:require [cljs.test :refer [deftest is testing]]
|
||||
[status-im.activity-center.notification-types :as notification-types]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.data-store.activities :as store]))
|
||||
[status-im.data-store.activities :as store]
|
||||
[status-im2.contexts.activity-center.notification-types :as notification-types]))
|
||||
|
||||
(def chat-id
|
||||
"0x04c66155")
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
(:require [clojure.set :as clojure.set]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.data-store.messages :as messages]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.types :as types]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
@@ -109,10 +108,10 @@
|
||||
rpc->type
|
||||
unmarshal-members))
|
||||
|
||||
(fx/defn fetch-chats-rpc
|
||||
(rf/defn fetch-chats-rpc
|
||||
[_ {:keys [on-success]}]
|
||||
{::json-rpc/call [{:method "wakuext_chatsPreview"
|
||||
:params []
|
||||
:js-response true
|
||||
:on-success #(on-success ^js %)
|
||||
:on-error #(log/error "failed to fetch chats" 0 -1 %)}]})
|
||||
{:json-rpc/call [{:method "wakuext_chatsPreview"
|
||||
:params []
|
||||
:js-response true
|
||||
:on-success #(on-success ^js %)
|
||||
:on-error #(log/error "failed to fetch chats" 0 -1 %)}]})
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
(ns status-im.data-store.contacts
|
||||
(:require [clojure.set :as clojure.set]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn <-rpc
|
||||
@@ -22,50 +21,50 @@
|
||||
(and (:added contact)
|
||||
(:hasAddedUs contact)))))
|
||||
|
||||
(fx/defn fetch-contacts-rpc
|
||||
(rf/defn fetch-contacts-rpc
|
||||
[_ on-success]
|
||||
{::json-rpc/call [{:method "wakuext_contacts"
|
||||
:params []
|
||||
:on-success #(on-success (map <-rpc %))
|
||||
:on-error #(log/error "failed to fetch contacts" %)}]})
|
||||
{:json-rpc/call [{:method "wakuext_contacts"
|
||||
:params []
|
||||
:on-success #(on-success (map <-rpc %))
|
||||
:on-error #(log/error "failed to fetch contacts" %)}]})
|
||||
|
||||
(fx/defn add
|
||||
(rf/defn add
|
||||
[_ public-key nickname ens-name on-success]
|
||||
{::json-rpc/call [{:method "wakuext_addContact"
|
||||
:params [{:id public-key :nickname nickname :ensName ens-name}]
|
||||
:js-response true
|
||||
:on-success #(do
|
||||
(log/info "saved contact" public-key "successfuly")
|
||||
(when on-success
|
||||
(on-success %)))
|
||||
:on-error #(log/error "failed to add contact" public-key %)}]})
|
||||
{:json-rpc/call [{:method "wakuext_addContact"
|
||||
:params [{:id public-key :nickname nickname :ensName ens-name}]
|
||||
:js-response true
|
||||
:on-success #(do
|
||||
(log/info "saved contact" public-key "successfuly")
|
||||
(when on-success
|
||||
(on-success %)))
|
||||
:on-error #(log/error "failed to add contact" public-key %)}]})
|
||||
|
||||
(fx/defn set-nickname
|
||||
(rf/defn set-nickname
|
||||
[_ public-key nickname on-success]
|
||||
{::json-rpc/call [{:method "wakuext_setContactLocalNickname"
|
||||
:params [{:id public-key :nickname nickname}]
|
||||
:js-response true
|
||||
:on-success #(do
|
||||
(log/debug "set contact nickname" public-key "successfuly" nickname)
|
||||
(when on-success
|
||||
(on-success %)))
|
||||
:on-error #(log/error "failed to set contact nickname "
|
||||
public-key
|
||||
nickname
|
||||
%)}]})
|
||||
{:json-rpc/call [{:method "wakuext_setContactLocalNickname"
|
||||
:params [{:id public-key :nickname nickname}]
|
||||
:js-response true
|
||||
:on-success #(do
|
||||
(log/debug "set contact nickname" public-key "successfuly" nickname)
|
||||
(when on-success
|
||||
(on-success %)))
|
||||
:on-error #(log/error "failed to set contact nickname "
|
||||
public-key
|
||||
nickname
|
||||
%)}]})
|
||||
|
||||
(fx/defn block
|
||||
(rf/defn block
|
||||
[_ contact-id on-success]
|
||||
{::json-rpc/call [{:method "wakuext_blockContact"
|
||||
:params [contact-id]
|
||||
:js-response true
|
||||
:on-success on-success
|
||||
:on-error #(log/error "failed to block contact" % contact-id)}]})
|
||||
{:json-rpc/call [{:method "wakuext_blockContact"
|
||||
:params [contact-id]
|
||||
:js-response true
|
||||
:on-success on-success
|
||||
:on-error #(log/error "failed to block contact" % contact-id)}]})
|
||||
|
||||
(fx/defn unblock
|
||||
(rf/defn unblock
|
||||
[_ contact-id on-success]
|
||||
{::json-rpc/call [{:method "wakuext_unblockContact"
|
||||
:params [contact-id]
|
||||
:on-success on-success
|
||||
:js-response true
|
||||
:on-error #(log/error "failed to unblock contact" % contact-id)}]})
|
||||
{:json-rpc/call [{:method "wakuext_unblockContact"
|
||||
:params [contact-id]
|
||||
:on-success on-success
|
||||
:js-response true
|
||||
:on-error #(log/error "failed to unblock contact" % contact-id)}]})
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
(ns status-im.data-store.messages
|
||||
(:require [clojure.set :as clojure.set]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn ->rpc
|
||||
@@ -36,6 +35,7 @@
|
||||
:audioDurationMs :audio-duration-ms
|
||||
:deleted :deleted?
|
||||
:deletedForMe :deleted-for-me?
|
||||
:albumId :album-id
|
||||
:new :new?})
|
||||
|
||||
(update :quoted-message
|
||||
@@ -65,54 +65,54 @@
|
||||
limit
|
||||
on-success
|
||||
on-error]
|
||||
{::json-rpc/call [{:method "wakuext_chatMessages"
|
||||
:params [chat-id cursor limit]
|
||||
:on-success (fn [result]
|
||||
(on-success (update result :messages #(map <-rpc %))))
|
||||
:on-error on-error}]})
|
||||
{:json-rpc/call [{:method "wakuext_chatMessages"
|
||||
:params [chat-id cursor limit]
|
||||
:on-success (fn [result]
|
||||
(on-success (update result :messages #(map <-rpc %))))
|
||||
:on-error on-error}]})
|
||||
|
||||
(defn mark-seen-rpc
|
||||
[chat-id ids on-success]
|
||||
{::json-rpc/call [{:method "wakuext_markMessagesSeen"
|
||||
:params [chat-id ids]
|
||||
:on-success #(do
|
||||
(log/debug "successfully marked as seen" %)
|
||||
(when on-success (on-success chat-id ids %)))
|
||||
:on-error #(log/error "failed to get messages" %)}]})
|
||||
{:json-rpc/call [{:method "wakuext_markMessagesSeen"
|
||||
:params [chat-id ids]
|
||||
:on-success #(do
|
||||
(log/debug "successfully marked as seen" %)
|
||||
(when on-success (on-success chat-id ids %)))
|
||||
:on-error #(log/error "failed to get messages" %)}]})
|
||||
|
||||
(defn delete-message-rpc
|
||||
[id]
|
||||
{::json-rpc/call [{:method "wakuext_deleteMessage"
|
||||
:params [id]
|
||||
:on-success #(log/debug "successfully deleted message" id)
|
||||
:on-error #(log/error "failed to delete message" % id)}]})
|
||||
{:json-rpc/call [{:method "wakuext_deleteMessage"
|
||||
:params [id]
|
||||
:on-success #(log/debug "successfully deleted message" id)
|
||||
:on-error #(log/error "failed to delete message" % id)}]})
|
||||
|
||||
(defn delete-messages-from-rpc
|
||||
[author]
|
||||
{::json-rpc/call [{:method "wakuext_deleteMessagesFrom"
|
||||
:params [author]
|
||||
:on-success #(log/debug "successfully deleted messages from" author)
|
||||
:on-error #(log/error "failed to delete messages from" % author)}]})
|
||||
{:json-rpc/call [{:method "wakuext_deleteMessagesFrom"
|
||||
:params [author]
|
||||
:on-success #(log/debug "successfully deleted messages from" author)
|
||||
:on-error #(log/error "failed to delete messages from" % author)}]})
|
||||
|
||||
(defn delete-messages-by-chat-id-rpc
|
||||
[chat-id]
|
||||
{::json-rpc/call [{:method "wakuext_deleteMessagesByChatID"
|
||||
:params [chat-id]
|
||||
:on-success #(log/debug "successfully deleted messages by chat-id" chat-id)
|
||||
:on-error #(log/error "failed to delete messages by chat-id" % chat-id)}]})
|
||||
{:json-rpc/call [{:method "wakuext_deleteMessagesByChatID"
|
||||
:params [chat-id]
|
||||
:on-success #(log/debug "successfully deleted messages by chat-id" chat-id)
|
||||
:on-error #(log/error "failed to delete messages by chat-id" % chat-id)}]})
|
||||
|
||||
(fx/defn delete-message
|
||||
(rf/defn delete-message
|
||||
[cofx id]
|
||||
(delete-message-rpc id))
|
||||
|
||||
(fx/defn delete-messages-from
|
||||
(rf/defn delete-messages-from
|
||||
[cofx author]
|
||||
(delete-messages-from-rpc author))
|
||||
|
||||
(fx/defn mark-messages-seen
|
||||
(rf/defn mark-messages-seen
|
||||
[cofx chat-id ids on-success]
|
||||
(mark-seen-rpc chat-id ids on-success))
|
||||
|
||||
(fx/defn delete-messages-by-chat-id
|
||||
(rf/defn delete-messages-by-chat-id
|
||||
[cofx chat-id]
|
||||
(delete-messages-by-chat-id-rpc chat-id))
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
(ns status-im.data-store.pin-messages
|
||||
(:require [clojure.set :as clojure.set]
|
||||
[status-im.data-store.messages :as messages]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn <-rpc
|
||||
@@ -19,18 +18,18 @@
|
||||
limit
|
||||
on-success
|
||||
on-error]
|
||||
{::json-rpc/call [{:method "wakuext_chatPinnedMessages"
|
||||
:params [chat-id cursor limit]
|
||||
:on-success (fn [result]
|
||||
(let [result (clojure.set/rename-keys result
|
||||
{:pinnedMessages
|
||||
:pinned-messages})]
|
||||
(on-success (update result :pinned-messages #(map <-rpc %)))))
|
||||
:on-error on-error}]})
|
||||
{:json-rpc/call [{:method "wakuext_chatPinnedMessages"
|
||||
:params [chat-id cursor limit]
|
||||
:on-success (fn [result]
|
||||
(let [result (clojure.set/rename-keys result
|
||||
{:pinnedMessages
|
||||
:pinned-messages})]
|
||||
(on-success (update result :pinned-messages #(map <-rpc %)))))
|
||||
:on-error on-error}]})
|
||||
|
||||
(fx/defn send-pin-message
|
||||
(rf/defn send-pin-message
|
||||
[cofx pin-message]
|
||||
{::json-rpc/call [{:method "wakuext_sendPinMessage"
|
||||
:params [(messages/->rpc pin-message)]
|
||||
:on-success #(log/debug "successfully pinned message" pin-message)
|
||||
:on-error #(log/error "failed to pin message" % pin-message)}]})
|
||||
{:json-rpc/call [{:method "wakuext_sendPinMessage"
|
||||
:params [(messages/->rpc pin-message)]
|
||||
:on-success #(log/debug "successfully pinned message" pin-message)
|
||||
:on-error #(log/error "failed to pin message" % pin-message)}]})
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
(ns status-im.data-store.reactions
|
||||
(:require [clojure.set :as clojure.set]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]))
|
||||
(:require [clojure.set :as clojure.set]))
|
||||
|
||||
(defn ->rpc
|
||||
[message]
|
||||
@@ -27,8 +26,8 @@
|
||||
limit
|
||||
on-success
|
||||
on-error]
|
||||
{::json-rpc/call [{:method "wakuext_emojiReactionsByChatID"
|
||||
:params [chat-id cursor limit]
|
||||
:on-success (fn [result]
|
||||
(on-success (map <-rpc result)))
|
||||
:on-error on-error}]})
|
||||
{:json-rpc/call [{:method "wakuext_emojiReactionsByChatID"
|
||||
:params [chat-id cursor limit]
|
||||
:on-success (fn [result]
|
||||
(on-success (map <-rpc result)))
|
||||
:on-error on-error}]})
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
(ns status-im.data-store.visibility-status-updates
|
||||
(:require [clojure.set :as clojure.set]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn <-rpc
|
||||
@@ -17,13 +16,13 @@
|
||||
{:current-user-status :current-user-visibility-status})
|
||||
(update :current-user-visibility-status <-rpc)))
|
||||
|
||||
(fx/defn fetch-visibility-status-updates-rpc
|
||||
(rf/defn fetch-visibility-status-updates-rpc
|
||||
[_]
|
||||
{::json-rpc/call [{:method "wakuext_statusUpdates"
|
||||
:params []
|
||||
:on-success #(re-frame/dispatch
|
||||
[:visibility-status-updates/visibility-status-updates-loaded
|
||||
(:statusUpdates ^js %)])
|
||||
:on-error #(log/error
|
||||
"failed to fetch visibility-status-updates"
|
||||
%)}]})
|
||||
{:json-rpc/call [{:method "wakuext_statusUpdates"
|
||||
:params []
|
||||
:on-success #(re-frame/dispatch
|
||||
[:visibility-status-updates/visibility-status-updates-loaded
|
||||
(:statusUpdates ^js %)])
|
||||
:on-error #(log/error
|
||||
"failed to fetch visibility-status-updates"
|
||||
%)}]})
|
||||
|
||||
+30
-30
@@ -9,7 +9,7 @@
|
||||
[status-im.ethereum.stateofus :as stateofus]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.utils.datetime :as datetime]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im2.navigation.events :as navigation]))
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
(fn [[chain-id name cb]]
|
||||
(ens/expire-at chain-id name cb)))
|
||||
|
||||
(fx/defn update-ens-tx-state
|
||||
(rf/defn update-ens-tx-state
|
||||
{:events [:update-ens-tx-state]}
|
||||
[{:keys [db]} new-state username custom-domain? tx-hash]
|
||||
{:db (assoc-in db
|
||||
@@ -48,7 +48,7 @@
|
||||
:username username
|
||||
:custom-domain? custom-domain?})})
|
||||
|
||||
(fx/defn redirect-to-ens-summary
|
||||
(rf/defn redirect-to-ens-summary
|
||||
{:events [::redirect-to-ens-summary]}
|
||||
[cofx]
|
||||
;; we reset navigation so that navigate back doesn't return
|
||||
@@ -58,19 +58,19 @@
|
||||
[:my-profile
|
||||
:ens-confirmation]))
|
||||
|
||||
(fx/defn update-ens-tx-state-and-redirect
|
||||
(rf/defn update-ens-tx-state-and-redirect
|
||||
{:events [:update-ens-tx-state-and-redirect]}
|
||||
[cofx new-state username custom-domain? tx-hash]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(update-ens-tx-state new-state username custom-domain? tx-hash)
|
||||
(redirect-to-ens-summary)))
|
||||
|
||||
(fx/defn clear-ens-registration
|
||||
(rf/defn clear-ens-registration
|
||||
{:events [:clear-ens-registration]}
|
||||
[{:keys [db]} tx-hash]
|
||||
{:db (update db :ens/registrations dissoc tx-hash)})
|
||||
|
||||
(fx/defn set-state
|
||||
(rf/defn set-state
|
||||
{:events [::name-resolved]}
|
||||
[{:keys [db]} username state address]
|
||||
(when (= username
|
||||
@@ -79,13 +79,13 @@
|
||||
(assoc-in [:ens/registration :state] state)
|
||||
(assoc-in [:ens/registration :address] address))}))
|
||||
|
||||
(fx/defn save-username
|
||||
(rf/defn save-username
|
||||
{:events [::save-username]}
|
||||
[{:keys [db] :as cofx} custom-domain? username redirectToSummary]
|
||||
(let [name (fullname custom-domain? username)
|
||||
names (get-in db [:multiaccount :usernames] [])
|
||||
new-names (conj names name)]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:usernames
|
||||
new-names
|
||||
@@ -97,7 +97,7 @@
|
||||
name
|
||||
{})))))
|
||||
|
||||
(fx/defn set-pub-key
|
||||
(rf/defn set-pub-key
|
||||
{:events [::set-pub-key]}
|
||||
[{:keys [db]}]
|
||||
(let [{:keys [username address custom-domain?]} (:ens/registration db)
|
||||
@@ -115,7 +115,7 @@
|
||||
:on-result [::save-username custom-domain? username true]
|
||||
:on-error [::on-registration-failure]}]))))
|
||||
|
||||
(fx/defn on-input-submitted
|
||||
(rf/defn on-input-submitted
|
||||
{:events [::input-submitted]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [state username custom-domain?]} (:ens/registration db)]
|
||||
@@ -164,7 +164,7 @@
|
||||
5 10
|
||||
1 10))
|
||||
|
||||
(fx/defn register-name
|
||||
(rf/defn register-name
|
||||
{:events [::register-name-pressed]}
|
||||
[{:keys [db]} address]
|
||||
(let [{:keys [username]}
|
||||
@@ -207,7 +207,7 @@
|
||||
;;NOTE we want to handle only last resolve
|
||||
(def resolve-last-id (atom nil))
|
||||
|
||||
(fx/defn set-username-candidate
|
||||
(rf/defn set-username-candidate
|
||||
{:events [::set-username-candidate]}
|
||||
[{:keys [db]} username]
|
||||
(let [{:keys [custom-domain?]} (:ens/registration db)
|
||||
@@ -236,10 +236,10 @@
|
||||
resolve-last-id
|
||||
@resolve-last-id)]})))))
|
||||
|
||||
(fx/defn return-to-ens-main-screen
|
||||
(rf/defn return-to-ens-main-screen
|
||||
{:events [::got-it-pressed ::cancel-pressed]}
|
||||
[{:keys [db] :as cofx} _]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
;; clear registration data
|
||||
{:db (dissoc db :ens/registration)}
|
||||
;; we reset navigation so that navigate back doesn't return
|
||||
@@ -248,22 +248,22 @@
|
||||
[:my-profile
|
||||
:ens-main])))
|
||||
|
||||
(fx/defn switch-domain-type
|
||||
(rf/defn switch-domain-type
|
||||
{:events [::switch-domain-type]}
|
||||
[{:keys [db] :as cofx} _]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(update :ens/registration dissoc :username :state)
|
||||
(update-in [:ens/registration :custom-domain?] not))}))
|
||||
|
||||
(fx/defn change-address
|
||||
(rf/defn change-address
|
||||
{:events [::change-address]}
|
||||
[{:keys [db] :as cofx} _ {:keys [address]}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:ens/registration :address] address)}
|
||||
(bottom-sheet/hide-bottom-sheet)))
|
||||
|
||||
(fx/defn save-preferred-name
|
||||
(rf/defn save-preferred-name
|
||||
{:events [::save-preferred-name]}
|
||||
[cofx name]
|
||||
(multiaccounts.update/multiaccount-update cofx
|
||||
@@ -271,24 +271,24 @@
|
||||
name
|
||||
{}))
|
||||
|
||||
(fx/defn on-registration-failure
|
||||
(rf/defn on-registration-failure
|
||||
"TODO not sure there is actually anything to do here
|
||||
it should only be called if the user cancels the signing
|
||||
Actual registration failure has not been implemented properly"
|
||||
{:events [::on-registration-failure]}
|
||||
[_ _])
|
||||
|
||||
(fx/defn store-name-address
|
||||
(rf/defn store-name-address
|
||||
{:events [::address-resolved]}
|
||||
[{:keys [db]} username address]
|
||||
{:db (assoc-in db [:ens/names username :address] address)})
|
||||
|
||||
(fx/defn store-name-public-key
|
||||
(rf/defn store-name-public-key
|
||||
{:events [::public-key-resolved]}
|
||||
[{:keys [db]} username public-key]
|
||||
{:db (assoc-in db [:ens/names username :public-key] public-key)})
|
||||
|
||||
(fx/defn store-expiration-date
|
||||
(rf/defn store-expiration-date
|
||||
{:events [::get-expiration-time-success]}
|
||||
[{:keys [now db]} username timestamp]
|
||||
{:db (-> db
|
||||
@@ -296,11 +296,11 @@
|
||||
(datetime/timestamp->year-month-day-date timestamp))
|
||||
(assoc-in [:ens/names username :releasable?] (<= timestamp now)))})
|
||||
|
||||
(fx/defn navigate-to-name
|
||||
(rf/defn navigate-to-name
|
||||
{:events [::navigate-to-name]}
|
||||
[{:keys [db] :as cofx} username]
|
||||
(let [chain-id (ethereum/chain-id db)]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{::get-expiration-time
|
||||
[chain-id
|
||||
(stateofus/username username)
|
||||
@@ -313,20 +313,20 @@
|
||||
#(re-frame/dispatch [::public-key-resolved username %])]}
|
||||
(navigation/navigate-to-cofx :ens-name-details username))))
|
||||
|
||||
(fx/defn start-registration
|
||||
(rf/defn start-registration
|
||||
{:events [::add-username-pressed ::get-started-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(set-username-candidate (get-in db [:ens/registration :username] ""))
|
||||
(navigation/navigate-to-cofx :ens-search {})))
|
||||
|
||||
(fx/defn remove-username
|
||||
(rf/defn remove-username
|
||||
{:events [::remove-username]}
|
||||
[{:keys [db] :as cofx} name]
|
||||
(let [names (get-in db [:multiaccount :usernames] [])
|
||||
preferred-name (get-in db [:multiaccount :preferred-name])
|
||||
new-names (remove #(= name %) names)]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:usernames
|
||||
new-names
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(ns status-im.ethereum.ens
|
||||
(:require [clojure.string :as string]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.native-module.core :as status]))
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im2.common.json-rpc.events :as json-rpc]))
|
||||
|
||||
;; this is the addresses of ens registries for the different networks
|
||||
(def ens-registries
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
(ns status-im.ethereum.subscriptions
|
||||
(:require [status-im.ethereum.eip55 :as eip55]
|
||||
[status-im.ethereum.transactions.core :as transactions]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.wallet.core :as wallet.core]
|
||||
[status-im.wallet.db :as wallet]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(fx/defn new-transfers
|
||||
(rf/defn new-transfers
|
||||
[cofx block-number accounts]
|
||||
(log/debug "[wallet-subs] new-transfers"
|
||||
"accounts" accounts
|
||||
"block" block-number)
|
||||
(transactions/check-watched-transactions cofx))
|
||||
|
||||
(fx/defn recent-history-fetching-started
|
||||
(rf/defn recent-history-fetching-started
|
||||
[{:keys [db]} accounts]
|
||||
(log/debug "[wallet-subs] recent-history-fetching-started"
|
||||
"accounts"
|
||||
@@ -26,7 +26,7 @@
|
||||
event
|
||||
(assoc :dispatch event))))
|
||||
|
||||
(fx/defn recent-history-fetching-ended
|
||||
(rf/defn recent-history-fetching-ended
|
||||
[{:keys [db]} {:keys [accounts blockNumber]}]
|
||||
(log/debug "[wallet-subs] recent-history-fetching-ended"
|
||||
"accounts" accounts
|
||||
@@ -55,18 +55,18 @@
|
||||
:before-block blockNumber
|
||||
:limit 20}})
|
||||
|
||||
(fx/defn fetching-error
|
||||
(rf/defn fetching-error
|
||||
[{:keys [db] :as cofx} {:keys [message]}]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (assoc db :wallet/fetching-error message)}
|
||||
(wallet.core/after-checking-history)))
|
||||
|
||||
(fx/defn non-archival-node-detected
|
||||
(rf/defn non-archival-node-detected
|
||||
[{:keys [db]} _]
|
||||
{:db (assoc db :wallet/non-archival-node true)})
|
||||
|
||||
(fx/defn new-wallet-event
|
||||
(rf/defn new-wallet-event
|
||||
[cofx {:keys [type blockNumber accounts] :as event}]
|
||||
(log/info "[wallet-subs] new-wallet-event"
|
||||
"event-type" type
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
[status-im.ethereum.decode :as decode]
|
||||
[status-im.ethereum.eip55 :as eip55]
|
||||
[status-im.ethereum.encode :as encode]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.utils.fx :as fx]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.mobile-sync :as utils.mobile-sync]
|
||||
[status-im.wallet.core :as wallet]
|
||||
[status-im2.common.json-rpc.events :as json-rpc]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(def confirmations-count-threshold 12)
|
||||
@@ -107,7 +107,7 @@
|
||||
|
||||
(def default-transfers-limit 20)
|
||||
|
||||
(fx/defn watch-transaction
|
||||
(rf/defn watch-transaction
|
||||
"Set a watch for the given transaction
|
||||
`watch-params` needs to contain a `trigger-fn` and `on-trigger` functions
|
||||
`trigger-fn` is a function that returns true if the watch has been triggered
|
||||
@@ -120,7 +120,7 @@
|
||||
[:ethereum/watched-transactions transaction-id]
|
||||
watch-params)}))
|
||||
|
||||
(fx/defn check-transaction
|
||||
(rf/defn check-transaction
|
||||
"Check if the transaction has been triggered and applies the effects returned
|
||||
by `on-trigger` if that is the case"
|
||||
[{:keys [db] :as cofx} {:keys [hash] :as transaction}]
|
||||
@@ -128,14 +128,14 @@
|
||||
(get-in db [:ethereum/watched-transactions hash])]
|
||||
(let [{:keys [trigger-fn on-trigger]} watch-params]
|
||||
(when (trigger-fn db transaction)
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (update db
|
||||
:ethereum/watched-transactions
|
||||
dissoc
|
||||
hash)}
|
||||
(on-trigger transaction))))))
|
||||
|
||||
(fx/defn check-watched-transactions
|
||||
(rf/defn check-watched-transactions
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [watched-transactions
|
||||
(reduce-kv (fn [acc _ {:keys [transactions]}]
|
||||
@@ -144,13 +144,13 @@
|
||||
(keys (get db :ethereum/watched-transactions)))))
|
||||
{}
|
||||
(get-in db [:wallet :accounts]))]
|
||||
(apply fx/merge
|
||||
(apply rf/merge
|
||||
cofx
|
||||
(map (fn [[_ transaction]]
|
||||
(check-transaction transaction))
|
||||
watched-transactions))))
|
||||
|
||||
(fx/defn add-transfer
|
||||
(rf/defn add-transfer
|
||||
"We determine a unique id for the transfer before adding it because some
|
||||
transaction can contain multiple transfers and they would overwrite each other
|
||||
in the transfer map if identified by hash"
|
||||
@@ -162,7 +162,7 @@
|
||||
(:type transfer-by-hash))))
|
||||
id
|
||||
hash))]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:wallet :accounts address :transactions unique-id]
|
||||
(assoc transfer :hash unique-id))}
|
||||
@@ -183,7 +183,7 @@
|
||||
(eip55/address->checksum address)
|
||||
:min-block-transfers-count]))
|
||||
|
||||
(fx/defn set-lowest-fetched-block
|
||||
(rf/defn set-lowest-fetched-block
|
||||
[{:keys [db]} address transfers]
|
||||
(let [checksum (eip55/address->checksum address)
|
||||
{:keys [min-block min-block-transfers-count]}
|
||||
@@ -231,15 +231,15 @@
|
||||
accounts
|
||||
addresses))))
|
||||
|
||||
(fx/defn tx-fetching-in-progress
|
||||
(rf/defn tx-fetching-in-progress
|
||||
[{:keys [db]} addresses]
|
||||
{:db (update-fetching-status db addresses :history? true)})
|
||||
|
||||
(fx/defn tx-fetching-ended
|
||||
(rf/defn tx-fetching-ended
|
||||
[{:keys [db]} addresses]
|
||||
{:db (update-fetching-status db addresses :history? false)})
|
||||
|
||||
(fx/defn tx-history-end-reached
|
||||
(rf/defn tx-history-end-reached
|
||||
[{:keys [db] :as cofx} address]
|
||||
(let [syncing-allowed? (utils.mobile-sync/syncing-allowed? cofx)]
|
||||
{:db (assoc-in db
|
||||
@@ -248,7 +248,7 @@
|
||||
:all
|
||||
:all-preloaded))}))
|
||||
|
||||
(fx/defn delete-pending-transactions
|
||||
(rf/defn delete-pending-transactions
|
||||
[{:keys [db]} address transactions]
|
||||
(let [all-transactions
|
||||
(get-in db [:wallet :accounts (eip55/address->checksum address) :transactions])
|
||||
@@ -261,7 +261,7 @@
|
||||
transactions)]
|
||||
{:wallet/delete-pending-transactions pending-tx-hashes}))
|
||||
|
||||
(fx/defn handle-new-transfer
|
||||
(rf/defn handle-new-transfer
|
||||
[{:keys [db] :as cofx} transfers {:keys [address limit]}]
|
||||
(log/debug "[transfers] new-transfers"
|
||||
"address" address
|
||||
@@ -290,9 +290,9 @@
|
||||
|
||||
(< (count transfers) limit)
|
||||
(conj (tx-history-end-reached checksum)))]
|
||||
(apply fx/merge cofx (tx-fetching-ended [checksum]) effects)))
|
||||
(apply rf/merge cofx (tx-fetching-ended [checksum]) effects)))
|
||||
|
||||
(fx/defn check-ens-transactions
|
||||
(rf/defn check-ens-transactions
|
||||
[{:keys [db] :as cofx} transfers]
|
||||
(let [set-of-transactions-hash (reduce (fn [acc {:keys [hash]}] (conj acc hash)) #{} transfers)
|
||||
registrations (filter
|
||||
@@ -310,7 +310,7 @@
|
||||
transaction-success (get transfer :transfer)]
|
||||
(cond
|
||||
(= transaction-success true)
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(ens/clear-ens-registration hash)
|
||||
(ens/save-username custom-domain? username false))
|
||||
(= type :failed)
|
||||
@@ -318,17 +318,17 @@
|
||||
:else
|
||||
nil)))
|
||||
registrations)]
|
||||
(apply fx/merge cofx fxs)))
|
||||
(apply rf/merge cofx fxs)))
|
||||
|
||||
(fx/defn new-transfers
|
||||
(rf/defn new-transfers
|
||||
{:events [::new-transfers]}
|
||||
[cofx transfers params]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(handle-new-transfer transfers params)
|
||||
(wallet/stop-fetching-on-empty-tx-history transfers)
|
||||
(check-ens-transactions transfers)))
|
||||
|
||||
(fx/defn tx-fetching-failed
|
||||
(rf/defn tx-fetching-failed
|
||||
{:events [::tx-fetching-failed]}
|
||||
[cofx error address]
|
||||
(log/debug "[transactions] tx-fetching-failed"
|
||||
@@ -371,13 +371,13 @@
|
||||
[db address]
|
||||
(not-empty (get-in db [:wallet :accounts address :transactions])))
|
||||
|
||||
(fx/defn fetch-more-tx
|
||||
(rf/defn fetch-more-tx
|
||||
{:events [:transactions/fetch-more]}
|
||||
[{:keys [db] :as cofx} address]
|
||||
(let [min-known-block (or (get-min-known-block db address)
|
||||
(:ethereum/current-block db))
|
||||
min-block-transfers-count (or (min-block-transfers-count db address) 0)]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:transactions/get-transfers
|
||||
{:chain-tokens (:wallet/all-tokens db)
|
||||
@@ -393,7 +393,7 @@
|
||||
min-block-transfers-count)}}}
|
||||
(tx-fetching-in-progress [address]))))
|
||||
|
||||
(fx/defn get-fetched-transfers
|
||||
(rf/defn get-fetched-transfers
|
||||
{:events [:transaction/get-fetched-transfers]}
|
||||
[{:keys [db]}]
|
||||
{:transactions/get-transfers
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user