Compare commits
14
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0aede3510d | ||
|
|
39e29cfb5a | ||
|
|
37909c2d81 | ||
|
|
01660765b7 | ||
|
|
c0c0742687 | ||
|
|
b074e9c58e | ||
|
|
8cf95cdb30 | ||
|
|
ba41d4b271 | ||
|
|
003b0ffb1e | ||
|
|
dbd61a34a0 | ||
|
|
cbb6571954 | ||
|
|
7b72391e60 | ||
|
|
269d13e2f8 | ||
|
|
fc07fbf787 |
+20
-20
@@ -1,20 +1,20 @@
|
||||
{: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
|
||||
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 [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
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
;; -*- mode: clojure -*-
|
||||
;; vi: ft=clojure
|
||||
{:width 105
|
||||
:style [;; community style
|
||||
;; https://github.com/kkinnear/zprint/blob/main/doc/reference.md#community
|
||||
:community
|
||||
|
||||
;; no comma in map
|
||||
:no-comma
|
||||
|
||||
:custom-justify
|
||||
|
||||
;; respect all newlines
|
||||
;; https://github.com/kkinnear/zprint/blob/main/doc/reference.md#respect-nl
|
||||
:respect-nl
|
||||
|
||||
;; respect blank line
|
||||
;; https://github.com/kkinnear/zprint/blob/main/doc/reference.md#respect-bl
|
||||
:respect-bl]
|
||||
:fn-map
|
||||
{"reg-sub" :arg1-pair
|
||||
"list-comp" :binding
|
||||
"defview" :arg1-body
|
||||
"letsubs" :binding
|
||||
"testing" :arg1-body
|
||||
"deftest-sub" :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?]]}]
|
||||
"set!" "reset!"
|
||||
"assoc-when" "assoc"
|
||||
"assoc-some" "assoc"
|
||||
"conj-when" "conj"
|
||||
"conj-some" "conj"}
|
||||
: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}}
|
||||
:map {:justify? true :justify {:max-variance 1000}}
|
||||
:pair {:justify? true :justify {:max-variance 1000}}}}}
|
||||
@@ -285,16 +285,20 @@ endif
|
||||
# Tests
|
||||
#--------------
|
||||
|
||||
lint: export TARGET := clojure
|
||||
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 src && echo src) && \
|
||||
clojure -Scp "$$CLASS_PATH" -m cljfmt.main check --indents indentation.edn $$TARGETS
|
||||
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
|
||||
|
||||
lint-fix: export TARGET := clojure
|
||||
lint-fix: export TARGET := default
|
||||
lint-fix: ##@test Run code style checks and fix issues
|
||||
clojure -Scp "$$CLASS_PATH" -m cljfmt.main fix src --indents indentation.edn
|
||||
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
|
||||
|
||||
|
||||
shadow-server: export TARGET := clojure
|
||||
shadow-server:##@ Start shadow-cljs in server mode for watching
|
||||
@@ -305,6 +309,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
|
||||
@@ -319,7 +331,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.
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
{letsubs [[:inner 0]]}
|
||||
+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
|
||||
{
|
||||
|
||||
+259
-181
@@ -51,6 +51,45 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "borkdude/edamame/0.0.11-alpha.28/edamame-0.0.11-alpha.28",
|
||||
"host": "https://repo.clojars.org",
|
||||
"pom": {
|
||||
"sha1": "488f403591739aab5a68ce6e7f82c0e855c23fd6",
|
||||
"sha256": "1cw712kzza733g55s02ql35q630zd8j8nmnpivcczjkg240jans4"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "371f3e232e7fdb04b7b2044825eb9822280e8f93",
|
||||
"sha256": "1iyxq6jypjd875cgdyllknh27mx5fnkyjz80mr927d5i94r0ywj4"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "borkdude/sci.impl.reflector/0.0.1/sci.impl.reflector-0.0.1",
|
||||
"host": "https://repo.clojars.org",
|
||||
"pom": {
|
||||
"sha1": "eb3aff6c7db85d91f7e05b98e06d1354a4fce36c",
|
||||
"sha256": "1bvr7cvpbvqi7swypzpbfrig16zipwvmg4m47y2x5chs5czwxv15"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "33dfc86102e0ea400498cbca47572459c1c43b00",
|
||||
"sha256": "0a5gxmj8kzc01y9bn7l4x7c1v5q9wcbvw5hdr525d3ylsyl6xfkw"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "borkdude/sci/0.2.1-alpha.1/sci-0.2.1-alpha.1",
|
||||
"host": "https://repo.clojars.org",
|
||||
"pom": {
|
||||
"sha1": "516cb8e3a8e430d59d9c3e7a51f9f859e3b249e0",
|
||||
"sha256": "1nrww29m90q1avaahw7i5418c18crc3cidhbg3ml7h7vjjplsl9y"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "96e39dcbc3fb3a41c6bf2e628303cf0f534b28a3",
|
||||
"sha256": "1cjvz85ls982rmx90igv4mcfaa53fj5z29df9mf4jplyig3l9dxb"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "cider/cider-nrepl/0.25.3/cider-nrepl-0.25.3",
|
||||
"host": "https://repo.clojars.org",
|
||||
@@ -78,15 +117,15 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "cljfmt/cljfmt/0.6.7/cljfmt-0.6.7",
|
||||
"path": "clj-stacktrace/clj-stacktrace/0.2.8/clj-stacktrace-0.2.8",
|
||||
"host": "https://repo.clojars.org",
|
||||
"pom": {
|
||||
"sha1": "3d7ac9112908c9c9349adc056d1d06ae2cd33c21",
|
||||
"sha256": "1q46q43mykn61f032y5734j84gcjca41pwd3iik9xghnzmphy2mn"
|
||||
"sha1": "c5a47e6858344c9fd42eecafc7920a7a18d6126d",
|
||||
"sha256": "1az0fs9k5xvzl8bz564apd77kqc83nl8sxsrvmswmbmkamvy4hd3"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "91e8afa2c19db72acdef7f881aad905871ba6e69",
|
||||
"sha256": "0ara83gaqnafjgr2aqz5zqmywdsmhsz483xkkxpiwbn9lfqvidmh"
|
||||
"sha1": "b0654b98763199ee57182526465d823492d1cc3f",
|
||||
"sha256": "1029wd82qyxv6ji9pd38m32nqia56h6845lqv4ym4dsz5i201g9a"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -104,15 +143,15 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "cljsjs/react/17.0.1-0/react-17.0.1-0",
|
||||
"path": "cljsjs/react-dom-server/17.0.1-0/react-dom-server-17.0.1-0",
|
||||
"host": "https://repo.clojars.org",
|
||||
"pom": {
|
||||
"sha1": "d5d3681281585d981375fe7bb29362bfcd0d4449",
|
||||
"sha256": "0rskh6mfq5h0l0wybs68w9v585a6zlnnfgrvsf5k3h51fk2p28da"
|
||||
"sha1": "ff154f318e1f63061b5bd42d9a38fc8547360cb4",
|
||||
"sha256": "166ynlrph7rx3nql0c85c37vcbcsnwbjamk71hw74rz451pgnncr"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "726da8a9305a865df90d81e9a8d58f87ff0ee8bd",
|
||||
"sha256": "0bfmvw8gk98vdf9azll6041r1jaz1pmb0dyb35cfc8dr3mmr4ag7"
|
||||
"sha1": "d5c53eca9f3884402c76268b82e3828223dcbf90",
|
||||
"sha256": "1530hwqpxzxfjm6dy77whqwjzzx79jpnd9xvnkxy1lnk7l7lj494"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -130,15 +169,15 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "cljsjs/react-dom-server/17.0.1-0/react-dom-server-17.0.1-0",
|
||||
"path": "cljsjs/react/17.0.1-0/react-17.0.1-0",
|
||||
"host": "https://repo.clojars.org",
|
||||
"pom": {
|
||||
"sha1": "ff154f318e1f63061b5bd42d9a38fc8547360cb4",
|
||||
"sha256": "166ynlrph7rx3nql0c85c37vcbcsnwbjamk71hw74rz451pgnncr"
|
||||
"sha1": "d5d3681281585d981375fe7bb29362bfcd0d4449",
|
||||
"sha256": "0rskh6mfq5h0l0wybs68w9v585a6zlnnfgrvsf5k3h51fk2p28da"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "d5c53eca9f3884402c76268b82e3828223dcbf90",
|
||||
"sha256": "1530hwqpxzxfjm6dy77whqwjzzx79jpnd9xvnkxy1lnk7l7lj494"
|
||||
"sha1": "726da8a9305a865df90d81e9a8d58f87ff0ee8bd",
|
||||
"sha256": "0bfmvw8gk98vdf9azll6041r1jaz1pmb0dyb35cfc8dr3mmr4ag7"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -272,32 +311,6 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "com/googlecode/java-diff-utils/diffutils/1.3.0/diffutils-1.3.0",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"pom": {
|
||||
"sha1": "7d5e372ff32c90095800f96d8308c41af0285a41",
|
||||
"sha256": "1dj7p0m0kwnjvy1y3kq63zb6bw0azjf79i5xbccmy3wv63b1vqrg"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "7e060dd5b19431e6d198e91ff670644372f60fbd",
|
||||
"sha256": "1hn5plp7iyl626h8mrra56sysfm2qannj1dapr1m5afwkb24vfk1"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "com/googlecode/json-simple/json-simple/1.1.1/json-simple-1.1.1",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"pom": {
|
||||
"sha1": "5e902aae26ac5c36f6420f689f43333129dd69e2",
|
||||
"sha256": "10vzlnl8vbjv2jqf818wdb7kgy9c6qjka7fjmmi3vdpg1mcn6pv6"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "c9ad4a0850ab676c5c64461a05ca524cdfff59f1",
|
||||
"sha256": "170rflxnqnah0265ik2aylmxkshyqbf2zas9bp2l32xqj9l6jsaf"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "com/google/elemental2/elemental2-core/1.0.0-RC1/elemental2-core-1.0.0-RC1",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
@@ -428,6 +441,19 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "com/googlecode/json-simple/json-simple/1.1.1/json-simple-1.1.1",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"pom": {
|
||||
"sha1": "5e902aae26ac5c36f6420f689f43333129dd69e2",
|
||||
"sha256": "10vzlnl8vbjv2jqf818wdb7kgy9c6qjka7fjmmi3vdpg1mcn6pv6"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "c9ad4a0850ab676c5c64461a05ca524cdfff59f1",
|
||||
"sha256": "170rflxnqnah0265ik2aylmxkshyqbf2zas9bp2l32xqj9l6jsaf"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "com/ibm/icu/icu4j/66.1/icu4j-66.1",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
@@ -441,58 +467,6 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "commons-codec/commons-codec/1.10/commons-codec-1.10",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"pom": {
|
||||
"sha1": "44b9477418d2942d45550f7e7c66c16262062d0e",
|
||||
"sha256": "1yscxabk7i59vgfjg7c1y3prj39h1d8prnwgxbisc4ni29qdpf5x"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "4b95f4897fa13f2cd904aee711aeafc0c5295cd8",
|
||||
"sha256": "0scm6321zz76dc3bs8sy2qyami755lz4lq5455gl67bi9slxyha2"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "commons-fileupload/commons-fileupload/1.4/commons-fileupload-1.4",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"pom": {
|
||||
"sha1": "65112009d674333c1acfafb4e198ff250d710764",
|
||||
"sha256": "007nyd66fqp3fbrmnsbfp1fpkhmr2lk33qmkp3salqld3xd7qlc8"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "f95188e3d372e20e7328706c37ef366e5d7859b0",
|
||||
"sha256": "1xyyl54sfxsdcwxdyq6b0azmr31b4dwqns850jjkw9a9dwrh5v54"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "commons-io/commons-io/2.6/commons-io-2.6",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"pom": {
|
||||
"sha1": "5060835593e5b6ed18c82fc2e782f0a3c30a00b1",
|
||||
"sha256": "0q4a6fp6xkyd86ikymkyv2plhf9vj8aqvggxg9d1yad2jcw8c8qc"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "815893df5f31da2ece4040fe0a12fd44b577afaf",
|
||||
"sha256": "04v5fg53jl9gbn6pyz3l7kbpxv0xjzyasnw6yd1a3hhacq2d6xzq"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "compojure/compojure/1.5.2/compojure-1.5.2",
|
||||
"host": "https://repo.clojars.org",
|
||||
"pom": {
|
||||
"sha1": "9e8da477b6682094d56802cb155291a2acb829bd",
|
||||
"sha256": "036z64iprypccz03iq7lqxvw99xjh4xlsfmfwbs37pmhfnfmbdnx"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "0b5258d0616ffc5f64c2b6d95f09de56d24df439",
|
||||
"sha256": "1s2k05lwnlm9a66mxnsss437i9gp70dny8y2rlfkl090s6mdqsaf"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "com/taoensso/encore/2.105.0/encore-2.105.0",
|
||||
"host": "https://repo.clojars.org",
|
||||
@@ -571,6 +545,58 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "commons-codec/commons-codec/1.10/commons-codec-1.10",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"pom": {
|
||||
"sha1": "44b9477418d2942d45550f7e7c66c16262062d0e",
|
||||
"sha256": "1yscxabk7i59vgfjg7c1y3prj39h1d8prnwgxbisc4ni29qdpf5x"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "4b95f4897fa13f2cd904aee711aeafc0c5295cd8",
|
||||
"sha256": "0scm6321zz76dc3bs8sy2qyami755lz4lq5455gl67bi9slxyha2"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "commons-fileupload/commons-fileupload/1.4/commons-fileupload-1.4",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"pom": {
|
||||
"sha1": "65112009d674333c1acfafb4e198ff250d710764",
|
||||
"sha256": "007nyd66fqp3fbrmnsbfp1fpkhmr2lk33qmkp3salqld3xd7qlc8"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "f95188e3d372e20e7328706c37ef366e5d7859b0",
|
||||
"sha256": "1xyyl54sfxsdcwxdyq6b0azmr31b4dwqns850jjkw9a9dwrh5v54"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "commons-io/commons-io/2.6/commons-io-2.6",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"pom": {
|
||||
"sha1": "5060835593e5b6ed18c82fc2e782f0a3c30a00b1",
|
||||
"sha256": "0q4a6fp6xkyd86ikymkyv2plhf9vj8aqvggxg9d1yad2jcw8c8qc"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "815893df5f31da2ece4040fe0a12fd44b577afaf",
|
||||
"sha256": "04v5fg53jl9gbn6pyz3l7kbpxv0xjzyasnw6yd1a3hhacq2d6xzq"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "compojure/compojure/1.5.2/compojure-1.5.2",
|
||||
"host": "https://repo.clojars.org",
|
||||
"pom": {
|
||||
"sha1": "9e8da477b6682094d56802cb155291a2acb829bd",
|
||||
"sha256": "036z64iprypccz03iq7lqxvw99xjh4xlsfmfwbs37pmhfnfmbdnx"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "0b5258d0616ffc5f64c2b6d95f09de56d24df439",
|
||||
"sha256": "1s2k05lwnlm9a66mxnsss437i9gp70dny8y2rlfkl090s6mdqsaf"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "crypto-equality/crypto-equality/1.0.0/crypto-equality-1.0.0",
|
||||
"host": "https://repo.clojars.org",
|
||||
@@ -649,6 +675,19 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "hashp/hashp/0.2.1/hashp-0.2.1",
|
||||
"host": "https://repo.clojars.org",
|
||||
"pom": {
|
||||
"sha1": "32530b9106a64fd5442d2aa27c6da4175d1f1440",
|
||||
"sha256": "1z94k8c52r87rq3nhc0mqazcxff6d4phi8gy1bgndhiz4nq1mia7"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "fb501db2eb4a028c1875382d58c17c381aec47b8",
|
||||
"sha256": "1lwirzb60zvksvkb3arpwi4fk1xnp0x5ljmrca5vf7dq25lmwmsd"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "hiccup/hiccup/1.0.5/hiccup-1.0.5",
|
||||
"host": "https://repo.clojars.org",
|
||||
@@ -779,6 +818,32 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "mvxcvi/arrangement/1.2.0/arrangement-1.2.0",
|
||||
"host": "https://repo.clojars.org",
|
||||
"pom": {
|
||||
"sha1": "4f19bd291595870162eadd35456a0b2e76444a64",
|
||||
"sha256": "1qqnl05nwcjnzhlgplcsbckrp8pqvf8n6bf8kr8rz7lz2q4px3vb"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "036e640bb9e14c2aa95589a45a018eb8358ce3f6",
|
||||
"sha256": "1m3v1rkpdmv7aym5vq2swh0mf9mg7xppdr3vrl4g6qm3s42c24b7"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "mvxcvi/puget/1.3.1/puget-1.3.1",
|
||||
"host": "https://repo.clojars.org",
|
||||
"pom": {
|
||||
"sha1": "07104dc20a13c7e255fffee4f16de9a6873c187f",
|
||||
"sha256": "1129rb3qksg7n85j03k6d3sr6868g724097vxids1r4wqj2phxkf"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "a4f7dcf71ccd8d69d4ecd2b19f3d671dfc169308",
|
||||
"sha256": "029znh7p8f1h91gri4jhzwqsa0rnn3i34yr3kav55npym2sw5sfp"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "net/cgrand/macrovich/0.2.1/macrovich-0.2.1",
|
||||
"host": "https://repo.clojars.org",
|
||||
@@ -884,15 +949,15 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/clojure/core.rrb-vector/0.1.1/core.rrb-vector-0.1.1",
|
||||
"path": "org/clojure/core.rrb-vector/0.1.2/core.rrb-vector-0.1.2",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"pom": {
|
||||
"sha1": "3231642aa1dcf628c864a5f208cd293fbd6a385a",
|
||||
"sha256": "18kk5sds5lg8r2kidhz9qpgyrvggkj8j4sgfdsmyyl93w3f16lnp"
|
||||
"sha1": "e9336ac820c5a7e07fe0aa431df981cbab6db3e3",
|
||||
"sha256": "07q9qmxc7ggaxh27imgs34svn4j269rhslbnrs63ahrqzk5bmqlf"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "aafb7677ec1e9f344fc834bbbdb91e8ba02af474",
|
||||
"sha256": "0cqyy1vqrhilgwrdxsibd7360ch3hhwjnbbnzsak38v6i6mg66xl"
|
||||
"sha1": "0404feea925608b921b56acd11d3b187a0d33fe4",
|
||||
"sha256": "13hkx1285f2imqlj6wbgyxki2yg8rmfr49iq1zijxm1cgfx8xyai"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -935,19 +1000,6 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/clojure/google-closure-library/0.0-20191016-6ae1f72f/google-closure-library-0.0-20191016-6ae1f72f",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"pom": {
|
||||
"sha1": "dea94d117aa88d75e281f877914454f79df06bf2",
|
||||
"sha256": "1nysls9ywj3b3zvlfwy68kayx47r4bacidmq1vx8w4h043l9kxrr"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "6025affb7181cd40418600864f58eed1ea80055d",
|
||||
"sha256": "0w6waii2qps7vp3nzbj5nai809xdq26ss0cabl4wz1s8fc6js6qw"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/clojure/google-closure-library-third-party/0.0-20191016-6ae1f72f/google-closure-library-third-party-0.0-20191016-6ae1f72f",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
@@ -961,6 +1013,19 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/clojure/google-closure-library/0.0-20191016-6ae1f72f/google-closure-library-0.0-20191016-6ae1f72f",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"pom": {
|
||||
"sha1": "dea94d117aa88d75e281f877914454f79df06bf2",
|
||||
"sha256": "1nysls9ywj3b3zvlfwy68kayx47r4bacidmq1vx8w4h043l9kxrr"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "6025affb7181cd40418600864f58eed1ea80055d",
|
||||
"sha256": "0w6waii2qps7vp3nzbj5nai809xdq26ss0cabl4wz1s8fc6js6qw"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/clojure/spec.alpha/0.2.176/spec.alpha-0.2.176",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
@@ -987,19 +1052,6 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/clojure/tools.analyzer/1.0.0/tools.analyzer-1.0.0",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"pom": {
|
||||
"sha1": "fa72b6392b31762b55e0dc3de1c220ecdc6bb8a7",
|
||||
"sha256": "1yg46a9zbga7rsrhwdv877hh60hcbyaykn37r3i50icxmgqcylq4"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "d2fb65426c7998647fb1fb3db1fb5b222ab91df6",
|
||||
"sha256": "0mj1xi3v03fzcw1smpayvbvbgly2p3ysbgfz7jgfdhmxi4gl6gs6"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/clojure/tools.analyzer.jvm/1.1.0/tools.analyzer.jvm-1.1.0",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
@@ -1013,6 +1065,19 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/clojure/tools.analyzer/1.0.0/tools.analyzer-1.0.0",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"pom": {
|
||||
"sha1": "fa72b6392b31762b55e0dc3de1c220ecdc6bb8a7",
|
||||
"sha256": "1yg46a9zbga7rsrhwdv877hh60hcbyaykn37r3i50icxmgqcylq4"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "d2fb65426c7998647fb1fb3db1fb5b222ab91df6",
|
||||
"sha256": "0mj1xi3v03fzcw1smpayvbvbgly2p3ysbgfz7jgfdhmxi4gl6gs6"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/clojure/tools.cli/1.0.194/tools.cli-1.0.194",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
@@ -1078,19 +1143,6 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/graalvm/js/js/20.1.0/js-20.1.0",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"pom": {
|
||||
"sha1": "95452a7fdac1d358f1dd66b33e49f4440e986922",
|
||||
"sha256": "0gkazzg8771g3pc90fb99wmlk99rjimcryrmzz6zab742m4dbina"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "0abe5e8068014ccb34cf075637a00b7ce37e4a8c",
|
||||
"sha256": "0v5pxjl9p7wwfrrzkkqh6qbvnn0p8n342smxzcqk3qxl4ah3aqnk"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/graalvm/js/js-scriptengine/20.1.0/js-scriptengine-20.1.0",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
@@ -1104,6 +1156,19 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/graalvm/js/js/20.1.0/js-20.1.0",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"pom": {
|
||||
"sha1": "95452a7fdac1d358f1dd66b33e49f4440e986922",
|
||||
"sha256": "0gkazzg8771g3pc90fb99wmlk99rjimcryrmzz6zab742m4dbina"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "0abe5e8068014ccb34cf075637a00b7ce37e4a8c",
|
||||
"sha256": "0v5pxjl9p7wwfrrzkkqh6qbvnn0p8n342smxzcqk3qxl4ah3aqnk"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/graalvm/regex/regex/20.1.0/regex-20.1.0",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
@@ -1234,19 +1299,6 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/ow2/asm/asm/7.1/asm-7.1",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"pom": {
|
||||
"sha1": "7e40eb6619fd20bd7d98bf775bfdd810aec87ac7",
|
||||
"sha256": "101i3pyrq082kjyz413hfqwkjjsyfnk9kx3rqr38ln56mlp78a8g"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "fa29aa438674ff19d5e1386d2c3527a0267f291e",
|
||||
"sha256": "1pnlb1ick32bihpzc599xl9ppd07qhls6pm0xaqwrj9cdlmzmcja"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/ow2/asm/asm-analysis/7.1/asm-analysis-7.1",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
@@ -1299,6 +1351,19 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/ow2/asm/asm/7.1/asm-7.1",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
"pom": {
|
||||
"sha1": "7e40eb6619fd20bd7d98bf775bfdd810aec87ac7",
|
||||
"sha256": "101i3pyrq082kjyz413hfqwkjjsyfnk9kx3rqr38ln56mlp78a8g"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "fa29aa438674ff19d5e1386d2c3527a0267f291e",
|
||||
"sha256": "1pnlb1ick32bihpzc599xl9ppd07qhls6pm0xaqwrj9cdlmzmcja"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "org/wildfly/client/wildfly-client-config/1.0.1.Final/wildfly-client-config-1.0.1.Final",
|
||||
"host": "https://repo1.maven.org/maven2",
|
||||
@@ -1351,19 +1416,6 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "reagent/reagent/1.0.0/reagent-1.0.0",
|
||||
"host": "https://repo.clojars.org",
|
||||
"pom": {
|
||||
"sha1": "93ad5ccb0101108fb0843a3f2c50da28f8fd8336",
|
||||
"sha256": "1l4xzgc4wbd8b29mhj5j336cf8w1zccaia0w413zf3bnj6jf5m38"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "a1dd4d40425bb2e1afad0fe72780b43ff394ccfa",
|
||||
"sha256": "1g607s1ymns85923bvhwrsj0y5czyqqq1jmxx0a58fnsm1b318fa"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "re-com/re-com/2.8.0/re-com-2.8.0",
|
||||
"host": "https://repo.clojars.org",
|
||||
@@ -1377,19 +1429,6 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "refactor-nrepl/refactor-nrepl/2.5.0/refactor-nrepl-2.5.0",
|
||||
"host": "https://repo.clojars.org",
|
||||
"pom": {
|
||||
"sha1": "0bce30b420249ba7e4b90cbb3e046b4bb5416389",
|
||||
"sha256": "0zmg5qc8d55pry7832isiwd2q237znfjqjpxchd2hvlpalh5qnva"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "6bc3441afc94f7ca024e41a864ca75e05df7e207",
|
||||
"sha256": "0w8hax99y98l53mixxzx2ja0vcnhjv8dnsaz1zj3vqk775ns5w6i"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "re-frame/re-frame/0.12.0/re-frame-0.12.0",
|
||||
"host": "https://repo.clojars.org",
|
||||
@@ -1429,6 +1468,32 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "reagent/reagent/1.0.0/reagent-1.0.0",
|
||||
"host": "https://repo.clojars.org",
|
||||
"pom": {
|
||||
"sha1": "93ad5ccb0101108fb0843a3f2c50da28f8fd8336",
|
||||
"sha256": "1l4xzgc4wbd8b29mhj5j336cf8w1zccaia0w413zf3bnj6jf5m38"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "a1dd4d40425bb2e1afad0fe72780b43ff394ccfa",
|
||||
"sha256": "1g607s1ymns85923bvhwrsj0y5czyqqq1jmxx0a58fnsm1b318fa"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "refactor-nrepl/refactor-nrepl/2.5.0/refactor-nrepl-2.5.0",
|
||||
"host": "https://repo.clojars.org",
|
||||
"pom": {
|
||||
"sha1": "0bce30b420249ba7e4b90cbb3e046b4bb5416389",
|
||||
"sha256": "0zmg5qc8d55pry7832isiwd2q237znfjqjpxchd2hvlpalh5qnva"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "6bc3441afc94f7ca024e41a864ca75e05df7e207",
|
||||
"sha256": "0w8hax99y98l53mixxzx2ja0vcnhjv8dnsaz1zj3vqk775ns5w6i"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "rewrite-clj/rewrite-clj/0.6.1/rewrite-clj-0.6.1",
|
||||
"host": "https://repo.clojars.org",
|
||||
@@ -1443,15 +1508,15 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "rewrite-cljs/rewrite-cljs/0.4.4/rewrite-cljs-0.4.4",
|
||||
"path": "rewrite-cljs/rewrite-cljs/0.4.5/rewrite-cljs-0.4.5",
|
||||
"host": "https://repo.clojars.org",
|
||||
"pom": {
|
||||
"sha1": "4e7a2542517a5b0231631305461603605bea1592",
|
||||
"sha256": "050imgkzw5q7200klwrkd4v32xxy1f4aghs8g4ma5dbg4rl4pgcd"
|
||||
"sha1": "378cd53218027b9a93640dcf64c040665f6c9c6b",
|
||||
"sha256": "1qrhrgzhqdyqizh0ngnr4zgj9xkfzq0qhsws4pxxra3qc9ikl9cq"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "dd14a371d0d09eedccb39f01e3edabefb2d1e64f",
|
||||
"sha256": "0hb07wg71i2bjn8wzs8q6w1nb3jb2s36nhr9kv9mc0gyrr6im244"
|
||||
"sha1": "c35be115c39dadc71a4de3f584aa8ca295e11257",
|
||||
"sha256": "1dnw0jhr1hhqz80w3z5d8qdbaqdvgzg4fyhv6lffa51c9ca1dsr1"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1583,5 +1648,18 @@
|
||||
"sha1": "09af0b348e6253dcf9fd567d0d22ffebdea46176",
|
||||
"sha256": "1qg2iyblykfkzmplc2c46916b9m0h5ad6lxmvrk5qn3pdxqr8vw0"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "zprint/zprint/1.1.1/zprint-1.1.1",
|
||||
"host": "https://repo.clojars.org",
|
||||
"pom": {
|
||||
"sha1": "d7225bdc4978d3a8eac8613187cddd2efb9e39d2",
|
||||
"sha256": "0yyy31h88zww238c2v4zi9va3pjp7ii76zjggglakd3wm1fdbnck"
|
||||
},
|
||||
"jar": {
|
||||
"sha1": "3bd9bbedb188a66ccf72c1e22819e8e423a6757a",
|
||||
"sha256": "1bvrarxw0dqvxlhj6gdwrv6mklzh4p79537g293fqlm07f2knfph"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
+23
-17
@@ -2,13 +2,16 @@ args4j/args4j/2.0.26/args4j-2.0.26.jar
|
||||
bidi/bidi/2.1.6/bidi-2.1.6.jar
|
||||
binaryage/env-config/0.2.2/env-config-0.2.2.jar
|
||||
binaryage/oops/0.7.0/oops-0.7.0.jar
|
||||
borkdude/edamame/0.0.11-alpha.28/edamame-0.0.11-alpha.28.jar
|
||||
borkdude/sci.impl.reflector/0.0.1/sci.impl.reflector-0.0.1.jar
|
||||
borkdude/sci/0.2.1-alpha.1/sci-0.2.1-alpha.1.jar
|
||||
cider/cider-nrepl/0.25.3/cider-nrepl-0.25.3.jar
|
||||
cider/piggieback/0.4.1/piggieback-0.4.1.jar
|
||||
cljfmt/cljfmt/0.6.7/cljfmt-0.6.7.jar
|
||||
clj-stacktrace/clj-stacktrace/0.2.8/clj-stacktrace-0.2.8.jar
|
||||
cljs-bean/cljs-bean/1.3.0/cljs-bean-1.3.0.jar
|
||||
cljsjs/react/17.0.1-0/react-17.0.1-0.jar
|
||||
cljsjs/react-dom/17.0.1-0/react-dom-17.0.1-0.jar
|
||||
cljsjs/react-dom-server/17.0.1-0/react-dom-server-17.0.1-0.jar
|
||||
cljsjs/react-dom/17.0.1-0/react-dom-17.0.1-0.jar
|
||||
cljsjs/react/17.0.1-0/react-17.0.1-0.jar
|
||||
clout/clout/2.1.2/clout-2.1.2.jar
|
||||
com/andrewmcveigh/cljs-time/0.5.2/cljs-time-0.5.2.jar
|
||||
com/bhauman/cljs-test-display/0.1.1/cljs-test-display-0.1.1.jar
|
||||
@@ -19,8 +22,6 @@ com/cognitect/transit-js/0.8.846/transit-js-0.8.846.jar
|
||||
com/fasterxml/jackson/core/jackson-core/2.8.7/jackson-core-2.8.7.jar
|
||||
com/google/code/findbugs/jsr305/3.0.1/jsr305-3.0.1.jar
|
||||
com/google/code/gson/gson/2.7/gson-2.7.jar
|
||||
com/googlecode/java-diff-utils/diffutils/1.3.0/diffutils-1.3.0.jar
|
||||
com/googlecode/json-simple/json-simple/1.1.1/json-simple-1.1.1.jar
|
||||
com/google/elemental2/elemental2-core/1.0.0-RC1/elemental2-core-1.0.0-RC1.jar
|
||||
com/google/errorprone/error_prone_annotations/2.3.1/error_prone_annotations-2.3.1.jar
|
||||
com/google/guava/guava/25.1-jre/guava-25.1-jre.jar
|
||||
@@ -31,23 +32,25 @@ com/google/jsinterop/base/1.0.0/base-1.0.0.jar
|
||||
com/google/jsinterop/jsinterop-annotations/1.0.2/jsinterop-annotations-1.0.2.jar
|
||||
com/google/protobuf/protobuf-java/3.11.1/protobuf-java-3.11.1.jar
|
||||
com/google/re2j/re2j/1.3/re2j-1.3.jar
|
||||
com/googlecode/json-simple/json-simple/1.1.1/json-simple-1.1.1.jar
|
||||
com/ibm/icu/icu4j/66.1/icu4j-66.1.jar
|
||||
commons-codec/commons-codec/1.10/commons-codec-1.10.jar
|
||||
commons-fileupload/commons-fileupload/1.4/commons-fileupload-1.4.jar
|
||||
commons-io/commons-io/2.6/commons-io-2.6.jar
|
||||
compojure/compojure/1.5.2/compojure-1.5.2.jar
|
||||
com/taoensso/encore/2.105.0/encore-2.105.0.jar
|
||||
com/taoensso/timbre/4.10.0/timbre-4.10.0.jar
|
||||
com/taoensso/truss/1.5.0/truss-1.5.0.jar
|
||||
com/taoensso/tufte/2.1.0/tufte-2.1.0.jar
|
||||
com/wsscode/pathom/2.2.31/pathom-2.2.31.jar
|
||||
com/wsscode/spec-inspec/1.0.0-alpha2/spec-inspec-1.0.0-alpha2.jar
|
||||
commons-codec/commons-codec/1.10/commons-codec-1.10.jar
|
||||
commons-fileupload/commons-fileupload/1.4/commons-fileupload-1.4.jar
|
||||
commons-io/commons-io/2.6/commons-io-2.6.jar
|
||||
compojure/compojure/1.5.2/compojure-1.5.2.jar
|
||||
crypto-equality/crypto-equality/1.0.0/crypto-equality-1.0.0.jar
|
||||
crypto-random/crypto-random/1.2.0/crypto-random-1.2.0.jar
|
||||
day8/re-frame/test/0.1.5/test-0.1.5.jar
|
||||
edn-query-language/eql/0.0.9/eql-0.0.9.jar
|
||||
expound/expound/0.8.5/expound-0.8.5.jar
|
||||
fipp/fipp/0.6.23/fipp-0.6.23.jar
|
||||
hashp/hashp/0.2.1/hashp-0.2.1.jar
|
||||
hiccup/hiccup/1.0.5/hiccup-1.0.5.jar
|
||||
hickory/hickory/0.7.1/hickory-0.7.1.jar
|
||||
http-kit/http-kit/2.2.0/http-kit-2.2.0.jar
|
||||
@@ -58,6 +61,8 @@ javax/servlet/servlet-api/2.5/servlet-api-2.5.jar
|
||||
javax/xml/bind/jaxb-api/2.3.0/jaxb-api-2.3.0.jar
|
||||
medley/medley/0.8.2/medley-0.8.2.jar
|
||||
mvxcvi/alphabase/1.0.0/alphabase-1.0.0.jar
|
||||
mvxcvi/arrangement/1.2.0/arrangement-1.2.0.jar
|
||||
mvxcvi/puget/1.3.1/puget-1.3.1.jar
|
||||
net/cgrand/macrovich/0.2.1/macrovich-0.2.1.jar
|
||||
nrepl/nrepl/0.7.0/nrepl-0.7.0.jar
|
||||
org/checkerframework/checker-qual/2.0.0/checker-qual-2.0.0.jar
|
||||
@@ -66,23 +71,23 @@ org/clojure/clojurescript/1.10.773/clojurescript-1.10.773.jar
|
||||
org/clojure/core.async/1.3.610/core.async-1.3.610.jar
|
||||
org/clojure/core.cache/1.0.207/core.cache-1.0.207.jar
|
||||
org/clojure/core.memoize/1.0.236/core.memoize-1.0.236.jar
|
||||
org/clojure/core.rrb-vector/0.1.1/core.rrb-vector-0.1.1.jar
|
||||
org/clojure/core.rrb-vector/0.1.2/core.rrb-vector-0.1.2.jar
|
||||
org/clojure/core.specs.alpha/0.2.44/core.specs.alpha-0.2.44.jar
|
||||
org/clojure/data.json/1.0.0/data.json-1.0.0.jar
|
||||
org/clojure/data.priority-map/1.0.0/data.priority-map-1.0.0.jar
|
||||
org/clojure/google-closure-library/0.0-20191016-6ae1f72f/google-closure-library-0.0-20191016-6ae1f72f.jar
|
||||
org/clojure/google-closure-library-third-party/0.0-20191016-6ae1f72f/google-closure-library-third-party-0.0-20191016-6ae1f72f.jar
|
||||
org/clojure/google-closure-library/0.0-20191016-6ae1f72f/google-closure-library-0.0-20191016-6ae1f72f.jar
|
||||
org/clojure/spec.alpha/0.2.176/spec.alpha-0.2.176.jar
|
||||
org/clojure/test.check/1.1.0/test.check-1.1.0.jar
|
||||
org/clojure/tools.analyzer/1.0.0/tools.analyzer-1.0.0.jar
|
||||
org/clojure/tools.analyzer.jvm/1.1.0/tools.analyzer.jvm-1.1.0.jar
|
||||
org/clojure/tools.analyzer/1.0.0/tools.analyzer-1.0.0.jar
|
||||
org/clojure/tools.cli/1.0.194/tools.cli-1.0.194.jar
|
||||
org/clojure/tools.logging/0.4.1/tools.logging-0.4.1.jar
|
||||
org/clojure/tools.macro/0.1.5/tools.macro-0.1.5.jar
|
||||
org/clojure/tools.reader/1.3.3/tools.reader-1.3.3.jar
|
||||
org/codehaus/mojo/animal-sniffer-annotations/1.14/animal-sniffer-annotations-1.14.jar
|
||||
org/graalvm/js/js/20.1.0/js-20.1.0.jar
|
||||
org/graalvm/js/js-scriptengine/20.1.0/js-scriptengine-20.1.0.jar
|
||||
org/graalvm/js/js/20.1.0/js-20.1.0.jar
|
||||
org/graalvm/regex/regex/20.1.0/regex-20.1.0.jar
|
||||
org/graalvm/sdk/graal-sdk/20.1.0/graal-sdk-20.1.0.jar
|
||||
org/graalvm/truffle/truffle-api/20.1.0/truffle-api-20.1.0.jar
|
||||
@@ -93,23 +98,23 @@ org/jboss/xnio/xnio-api/3.8.0.Final/xnio-api-3.8.0.Final.jar
|
||||
org/jboss/xnio/xnio-nio/3.8.0.Final/xnio-nio-3.8.0.Final.jar
|
||||
org/jsoup/jsoup/1.9.2/jsoup-1.9.2.jar
|
||||
org/msgpack/msgpack/0.6.12/msgpack-0.6.12.jar
|
||||
org/ow2/asm/asm/7.1/asm-7.1.jar
|
||||
org/ow2/asm/asm-analysis/7.1/asm-analysis-7.1.jar
|
||||
org/ow2/asm/asm-commons/7.1/asm-commons-7.1.jar
|
||||
org/ow2/asm/asm-tree/7.1/asm-tree-7.1.jar
|
||||
org/ow2/asm/asm-util/7.1/asm-util-7.1.jar
|
||||
org/ow2/asm/asm/7.1/asm-7.1.jar
|
||||
org/wildfly/client/wildfly-client-config/1.0.1.Final/wildfly-client-config-1.0.1.Final.jar
|
||||
org/wildfly/common/wildfly-common/1.5.2.Final/wildfly-common-1.5.2.Final.jar
|
||||
prismatic/schema/1.1.7/schema-1.1.7.jar
|
||||
quoin/quoin/0.1.2/quoin-0.1.2.jar
|
||||
reagent/reagent/1.0.0/reagent-1.0.0.jar
|
||||
re-com/re-com/2.8.0/re-com-2.8.0.jar
|
||||
refactor-nrepl/refactor-nrepl/2.5.0/refactor-nrepl-2.5.0.jar
|
||||
re-frame/re-frame/0.12.0/re-frame-0.12.0.jar
|
||||
re-frisk-remote/re-frisk-remote/1.6.0/re-frisk-remote-1.6.0.jar
|
||||
re-frisk/sente/1.15.0/sente-1.15.0.jar
|
||||
reagent/reagent/1.0.0/reagent-1.0.0.jar
|
||||
refactor-nrepl/refactor-nrepl/2.5.0/refactor-nrepl-2.5.0.jar
|
||||
rewrite-clj/rewrite-clj/0.6.1/rewrite-clj-0.6.1.jar
|
||||
rewrite-cljs/rewrite-cljs/0.4.4/rewrite-cljs-0.4.4.jar
|
||||
rewrite-cljs/rewrite-cljs/0.4.5/rewrite-cljs-0.4.5.jar
|
||||
ring-cors/ring-cors/0.1.8/ring-cors-0.1.8.jar
|
||||
ring/ring-codec/1.1.2/ring-codec-1.1.2.jar
|
||||
ring/ring-core/1.8.1/ring-core-1.8.1.jar
|
||||
@@ -120,3 +125,4 @@ thheller/shadow-cljs/2.11.16/shadow-cljs-2.11.16-aot.jar
|
||||
thheller/shadow-cljsjs/0.0.21/shadow-cljsjs-0.0.21.jar
|
||||
thheller/shadow-util/0.7.0/shadow-util-0.7.0.jar
|
||||
viebel/codox-klipse-theme/0.0.1/codox-klipse-theme-0.0.1.jar
|
||||
zprint/zprint/1.1.1/zprint-1.1.1.jar
|
||||
|
||||
@@ -17,6 +17,8 @@ in mkShell {
|
||||
lsof # used in start-react-native.sh
|
||||
# build specific utilities
|
||||
clojure maven watchman
|
||||
# lint specific utilities
|
||||
clj-kondo zprint clojure-lsp
|
||||
# other nice to have stuff
|
||||
yarn nodejs python27
|
||||
] # and some special cases
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ let
|
||||
|
||||
# for calling clojure targets in CI or Makefile
|
||||
clojure = mkShell {
|
||||
buildInputs = with pkgs; [ clojure flock maven openjdk clj-kondo ];
|
||||
buildInputs = with pkgs; [ clojure flock maven openjdk ];
|
||||
inputsFrom = [ nodejs-sh ];
|
||||
# CLASSPATH from clojure deps with 'src' appended to find local sources.
|
||||
shellHook = with pkgs; ''
|
||||
|
||||
@@ -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 |
+110
-106
@@ -1,116 +1,120 @@
|
||||
;; shadow-cljs configuration
|
||||
{:source-paths ["src" "test/cljs"]
|
||||
{:source-paths ["src" "test/cljs"]
|
||||
|
||||
:dependencies [[reagent "1.0.0"]
|
||||
[re-frame "0.12.0"]
|
||||
[binaryage/oops "0.7.0"]
|
||||
[com.andrewmcveigh/cljs-time "0.5.2"]
|
||||
[status-im/timbre "4.10.0-2-status"]
|
||||
[com.taoensso/encore "2.105.0"]
|
||||
[hickory "0.7.1"]
|
||||
[cljs-bean "1.3.0"]
|
||||
[com.cognitect/transit-cljs "0.8.248"]
|
||||
[mvxcvi/alphabase "1.0.0"]
|
||||
;; dev dependencies
|
||||
[refactor-nrepl "2.5.0"]
|
||||
[cider/cider-nrepl "0.25.3"]
|
||||
[cider/piggieback "0.4.1"]
|
||||
[re-frisk-remote "1.6.0"]
|
||||
;; routing
|
||||
[bidi "2.1.6"]
|
||||
;; test dependencies
|
||||
[day8.re-frame/test "0.1.5"]
|
||||
[com.taoensso/tufte "2.1.0"]
|
||||
;; linting
|
||||
[cljfmt/cljfmt "0.6.7"]]
|
||||
:dependencies [[reagent "1.0.0"]
|
||||
[re-frame "0.12.0"]
|
||||
[binaryage/oops "0.7.0"]
|
||||
[com.andrewmcveigh/cljs-time "0.5.2"]
|
||||
[status-im/timbre "4.10.0-2-status"]
|
||||
[com.taoensso/encore "2.105.0"]
|
||||
[hickory "0.7.1"]
|
||||
[cljs-bean "1.3.0"]
|
||||
[com.cognitect/transit-cljs "0.8.248"]
|
||||
[mvxcvi/alphabase "1.0.0"]
|
||||
;; dev dependencies
|
||||
[refactor-nrepl "2.5.0"]
|
||||
[cider/cider-nrepl "0.25.3"]
|
||||
[cider/piggieback "0.4.1"]
|
||||
[re-frisk-remote "1.6.0"]
|
||||
;; routing
|
||||
[bidi "2.1.6"]
|
||||
;; test dependencies
|
||||
[day8.re-frame/test "0.1.5"]
|
||||
[com.taoensso/tufte "2.1.0"]]
|
||||
|
||||
;; port and middleware for repl in development
|
||||
:nrepl {:port 7888
|
||||
:middleware [cider.piggieback/wrap-cljs-repl
|
||||
refactor-nrepl.middleware/wrap-refactor]}
|
||||
:nrepl {:port 7888
|
||||
:middleware [cider.piggieback/wrap-cljs-repl
|
||||
refactor-nrepl.middleware/wrap-refactor]}
|
||||
|
||||
;; shadow-cljs web interface
|
||||
:http {:port 3449
|
||||
:host "0.0.0.0"}
|
||||
:http {:port 3449
|
||||
:host "0.0.0.0"}
|
||||
|
||||
:cache-blockers #{status-im.utils.js-resources status-im.ui.components.icons.icons}
|
||||
|
||||
:builds {:mobile
|
||||
{:target :react-native
|
||||
:output-dir "app"
|
||||
:init-fn status-im2.setup.core/init
|
||||
;; When false, the Shadow-CLJS watcher won't automatically refresh
|
||||
;; the target files (a.k.a hot reload). When false, you can manually
|
||||
;; reload by calling `shadow.cljs.devtools.api/watch-compile-all!`.
|
||||
:devtools {:autobuild #shadow/env ["SHADOW_AUTOBUILD_ENABLED" :default true :as :bool]}
|
||||
:dev {:devtools {:after-load status-im2.setup.hot-reload/reload
|
||||
:build-notify status-im2.setup.hot-reload/build-notify
|
||||
:preloads [re-frisk-remote.preload]}
|
||||
: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 {:output-feature-set :es5
|
||||
:closure-defines
|
||||
{re-frame.trace/trace-enabled? true}
|
||||
:source-map false
|
||||
:infer-externs true}
|
||||
;; if you want to use a real device, set your local ip
|
||||
;; in the SHADOW_HOST env variable to make sure that
|
||||
;; it will use the right interface
|
||||
:local-ip #shadow/env "SHADOW_HOST"}
|
||||
:chunks {:fleets status-im.fleet.default-fleet/default-fleets
|
||||
:chats status-im.chat.default-chats/default-chats}
|
||||
:release
|
||||
{: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 {:output-feature-set :es6
|
||||
;;disable for android build as there
|
||||
;;is an intermittent warning with deftype
|
||||
:warnings-as-errors false
|
||||
:infer-externs :auto
|
||||
:static-fns true
|
||||
:fn-invoke-direct true
|
||||
:optimizations :advanced
|
||||
:js-options {:js-provider :closure}}}}
|
||||
;; the tests are ran with node, react-native dependencies are mocked
|
||||
;; by using node --require override.js, which uses the node-library
|
||||
;; produced by the target :mocks below and redefines node require
|
||||
;; function to use the mocks instead of the rn libraries
|
||||
:test
|
||||
{:output-to "target/test/test.js"
|
||||
:output-dir "target/test"
|
||||
:optimizations :simple
|
||||
:target :node-test
|
||||
:main status-im.test-runner/main
|
||||
;; set :ui-driven to true to let shadow-cljs inject node-repl
|
||||
: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}}
|
||||
:builds
|
||||
{:mobile
|
||||
{:target :react-native
|
||||
:output-dir "app"
|
||||
:init-fn status-im2.setup.core/init
|
||||
;; When false, the Shadow-CLJS watcher won't automatically refresh
|
||||
;; the target files (a.k.a hot reload). When false, you can manually
|
||||
;; reload by calling `shadow.cljs.devtools.api/watch-compile-all!`.
|
||||
:devtools {:autobuild #shadow/env ["SHADOW_AUTOBUILD_ENABLED" :default true :as :bool]}
|
||||
:dev {:devtools {:after-load status-im2.setup.hot-reload/reload
|
||||
:build-notify status-im2.setup.hot-reload/build-notify
|
||||
:preloads [re-frisk-remote.preload]}
|
||||
: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 {:output-feature-set :es5
|
||||
:closure-defines
|
||||
{re-frame.trace/trace-enabled? true}
|
||||
:source-map false
|
||||
:infer-externs true}
|
||||
;; if you want to use a real device, set your local ip
|
||||
;; in the SHADOW_HOST env variable to make sure that
|
||||
;; it will use the right interface
|
||||
:local-ip #shadow/env "SHADOW_HOST"}
|
||||
:chunks {:fleets status-im.fleet.default-fleet/default-fleets
|
||||
:chats status-im.chat.default-chats/default-chats}
|
||||
:release
|
||||
{: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 {:output-feature-set :es6
|
||||
;;disable for android build as there
|
||||
;;is an intermittent warning with deftype
|
||||
:warnings-as-errors false
|
||||
:infer-externs :auto
|
||||
:static-fns true
|
||||
:fn-invoke-direct true
|
||||
:optimizations :advanced
|
||||
:js-options {:js-provider :closure}}}}
|
||||
;; the tests are ran with node, react-native dependencies are mocked
|
||||
;; by using node --require override.js, which uses the node-library
|
||||
;; produced by the target :mocks below and redefines node require
|
||||
;; function to use the mocks instead of the rn libraries
|
||||
:test
|
||||
{:output-to "target/test/test.js"
|
||||
:output-dir "target/test"
|
||||
:optimizations :simple
|
||||
:target :node-test
|
||||
;; 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
|
||||
: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}}
|
||||
|
||||
;; mock.js-dependencies is mocking the react-native libraries
|
||||
;; we build it as a node library so that it can be required by
|
||||
;; override.js
|
||||
:mocks
|
||||
{:target :node-library
|
||||
:exports {:mocks mocks.js-dependencies/mock}
|
||||
:output-to "target/mocks/mocks.js"
|
||||
:output-dir "target/mocks"
|
||||
:compiler-options {:optimizations :simple
|
||||
:source-map false}}
|
||||
:component-test {:target :npm-module
|
||||
:entries [quo2.core-spec]
|
||||
:ns-regexp "-component-spec$"
|
||||
:output-dir "component-spec"
|
||||
:compiler-options {:warnings-as-errors false
|
||||
:static-fns false
|
||||
: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
|
||||
;; override.js
|
||||
:mocks
|
||||
{:target :node-library
|
||||
:exports {:mocks mocks.js-dependencies/mock}
|
||||
:output-to "target/mocks/mocks.js"
|
||||
:output-dir "target/mocks"
|
||||
:compiler-options {:optimizations :simple
|
||||
:source-map false}}
|
||||
:component-test {:target :npm-module
|
||||
:entries [quo2.core-spec]
|
||||
:ns-regexp "-component-spec$"
|
||||
:output-dir "component-spec"
|
||||
:compiler-options {:warnings-as-errors false
|
||||
:static-fns false
|
||||
:infer-externs true}}}}
|
||||
|
||||
@@ -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,20 @@
|
||||
(: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 {}}})
|
||||
@@ -111,7 +125,9 @@
|
||||
(def react-native-shake #js {})
|
||||
(def react-native-share #js {:default {}})
|
||||
(def react-native-svg #js {:SvgUri #js {:render identity}
|
||||
:SvgXml #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 {})
|
||||
@@ -207,7 +223,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 {}
|
||||
:State #js {:BEGAN nil
|
||||
:ACTIVE nil
|
||||
@@ -284,6 +303,8 @@
|
||||
|
||||
(def shell-worklets #js {})
|
||||
|
||||
(def record-audio-worklets #js {})
|
||||
|
||||
;; Update i18n_resources.cljs
|
||||
(defn mock [module]
|
||||
(case module
|
||||
@@ -331,6 +352,7 @@
|
||||
"react-native-svg" react-native-svg
|
||||
"../src/js/worklet_factory.js" worklet-factory
|
||||
"../src/js/shell_worklets.js" shell-worklets
|
||||
"../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,106 @@
|
||||
(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)}])]])})))
|
||||
@@ -0,0 +1,82 @@
|
||||
(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 :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)}])
|
||||
@@ -0,0 +1,212 @@
|
||||
(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,553 @@
|
||||
(ns quo2.components.record-audio.record-audio.view
|
||||
(:require [quo.react :refer [memo effect!]]
|
||||
[react-native.core :as rn]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.buttons.button :as button]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[reagent.core :as reagent]
|
||||
[cljs-bean.core :as bean]
|
||||
[quo2.components.record-audio.record-audio.style :as style]
|
||||
[status-im.utils.utils :as utils]
|
||||
[oops.core :as oops]))
|
||||
|
||||
(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?]])))])
|
||||
@@ -0,0 +1,63 @@
|
||||
(ns quo2.components.settings.privacy-option
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.selectors.selectors :as selectors]
|
||||
[quo2.components.settings.style :as style]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]))
|
||||
|
||||
(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))})
|
||||
+9
-1
@@ -36,14 +36,18 @@
|
||||
quo2.components.tags.tags
|
||||
quo2.components.tags.context-tags
|
||||
quo2.components.tabs.tabs
|
||||
quo2.components.notifications.toast
|
||||
quo2.components.tabs.account-selector
|
||||
quo2.components.navigation.floating-shell-button
|
||||
quo2.components.tags.status-tags
|
||||
quo2.components.navigation.page-nav
|
||||
quo2.components.selectors.disclaimer
|
||||
quo2.components.selectors.selectors
|
||||
quo2.components.loaders.skeleton))
|
||||
quo2.components.settings.privacy-option
|
||||
quo2.components.loaders.skeleton
|
||||
quo2.components.notifications.count-down-circle))
|
||||
|
||||
(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)
|
||||
@@ -106,3 +110,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)
|
||||
|
||||
@@ -13,6 +13,20 @@
|
||||
(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
|
||||
@@ -49,6 +63,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))
|
||||
@@ -67,11 +82,16 @@
|
||||
(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-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
|
||||
|
||||
@@ -91,6 +111,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,9 +1,12 @@
|
||||
(ns react-native.core
|
||||
(:require [reagent.core :as reagent]
|
||||
(:require ["react" :as react]
|
||||
["react-native" :as react-native]
|
||||
[cljs-bean.core :as bean]
|
||||
["@react-native-community/blur" :as blur]
|
||||
[oops.core :as oops]
|
||||
[react-native.flat-list :as flat-list]
|
||||
[react-native.section-list :as section-list]
|
||||
[reagent.core :as reagent]
|
||||
[react-native.platform :as platform]))
|
||||
|
||||
(def app-state ^js (.-AppState ^js react-native))
|
||||
@@ -57,6 +60,9 @@
|
||||
|
||||
(def status-bar (.-StatusBar ^js react-native))
|
||||
|
||||
(defn status-bar-height []
|
||||
(.-currentHeight ^js status-bar))
|
||||
|
||||
(defn hw-back-add-listener [callback]
|
||||
(.addEventListener (.-BackHandler ^js react-native) "hardwareBackPress" callback))
|
||||
|
||||
@@ -70,3 +76,15 @@
|
||||
(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"))))))
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
(ns react-native.reanimated
|
||||
(:require ["react-native" :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[clojure.string :as string]
|
||||
["react-native-linear-gradient" :default LinearGradient]
|
||||
["react-native-reanimated" :default reanimated
|
||||
:refer (useSharedValue useAnimatedStyle withTiming withDelay withSpring withRepeat Easing Keyframe)]))
|
||||
: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)))
|
||||
@@ -25,6 +30,7 @@
|
||||
(def with-spring withSpring)
|
||||
(def key-frame Keyframe)
|
||||
(def with-repeat withRepeat)
|
||||
(def cancel-animation cancelAnimation)
|
||||
|
||||
;; Easings
|
||||
(def bezier (.-bezier ^js Easing))
|
||||
@@ -54,6 +60,12 @@
|
||||
;; 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
|
||||
@@ -75,4 +87,21 @@
|
||||
|
||||
(defn animate-shared-value-with-repeat [anim val duration easing number-of-repetitions reverse?]
|
||||
(set-shared-value anim (with-repeat (with-timing val (js-obj "duration" duration
|
||||
"easing" (get easings easing))) number-of-repetitions reverse?)))
|
||||
"easing" (get easings easing))) number-of-repetitions 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))))
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
(defn consumer [component]
|
||||
[consumer-raw
|
||||
(fn [insets]
|
||||
(fn [^js insets]
|
||||
(reagent/as-element
|
||||
[component (js->clj insets :keywordize-keys true)]))])
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
(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))
|
||||
@@ -1,19 +1,19 @@
|
||||
(ns status-im.add-new.core
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.add-new.db :as db]
|
||||
[status-im.chat.models :as chat]
|
||||
[status-im.contact.core :as contact]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im.add-new.db :as db]
|
||||
[status-im.ethereum.stateofus :as stateofus]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.router.core :as router]
|
||||
[status-im.utils.db :as utils.db]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.chat.models :as chat]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.contact.core :as contact]
|
||||
[status-im.router.core :as router]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.ethereum.stateofus :as stateofus]
|
||||
[status-im.utils.db :as utils.db]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:resolve-public-key
|
||||
@@ -24,19 +24,19 @@
|
||||
;;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)))]
|
||||
(when (or (not id) (= id @resolve-last-id))
|
||||
(if ens-error
|
||||
{:db (assoc-in db [:contacts/new-identity :state] :error)}
|
||||
(let [new-identity (utils/safe-trim new-identity-raw)
|
||||
(let [new-identity (utils/safe-trim new-identity-raw)
|
||||
is-public-key? (and (string? new-identity)
|
||||
(utils.db/valid-public-key? new-identity))
|
||||
is-ens? (and (not is-public-key?)
|
||||
(ens/valid-eth-name-prefix? new-identity))
|
||||
error (db/validate-pub-key db new-identity)]
|
||||
is-ens? (and (not is-public-key?)
|
||||
(ens/valid-eth-name-prefix? new-identity))
|
||||
error (db/validate-pub-key db new-identity)]
|
||||
(reset! resolve-last-id nil)
|
||||
(merge {:db (assoc db
|
||||
:contacts/new-identity
|
||||
@@ -61,25 +61,27 @@
|
||||
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}]
|
||||
(let [public-key? (and (string? data)
|
||||
(string/starts-with? data "0x"))
|
||||
chat-key (cond
|
||||
(= type :private-chat) chat-id
|
||||
(= type :contact) public-key
|
||||
(and (= type :undefined)
|
||||
public-key?) data)
|
||||
[{:keys [db] :as cofx} {:keys [type public-key chat-id data ens-name]}
|
||||
{:keys [new-contact? nickname] :as opts}]
|
||||
(let [public-key? (and (string? data)
|
||||
(string/starts-with? data "0x"))
|
||||
chat-key (cond
|
||||
(= type :private-chat) chat-id
|
||||
(= type :contact) public-key
|
||||
(and (= type :undefined)
|
||||
public-key?)
|
||||
data)
|
||||
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))
|
||||
@@ -91,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,23 +1,23 @@
|
||||
(ns status-im.backup.core
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.utils.fx :as fx]))
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(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)
|
||||
{:db (assoc db :backup/performing-backup true)
|
||||
::json-rpc/call [{:method "wakuext_backupData"
|
||||
:params []
|
||||
:on-error #(do
|
||||
|
||||
@@ -4,24 +4,27 @@
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.utils.fx :as fx]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(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})")
|
||||
|
||||
(defn valid-address? [address]
|
||||
(defn valid-address?
|
||||
[address]
|
||||
(re-matches address-regex address))
|
||||
|
||||
(defn- build [id bootnode-name address chain]
|
||||
(defn- build
|
||||
[id bootnode-name address chain]
|
||||
{:address address
|
||||
:chain chain
|
||||
:id (string/replace id "-" "")
|
||||
:name bootnode-name})
|
||||
|
||||
(fx/defn fetch [cofx id]
|
||||
(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
|
||||
@@ -35,16 +38,17 @@
|
||||
: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
|
||||
(set-input :id id)
|
||||
(set-input :url (str address))
|
||||
(set-input :name (str name)))]
|
||||
name]}
|
||||
(fetch cofx id)
|
||||
fxs (rf/merge cofx
|
||||
(set-input :id id)
|
||||
(set-input :url (str address))
|
||||
(set-input :name (str name)))]
|
||||
(assoc fxs :dispatch [:navigate-to :edit-bootnode])))
|
||||
|
||||
(defn custom-bootnodes-in-use?
|
||||
@@ -52,68 +56,75 @@
|
||||
(let [network (:networks/current-network db)]
|
||||
(get-in db [:multiaccount :custom-bootnodes-enabled? network])))
|
||||
|
||||
(fx/defn delete [{{:keys [multiaccount] :as db} :db :as cofx} id]
|
||||
(let [network (:networks/current-network db)
|
||||
(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 (:custom-bootnodes new-multiaccount)
|
||||
:custom-bootnodes
|
||||
(:custom-bootnodes new-multiaccount)
|
||||
{:success-event (when (custom-bootnodes-in-use? cofx)
|
||||
[:multiaccounts.update.callback/save-settings-success])}))))
|
||||
|
||||
(fx/defn upsert
|
||||
{:events [:bootnodes.ui/save-pressed]
|
||||
(rf/defn upsert
|
||||
{:events [:bootnodes.ui/save-pressed]
|
||||
:interceptors [(re-frame/inject-cofx :random-id-generator)]}
|
||||
[{{:bootnodes/keys [manage] :keys [multiaccount] :as db} :db
|
||||
random-id-generator :random-id-generator :as cofx}]
|
||||
random-id-generator :random-id-generator
|
||||
:as cofx}]
|
||||
(let [{:keys [name id url]} manage
|
||||
network (:networks/current-network db)
|
||||
bootnode (build
|
||||
(or (:value id) (random-id-generator))
|
||||
(:value name)
|
||||
(:value url)
|
||||
network)
|
||||
new-bootnodes (assoc-in
|
||||
(:custom-bootnodes multiaccount)
|
||||
[network (:id bootnode)]
|
||||
bootnode)]
|
||||
network (:networks/current-network db)
|
||||
bootnode (build
|
||||
(or (:value id) (random-id-generator))
|
||||
(:value name)
|
||||
(:value url)
|
||||
network)
|
||||
new-bootnodes (assoc-in
|
||||
(:custom-bootnodes multiaccount)
|
||||
[network (:id bootnode)]
|
||||
bootnode)]
|
||||
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (dissoc db :bootnodes/manage)
|
||||
:dispatch [:navigate-back]}
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:custom-bootnodes new-bootnodes
|
||||
:custom-bootnodes
|
||||
new-bootnodes
|
||||
{: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)
|
||||
(let [current-network (:networks/current-network db)
|
||||
bootnodes-settings (get-in db [:multiaccount :custom-bootnodes-enabled?])]
|
||||
(multiaccounts.update/multiaccount-update
|
||||
cofx
|
||||
:custom-bootnodes-enabled? (assoc bootnodes-settings current-network value)
|
||||
:custom-bootnodes-enabled?
|
||||
(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]))
|
||||
: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)
|
||||
:content (i18n/label :t/delete-bootnode-are-you-sure)
|
||||
{:ui/show-confirmation {:title (i18n/label :t/delete-bootnode-title)
|
||||
:content (i18n/label :t/delete-bootnode-are-you-sure)
|
||||
:confirm-button-text (i18n/label :t/delete-bootnode)
|
||||
:on-accept #(re-frame/dispatch [:bootnodes.ui/delete-confirmed bootnode-id])}})
|
||||
: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,15 +1,15 @@
|
||||
(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
|
||||
:bottom-sheet/show? true
|
||||
:bottom-sheet/view view
|
||||
:bottom-sheet/options options)})
|
||||
:db (assoc db
|
||||
:bottom-sheet/show? true
|
||||
: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,8 @@
|
||||
{: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)})
|
||||
|
||||
+195
-152
@@ -1,62 +1,65 @@
|
||||
(ns status-im.browser.core
|
||||
(:require [clojure.string :as string]
|
||||
(: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-im2.navigation.events :as navigation]
|
||||
[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]
|
||||
[status-im.signing.core :as signing]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.browser.webview-ref :as webview-ref]
|
||||
["eth-phishing-detect" :as eth-phishing-detect]
|
||||
[utils.debounce :as debounce]
|
||||
[status-im.browser.eip3085 :as eip3085]
|
||||
[status-im.browser.eip3326 :as eip3326]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(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)})
|
||||
|
||||
(defn get-current-browser [db]
|
||||
(defn get-current-browser
|
||||
[db]
|
||||
(get-in db [:browser/browsers (get-in db [:browser/options :browser-id])]))
|
||||
|
||||
(defn get-current-url [{:keys [history history-index]
|
||||
:or {history-index 0}}]
|
||||
(defn get-current-url
|
||||
[{:keys [history history-index]
|
||||
:or {history-index 0}}]
|
||||
(when history
|
||||
(nth history history-index)))
|
||||
|
||||
(defn secure? [{:keys [error? dapp?]} {:keys [url]}]
|
||||
(defn secure?
|
||||
[{:keys [error? dapp?]} {:keys [url]}]
|
||||
(or dapp?
|
||||
(and (not error?)
|
||||
(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]
|
||||
{: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)
|
||||
@@ -65,106 +68,116 @@
|
||||
:params [browser-id]
|
||||
:on-success #()})})
|
||||
|
||||
(defn update-dapp-name [{:keys [name] :as browser}]
|
||||
(defn update-dapp-name
|
||||
[{:keys [name] :as browser}]
|
||||
(assoc browser :dapp? false :name (or name (i18n/label :t/browser))))
|
||||
|
||||
(defn check-if-phishing-url [{:keys [history history-index] :as browser}]
|
||||
(defn check-if-phishing-url
|
||||
[{:keys [history history-index] :as browser}]
|
||||
(let [history-host (http/url-host (try (nth history history-index) (catch js/Error _)))]
|
||||
(cond-> browser history-host (assoc :unsafe? (eth-phishing-detect history-host)))))
|
||||
|
||||
(defn resolve-ens-contenthash-callback [url]
|
||||
(defn resolve-ens-contenthash-callback
|
||||
[url]
|
||||
(if (not (string/blank? url))
|
||||
(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))
|
||||
host (http/url-host current-url)]
|
||||
host (http/url-host current-url)]
|
||||
(if (and (not resolved-url) (ens/is-valid-eth-name? host))
|
||||
{:db (update db :browser/options assoc :resolving? true)
|
||||
{:db (update db :browser/options assoc :resolving? true)
|
||||
:browser/resolve-ens-contenthash {:chain-id (ethereum/chain-id db)
|
||||
:ens-name host
|
||||
:cb resolve-ens-contenthash-callback}}
|
||||
{:db (update db :browser/options assoc :url (or resolved-url current-url) :resolving? false)}))))
|
||||
|
||||
(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])]
|
||||
{: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]
|
||||
{: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])
|
||||
(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]}]
|
||||
(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))
|
||||
host (http/url-host (get-current-url browser))]
|
||||
host (http/url-host (get-current-url browser))]
|
||||
(update-browser cofx (assoc browser :ignore-unsafe host))))
|
||||
|
||||
(defn can-go-forward? [{:keys [history-index history]}]
|
||||
(defn can-go-forward?
|
||||
[{: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)]
|
||||
@@ -173,73 +186,81 @@
|
||||
new-index (dec (count new-history))]
|
||||
(update-browser cofx
|
||||
(assoc browser
|
||||
:history new-history
|
||||
: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
|
||||
{:db (-> (update db :browser/options
|
||||
(rf/merge cofx
|
||||
{:db (-> (update db
|
||||
:browser/options
|
||||
assoc
|
||||
:url (str gateway path)
|
||||
:resolving? false)
|
||||
:url (str gateway path)
|
||||
: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 {:url (get-current-url (get-current-browser db))
|
||||
:resolving? false
|
||||
:error? true}))
|
||||
(update-browser-options cofx
|
||||
{:url (get-current-url (get-current-browser db))
|
||||
: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}))
|
||||
|
||||
(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])
|
||||
(let [browser (get-current-browser (:db cofx))
|
||||
options (get-in cofx [:db :browser/options])
|
||||
current-url (:url options)]
|
||||
(when (and browser (not (string/blank? url)) (not= "about:blank" url) (not= current-url url) (not= (str current-url "/") url))
|
||||
(when (and browser
|
||||
(not (string/blank? url))
|
||||
(not= "about:blank" url)
|
||||
(not= current-url url)
|
||||
(not= (str current-url "/") url))
|
||||
(let [resolved-ens (first (filter (fn [v]
|
||||
(not= (.indexOf ^js url (second v)) -1))
|
||||
(:resolved-ens options)))
|
||||
resolved-url (if resolved-ens
|
||||
(http/normalize-url (string/replace url (second resolved-ens) (first resolved-ens)))
|
||||
(http/normalize-url (string/replace url
|
||||
(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)
|
||||
@@ -247,59 +268,61 @@
|
||||
(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"
|
||||
{:events [:browser.ui/url-submitted]}
|
||||
[cofx url]
|
||||
(let [browser (get-current-browser (:db cofx))
|
||||
(let [browser (get-current-browser (:db cofx))
|
||||
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"
|
||||
{:events [:browser.ui/open-url]}
|
||||
[{:keys [db] :as cofx} url]
|
||||
(let [normalized-url (http/normalize-and-decode-url url)
|
||||
browser {:browser-id (random/id)
|
||||
:history-index 0
|
||||
:history [normalized-url]}]
|
||||
browser {:browser-id (random/id)
|
||||
:history-index 0
|
||||
:history [normalized-url]}]
|
||||
(if (links/universal-link? normalized-url)
|
||||
{:dispatch [:universal-links/handle-url normalized-url]}
|
||||
(fx/merge cofx
|
||||
{:db (assoc db :browser/options
|
||||
(rf/merge cofx
|
||||
{:db (assoc db
|
||||
:browser/options
|
||||
{:browser-id (:browser-id browser)})}
|
||||
(navigation/change-tab :browser)
|
||||
(navigation/set-stack-root :browser-stack :browser)
|
||||
(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
|
||||
{:db (assoc db :browser/options
|
||||
(rf/merge cofx
|
||||
{:db (assoc db
|
||||
:browser/options
|
||||
{:browser-id browser-id})}
|
||||
(update-browser browser)
|
||||
(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
|
||||
@@ -307,7 +330,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
|
||||
@@ -336,21 +359,24 @@
|
||||
(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})
|
||||
|
||||
(defn web3-sign-message? [method]
|
||||
(defn web3-sign-message?
|
||||
[method]
|
||||
(#{constants/web3-sign-typed-data constants/web3-sign-typed-data-v3 constants/web3-sign-typed-data-v4
|
||||
constants/web3-personal-sign
|
||||
constants/web3-eth-sign constants/web3-keycard-sign-typed-data} method))
|
||||
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])
|
||||
typed? (and (not= constants/web3-personal-sign method) (not= constants/web3-eth-sign method))]
|
||||
typed? (and (not= constants/web3-personal-sign method)
|
||||
(not= constants/web3-eth-sign method))]
|
||||
(if (or message? (= constants/web3-send-transaction method))
|
||||
(let [[address data] (cond (and (= method constants/web3-keycard-sign-typed-data)
|
||||
(not (vector? params)))
|
||||
@@ -359,34 +385,38 @@
|
||||
message? (normalize-sign-message-params params typed?)
|
||||
:else [nil nil])]
|
||||
(when (or (not message?) (and address data))
|
||||
(signing/sign cofx (merge
|
||||
(if message?
|
||||
{:message {:address address
|
||||
:data data
|
||||
:v4 (= constants/web3-sign-typed-data-v4 method)
|
||||
:typed? typed?
|
||||
:pinless? (= method constants/web3-keycard-sign-typed-data)
|
||||
:from dapps-address}}
|
||||
{:tx-obj (-> params
|
||||
first
|
||||
(update :from #(or % dapps-address))
|
||||
(dissoc :gasPrice))})
|
||||
{:on-result [:browser.dapp/transaction-on-result message-id id]
|
||||
:on-error [:browser.dapp/transaction-on-error message-id]}))))
|
||||
(signing/sign cofx
|
||||
(merge
|
||||
(if message?
|
||||
{:message {:address address
|
||||
:data data
|
||||
:v4 (= constants/web3-sign-typed-data-v4 method)
|
||||
:typed? typed?
|
||||
:pinless? (= method constants/web3-keycard-sign-typed-data)
|
||||
:from dapps-address}}
|
||||
{:tx-obj (-> params
|
||||
first
|
||||
(update :from #(or % dapps-address))
|
||||
(dissoc :gasPrice))})
|
||||
{:on-result [:browser.dapp/transaction-on-result message-id id]
|
||||
:on-error [:browser.dapp/transaction-on-error message-id]}))))
|
||||
(cond
|
||||
(#{"eth_accounts" "eth_coinbase"} method)
|
||||
(send-to-bridge cofx {:type constants/web3-send-async-callback
|
||||
:messageId message-id
|
||||
:result {:jsonrpc "2.0"
|
||||
:id (int id)
|
||||
:result (if (= method "eth_coinbase") dapps-address [dapps-address])}})
|
||||
(send-to-bridge
|
||||
cofx
|
||||
{:type constants/web3-send-async-callback
|
||||
:messageId message-id
|
||||
:result {:jsonrpc "2.0"
|
||||
:id (int id)
|
||||
:result (if (= method "eth_coinbase") dapps-address [dapps-address])}})
|
||||
(= method "personal_ecRecover")
|
||||
{:signing.fx/recover-message {:params {:message (first params)
|
||||
{:signing.fx/recover-message {:params {:message (first params)
|
||||
:signature (second params)}
|
||||
:on-completed #(re-frame/dispatch [:browser.callback/call-rpc
|
||||
{:type constants/web3-send-async-callback
|
||||
:messageId message-id
|
||||
:result (types/json->clj %)}])}}
|
||||
:on-completed #(re-frame/dispatch
|
||||
[:browser.callback/call-rpc
|
||||
{:type constants/web3-send-async-callback
|
||||
:messageId message-id
|
||||
:result (types/json->clj %)}])}}
|
||||
(= method "wallet_switchEthereumChain")
|
||||
(eip3326/handle-switch-ethereum-chain cofx dapp-name id message-id (first params))
|
||||
|
||||
@@ -401,7 +431,8 @@
|
||||
:error %1
|
||||
:result %2}])]}))))
|
||||
|
||||
(fx/defn handle-no-permissions [cofx {:keys [method id]} message-id]
|
||||
(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
|
||||
(send-to-bridge cofx
|
||||
@@ -420,41 +451,48 @@
|
||||
"keycard_signTypedData"
|
||||
"eth_signTypedData" "personal_sign" "personal_ecRecover"})
|
||||
|
||||
(defn has-permissions? [{:dapps/keys [permissions]} dapp-name method]
|
||||
(defn has-permissions?
|
||||
[{:dapps/keys [permissions]} dapp-name method]
|
||||
(boolean
|
||||
(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 db)
|
||||
url-original (get-current-url browser)
|
||||
data (types/json->clj message)
|
||||
(let [browser (get-current-browser
|
||||
db)
|
||||
url-original (get-current-url
|
||||
browser)
|
||||
data (types/json->clj
|
||||
message)
|
||||
{{:keys [url]} :navState :keys [type permission payload messageId params]} data
|
||||
{:keys [dapp? name]} browser
|
||||
dapp-name (if dapp? name (http/url-host url-original))]
|
||||
{:keys [dapp? name]} browser
|
||||
dapp-name (if dapp?
|
||||
name
|
||||
(http/url-host
|
||||
url-original))]
|
||||
(cond
|
||||
(and (= type constants/history-state-changed)
|
||||
(not= "about:blank" url))
|
||||
@@ -474,10 +512,13 @@
|
||||
(re-frame/reg-fx
|
||||
:browser/send-to-bridge
|
||||
(fn [message]
|
||||
(let [^js webview @webview-ref/webview-ref
|
||||
msg (str "(function() { var __send = function() { if (ReactNativeWebView.onMessage) { ReactNativeWebView.onMessage('"
|
||||
(types/clj->json message)
|
||||
"');} else {setTimeout(__send, 0)}}; __send();})();")]
|
||||
(let
|
||||
[^js webview @webview-ref/webview-ref
|
||||
msg
|
||||
(str
|
||||
"(function() { var __send = function() { if (ReactNativeWebView.onMessage) { ReactNativeWebView.onMessage('"
|
||||
(types/clj->json message)
|
||||
"');} else {setTimeout(__send, 0)}}; __send();})();")]
|
||||
(when (and message webview)
|
||||
(.injectJavaScript webview msg)))))
|
||||
|
||||
@@ -508,59 +549,61 @@
|
||||
(fn []
|
||||
(status/clear-web-data)))
|
||||
|
||||
(defn share-link [url]
|
||||
(defn share-link
|
||||
[url]
|
||||
(let [link (links/generate-link :browse :external url)
|
||||
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)
|
||||
(multiaccounts.update/multiaccount-update :dapps-address address {})
|
||||
#(when (= (:view-id db) :browser)
|
||||
(merge (navigation/navigate-back %)
|
||||
{:dispatch [:browser.ui/browser-item-selected (get-in db [:browser/options :browser-id])]}))))
|
||||
{: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))
|
||||
{}
|
||||
bookmarks)
|
||||
stored-bookmarks (get-in db [:bookmarks/bookmarks])]
|
||||
stored-bookmarks (get-in db [:bookmarks/bookmarks])]
|
||||
{:db (assoc-in db [:bookmarks/bookmarks] (merge stored-bookmarks changed-bookmarks))}))
|
||||
|
||||
@@ -1,69 +1,76 @@
|
||||
;reference https://eips.ethereum.org/EIPS/eip-3085 EIP-3085: Wallet Add Ethereum Chain RPC Method (`wallet_addEthereumChain`)
|
||||
;reference https://eips.ethereum.org/EIPS/eip-3085 EIP-3085: Wallet Add Ethereum Chain RPC Method
|
||||
;(`wallet_addEthereumChain`)
|
||||
(ns status-im.browser.eip3085
|
||||
(:require [status-im.constants :as constants]
|
||||
[clojure.string :as string]
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.network.core :as network]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.ui.screens.browser.eip3085.sheet :as sheet]))
|
||||
[status-im.network.core :as network]
|
||||
[status-im.ui.screens.browser.eip3085.sheet :as sheet]
|
||||
[status-im.utils.random :as random]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(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
|
||||
{:browser/send-to-bridge {:type constants/web3-send-async-callback
|
||||
:messageId messageId
|
||||
:result {:jsonrpc "2.0"
|
||||
:id (int id)
|
||||
:result nil}}})
|
||||
:result {:jsonrpc "2.0"
|
||||
: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])
|
||||
{: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]})
|
||||
: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
|
||||
{:browser/send-to-bridge {:type constants/web3-send-async-callback
|
||||
:messageId message-id
|
||||
:error {:code 4001
|
||||
:message "User rejected the request."}}
|
||||
:dispatch [:bottom-sheet/hide]})
|
||||
:error {:code 4001
|
||||
: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 {:keys [chainId blockExplorerUrls chainName iconUrls nativeCurrency rpcUrls] :as params}]
|
||||
(let [manage {:name {:value chainName}
|
||||
:symbol {:value (:symbol nativeCurrency)}
|
||||
:url {:value (first rpcUrls)}
|
||||
dapp-name id message-id
|
||||
{:keys [chainId blockExplorerUrls chainName iconUrls nativeCurrency rpcUrls] :as params}]
|
||||
(let [manage {:name {:value chainName}
|
||||
:symbol {:value (:symbol nativeCurrency)}
|
||||
:url {:value (first rpcUrls)}
|
||||
:network-id {:value chainId}
|
||||
:chain {:value :custom}}]
|
||||
:chain {:value :custom}}]
|
||||
(if (network/valid-manage? manage)
|
||||
(let [{:keys [name url chain network-id symbol]} manage
|
||||
random-id (string/replace (random/id) "-" "")
|
||||
network (network/new-network random-id
|
||||
(:value name)
|
||||
(:value symbol)
|
||||
(:value url)
|
||||
(:value chain)
|
||||
(:value network-id))
|
||||
new-networks (assoc networks random-id network)
|
||||
params (assoc params :new-networks new-networks :id id :new-network network)]
|
||||
random-id (string/replace (random/id) "-" "")
|
||||
network (network/new-network random-id
|
||||
(:value name)
|
||||
(:value symbol)
|
||||
(:value url)
|
||||
(:value chain)
|
||||
(:value network-id))
|
||||
new-networks (assoc networks random-id network)
|
||||
params (assoc params
|
||||
:new-networks new-networks
|
||||
:id id
|
||||
:new-network network)]
|
||||
(if (network/chain-id-available? networks network)
|
||||
{:dispatch [:bottom-sheet/show-sheet {:content (fn []
|
||||
[sheet/permissions-panel dapp-name message-id params])}]}
|
||||
{:dispatch [:bottom-sheet/show-sheet
|
||||
{:content (fn []
|
||||
[sheet/permissions-panel dapp-name message-id params])}]}
|
||||
(send-success-call-to-bridge cofx id message-id)))
|
||||
{:browser/send-to-bridge {:type constants/web3-send-async-callback
|
||||
{:browser/send-to-bridge {:type constants/web3-send-async-callback
|
||||
:messageId message-id
|
||||
:error {:code -32602
|
||||
:message "invalid network parameters"}}})))
|
||||
:error {:code -32602
|
||||
:message "invalid network parameters"}}})))
|
||||
|
||||
|
||||
@@ -1,43 +1,54 @@
|
||||
;reference https://eips.ethereum.org/EIPS/eip-3326 EIP-3326: Wallet Switch Ethereum Chain RPC Method (`wallet_switchEthereumChain`)
|
||||
;reference https://eips.ethereum.org/EIPS/eip-3326 EIP-3326: Wallet Switch Ethereum Chain RPC Method
|
||||
;(`wallet_switchEthereumChain`)
|
||||
(ns status-im.browser.eip3326
|
||||
(:require [status-im.constants :as constants]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ui.screens.browser.eip3326.sheet :as sheet]))
|
||||
[status-im.ui.screens.browser.eip3326.sheet :as sheet]
|
||||
[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
|
||||
{:browser/send-to-bridge {:type constants/web3-send-async-callback
|
||||
:messageId message-id
|
||||
:error {:code 4001
|
||||
:message "User rejected the request."}}
|
||||
:dispatch [:bottom-sheet/hide]})
|
||||
:error {:code 4001
|
||||
: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)
|
||||
networks (vals (get-in db [:networks/networks]))
|
||||
exist-chain-ids (set (map ethereum/network->chain-id networks))
|
||||
(let [target-chain-id (js/parseInt chainId 16)
|
||||
networks (vals (get-in db [:networks/networks]))
|
||||
exist-chain-ids (set (map ethereum/network->chain-id networks))
|
||||
current-chain-id (ethereum/chain-id db)]
|
||||
(if (exist-chain-ids target-chain-id)
|
||||
(if (= current-chain-id target-chain-id)
|
||||
{:browser/send-to-bridge {:type constants/web3-send-async-callback
|
||||
{:browser/send-to-bridge {:type constants/web3-send-async-callback
|
||||
:messageId message-id
|
||||
:result {:jsonrpc "2.0"
|
||||
:id (int id)
|
||||
:result nil}}}
|
||||
(let [target-network (first (filter #(= (ethereum/network->chain-id %1) target-chain-id) networks))
|
||||
:result {:jsonrpc "2.0"
|
||||
:id (int id)
|
||||
:result nil}}}
|
||||
(let [target-network (first (filter #(= (ethereum/network->chain-id %1) target-chain-id)
|
||||
networks))
|
||||
target-network-id (:id target-network)
|
||||
current-network (ethereum/current-network db)
|
||||
network-from (:name current-network)
|
||||
network-to (:name target-network)
|
||||
params (assoc params :target-network-id target-network-id :network-from network-from :network-to network-to)]
|
||||
{:dispatch [:bottom-sheet/show-sheet {:content (fn []
|
||||
[sheet/permissions-panel dapp-name message-id params])}]}))
|
||||
{:browser/send-to-bridge {:type constants/web3-send-async-callback
|
||||
current-network (ethereum/current-network db)
|
||||
network-from (:name current-network)
|
||||
network-to (:name target-network)
|
||||
params (assoc params
|
||||
:target-network-id target-network-id
|
||||
:network-from network-from
|
||||
:network-to network-to)]
|
||||
{:dispatch [:bottom-sheet/show-sheet
|
||||
{:content (fn []
|
||||
[sheet/permissions-panel dapp-name message-id params])}]}))
|
||||
{:browser/send-to-bridge {:type constants/web3-send-async-callback
|
||||
:messageId message-id
|
||||
:error {:code 4902
|
||||
:message (str "Unrecognized chain ID: " target-chain-id ". Try adding the chain using wallet_addEthereumChain first.")}}})))
|
||||
:error
|
||||
{:code 4902
|
||||
:message
|
||||
(str
|
||||
"Unrecognized chain ID: "
|
||||
target-chain-id
|
||||
". Try adding the chain using wallet_addEthereumChain first.")}}})))
|
||||
|
||||
|
||||
@@ -2,51 +2,53 @@
|
||||
(:require [status-im.constants :as constants]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.qr-scanner.core :as qr-scanner]
|
||||
[status-im.utils.fx :as fx]))
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(declare process-next-permission)
|
||||
(declare send-response-to-bridge)
|
||||
|
||||
(def supported-permissions
|
||||
{constants/dapp-permission-qr-code {:yield-control? true
|
||||
:allowed? true}
|
||||
constants/dapp-permission-contact-code {:type :profile
|
||||
:title (i18n/label :t/wants-to-access-profile)
|
||||
:description (i18n/label :t/your-contact-code)
|
||||
:icon :main-icons/profile}
|
||||
constants/dapp-permission-web3 {:type :wallet
|
||||
:title (i18n/label :t/dapp-would-like-to-connect-wallet)
|
||||
:description (i18n/label :t/allowing-authorizes-this-dapp)
|
||||
:icon :main-icons/wallet}})
|
||||
{constants/dapp-permission-qr-code {:yield-control? true
|
||||
:allowed? true}
|
||||
constants/dapp-permission-contact-code {:type :profile
|
||||
:title (i18n/label :t/wants-to-access-profile)
|
||||
:description (i18n/label :t/your-contact-code)
|
||||
:icon :main-icons/profile}
|
||||
constants/dapp-permission-web3 {:type :wallet
|
||||
:title (i18n/label :t/dapp-would-like-to-connect-wallet)
|
||||
: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]
|
||||
{:requested-permission permission
|
||||
:message-id message-id
|
||||
:dapp-name dapp-name
|
||||
:yield-control? yield-control?})})
|
||||
{:db (assoc-in db
|
||||
[:browser/options :show-permission]
|
||||
{:requested-permission permission
|
||||
:message-id message-id
|
||||
:dapp-name dapp-name
|
||||
:yield-control? yield-control?})})
|
||||
|
||||
(defn get-permission-data [cofx allowed-permission]
|
||||
(defn get-permission-data
|
||||
[cofx allowed-permission]
|
||||
(let [multiaccount (get-in cofx [:db :multiaccount])]
|
||||
(get {constants/dapp-permission-contact-code (:public-key multiaccount)
|
||||
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]
|
||||
@@ -57,7 +59,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?
|
||||
@@ -65,28 +67,28 @@
|
||||
(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]
|
||||
{: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
|
||||
(rf/merge cofx
|
||||
{:db (update-in db [:dapps/permissions] dissoc dapp)
|
||||
::json-rpc/call [{:method "permissions_deleteDappPermissions"
|
||||
:params [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)
|
||||
@@ -95,7 +97,7 @@
|
||||
: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"
|
||||
@@ -105,46 +107,47 @@
|
||||
{:db db}
|
||||
(let [pending-permissions (get-in db [:browser/options :pending-permissions])
|
||||
next-permission (last pending-permissions)
|
||||
new-cofx (update-in cofx [:db :browser/options :pending-permissions] butlast)]
|
||||
new-cofx (update-in cofx [:db :browser/options :pending-permissions] butlast)]
|
||||
(when-let [{:keys [yield-control? permission message-id allowed? params]} next-permission]
|
||||
(if (and yield-control? allowed?)
|
||||
(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)
|
||||
(let [{:keys [requested-permission message-id dapp-name]} (get-in db
|
||||
[:browser/options :show-permission])]
|
||||
(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"
|
||||
@@ -156,15 +159,18 @@
|
||||
(not supported-permission)
|
||||
(send-response-to-bridge cofx permission message-id false nil)
|
||||
|
||||
(and (or permission-allowed? (:allowed? supported-permission)) (not (:yield-control? supported-permission)))
|
||||
(and (or permission-allowed? (:allowed? supported-permission))
|
||||
(not (:yield-control? supported-permission)))
|
||||
(send-response-to-bridge cofx permission message-id true (get-permission-data cofx permission))
|
||||
|
||||
:else
|
||||
(process-next-permission (update-in cofx [:db :browser/options :pending-permissions]
|
||||
conj {:permission permission
|
||||
:allowed? (or permission-allowed?
|
||||
(:allowed? supported-permission))
|
||||
:yield-control? (:yield-control? supported-permission)
|
||||
:params params
|
||||
:message-id message-id})
|
||||
(process-next-permission (update-in cofx
|
||||
[:db :browser/options :pending-permissions]
|
||||
conj
|
||||
{:permission permission
|
||||
:allowed? (or permission-allowed?
|
||||
(:allowed? supported-permission))
|
||||
:yield-control? (:yield-control? supported-permission)
|
||||
:params params
|
||||
:message-id message-id})
|
||||
dapp-name))))
|
||||
|
||||
+164
-150
@@ -1,31 +1,33 @@
|
||||
(ns status-im.chat.models
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.multiaccounts.model :as multiaccounts.model]
|
||||
(:require [clojure.set :as set]
|
||||
[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.loading :as loading]
|
||||
[status-im.chat.models.message-list :as message-list]
|
||||
[status-im.chat.models.delete-message :as delete-message]
|
||||
[status-im.chat.models.delete-message-for-me :as delete-for-me]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.data-store.chats :as chats-store]
|
||||
[status-im.mailserver.core :as mailserver]
|
||||
[status-im.data-store.contacts :as contacts-store]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[quo.design-system.colors :as colors]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.utils.clocks :as utils.clocks]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.add-new.db :as new-public-chat.db]
|
||||
[status-im.chat.models.loading :as loading]
|
||||
[status-im.mailserver.core :as mailserver]
|
||||
[status-im.multiaccounts.model :as multiaccounts.model]
|
||||
[status-im.ui.screens.chat.state :as chat.state]
|
||||
[clojure.set :as set]
|
||||
[status-im2.navigation.events :as navigation]))
|
||||
[status-im.utils.clocks :as utils.clocks]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im2.contexts.chat.messages.message.delete-message-for-me.events :as delete-for-me]
|
||||
[status-im2.contexts.chat.messages.message.delete-message.events :as delete-message]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn chats []
|
||||
(defn chats
|
||||
[]
|
||||
(:chats (types/json->clj (js/require "./chats.js"))))
|
||||
|
||||
(defn- get-chat [cofx chat-id]
|
||||
(defn- get-chat
|
||||
[cofx chat-id]
|
||||
(get-in cofx [:db :chats chat-id]))
|
||||
|
||||
(defn multi-user-chat?
|
||||
@@ -49,7 +51,8 @@
|
||||
([cofx chat-id]
|
||||
(community-chat? (get-chat cofx chat-id))))
|
||||
|
||||
(defn active-chat? [cofx chat-id]
|
||||
(defn active-chat?
|
||||
[cofx chat-id]
|
||||
(let [chat (get-chat cofx chat-id)]
|
||||
(:active chat)))
|
||||
|
||||
@@ -85,52 +88,56 @@
|
||||
(defn- create-new-chat
|
||||
[chat-id {:keys [db now]}]
|
||||
(let [name (get-in db [:contacts/contacts chat-id :name])]
|
||||
{:chat-id chat-id
|
||||
:name (or name "")
|
||||
:color (rand-nth colors/chat-colors)
|
||||
:chat-type constants/one-to-one-chat-type
|
||||
:group-chat false
|
||||
:timestamp now
|
||||
:contacts #{chat-id}
|
||||
:last-clock-value 0}))
|
||||
{:chat-id chat-id
|
||||
:name (or name "")
|
||||
:color (rand-nth colors/chat-colors)
|
||||
:chat-type constants/one-to-one-chat-type
|
||||
:group-chat false
|
||||
:timestamp now
|
||||
:contacts #{chat-id}
|
||||
:last-clock-value 0}))
|
||||
|
||||
(defn map-chats [{:keys [db] :as cofx}]
|
||||
(defn map-chats
|
||||
[{:keys [db] :as cofx}]
|
||||
(fn [val]
|
||||
(assoc
|
||||
(merge
|
||||
(or (get (:chats db) (:chat-id val))
|
||||
(create-new-chat (:chat-id val) cofx))
|
||||
val)
|
||||
:invitation-admin (:invitation-admin val))))
|
||||
:invitation-admin
|
||||
(:invitation-admin val))))
|
||||
|
||||
(defn filter-chats [db]
|
||||
(defn filter-chats
|
||||
[db]
|
||||
(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}]
|
||||
: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]}
|
||||
(reduce (fn [acc {:keys [chat-id profile-public-key timeline? community-id active muted] :as chat}]
|
||||
(if (not (or active muted))
|
||||
(update acc :removed-chats conj chat-id)
|
||||
(cond-> acc
|
||||
(and (not profile-public-key) (not timeline?) (not community-id) active)
|
||||
(update :chats-home-list conj chat-id)
|
||||
:always
|
||||
(assoc-in [:all-chats chat-id] chat))))
|
||||
{:all-chats {}
|
||||
:chats-home-list #{}
|
||||
:removed-chats #{}}
|
||||
(map (map-chats cofx) chats))]
|
||||
(fx/merge
|
||||
(reduce
|
||||
(fn [acc {:keys [chat-id profile-public-key timeline? community-id active muted] :as chat}]
|
||||
(if (not (or active muted))
|
||||
(update acc :removed-chats conj chat-id)
|
||||
(cond-> acc
|
||||
(and (not profile-public-key) (not timeline?) (not community-id) active)
|
||||
(update :chats-home-list conj chat-id)
|
||||
:always
|
||||
(assoc-in [:all-chats chat-id] chat))))
|
||||
{:all-chats {}
|
||||
:chats-home-list #{}
|
||||
:removed-chats #{}}
|
||||
(map (map-chats cofx) chats))]
|
||||
(rf/merge
|
||||
cofx
|
||||
(merge {:db (-> db
|
||||
(update :chats merge all-chats)
|
||||
@@ -143,62 +150,66 @@
|
||||
(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?
|
||||
deleted-at-clock-value]} (get-in db [:chats chat-id])
|
||||
deleted-at-clock-value]}
|
||||
(get-in db [:chats chat-id])
|
||||
last-message-clock-value (if (and public? remove-chat?)
|
||||
0
|
||||
(or (:clock-value last-message)
|
||||
deleted-at-clock-value
|
||||
(utils.clocks/send 0)))]
|
||||
{:db (-> db
|
||||
(assoc-in [:messages chat-id] {})
|
||||
(update-in [:message-lists] dissoc chat-id)
|
||||
(update :chats (fn [chats]
|
||||
(if (contains? chats chat-id)
|
||||
(update chats chat-id merge
|
||||
{:last-message nil
|
||||
:unviewed-messages-count 0
|
||||
:unviewed-mentions-count 0
|
||||
:deleted-at-clock-value last-message-clock-value})
|
||||
chats))))}))
|
||||
{:db (-> db
|
||||
(assoc-in [:messages chat-id] {})
|
||||
(update-in [:message-lists] dissoc chat-id)
|
||||
(update :chats
|
||||
(fn [chats]
|
||||
(if (contains? chats chat-id)
|
||||
(update chats
|
||||
chat-id
|
||||
merge
|
||||
{:last-message nil
|
||||
:unviewed-messages-count 0
|
||||
:unviewed-mentions-count 0
|
||||
: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}]
|
||||
(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 %)}]}
|
||||
: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}]
|
||||
{: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 %)}]}
|
||||
: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
|
||||
@@ -208,52 +219,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)
|
||||
@@ -266,11 +277,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))
|
||||
@@ -282,65 +293,68 @@
|
||||
#(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)))
|
||||
(let [chat (chats-store/<-rpc (first (:chats response)))
|
||||
contact-rpc (first (:contacts response))
|
||||
contact (when contact-rpc (contacts-store/<-rpc contact-rpc))]
|
||||
{:db (cond-> db
|
||||
contact
|
||||
(assoc-in [:contacts/contacts chat-id] contact)
|
||||
:always
|
||||
(assoc-in [:chats chat-id] chat)
|
||||
:always
|
||||
(update :chats-home-list conj chat-id))
|
||||
contact (when contact-rpc (contacts-store/<-rpc contact-rpc))]
|
||||
{:db (cond-> db
|
||||
contact
|
||||
(assoc-in [:contacts/contacts chat-id] contact)
|
||||
:always
|
||||
(assoc-in [:chats chat-id] chat)
|
||||
:always
|
||||
(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}]
|
||||
{::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 %)}]}))
|
||||
:on-error #(log/error "failed to create one-to-on chat" chat-id %)}]}))
|
||||
|
||||
(defn profile-chat-topic [public-key]
|
||||
(defn profile-chat-topic
|
||||
[public-key]
|
||||
(str "@" public-key))
|
||||
|
||||
(defn my-profile-chat-topic [db]
|
||||
(defn my-profile-chat-topic
|
||||
[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
|
||||
(assoc-in [:chats chat-id] (chats-store/<-rpc (first (:chats response))))
|
||||
(update :chats-home-list conj chat-id))
|
||||
{:db (-> db
|
||||
(assoc-in [:chats chat-id] (chats-store/<-rpc (first (:chats response))))
|
||||
(update :chats-home-list conj chat-id))
|
||||
:dispatch [:chat.ui/navigate-to-chat chat-id]})
|
||||
|
||||
(fx/defn create-public-chat-go [_ chat-id]
|
||||
{::json-rpc/call [{:method "wakuext_createPublicChat"
|
||||
:params [{:id chat-id}]
|
||||
(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 %)}]})
|
||||
: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]
|
||||
@@ -353,10 +367,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
|
||||
@@ -366,19 +380,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}]
|
||||
{::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 %)}]})))
|
||||
: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]}]
|
||||
@@ -392,40 +406,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? %])
|
||||
{: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
|
||||
@@ -436,19 +450,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)
|
||||
@@ -457,44 +471,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]
|
||||
{::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 %])}]})
|
||||
: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]
|
||||
{::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 %])}]})
|
||||
: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
|
||||
@@ -505,7 +519,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
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
(ns status-im.chat.models.images
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.utils.fx :as fx]
|
||||
["@react-native-community/cameraroll" :as CameraRoll]
|
||||
(:require ["@react-native-community/cameraroll" :as CameraRoll]
|
||||
["react-native-blob-util" :default ReactNativeBlobUtil]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.utils.config :as config]
|
||||
[clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.chat.models :as chat]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.ui.components.permissions :as permissions]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.utils.image-processing :as image-processing]
|
||||
[taoensso.timbre :as log]
|
||||
[clojure.string :as string]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.utils.fs :as fs]
|
||||
[status-im.chat.models :as chat]))
|
||||
[status-im.utils.image-processing :as image-processing]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.utils.utils :as utils]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def maximum-image-size-px 2000)
|
||||
|
||||
(defn- resize-and-call [uri cb]
|
||||
(defn- resize-and-call
|
||||
[uri cb]
|
||||
(react/image-get-size
|
||||
uri
|
||||
(fn [width height]
|
||||
@@ -34,16 +35,19 @@
|
||||
(cb path)))
|
||||
#(log/error "could not resize image" %))))))
|
||||
|
||||
(defn result->id [^js result]
|
||||
(defn result->id
|
||||
[^js result]
|
||||
(if platform/ios?
|
||||
(.-localIdentifier result)
|
||||
(.-path result)))
|
||||
|
||||
(def temp-image-url (str (fs/cache-dir) "/StatusIm_Image.jpeg"))
|
||||
|
||||
(defn download-image-http [base64-uri on-success]
|
||||
(-> (.config ReactNativeBlobUtil (clj->js {:trusty platform/ios?
|
||||
:path temp-image-url}))
|
||||
(defn download-image-http
|
||||
[base64-uri on-success]
|
||||
(-> (.config ReactNativeBlobUtil
|
||||
(clj->js {:trusty platform/ios?
|
||||
:path temp-image-url}))
|
||||
(.fetch "GET" base64-uri)
|
||||
(.then #(on-success (.path %)))
|
||||
(.catch #(log/error "could not save image"))))
|
||||
@@ -70,7 +74,8 @@
|
||||
::chat-open-image-picker-camera
|
||||
(fn [current-chat-id]
|
||||
(react/show-image-picker-camera
|
||||
#(re-frame/dispatch [:chat.ui/image-captured current-chat-id (.-path %)]) {})))
|
||||
#(re-frame/dispatch [:chat.ui/image-captured current-chat-id (.-path %)])
|
||||
{})))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::chat-open-image-picker
|
||||
@@ -100,15 +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))
|
||||
@@ -117,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))
|
||||
@@ -162,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))
|
||||
@@ -175,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))
|
||||
@@ -192,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})
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
[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]
|
||||
[status-im.utils.utils :as utils]
|
||||
[taoensso.timbre :as log]))
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn text->emoji
|
||||
"Replaces emojis in a specified `text`"
|
||||
@@ -26,7 +26,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,24 +34,25 @@
|
||||
(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))})
|
||||
{: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)
|
||||
(assoc-in [:chats/mention-suggestions chat-id] nil))
|
||||
{:db (-> db
|
||||
(assoc-in [:chats/cursor chat-id] cursor)
|
||||
(assoc-in [:chats/mention-suggestions chat-id] nil))
|
||||
:set-text-input-value [chat-id new-text text-input-ref]}
|
||||
(set-chat-input-text new-text chat-id)
|
||||
;; NOTE(rasom): Some keyboards do not react on selection property passed to
|
||||
@@ -74,67 +75,77 @@
|
||||
:end end}))
|
||||
(mentions/recheck-at-idxs {alias user}))))
|
||||
|
||||
(defn- start-cooldown [{:keys [db]} cooldowns]
|
||||
(defn- start-cooldown
|
||||
[{:keys [db]} cooldowns]
|
||||
{:dispatch-later [{:dispatch [:chat/disable-cooldown]
|
||||
:ms (chat.constants/cooldown-periods-ms
|
||||
cooldowns
|
||||
chat.constants/default-cooldown-period-ms)}]
|
||||
:show-cooldown-warning nil
|
||||
:db (assoc db
|
||||
:chat/cooldowns (if (= chat.constants/cooldown-reset-threshold cooldowns)
|
||||
0
|
||||
cooldowns)
|
||||
:chat/cooldowns (if
|
||||
(=
|
||||
chat.constants/cooldown-reset-threshold
|
||||
cooldowns)
|
||||
0
|
||||
cooldowns)
|
||||
:chat/spam-messages-frequency 0
|
||||
:chat/cooldown-enabled? true)})
|
||||
: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
|
||||
chat/spam-messages-frequency
|
||||
current-chat-id] :as db} :db :as cofx}]
|
||||
current-chat-id]
|
||||
:as db}
|
||||
:db
|
||||
:as cofx}]
|
||||
(when (chat/public-chat? cofx current-chat-id)
|
||||
(let [spamming-fast? (< (- (datetime/timestamp) last-outgoing-message-sent-at)
|
||||
(+ chat.constants/spam-interval-ms (* 1000 cooldowns)))
|
||||
spamming-frequently? (= chat.constants/spam-message-frequency-threshold spam-messages-frequency)]
|
||||
(let [spamming-fast? (< (- (datetime/timestamp) last-outgoing-message-sent-at)
|
||||
(+ chat.constants/spam-interval-ms (* 1000 cooldowns)))
|
||||
spamming-frequently? (= chat.constants/spam-message-frequency-threshold
|
||||
spam-messages-frequency)]
|
||||
(cond-> {:db (assoc db
|
||||
:chat/last-outgoing-message-sent-at (datetime/timestamp)
|
||||
:chat/spam-messages-frequency (if spamming-fast?
|
||||
(inc spam-messages-frequency)
|
||||
0))}
|
||||
:chat/spam-messages-frequency (if spamming-fast?
|
||||
(inc spam-messages-frequency)
|
||||
0))}
|
||||
|
||||
(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)
|
||||
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message] nil)
|
||||
(update-in [:chat/inputs current-chat-id :metadata]
|
||||
dissoc :sending-image))})))
|
||||
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]
|
||||
(let [current-chat-id (:current-chat-id db)
|
||||
|
||||
text (get-in message [:content :text])]
|
||||
text (get-in message [:content :text])]
|
||||
{:dispatch [:chat.ui.input/set-chat-input-text text current-chat-id]
|
||||
:db (-> db
|
||||
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message]
|
||||
message)
|
||||
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message] nil)
|
||||
(update-in [:chat/inputs current-chat-id :metadata]
|
||||
dissoc :sending-image))}))
|
||||
:db (-> db
|
||||
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message]
|
||||
message)
|
||||
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message] nil)
|
||||
(update-in [:chat/inputs current-chat-id :metadata]
|
||||
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}]
|
||||
@@ -146,9 +157,10 @@
|
||||
nil)
|
||||
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message] nil)
|
||||
(update-in [:chat/inputs current-chat-id :metadata]
|
||||
dissoc :sending-image))}))
|
||||
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]}]
|
||||
@@ -160,16 +172,16 @@
|
||||
(when-not (string/blank? input-text)
|
||||
(let [{:keys [message-id]}
|
||||
(get-in db [:chat/inputs current-chat-id :metadata :responding-to-message])
|
||||
preferred-name (get-in db [:multiaccount :preferred-name])
|
||||
emoji? (message-content/emoji-only-content? {:text input-text
|
||||
:response-to message-id})]
|
||||
preferred-name (get-in db [:multiaccount :preferred-name])
|
||||
emoji? (message-content/emoji-only-content? {:text input-text
|
||||
:response-to message-id})]
|
||||
{:chat-id current-chat-id
|
||||
:content-type (if emoji?
|
||||
constants/content-type-emoji
|
||||
constants/content-type-text)
|
||||
:text input-text
|
||||
:response-to message-id
|
||||
:ens-name preferred-name})))
|
||||
:text input-text
|
||||
:response-to message-id
|
||||
:ens-name preferred-name})))
|
||||
|
||||
(defn build-image-messages
|
||||
[{db :db} chat-id]
|
||||
@@ -181,8 +193,9 @@
|
||||
:text (i18n/label :t/update-to-see-image {"locale" "en"})})
|
||||
images)))
|
||||
|
||||
(fx/defn clean-input [{:keys [db] :as cofx} current-chat-id]
|
||||
(fx/merge cofx
|
||||
(rf/defn clean-input
|
||||
[{:keys [db] :as cofx} current-chat-id]
|
||||
(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)
|
||||
@@ -190,131 +203,137 @@
|
||||
(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 [{:keys [db] :as cofx} input-text current-chat-id]
|
||||
(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))]
|
||||
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}]
|
||||
(let [current-chat-id (chat/my-profile-chat-topic db)
|
||||
(let [current-chat-id (chat/my-profile-chat-topic db)
|
||||
{:keys [input-text]} (get-in db [:chat/inputs current-chat-id])
|
||||
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))]
|
||||
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)
|
||||
(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 cofx {:chat-id current-chat-id
|
||||
:content-type constants/content-type-audio
|
||||
:audio-path audio-path
|
||||
:audio-duration-ms duration
|
||||
:text (i18n/label :t/update-to-listen-audio {"locale" "en"})})))
|
||||
(chat.message/send-message
|
||||
cofx
|
||||
{:chat-id current-chat-id
|
||||
:content-type constants/content-type-audio
|
||||
:audio-path audio-path
|
||||
: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 {:chat-id current-chat-id
|
||||
:content-type constants/content-type-sticker
|
||||
:sticker {:hash hash
|
||||
(chat.message/send-message cofx
|
||||
{:chat-id current-chat-id
|
||||
:content-type constants/content-type-sticker
|
||||
:sticker {:hash hash
|
||||
:pack (int (if (string/blank? packID) pack packID))}
|
||||
:text (i18n/label :t/update-to-see-sticker {"locale" "en"})})))
|
||||
:text (i18n/label :t/update-to-see-sticker {"locale" "en"})})))
|
||||
|
||||
(fx/defn send-edited-message [{:keys [db] :as cofx} text {:keys [message-id quoted-message]}]
|
||||
(fx/merge
|
||||
(rf/defn send-edited-message
|
||||
[{:keys [db] :as cofx} text {:keys [message-id quoted-message]}]
|
||||
(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)}]
|
||||
{::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 %])}]}
|
||||
: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
|
||||
editing-message (:editing-message metadata)
|
||||
input-text-with-mentions (mentions/check-mentions cofx input-text)]
|
||||
(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" %)
|
||||
:on-success #(re-frame/dispatch [:transport/message-sent %])}]}
|
||||
:params [{:id public-key :message message}]
|
||||
:on-error #(log/warn "failed to send a contact request" %)
|
||||
:on-success #(re-frame/dispatch [:transport/message-sent %])}]}
|
||||
(mentions/clear-mentions)
|
||||
(mentions/clear-cursor)
|
||||
(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)))
|
||||
{: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,15 @@
|
||||
(ns status-im.chat.models.link-preview
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.communities.core :as models.communities]
|
||||
[taoensso.timbre :as log]))
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(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 +17,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?
|
||||
@@ -28,37 +28,42 @@
|
||||
#{})
|
||||
{})))
|
||||
|
||||
(defn community-resolved [db community-id]
|
||||
(defn community-resolved
|
||||
[db community-id]
|
||||
(update db :communities/resolve-community-info dissoc community-id))
|
||||
|
||||
(defn community-failed-to-resolve [db community-id]
|
||||
(defn community-failed-to-resolve
|
||||
[db community-id]
|
||||
(update db :communities/resolve-community-info dissoc community-id))
|
||||
|
||||
(defn community-resolving [db community-id]
|
||||
(defn community-resolving
|
||||
[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)})
|
||||
|
||||
(defn community-link [id]
|
||||
(defn community-link
|
||||
[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 [::cache-link-preview-data
|
||||
(community-link community-id) community]))
|
||||
(assoc :dispatch
|
||||
[::cache-link-preview-data
|
||||
(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)
|
||||
{:db (community-resolving db community-id)
|
||||
::json-rpc/call [{:method "wakuext_requestCommunityInfoFromMailserver"
|
||||
:params [community-id]
|
||||
:on-success #(re-frame/dispatch [::community-resolved community-id %])
|
||||
@@ -66,17 +71,18 @@
|
||||
(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)}])}]})
|
||||
: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
|
||||
@@ -90,23 +96,25 @@
|
||||
(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
|
||||
cofx
|
||||
:link-preview-request-enabled (boolean enabled?)
|
||||
:link-preview-request-enabled
|
||||
(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")}]})
|
||||
|
||||
(fx/defn save-link-preview-whitelist
|
||||
(rf/defn save-link-preview-whitelist
|
||||
{:events [::link-preview-whitelist-received]}
|
||||
[{:keys [db]} whitelist]
|
||||
{:db (assoc db :link-previews-whitelist
|
||||
{:db (assoc db
|
||||
:link-previews-whitelist
|
||||
whitelist)})
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
(ns status-im.chat.models.loading
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[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.utils.fx :as fx]
|
||||
[status-im.chat.models.message-list :as message-list]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.activity-center.core :as activity-center]))
|
||||
[status-im2.contexts.activity-center.events :as activity-center]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn cursor->clock-value
|
||||
[^js cursor]
|
||||
(js/parseInt (.substring cursor 51 64)))
|
||||
|
||||
(defn clock-value->cursor [clock-value]
|
||||
(defn clock-value->cursor
|
||||
[clock-value]
|
||||
(str "000000000000000000000000000000000000000000000000000"
|
||||
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]}
|
||||
@@ -30,27 +31,28 @@
|
||||
(update :chats-home-list conj chat-id)
|
||||
:always
|
||||
(assoc-in [:all-chats chat-id] chat))))
|
||||
{:all-chats {}
|
||||
{:all-chats {}
|
||||
:chats-home-list #{}}
|
||||
new-chats-js)]
|
||||
{:db (assoc db :chats all-chats
|
||||
{:db (assoc db
|
||||
:chats all-chats
|
||||
:chats-home-list chats-home-list
|
||||
:chats/loading? false)}))
|
||||
: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]
|
||||
{::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 %)}]})
|
||||
: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)
|
||||
@@ -59,52 +61,55 @@
|
||||
|
||||
(defn mark-chat-all-read
|
||||
[db chat-id]
|
||||
(update-in db [:chats chat-id] assoc
|
||||
(update-in db
|
||||
[:chats chat-id]
|
||||
assoc
|
||||
:unviewed-messages-count 0
|
||||
:unviewed-mentions-count 0
|
||||
:highlight false))
|
||||
: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"
|
||||
:params [chat-id]
|
||||
:on-success #(re-frame/dispatch [::mark-all-read-successful])}]})
|
||||
{: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"
|
||||
: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"
|
||||
:params [community-id]
|
||||
:on-success #(re-frame/dispatch [::mark-all-read-in-community-successful %])}]}))
|
||||
{:clear-message-notifications [community-chat-ids
|
||||
(get-in db [:multiaccount :remote-push-notifications-enabled?])]
|
||||
::json-rpc/call [{:method "wakuext_markAllReadInCommunity"
|
||||
:params [community-id]
|
||||
:on-success #(re-frame/dispatch
|
||||
[::mark-all-read-in-community-successful %])}]}))
|
||||
|
||||
(fx/defn messages-loaded
|
||||
(rf/defn messages-loaded
|
||||
"Loads more messages for current chat"
|
||||
{:events [::messages-loaded]}
|
||||
[{db :db} chat-id session-id {:keys [cursor messages]}]
|
||||
(when-not (and (get-in db [:pagination-info chat-id :messages-initialized?])
|
||||
(not= session-id
|
||||
(get-in db [:pagination-info chat-id :messages-initialized?])))
|
||||
(let [already-loaded-messages (get-in db [:messages chat-id])
|
||||
(let [already-loaded-messages (get-in db [:messages chat-id])
|
||||
;; We remove those messages that are already loaded, as we might get some duplicates
|
||||
{:keys [all-messages new-messages senders contacts]}
|
||||
(reduce (fn [{:keys [all-messages] :as acc}
|
||||
@@ -124,8 +129,11 @@
|
||||
:contacts {}
|
||||
:new-messages []}
|
||||
messages)
|
||||
current-clock-value (get-in db [:pagination-info chat-id :cursor-clock-value])
|
||||
clock-value (when cursor (cursor->clock-value cursor))]
|
||||
current-clock-value (get-in db
|
||||
[:pagination-info chat-id
|
||||
:cursor-clock-value])
|
||||
clock-value (when cursor
|
||||
(cursor->clock-value cursor))]
|
||||
{:dispatch [:chat/add-senders-to-chat-users (vals senders)]
|
||||
:db (-> db
|
||||
(update-in [:pagination-info chat-id :cursor-clock-value]
|
||||
@@ -134,7 +142,9 @@
|
||||
%))
|
||||
|
||||
(update-in [:pagination-info chat-id :cursor]
|
||||
#(if (or (empty? cursor) (not current-clock-value) (< clock-value current-clock-value))
|
||||
#(if (or (empty? cursor)
|
||||
(not current-clock-value)
|
||||
(< clock-value current-clock-value))
|
||||
cursor
|
||||
%))
|
||||
(assoc-in [:pagination-info chat-id :loading-messages?] false)
|
||||
@@ -144,7 +154,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?])]
|
||||
@@ -163,16 +173,16 @@
|
||||
#(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
|
||||
{:db (assoc-in db [:pagination-info chat-id :messages-initialized?] now)
|
||||
(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?])
|
||||
{:ms 100 :dispatch [:pin-message/load-pin-messages chat-id]})]}
|
||||
|
||||
@@ -1,23 +1,26 @@
|
||||
(ns status-im.chat.models.mentions
|
||||
(:require [clojure.string :as string]
|
||||
[quo.react :as react]
|
||||
[quo.react-native :as rn]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.contact.db :as contact.db]
|
||||
[status-im.utils.platform :as platform]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.multiaccounts.core :as multiaccounts]
|
||||
[status-im.native-module.core :as status]
|
||||
[quo.react-native :as rn]
|
||||
[quo.react :as react]
|
||||
[status-im.multiaccounts.core :as multiaccounts]))
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.utils :as utils]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def at-sign "@")
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn re-pos [re s]
|
||||
(loop [res [] s s last-idx 0]
|
||||
(defn re-pos
|
||||
[re s]
|
||||
(loop [res []
|
||||
s s
|
||||
last-idx 0]
|
||||
(if-let [m (.exec re s)]
|
||||
(let [new-idx (.-index m)
|
||||
idx (+ last-idx new-idx)
|
||||
@@ -25,7 +28,8 @@
|
||||
(recur (conj res [idx c]) (subs s (inc new-idx)) (inc idx)))
|
||||
res)))
|
||||
|
||||
(defn check-style-tag [text idxs idx]
|
||||
(defn check-style-tag
|
||||
[text idxs idx]
|
||||
(let [[pos c] (get idxs idx)
|
||||
[pos2 c2] (get idxs (inc idx))
|
||||
[pos3 c3] (get idxs (+ 2 idx))
|
||||
@@ -63,7 +67,8 @@
|
||||
(doall
|
||||
((fnil concat []) checked new-idxs)))))))
|
||||
|
||||
(defn apply-style-tag [data idx pos c len start? end?]
|
||||
(defn apply-style-tag
|
||||
[data idx pos c len start? end?]
|
||||
(let [was-started? (get data c)
|
||||
tripple-tilde? (and (= "~" c) (= 3 len))]
|
||||
(cond
|
||||
@@ -87,8 +92,9 @@
|
||||
|
||||
start?
|
||||
{:data (-> data
|
||||
(assoc c {:len len
|
||||
:idx pos})
|
||||
(assoc c
|
||||
{:len len
|
||||
:idx pos})
|
||||
(clear-pending-at-signs pos))
|
||||
:next-idx (+ idx len)}
|
||||
|
||||
@@ -96,7 +102,8 @@
|
||||
{:data data
|
||||
:next-idx (+ idx len)})))
|
||||
|
||||
(defn code-tag-len [idxs idx]
|
||||
(defn code-tag-len
|
||||
[idxs idx]
|
||||
(let [[pos c] (get idxs idx)
|
||||
[pos2 c2] (get idxs (inc idx))
|
||||
[pos3 c3] (get idxs (+ 2 idx))]
|
||||
@@ -147,7 +154,8 @@
|
||||
(string/blank? (subs text (first prev-newlines) (dec pos)))))
|
||||
(recur (-> data
|
||||
(dissoc :newline "*" "_" "~" "`")
|
||||
(assoc ">" {:idx pos})) (inc idx))
|
||||
(assoc ">" {:idx pos}))
|
||||
(inc idx))
|
||||
(recur data (inc idx))))
|
||||
|
||||
at-sign?
|
||||
@@ -155,7 +163,7 @@
|
||||
(inc idx))
|
||||
|
||||
code-tag?
|
||||
(let [len (code-tag-len idxs idx)
|
||||
(let [len (code-tag-len idxs idx)
|
||||
{:keys [data next-idx]}
|
||||
(apply-style-tag data idx pos c len true true)]
|
||||
(recur data next-idx))
|
||||
@@ -167,7 +175,7 @@
|
||||
(apply-style-tag data idx pos c len can-be-start? can-be-end?)]
|
||||
(recur data next-idx))
|
||||
|
||||
:else (recur data (inc idx)))))))))
|
||||
:else (recur data (inc idx)))))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
@@ -201,7 +209,8 @@
|
||||
:ens-verified ens-verified
|
||||
:public-key public-key})))
|
||||
|
||||
(defn mentionable-contacts [contacts]
|
||||
(defn mentionable-contacts
|
||||
[contacts]
|
||||
(reduce
|
||||
(fn [acc [key contact]]
|
||||
(let [mentionable-contact (add-searchable-phrases-to-contact contact false)]
|
||||
@@ -211,38 +220,49 @@
|
||||
{}
|
||||
contacts))
|
||||
|
||||
(defn mentionable-contacts-from-identites [contacts my-public-key identities]
|
||||
(defn mentionable-contacts-from-identites
|
||||
[contacts my-public-key identities]
|
||||
(reduce (fn [acc identity]
|
||||
(let [contact (multiaccounts/contact-by-identity
|
||||
contacts identity)
|
||||
contacts
|
||||
identity)
|
||||
contact (if (string/blank? (:alias contact))
|
||||
(assoc contact :alias
|
||||
(assoc contact
|
||||
:alias
|
||||
(get-in contact [:names :three-words-name]))
|
||||
contact)
|
||||
mentionable-contact (add-searchable-phrases-to-contact
|
||||
contact true)]
|
||||
(if (nil? mentionable-contact) acc
|
||||
(assoc acc identity mentionable-contact))))
|
||||
contact
|
||||
true)]
|
||||
(if (nil? mentionable-contact)
|
||||
acc
|
||||
(assoc acc identity mentionable-contact))))
|
||||
{}
|
||||
(remove #(= my-public-key %) identities)))
|
||||
|
||||
(defn get-mentionable-users [chat all-contacts current-multiaccount community-members]
|
||||
(let [{:keys [name preferred-name public-key]} current-multiaccount
|
||||
(defn get-mentionable-users
|
||||
[chat all-contacts current-multiaccount community-members]
|
||||
(let [{:keys [name preferred-name public-key]} current-multiaccount
|
||||
{:keys [chat-id users contacts chat-type]} chat
|
||||
mentionable-contacts (mentionable-contacts all-contacts)
|
||||
mentionable-users (assoc users public-key {:alias name
|
||||
:name (or preferred-name name)
|
||||
:public-key public-key})]
|
||||
mentionable-contacts (mentionable-contacts all-contacts)
|
||||
mentionable-users (assoc users
|
||||
public-key
|
||||
{:alias name
|
||||
:name (or preferred-name name)
|
||||
:public-key public-key})]
|
||||
(cond
|
||||
(= chat-type constants/private-group-chat-type)
|
||||
(merge mentionable-users
|
||||
(mentionable-contacts-from-identites all-contacts public-key contacts))
|
||||
|
||||
(= chat-type constants/one-to-one-chat-type)
|
||||
(assoc mentionable-users chat-id (get mentionable-contacts chat-id
|
||||
(-> chat-id
|
||||
contact.db/public-key->new-contact
|
||||
contact.db/enrich-contact)))
|
||||
(assoc mentionable-users
|
||||
chat-id
|
||||
(get mentionable-contacts
|
||||
chat-id
|
||||
(-> chat-id
|
||||
contact.db/public-key->new-contact
|
||||
contact.db/enrich-contact)))
|
||||
|
||||
(= chat-type constants/community-chat-type)
|
||||
(mentionable-contacts-from-identites
|
||||
@@ -253,13 +273,14 @@
|
||||
(= chat-type constants/public-chat-type)
|
||||
(merge mentionable-users (select-keys mentionable-contacts (keys mentionable-users)))
|
||||
|
||||
:else mentionable-users)))
|
||||
:else mentionable-users)))
|
||||
|
||||
(def ending-chars "[\\s\\.,;:]")
|
||||
(def ending-chars-regex (re-pattern ending-chars))
|
||||
(def word-regex (re-pattern (str "^[\\w\\d]*" ending-chars "|^[\\S]*$")))
|
||||
|
||||
(defn mentioned? [{:keys [alias name]} text]
|
||||
(defn mentioned?
|
||||
[{:keys [alias name]} text]
|
||||
(let [lcase-name (string/lower-case name)
|
||||
lcase-alias (string/lower-case alias)
|
||||
regex (re-pattern
|
||||
@@ -272,7 +293,8 @@
|
||||
lcase-text (string/lower-case text)]
|
||||
(re-find regex lcase-text)))
|
||||
|
||||
(defn get-user-suggestions [users searched-text]
|
||||
(defn get-user-suggestions
|
||||
[users searched-text]
|
||||
(reduce
|
||||
(fn [acc [k {:keys [alias name nickname searchable-phrases] :as user}]]
|
||||
(if-let [match
|
||||
@@ -301,9 +323,11 @@
|
||||
(string/lower-case name)
|
||||
searched-text)
|
||||
name))]
|
||||
(assoc acc k (assoc user
|
||||
:match match
|
||||
:searched-text searched-text))
|
||||
(assoc acc
|
||||
k
|
||||
(assoc user
|
||||
:match match
|
||||
:searched-text searched-text))
|
||||
acc))
|
||||
{}
|
||||
users))
|
||||
@@ -324,21 +348,25 @@
|
||||
text))
|
||||
user-suggestions (get-user-suggestions users searched-text)
|
||||
user-suggestions-cnt (count user-suggestions)]
|
||||
(cond (zero? user-suggestions-cnt)
|
||||
nil
|
||||
(cond
|
||||
(zero? user-suggestions-cnt)
|
||||
nil
|
||||
|
||||
(and (= 1 user-suggestions-cnt)
|
||||
(mentioned? (second (first user-suggestions))
|
||||
(subs text (inc mention-key-idx))))
|
||||
(second (first user-suggestions))
|
||||
(and (= 1 user-suggestions-cnt)
|
||||
(mentioned? (second (first user-suggestions))
|
||||
(subs text (inc mention-key-idx))))
|
||||
(second (first user-suggestions))
|
||||
|
||||
(> user-suggestions-cnt 1)
|
||||
(let [word-len (count word)
|
||||
text-len (count text)
|
||||
next-word-start (+ next-word-idx word-len)]
|
||||
(when (> text-len next-word-start)
|
||||
(match-mention text users mention-key-idx
|
||||
next-word-start new-words))))))))
|
||||
(> user-suggestions-cnt 1)
|
||||
(let [word-len (count word)
|
||||
text-len (count text)
|
||||
next-word-start (+ next-word-idx word-len)]
|
||||
(when (> text-len next-word-start)
|
||||
(match-mention text
|
||||
users
|
||||
mention-key-idx
|
||||
next-word-start
|
||||
new-words))))))))
|
||||
|
||||
(defn replace-mentions
|
||||
([text users]
|
||||
@@ -360,18 +388,25 @@
|
||||
(let [new-text (string/join
|
||||
[(subs text 0 (inc mention-key-idx))
|
||||
public-key
|
||||
(subs text (+ (inc mention-key-idx)
|
||||
(count match)))])]
|
||||
(recur new-text users (rest idxs)
|
||||
(subs text
|
||||
(+ (inc mention-key-idx)
|
||||
(count match)))])]
|
||||
(recur new-text
|
||||
users
|
||||
(rest idxs)
|
||||
(+ diff (- (count text) (count new-text)))))))))))))
|
||||
|
||||
(defn check-mentions [{:keys [db]} text]
|
||||
(defn check-mentions
|
||||
[{:keys [db]} text]
|
||||
(let [current-chat-id (:current-chat-id db)
|
||||
chat (get-in db [:chats current-chat-id])
|
||||
all-contacts (:contacts/contacts db)
|
||||
current-multiaccount (:multiaccount db)
|
||||
community-members (get-in db [:communities (:community-id chat) :members])
|
||||
mentionable-users (get-mentionable-users chat all-contacts current-multiaccount community-members)]
|
||||
mentionable-users (get-mentionable-users chat
|
||||
all-contacts
|
||||
current-multiaccount
|
||||
community-members)]
|
||||
(replace-mentions text mentionable-users)))
|
||||
|
||||
(defn get-at-sign-idxs
|
||||
@@ -396,7 +431,7 @@
|
||||
{:from idx
|
||||
:checked? false})
|
||||
new-idxs)
|
||||
(let [diff (- new-text-len old-text-len)
|
||||
(let [diff (- new-text-len old-text-len)
|
||||
{:keys [state added?]}
|
||||
(->> at-idxs
|
||||
(keep (fn [{:keys [from to] :as entry}]
|
||||
@@ -406,7 +441,7 @@
|
||||
(>= from old-end)
|
||||
(assoc entry
|
||||
:from (+ from diff)
|
||||
:to (+ to diff))
|
||||
:to (+ to diff))
|
||||
|
||||
;; starts and end before change
|
||||
(and
|
||||
@@ -431,20 +466,22 @@
|
||||
(> from last-new-idx)
|
||||
(not added?))
|
||||
{:state (conj
|
||||
(into state (map (fn [idx]
|
||||
{:from idx
|
||||
:checked? false})
|
||||
new-idxs))
|
||||
(into state
|
||||
(map (fn [idx]
|
||||
{:from idx
|
||||
:checked? false})
|
||||
new-idxs))
|
||||
entry)
|
||||
:added? true}
|
||||
(update acc :state conj entry)))
|
||||
{:state []}))]
|
||||
(if added?
|
||||
state
|
||||
(into state (map (fn [idx]
|
||||
{:from idx
|
||||
:checked? false})
|
||||
new-idxs)))))))
|
||||
(into state
|
||||
(map (fn [idx]
|
||||
{:from idx
|
||||
:checked? false})
|
||||
new-idxs)))))))
|
||||
|
||||
(defn check-entry
|
||||
[text {:keys [from checked?] :as entry} mentionable-users]
|
||||
@@ -453,14 +490,14 @@
|
||||
(let [{user-match :match}
|
||||
(match-mention (str text "@") mentionable-users from)]
|
||||
(if user-match
|
||||
{:from from
|
||||
:to (+ from (count user-match))
|
||||
{:from from
|
||||
:to (+ from (count user-match))
|
||||
:checked? true
|
||||
:mention? true}
|
||||
{:from from
|
||||
:to (count text)
|
||||
{:from from
|
||||
:to (count text)
|
||||
:checked? true
|
||||
:mention false}))))
|
||||
:mention false}))))
|
||||
|
||||
(defn check-idx-for-mentions
|
||||
[text idxs mentionable-users]
|
||||
@@ -489,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)
|
||||
@@ -499,31 +536,34 @@
|
||||
(if platform/android?
|
||||
previous-text
|
||||
(subs previous-text start end))
|
||||
chat-id (:current-chat-id db)
|
||||
previous-state (get-in db [:chats/mentions chat-id :mentions])
|
||||
new-state (-> previous-state
|
||||
(merge args)
|
||||
(assoc :previous-text normalized-previous-text))
|
||||
new-at-idxs (calc-at-idxs new-state)
|
||||
new-state (assoc new-state :at-idxs new-at-idxs)]
|
||||
chat-id (:current-chat-id db)
|
||||
previous-state (get-in db [:chats/mentions chat-id :mentions])
|
||||
new-state (-> previous-state
|
||||
(merge args)
|
||||
(assoc :previous-text normalized-previous-text))
|
||||
new-at-idxs (calc-at-idxs new-state)
|
||||
new-state (assoc new-state :at-idxs new-at-idxs)]
|
||||
(log/debug "[mentions] on-text-input state" new-state)
|
||||
{:db (assoc-in db [:chats/mentions chat-id :mentions] new-state)}))
|
||||
|
||||
(defn calculate-input [text [first-idx :as idxs]]
|
||||
(defn calculate-input
|
||||
[text [first-idx :as idxs]]
|
||||
(if-not first-idx
|
||||
[[:text text]]
|
||||
(let [idx-cnt (count idxs)
|
||||
(let [idx-cnt (count idxs)
|
||||
last-from (get-in idxs [(dec idx-cnt) :from])]
|
||||
(reduce
|
||||
(fn [acc {:keys [from to next-at-idx mention?]}]
|
||||
(cond
|
||||
(and mention? next-at-idx)
|
||||
(into acc [[:mention (subs text from (inc to))]
|
||||
[:text (subs text (inc to) next-at-idx)]])
|
||||
(into acc
|
||||
[[:mention (subs text from (inc to))]
|
||||
[:text (subs text (inc to) next-at-idx)]])
|
||||
|
||||
(and mention? (= last-from from))
|
||||
(into acc [[:mention (subs text from (inc to))]
|
||||
[:text (subs text (inc to))]])
|
||||
(into acc
|
||||
[[:mention (subs text from (inc to))]
|
||||
[:text (subs text (inc to))]])
|
||||
|
||||
:else
|
||||
(conj acc [:text (subs text from (inc to))])))
|
||||
@@ -533,79 +573,82 @@
|
||||
[[: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])
|
||||
state (get-in db [:chats/mentions chat-id :mentions])
|
||||
new-at-idxs (check-idx-for-mentions
|
||||
text
|
||||
(:at-idxs state)
|
||||
mentionable-users)
|
||||
(let [chat-id (:current-chat-id db)
|
||||
text (get-in db [:chat/inputs chat-id :input-text])
|
||||
state (get-in db [:chats/mentions chat-id :mentions])
|
||||
new-at-idxs (check-idx-for-mentions
|
||||
text
|
||||
(:at-idxs state)
|
||||
mentionable-users)
|
||||
calculated-input (calculate-input text new-at-idxs)]
|
||||
(log/debug "[mentions] new-at-idxs" new-at-idxs calculated-input)
|
||||
{:db (-> db
|
||||
(update-in
|
||||
[:chats/mentions chat-id :mentions]
|
||||
assoc
|
||||
:at-idxs new-at-idxs)
|
||||
:at-idxs
|
||||
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)
|
||||
text (get-in db [:chat/inputs chat-id :input-text])
|
||||
(let [chat-id (:current-chat-id db)
|
||||
text (get-in db [:chat/inputs chat-id :input-text])
|
||||
{:keys [new-text at-idxs start end] :as state}
|
||||
(get-in db [:chats/mentions chat-id :mentions])
|
||||
new-text (or new-text text)]
|
||||
new-text (or new-text text)]
|
||||
(log/info "[mentions] calculate suggestions"
|
||||
"state" state)
|
||||
"state"
|
||||
state)
|
||||
(if-not (seq at-idxs)
|
||||
{:db (-> db
|
||||
(assoc-in [:chats/mention-suggestions chat-id] nil)
|
||||
(assoc-in [:chats/mentions chat-id :mentions :at-idxs] nil)
|
||||
(assoc-in [:chat/inputs-with-mentions chat-id] [[:text text]]))}
|
||||
(let [new-at-idxs (check-idx-for-mentions
|
||||
text
|
||||
at-idxs
|
||||
mentionable-users)
|
||||
(let [new-at-idxs (check-idx-for-mentions
|
||||
text
|
||||
at-idxs
|
||||
mentionable-users)
|
||||
calculated-input (calculate-input text new-at-idxs)
|
||||
addition? (<= start end)
|
||||
end (if addition?
|
||||
(+ start (count new-text))
|
||||
start)
|
||||
at-sign-idx (string/last-index-of text at-sign start)
|
||||
searched-text (string/lower-case (subs text (inc at-sign-idx) end))
|
||||
addition? (<= start end)
|
||||
end (if addition?
|
||||
(+ start (count new-text))
|
||||
start)
|
||||
at-sign-idx (string/last-index-of text at-sign start)
|
||||
searched-text (string/lower-case (subs text (inc at-sign-idx) end))
|
||||
mentions
|
||||
(when (and (not (> at-sign-idx start))
|
||||
(not (> (- end at-sign-idx) 100)))
|
||||
(get-user-suggestions mentionable-users searched-text))]
|
||||
(log/debug "[mentions] mention check"
|
||||
"addition" addition?
|
||||
"at-sign-idx" at-sign-idx
|
||||
"start" start
|
||||
"end" end
|
||||
"addition" addition?
|
||||
"at-sign-idx" at-sign-idx
|
||||
"start" start
|
||||
"end" end
|
||||
"searched-text" (pr-str searched-text)
|
||||
"mentions" (count mentions))
|
||||
"mentions" (count mentions))
|
||||
(log/debug "[mentions] new-at-idxs" new-at-idxs calculated-input)
|
||||
{:db (-> db
|
||||
(update-in [:chats/mentions chat-id :mentions]
|
||||
assoc
|
||||
:at-sign-idx at-sign-idx
|
||||
:at-idxs new-at-idxs
|
||||
:at-idxs new-at-idxs
|
||||
:mention-end end)
|
||||
(assoc-in [:chat/inputs-with-mentions chat-id] calculated-input)
|
||||
(assoc-in [:chats/mention-suggestions chat-id] mentions))}))))
|
||||
|
||||
(defn new-input-text-with-mention
|
||||
[{:keys [db]} {:keys [name]}]
|
||||
(let [chat-id (:current-chat-id db)
|
||||
text (get-in db [:chat/inputs chat-id :input-text])
|
||||
(let [chat-id (:current-chat-id db)
|
||||
text (get-in db [:chat/inputs chat-id :input-text])
|
||||
{:keys [mention-end at-sign-idx]}
|
||||
(get-in db [:chats/mentions chat-id :mentions])]
|
||||
(log/debug "[mentions] clear suggestions"
|
||||
"state" new-input-text-with-mention)
|
||||
"state"
|
||||
new-input-text-with-mention)
|
||||
(string/join
|
||||
[(subs text 0 (inc at-sign-idx))
|
||||
name
|
||||
@@ -616,36 +659,36 @@
|
||||
" "))
|
||||
(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}
|
||||
mentionable-users]
|
||||
(let [chat-id (:current-chat-id db)
|
||||
(let [chat-id (:current-chat-id db)
|
||||
{:keys [mention-end at-idxs]}
|
||||
(get-in db [:chats/mentions chat-id :mentions])]
|
||||
(when (seq at-idxs)
|
||||
@@ -655,12 +698,13 @@
|
||||
(<= (dec end) to))
|
||||
idx))
|
||||
at-idxs)
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (update-in db [:chats/mentions chat-id :mentions]
|
||||
{:db (update-in db
|
||||
[:chats/mentions chat-id :mentions]
|
||||
assoc
|
||||
:start end
|
||||
:end end
|
||||
:start end
|
||||
:end end
|
||||
:new-text "")}
|
||||
(calculate-suggestions mentionable-users))
|
||||
(clear-suggestions cofx)))))
|
||||
@@ -673,26 +717,28 @@
|
||||
(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]})
|
||||
|
||||
(defn is-valid-terminating-character? [c]
|
||||
(defn is-valid-terminating-character?
|
||||
[c]
|
||||
(case c
|
||||
"\t" true ; tab
|
||||
"\t" true ; tab
|
||||
"\n" true ; newline
|
||||
"\f" true ; new page
|
||||
"\r" true ; carriage return
|
||||
" " true ; whitespace
|
||||
"," true
|
||||
"." true
|
||||
":" true
|
||||
";" true
|
||||
" " true ; whitespace
|
||||
"," true
|
||||
"." true
|
||||
":" true
|
||||
";" true
|
||||
false))
|
||||
|
||||
(def hex-reg #"[0-9a-f]")
|
||||
|
||||
(defn is-public-key-character? [c]
|
||||
(defn is-public-key-character?
|
||||
[c]
|
||||
(.test hex-reg c))
|
||||
|
||||
(def mention-length 133)
|
||||
@@ -710,7 +756,7 @@
|
||||
current-text
|
||||
current-mention
|
||||
current-mention-length]} character]
|
||||
(let [is-pk-character (is-public-key-character? character)
|
||||
(let [is-pk-character (is-public-key-character? character)
|
||||
is-termination-character (is-valid-terminating-character? character)]
|
||||
(cond
|
||||
;; It's a valid mention.
|
||||
@@ -720,13 +766,13 @@
|
||||
(and (= current-mention-length mention-length)
|
||||
is-termination-character)
|
||||
{:current-mention-length 0
|
||||
:current-mention ""
|
||||
:current-text character
|
||||
:text (cond-> text
|
||||
(seq current-text)
|
||||
(conj [:text current-text])
|
||||
:always
|
||||
(conj [:mention current-mention]))}
|
||||
:current-mention ""
|
||||
:current-text character
|
||||
:text (cond-> text
|
||||
(seq current-text)
|
||||
(conj [:text current-text])
|
||||
:always
|
||||
(conj [:mention current-mention]))}
|
||||
|
||||
|
||||
;; It's either a pk character, or the `x` in the pk
|
||||
@@ -739,9 +785,9 @@
|
||||
(and (= 2 current-mention-length)
|
||||
(= "x" character)))
|
||||
{:current-mention-length (inc current-mention-length)
|
||||
:current-text current-text
|
||||
:current-mention (str current-mention character)
|
||||
:text text}
|
||||
:current-text current-text
|
||||
:current-mention (str current-mention character)
|
||||
:text text}
|
||||
|
||||
|
||||
;; The beginning of a mention, discard the @ sign
|
||||
@@ -750,29 +796,29 @@
|
||||
|
||||
(= "@" character)
|
||||
{:current-mention-length 1
|
||||
:current-mention ""
|
||||
:current-text current-text
|
||||
:text text}
|
||||
:current-mention ""
|
||||
:current-text current-text
|
||||
:text text}
|
||||
|
||||
;; Not a mention character, but we were following a mention
|
||||
;; discard everything up to know an count as text
|
||||
(and (not is-pk-character)
|
||||
(pos? current-mention-length))
|
||||
{:current-mention-length 0
|
||||
:current-text (str current-text "@" current-mention character)
|
||||
:current-mention ""
|
||||
:text text}
|
||||
:current-text (str current-text "@" current-mention character)
|
||||
:current-mention ""
|
||||
:text text}
|
||||
|
||||
;; Just a normal text character
|
||||
:else
|
||||
{:current-mention-length 0
|
||||
:current-mention ""
|
||||
:current-text (str current-text character)
|
||||
:text text})))
|
||||
:current-mention ""
|
||||
:current-text (str current-text character)
|
||||
:text text})))
|
||||
{:current-mention-length 0
|
||||
:current-text ""
|
||||
:current-mention ""
|
||||
:text []}
|
||||
:current-text ""
|
||||
:current-mention ""
|
||||
:text []}
|
||||
text)]
|
||||
;; Process any remaining mention/text
|
||||
(cond-> text
|
||||
@@ -788,32 +834,32 @@
|
||||
[m]
|
||||
(reduce (fn [{:keys [start end at-idxs at-sign-idx mention-end]} [t text]]
|
||||
(if (= :mention t)
|
||||
(let [new-mention {:checked? true
|
||||
:mention? true
|
||||
:from mention-end
|
||||
:to (+ start (count text))}
|
||||
(let [new-mention {:checked? true
|
||||
:mention? true
|
||||
:from mention-end
|
||||
:to (+ start (count text))}
|
||||
has-previous? (seq at-idxs)]
|
||||
{:new-text (last text)
|
||||
{:new-text (last text)
|
||||
:previous-text ""
|
||||
:start (+ start (count text))
|
||||
:end (+ end (count text))
|
||||
:at-idxs (cond-> at-idxs
|
||||
has-previous?
|
||||
(-> pop
|
||||
(conj (assoc (peek at-idxs) :next-at-idx mention-end)))
|
||||
:always
|
||||
(conj new-mention))
|
||||
:at-sign-idx mention-end
|
||||
:mention-end (+ mention-end (count text))})
|
||||
{:new-text (last text)
|
||||
:start (+ start (count text))
|
||||
:end (+ end (count text))
|
||||
:at-idxs (cond-> at-idxs
|
||||
has-previous?
|
||||
(-> pop
|
||||
(conj (assoc (peek at-idxs) :next-at-idx mention-end)))
|
||||
:always
|
||||
(conj new-mention))
|
||||
:at-sign-idx mention-end
|
||||
:mention-end (+ mention-end (count text))})
|
||||
{:new-text (last text)
|
||||
:previous-text ""
|
||||
:start (+ start (count text))
|
||||
:end (+ end (count text))
|
||||
:at-idxs at-idxs
|
||||
:at-sign-idx at-sign-idx
|
||||
:mention-end (+ mention-end (count text))}))
|
||||
{:start -1
|
||||
:end -1
|
||||
:at-idxs []
|
||||
:start (+ start (count text))
|
||||
:end (+ end (count text))
|
||||
:at-idxs at-idxs
|
||||
:at-sign-idx at-sign-idx
|
||||
:mention-end (+ mention-end (count text))}))
|
||||
{:start -1
|
||||
:end -1
|
||||
:at-idxs []
|
||||
:mention-end 0}
|
||||
m))
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
(: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]
|
||||
@@ -11,11 +10,12 @@
|
||||
[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]
|
||||
[status-im.utils.gfycat.core :as gfycat]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.types :as types]
|
||||
[taoensso.timbre :as log]))
|
||||
[status-im2.contexts.chat.messages.message.delete-message.events :as delete-message]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- message-loaded?
|
||||
[db chat-id message-id]
|
||||
@@ -25,7 +25,8 @@
|
||||
[db chat-id clock-value]
|
||||
(>= (get-in db [:chats chat-id :deleted-at-clock-value]) clock-value))
|
||||
|
||||
(defn add-timeline-message [acc chat-id message-id message]
|
||||
(defn add-timeline-message
|
||||
[acc chat-id message-id message]
|
||||
(-> acc
|
||||
(update-in [:db :messages chat-id] assoc message-id message)
|
||||
(update-in [:db :message-lists chat-id] message-list/add message)))
|
||||
@@ -36,14 +37,16 @@
|
||||
;; 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]}]
|
||||
(let [alias (if (string/blank? alias)
|
||||
(gfycat/generate-gfy from)
|
||||
alias)]
|
||||
(update-in acc [:db :chats chat-id :users] assoc
|
||||
(update-in acc
|
||||
[:db :chats chat-id :users]
|
||||
assoc
|
||||
from
|
||||
(mentions/add-searchable-phrases
|
||||
{:alias alias
|
||||
@@ -54,7 +57,8 @@
|
||||
{:db db}
|
||||
messages))
|
||||
|
||||
(defn timeline-message? [db chat-id]
|
||||
(defn timeline-message?
|
||||
[db chat-id]
|
||||
(and
|
||||
(get-in db [:pagination-info constants/timeline-chat-id :messages-initialized?])
|
||||
(or
|
||||
@@ -62,11 +66,13 @@
|
||||
(when-let [pub-key (get-in db [:chats chat-id :profile-public-key])]
|
||||
(get-in db [:contacts/contacts pub-key :added])))))
|
||||
|
||||
(defn get-timeline-message [db chat-id message-js]
|
||||
(defn get-timeline-message
|
||||
[db chat-id message-js]
|
||||
(when (timeline-message? db chat-id)
|
||||
(data-store.messages/<-rpc (types/js->clj message-js))))
|
||||
|
||||
(defn add-message [{:keys [db] :as acc} message-js chat-id message-id cursor-clock-value]
|
||||
(defn add-message
|
||||
[{:keys [db] :as acc} message-js chat-id message-id cursor-clock-value]
|
||||
(let [{:keys [replace from clock-value] :as message}
|
||||
(data-store.messages/<-rpc (types/js->clj message-js))]
|
||||
(if (message-loaded? db chat-id message-id)
|
||||
@@ -82,8 +88,9 @@
|
||||
(update-in [:db :message-lists chat-id] message-list/add message)
|
||||
|
||||
(or (not cursor-clock-value) (< clock-value cursor-clock-value))
|
||||
(update-in [:db :pagination-info chat-id] assoc
|
||||
:cursor (chat.loading/clock-value->cursor clock-value)
|
||||
(update-in [:db :pagination-info chat-id]
|
||||
assoc
|
||||
:cursor (chat.loading/clock-value->cursor clock-value)
|
||||
:cursor-clock-value clock-value)
|
||||
|
||||
;;conj sender for add-sender-to-chat-users
|
||||
@@ -94,11 +101,12 @@
|
||||
;;TODO this is expensive
|
||||
(hide-message chat-id replace)))))
|
||||
|
||||
(defn reduce-js-messages [{:keys [db] :as acc} ^js message-js]
|
||||
(let [chat-id (.-localChatId message-js)
|
||||
clock-value (.-clock message-js)
|
||||
message-id (.-id message-js)
|
||||
current-chat-id (:current-chat-id db)
|
||||
(defn reduce-js-messages
|
||||
[{:keys [db] :as acc} ^js message-js]
|
||||
(let [chat-id (.-localChatId message-js)
|
||||
clock-value (.-clock message-js)
|
||||
message-id (.-id message-js)
|
||||
current-chat-id (:current-chat-id db)
|
||||
cursor-clock-value (get-in db [:pagination-info current-chat-id :cursor-clock-value])]
|
||||
;;ignore not opened chats and earlier clock
|
||||
(if (and (get-in db [:pagination-info chat-id :messages-initialized?])
|
||||
@@ -110,26 +118,30 @@
|
||||
(add-message acc message-js chat-id message-id cursor-clock-value)
|
||||
;; Not in the current view, set all-loaded to false
|
||||
;; and offload to db and update cursor if necessary
|
||||
;;TODO if we'll offload messages , it will conflict with end reached, so probably if we reached the end of visible area,
|
||||
;; we need to drop other messages with (< clock-value cursor-clock-value) from response-js so we don't update
|
||||
;;TODO if we'll offload messages , it will conflict with end reached, so probably if we reached
|
||||
;;the end of visible area,
|
||||
;; we need to drop other messages with (< clock-value cursor-clock-value) from response-js so we
|
||||
;; don't update
|
||||
;; :cursor-clock-value because it will be changed when we loadMore message
|
||||
{:db (cond-> (assoc-in db [:pagination-info chat-id :all-loaded?] false)
|
||||
(> clock-value cursor-clock-value)
|
||||
;;TODO cut older messages from messages-list
|
||||
(update-in [:pagination-info chat-id] assoc
|
||||
:cursor (chat.loading/clock-value->cursor clock-value)
|
||||
(update-in [:pagination-info chat-id]
|
||||
assoc
|
||||
:cursor (chat.loading/clock-value->cursor clock-value)
|
||||
:cursor-clock-value clock-value))})
|
||||
acc)))
|
||||
|
||||
(defn receive-many [{:keys [db]} ^js response-js]
|
||||
(let [messages-js ^js (.splice (.-messages response-js) 0 (if platform/low-device? 3 10))
|
||||
(defn receive-many
|
||||
[{:keys [db]} ^js response-js]
|
||||
(let [messages-js ^js (.splice (.-messages response-js) 0 (if platform/low-device? 3 10))
|
||||
{:keys [db senders]}
|
||||
(reduce reduce-js-messages
|
||||
{:db db :chats #{} :senders {} :transactions #{}}
|
||||
messages-js)]
|
||||
;;we want to render new messages as soon as possible
|
||||
;;so we dispatch later all other events which can be handled async
|
||||
{:db db
|
||||
{:db db
|
||||
:utils/dispatch-later
|
||||
(concat [{:ms 20 :dispatch [:process-response response-js]}]
|
||||
(when (and (:current-chat-id db) (= "active" (:app-state db)))
|
||||
@@ -137,7 +149,8 @@
|
||||
(when (seq senders)
|
||||
[{:ms 100 :dispatch [:chat/add-senders-to-chat-users (vals senders)]}]))}))
|
||||
|
||||
(defn reduce-js-statuses [db ^js message-js]
|
||||
(defn reduce-js-statuses
|
||||
[db ^js message-js]
|
||||
(let [chat-id (.-localChatId message-js)
|
||||
profile-initialized (get-in db [:pagination-info chat-id :messages-initialized?])
|
||||
timeline-message (timeline-message? db chat-id)
|
||||
@@ -155,60 +168,66 @@
|
||||
(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)})))
|
||||
[: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]
|
||||
(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" %)}]}
|
||||
: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
|
||||
(map #(assoc % :message-id (:messageId %)))
|
||||
(group-by :chatId)
|
||||
(mapv (fn [[chat-id messages]] (delete-message/delete-messages-localy messages chat-id))))
|
||||
mark-as-seen-fx (mapv (fn [removed-message]
|
||||
(let [chat-id (:chatId removed-message)
|
||||
message-id (:messageId removed-message)]
|
||||
(data-store.messages/mark-messages-seen chat-id
|
||||
[message-id]
|
||||
#(re-frame/dispatch [:chat/decrease-unviewed-count chat-id %3]))))
|
||||
removed-messages)
|
||||
(mapv (fn [[chat-id messages]]
|
||||
(delete-message/delete-messages-localy messages chat-id))))
|
||||
mark-as-seen-fx (mapv
|
||||
(fn [removed-message]
|
||||
(let [chat-id (:chatId removed-message)
|
||||
message-id (:messageId removed-message)]
|
||||
(data-store.messages/mark-messages-seen chat-id
|
||||
[message-id]
|
||||
#(re-frame/dispatch
|
||||
[:chat/decrease-unviewed-count
|
||||
chat-id %3]))))
|
||||
removed-messages)
|
||||
remove-messages-fx (fn [{:keys [db]}]
|
||||
{:dispatch [:activity-center.notifications/fetch-unread-count]})]
|
||||
(apply fx/merge cofx (-> mark-as-deleted-fx
|
||||
(concat mark-as-seen-fx)
|
||||
(conj remove-messages-fx)))))
|
||||
(apply rf/merge
|
||||
cofx
|
||||
(-> mark-as-deleted-fx
|
||||
(concat mark-as-seen-fx)
|
||||
(conj remove-messages-fx)))))
|
||||
|
||||
(comment
|
||||
(handle-removed-messages
|
||||
@@ -218,15 +237,20 @@
|
||||
:m4 {:chat-id :c2 :message-id :m4}}}}}
|
||||
[:m1 :m3]))
|
||||
|
||||
(defn remove-cleared-message [messages cleared-at]
|
||||
(into {} (remove #(let [message-clock (:clock-value (second %))]
|
||||
(<= message-clock cleared-at))
|
||||
messages)))
|
||||
(defn remove-cleared-message
|
||||
[messages cleared-at]
|
||||
(into {}
|
||||
(remove #(let [message-clock (:clock-value (second %))]
|
||||
(<= 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]
|
||||
(update-in acc [:messages (:chatId current)] remove-cleared-message (:clearedAt current)))
|
||||
(update-in acc
|
||||
[:messages (:chatId current)]
|
||||
remove-cleared-message
|
||||
(:clearedAt current)))
|
||||
db
|
||||
cleared-histories)})
|
||||
|
||||
@@ -2,22 +2,25 @@
|
||||
(: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}]
|
||||
(defn- add-datemark
|
||||
[{:keys [whisper-timestamp] :as msg}]
|
||||
;;TODO this is slow
|
||||
(assoc msg :datemark (time/day-relative whisper-timestamp)))
|
||||
|
||||
(defn- add-timestamp [{:keys [whisper-timestamp] :as msg}]
|
||||
(defn- add-timestamp
|
||||
[{:keys [whisper-timestamp] :as msg}]
|
||||
(assoc msg :timestamp-str (time/timestamp->time whisper-timestamp)))
|
||||
|
||||
(defn prepare-message [{:keys [message-id
|
||||
clock-value
|
||||
message-type
|
||||
from
|
||||
outgoing
|
||||
whisper-timestamp
|
||||
deleted-for-me?]}]
|
||||
(defn prepare-message
|
||||
[{:keys [message-id
|
||||
clock-value
|
||||
message-type
|
||||
from
|
||||
outgoing
|
||||
whisper-timestamp
|
||||
deleted-for-me?]}]
|
||||
(-> {:whisper-timestamp whisper-timestamp
|
||||
:from from
|
||||
:one-to-one? (= constants/message-type-one-to-one message-type)
|
||||
@@ -69,7 +72,8 @@
|
||||
the most recent message, similarly :first-in-group? is the most recent message
|
||||
in a group."
|
||||
[{:keys [system-message?
|
||||
one-to-one? outgoing] :as current-message}
|
||||
one-to-one? outgoing]
|
||||
:as current-message}
|
||||
{:keys [outgoing-seen?] :as previous-message}
|
||||
next-message]
|
||||
(let [last-in-group? (or (nil? next-message)
|
||||
@@ -87,7 +91,7 @@
|
||||
(not system-message?)
|
||||
(not outgoing)
|
||||
(not one-to-one?))
|
||||
:display-photo? (display-photo? current-message))))
|
||||
:display-photo? (display-photo? current-message))))
|
||||
|
||||
(defn update-next-message
|
||||
"Update next message in the list, we set :first? to false, and check if it
|
||||
@@ -95,26 +99,28 @@
|
||||
[current-message next-message]
|
||||
(assoc
|
||||
next-message
|
||||
:first? false
|
||||
:first? false
|
||||
:first-outgoing? (and
|
||||
(not (:first-outgoing? current-message))
|
||||
(:first-outgoing? next-message))
|
||||
:outgoing-seen? (:outgoing-seen? current-message)
|
||||
:outgoing-seen? (:outgoing-seen? current-message)
|
||||
:first-in-group?
|
||||
(not (same-group? current-message next-message))))
|
||||
|
||||
(defn update-previous-message
|
||||
"If this is a new group, we mark the previous as the last one in the group"
|
||||
[current-message {:keys [one-to-one?
|
||||
system-message?
|
||||
outgoing] :as previous-message}]
|
||||
[current-message
|
||||
{:keys [one-to-one?
|
||||
system-message?
|
||||
outgoing]
|
||||
:as previous-message}]
|
||||
(let [last-in-group? (not (same-group? current-message previous-message))]
|
||||
(assoc previous-message
|
||||
:display-username? (and last-in-group?
|
||||
(not system-message?)
|
||||
(not outgoing)
|
||||
(not one-to-one?))
|
||||
:last-in-group? last-in-group?)))
|
||||
:last-in-group? last-in-group?)))
|
||||
|
||||
(defn get-prev-element
|
||||
"Get previous item in the iterator, and wind it back to the initial state"
|
||||
@@ -135,11 +141,11 @@
|
||||
(defn update-message
|
||||
"Update the message and siblings with positional info"
|
||||
[^js tree message]
|
||||
(let [^js iter (.find tree message)
|
||||
^js previous-message (when (.-hasPrev iter)
|
||||
(get-prev-element iter))
|
||||
^js next-message (when (.-hasNext iter)
|
||||
(get-next-element iter))
|
||||
(let [^js iter (.find tree message)
|
||||
^js previous-message (when (.-hasPrev iter)
|
||||
(get-prev-element iter))
|
||||
^js next-message (when (.-hasNext iter)
|
||||
(get-next-element iter))
|
||||
^js message-with-pos-data (add-group-info message previous-message next-message)]
|
||||
(cond-> (.update iter message-with-pos-data)
|
||||
next-message
|
||||
@@ -157,9 +163,9 @@
|
||||
(let [iter (.find tree prepared-message)]
|
||||
(if (not iter)
|
||||
tree
|
||||
(let [^js new-tree (.remove iter)
|
||||
^js next-message (when (.-hasNext iter)
|
||||
(get-next-element iter))]
|
||||
(let [^js new-tree (.remove iter)
|
||||
^js next-message (when (.-hasNext iter)
|
||||
(get-next-element iter))]
|
||||
(if (not next-message)
|
||||
new-tree
|
||||
(update-message new-tree next-message))))))
|
||||
@@ -173,21 +179,26 @@
|
||||
(let [^js tree (.insert old-message-list prepared-message prepared-message)]
|
||||
(update-message tree prepared-message)))
|
||||
|
||||
(defn add [message-list message]
|
||||
(defn add
|
||||
[message-list message]
|
||||
(insert-message (or message-list (rb-tree compare-fn)) (prepare-message message)))
|
||||
|
||||
(defn add-many [message-list messages]
|
||||
(defn add-many
|
||||
[message-list messages]
|
||||
(reduce add
|
||||
message-list
|
||||
messages))
|
||||
|
||||
(defn ->seq [^js message-list]
|
||||
(defn ->seq
|
||||
[^js message-list]
|
||||
(if message-list
|
||||
(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]
|
||||
(add-many nil (vals (get-in db [:messages chat-id]))))})
|
||||
{:db (assoc-in db
|
||||
[:message-lists chat-id]
|
||||
(add-many nil (vals (get-in db [:messages chat-id]))))})
|
||||
|
||||
@@ -1,28 +1,36 @@
|
||||
(ns status-im.chat.models.reactions
|
||||
(:require [status-im.constants :as constants]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.utils.fx :as fx]
|
||||
[taoensso.timbre :as log]
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.data-store.reactions :as data-store.reactions]
|
||||
[status-im.transport.message.protocol :as message.protocol]
|
||||
[status-im.data-store.reactions :as data-store.reactions]))
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn update-reaction [acc retracted chat-id message-id emoji-id emoji-reaction-id reaction]
|
||||
(defn update-reaction
|
||||
[acc retracted chat-id message-id emoji-id emoji-reaction-id reaction]
|
||||
;; NOTE(Ferossgp): For a better performance, better to not keep in db all retracted reactions
|
||||
;; retraction will always come after the reaction so there shouldn't be a conflict
|
||||
(if retracted
|
||||
(update-in acc [chat-id message-id emoji-id] dissoc emoji-reaction-id)
|
||||
(assoc-in acc [chat-id message-id emoji-id emoji-reaction-id] reaction)))
|
||||
|
||||
(defn process-reactions [chats]
|
||||
(defn process-reactions
|
||||
[chats]
|
||||
(fn [reactions new-reactions]
|
||||
;; TODO(Ferossgp): handling own reaction in subscription could be expensive,
|
||||
;; for better performance we can here separate own reaction into 2 maps
|
||||
(reduce
|
||||
(fn [acc {:keys [chat-id message-id emoji-id emoji-reaction-id retracted]
|
||||
:as reaction}]
|
||||
(fn [acc
|
||||
{:keys [chat-id message-id emoji-id emoji-reaction-id retracted]
|
||||
:as reaction}]
|
||||
(cond-> (update-reaction acc retracted chat-id message-id emoji-id emoji-reaction-id reaction)
|
||||
(get-in chats [chat-id :profile-public-key])
|
||||
(update-reaction retracted constants/timeline-chat-id message-id emoji-id emoji-reaction-id reaction)))
|
||||
(update-reaction retracted
|
||||
constants/timeline-chat-id
|
||||
message-id
|
||||
emoji-id
|
||||
emoji-reaction-id
|
||||
reaction)))
|
||||
reactions
|
||||
new-reactions)))
|
||||
|
||||
@@ -32,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?])]
|
||||
@@ -48,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
|
||||
@@ -64,33 +72,36 @@
|
||||
;; Send reactions
|
||||
|
||||
|
||||
(fx/defn send-emoji-reaction
|
||||
(rf/defn send-emoji-reaction
|
||||
{:events [::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
|
||||
(rf/defn send-retract-emoji-reaction
|
||||
{:events [::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])})
|
||||
|
||||
(defn message-reactions [current-public-key reactions]
|
||||
(defn message-reactions
|
||||
[current-public-key reactions]
|
||||
(reduce
|
||||
(fn [acc [emoji-id reactions]]
|
||||
(if (pos? (count reactions))
|
||||
(let [own (first (filter (fn [[_ {:keys [from]}]]
|
||||
(= from current-public-key)) reactions))]
|
||||
(conj acc {:emoji-id emoji-id
|
||||
:own (boolean (seq own))
|
||||
:emoji-reaction-id (:emoji-reaction-id (second own))
|
||||
:quantity (count reactions)}))
|
||||
(= from current-public-key))
|
||||
reactions))]
|
||||
(conj acc
|
||||
{:emoji-id emoji-id
|
||||
:own (boolean (seq own))
|
||||
:emoji-reaction-id (:emoji-reaction-id (second own))
|
||||
:quantity (count reactions)}))
|
||||
acc))
|
||||
[]
|
||||
reactions))
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
;;this ns is needed because of cycled deps
|
||||
(ns status-im.chat.models.transport
|
||||
(:require [status-im.utils.fx :as fx]
|
||||
(:require [status-im.chat.models.message :as chat.message]
|
||||
[status-im.transport.message.core :as transport.message]
|
||||
[status-im.chat.models.message :as chat.message]))
|
||||
[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,7 +1,8 @@
|
||||
(ns status-im.chat.models-test
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.utils.clocks :as utils.clocks]
|
||||
[status-im.chat.models :as chat]))
|
||||
[status-im.chat.models :as chat]
|
||||
[status-im.chat.models.images :as images]))
|
||||
|
||||
(deftest clear-history-test
|
||||
(let [chat-id "1"
|
||||
@@ -91,3 +92,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)))))
|
||||
|
||||
@@ -2,44 +2,44 @@
|
||||
(: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
|
||||
:commands/select-account
|
||||
{:message message
|
||||
:from (ethereum/get-default-account (:multiaccount/accounts db))})
|
||||
{:db (assoc db
|
||||
:commands/select-account
|
||||
{:message message
|
||||
: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]
|
||||
{: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 %])}]})
|
||||
: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]
|
||||
{::json-rpc/call [{:method "wakuext_declineRequestAddressForTransaction"
|
||||
:params [message-id]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:transport/message-sent %])}]})
|
||||
: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]
|
||||
{::json-rpc/call [{:method "wakuext_declineRequestTransaction"
|
||||
:params [message-id]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:transport/message-sent %])}]})
|
||||
:on-success #(re-frame/dispatch [:transport/message-sent %])}]})
|
||||
|
||||
+201
-155
@@ -1,25 +1,24 @@
|
||||
(ns status-im.communities.core
|
||||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
[clojure.walk :as walk]
|
||||
[clojure.string :as string]
|
||||
[clojure.set :as clojure.set]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.async-storage.core :as async-storage]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.utils.universal-links.core :as universal-links]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[quo.design-system.colors :as colors]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.utils.handlers :refer [>evt]]
|
||||
[status-im.ui.components.emoji-thumbnail.styles :as emoji-thumbnail-styles]
|
||||
[status-im.activity-center.core :as activity-center]))
|
||||
(:require [clojure.set :as clojure.set]
|
||||
[clojure.string :as string]
|
||||
[clojure.walk :as walk]
|
||||
[quo.design-system.colors :as colors]
|
||||
[re-frame.core :as re-frame]
|
||||
[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.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]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def crop-size 1000)
|
||||
|
||||
(defn universal-link [community-id]
|
||||
(defn universal-link
|
||||
[community-id]
|
||||
(str (:external universal-links/domains)
|
||||
"/c/"
|
||||
community-id))
|
||||
@@ -28,18 +27,22 @@
|
||||
[{:name "Status"
|
||||
:id constants/status-community-id}])
|
||||
|
||||
(defn <-request-to-join-community-rpc [r]
|
||||
(clojure.set/rename-keys r {:communityId :community-id
|
||||
:publicKey :public-key
|
||||
:chatId :chat-id}))
|
||||
(defn <-request-to-join-community-rpc
|
||||
[r]
|
||||
(clojure.set/rename-keys r
|
||||
{:communityId :community-id
|
||||
:publicKey :public-key
|
||||
:chatId :chat-id}))
|
||||
|
||||
(defn <-requests-to-join-community-rpc [requests]
|
||||
(defn <-requests-to-join-community-rpc
|
||||
[requests]
|
||||
(reduce (fn [acc r]
|
||||
(assoc acc (:id r) (<-request-to-join-community-rpc r)))
|
||||
{}
|
||||
requests))
|
||||
|
||||
(defn <-chats-rpc [chats]
|
||||
(defn <-chats-rpc
|
||||
[chats]
|
||||
(reduce-kv (fn [acc k v]
|
||||
(assoc acc
|
||||
(name k)
|
||||
@@ -50,7 +53,8 @@
|
||||
{}
|
||||
chats))
|
||||
|
||||
(defn <-categories-rpc [categ]
|
||||
(defn <-categories-rpc
|
||||
[categ]
|
||||
(reduce-kv (fn [acc k v]
|
||||
(assoc acc
|
||||
(name k)
|
||||
@@ -58,7 +62,8 @@
|
||||
{}
|
||||
categ))
|
||||
|
||||
(defn <-rpc [c]
|
||||
(defn <-rpc
|
||||
[c]
|
||||
(-> c
|
||||
(clojure.set/rename-keys {:canRequestAccess :can-request-access?
|
||||
:canManageUsers :can-manage-users?
|
||||
@@ -70,25 +75,28 @@
|
||||
(update :chats <-chats-rpc)
|
||||
(update :categories <-categories-rpc)))
|
||||
|
||||
(defn fetch-community-id-input [{:keys [db]}]
|
||||
(defn fetch-community-id-input
|
||||
[{:keys [db]}]
|
||||
(:communities/community-id-input db))
|
||||
|
||||
(fx/defn handle-request-to-join [{:keys [db]} r]
|
||||
(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 [{:keys [db]} chat-ids]
|
||||
(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}]
|
||||
@@ -96,34 +104,36 @@
|
||||
db
|
||||
communities)})
|
||||
|
||||
(fx/defn handle-response [_ response-js]
|
||||
(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-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"
|
||||
@@ -134,7 +144,7 @@
|
||||
(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"
|
||||
@@ -145,7 +155,7 @@
|
||||
(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"
|
||||
@@ -156,7 +166,7 @@
|
||||
(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 %)
|
||||
@@ -168,10 +178,13 @@
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::left %])
|
||||
:on-error #(do
|
||||
(log/error "failed to leave community" community-id %)
|
||||
(log/error "failed to leave community"
|
||||
community-id
|
||||
%)
|
||||
(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 %])
|
||||
@@ -179,7 +192,7 @@
|
||||
(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"
|
||||
@@ -193,7 +206,7 @@
|
||||
: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)
|
||||
@@ -209,7 +222,7 @@
|
||||
:on-error #(do
|
||||
(log/error "failed to invite-user community" %)
|
||||
(re-frame/dispatch [::failed-to-invite-people %]))}]})))
|
||||
(fx/defn share-community
|
||||
(rf/defn share-community
|
||||
{:events [::share-community-confirmation-pressed]}
|
||||
[cofx user-pk contacts]
|
||||
(let [community-id (fetch-community-id-input cofx)
|
||||
@@ -226,7 +239,7 @@
|
||||
(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)]
|
||||
@@ -248,7 +261,7 @@
|
||||
(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)]
|
||||
@@ -268,10 +281,10 @@
|
||||
(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)
|
||||
(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
|
||||
@@ -279,7 +292,8 @@
|
||||
:description description
|
||||
:color color
|
||||
:emoji emoji}
|
||||
:permissions {:access constants/community-channel-access-no-membership}}]
|
||||
:permissions {:access
|
||||
constants/community-channel-access-no-membership}}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::community-channel-created %])
|
||||
:on-error #(do
|
||||
@@ -288,10 +302,11 @@
|
||||
|
||||
(def community-chat-id-length 68)
|
||||
|
||||
(defn to-community-chat-id [chat-id]
|
||||
(defn to-community-chat-id
|
||||
[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]}
|
||||
@@ -305,161 +320,171 @@
|
||||
:emoji emoji}
|
||||
:category_id category-id
|
||||
:position position
|
||||
:permissions {:access constants/community-channel-access-no-membership}}]
|
||||
: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]
|
||||
(defn require-membership?
|
||||
[permissions]
|
||||
(not= constants/community-no-membership-access (:access permissions)))
|
||||
|
||||
(defn can-post? [community _ local-chat-id]
|
||||
(defn can-post?
|
||||
[community _ local-chat-id]
|
||||
(let [chat-id (to-community-chat-id local-chat-id)]
|
||||
(get-in community [:chats chat-id :can-post?])))
|
||||
|
||||
(fx/defn reset-community-id-input [{:keys [db]} id]
|
||||
(rf/defn reset-community-id-input
|
||||
[{:keys [db]} id]
|
||||
{:db (assoc db :communities/community-id-input id)})
|
||||
|
||||
(fx/defn reset-channel-info [{:keys [db]}]
|
||||
(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
|
||||
{:db (assoc db :communities/create-channel {:name chat-name
|
||||
:description description
|
||||
:color color
|
||||
:community-id community-id
|
||||
:emoji emoji
|
||||
:edit-channel-id chat-id
|
||||
:category-id category-id
|
||||
:position position})}
|
||||
(rf/merge cofx
|
||||
{:db (assoc db
|
||||
:communities/create-channel
|
||||
{:name chat-name
|
||||
:description description
|
||||
:color color
|
||||
:community-id community-id
|
||||
:emoji emoji
|
||||
:edit-channel-id chat-id
|
||||
:category-id category-id
|
||||
:position position})}
|
||||
(navigation/open-modal :edit-community-channel nil))))
|
||||
|
||||
(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
|
||||
{:db (assoc db :communities/create {:id id
|
||||
:name name
|
||||
:description description
|
||||
:image (get-in images [:large :uri])
|
||||
:membership access
|
||||
:color color
|
||||
:editing? true})}
|
||||
{:keys [access]} permissions]
|
||||
(rf/merge cofx
|
||||
{:db (assoc db
|
||||
:communities/create
|
||||
{:id id
|
||||
:name name
|
||||
:description description
|
||||
:image (get-in images [:large :uri])
|
||||
:membership access
|
||||
:color color
|
||||
: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"
|
||||
@@ -467,35 +492,43 @@
|
||||
: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 %)}]})
|
||||
: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 %)}]})
|
||||
: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))})
|
||||
{: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"
|
||||
@@ -503,48 +536,56 @@
|
||||
: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]
|
||||
(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 %)}]})
|
||||
: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)}]})
|
||||
: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"
|
||||
@@ -557,12 +598,13 @@
|
||||
(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]))))]
|
||||
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
|
||||
@@ -572,7 +614,7 @@
|
||||
: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"
|
||||
@@ -581,7 +623,7 @@
|
||||
: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"
|
||||
@@ -591,7 +633,7 @@
|
||||
: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))
|
||||
@@ -605,11 +647,11 @@
|
||||
(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
|
||||
(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"
|
||||
@@ -621,7 +663,7 @@
|
||||
: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"
|
||||
@@ -632,17 +674,18 @@
|
||||
: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]
|
||||
(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])
|
||||
@@ -652,10 +695,11 @@
|
||||
state (get states hash)
|
||||
category-updated (assoc category :state state)]
|
||||
(assoc acc category-id category-updated)))
|
||||
{} categories-old)]
|
||||
{}
|
||||
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])
|
||||
@@ -669,26 +713,27 @@
|
||||
(-> acc
|
||||
(assoc-in [:hashes category-id] hash)
|
||||
(update :keys #(conj % hash)))))
|
||||
{} categories)]
|
||||
{}
|
||||
categories)]
|
||||
{::async-storage/get {:keys keys
|
||||
: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"
|
||||
@@ -702,7 +747,7 @@
|
||||
: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"
|
||||
@@ -710,8 +755,9 @@
|
||||
: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})]})
|
||||
:on-error
|
||||
#(log/error "failed to remove role from member"
|
||||
{:error %
|
||||
:community-id community-id
|
||||
:public-key public-key
|
||||
:role-id role-id})]})
|
||||
|
||||
@@ -200,3 +200,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")
|
||||
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
[status-im.contact.db :as contact.db]
|
||||
[status-im.data-store.chats :as chats-store]
|
||||
[status-im.data-store.contacts :as contacts-store]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.activity-center.core :as activity-center]
|
||||
[status-im.utils.fx :as fx]))
|
||||
[status-im2.contexts.activity-center.events :as activity-center]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn clean-up-chat
|
||||
(rf/defn clean-up-chat
|
||||
[{:keys [db] :as cofx}
|
||||
public-key
|
||||
{:keys [chat-id
|
||||
@@ -21,60 +21,63 @@
|
||||
(when (= from public-key)
|
||||
message-id))
|
||||
(get-in db [:messages chat-id]))
|
||||
db (-> db
|
||||
;; remove messages
|
||||
(update-in [:messages chat-id]
|
||||
#(apply dissoc % removed-messages-ids))
|
||||
(update-in [:chats chat-id]
|
||||
assoc
|
||||
:unviewed-messages-count unviewed-messages-count
|
||||
:unviewed-mentions-count unviewed-mentions-count
|
||||
:last-message last-message))]
|
||||
{:db (assoc-in db [:message-lists chat-id]
|
||||
(message-list/add-many nil (vals (get-in db [:messages chat-id]))))}))
|
||||
db (-> db
|
||||
;; remove messages
|
||||
(update-in [:messages chat-id]
|
||||
#(apply dissoc % removed-messages-ids))
|
||||
(update-in [:chats chat-id]
|
||||
assoc
|
||||
:unviewed-messages-count unviewed-messages-count
|
||||
:unviewed-mentions-count unviewed-mentions-count
|
||||
:last-message last-message))]
|
||||
{:db (assoc-in db
|
||||
[: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
|
||||
(clean-up-chat public-key))
|
||||
(types/js->clj chats)))]
|
||||
(apply rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(update :chats dissoc public-key)
|
||||
(update :chats-home-list disj public-key)
|
||||
(assoc-in [:contacts/contacts public-key :added] false))
|
||||
{:db (-> db
|
||||
(update :chats dissoc public-key)
|
||||
(update :chats-home-list disj public-key)
|
||||
(assoc-in [:contacts/contacts public-key :added] false))
|
||||
:clear-message-notifications
|
||||
[[public-key] (get-in db [:multiaccount :remote-push-notifications-enabled?])]}
|
||||
(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
|
||||
(:contacts/contacts db)
|
||||
public-key)
|
||||
(assoc :blocked true
|
||||
:added false))
|
||||
(let [contact (-> (contact.db/public-key->contact
|
||||
(:contacts/contacts db)
|
||||
public-key)
|
||||
(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)
|
||||
;; update the contact in contacts list
|
||||
(assoc-in [:contacts/contacts public-key] contact))}
|
||||
(contacts-store/block
|
||||
public-key #(do (re-frame/dispatch [::contact-blocked contact (.-chats %)])
|
||||
(re-frame/dispatch [:sanitize-messages-and-process-response %])
|
||||
(re-frame/dispatch [:hide-popover])))
|
||||
public-key
|
||||
#(do (re-frame/dispatch [::contact-blocked contact (.-chats %)])
|
||||
(re-frame/dispatch [:sanitize-messages-and-process-response %])
|
||||
(re-frame/dispatch [:hide-popover])))
|
||||
;; reset navigation to avoid going back to non existing one to one chat
|
||||
(if from-one-to-one-chat?
|
||||
(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])
|
||||
@@ -83,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
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
(ns status-im.contact.chat
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.chat.models :as chat]
|
||||
[status-im.contact.core :as contact]))
|
||||
[status-im.contact.core :as contact]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(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
|
||||
{:events [:contact.ui/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))
|
||||
|
||||
@@ -1,42 +1,44 @@
|
||||
(ns status-im.contact.core
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[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-im2.navigation.events :as navigation]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contact.block :as contact.block]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn load-contacts
|
||||
(rf/defn load-contacts
|
||||
{:events [::contacts-loaded]}
|
||||
[{:keys [db] :as cofx} all-contacts]
|
||||
(let [contacts-list (map #(vector (:public-key %) (if (empty? (:address %))
|
||||
(dissoc % :address)
|
||||
%))
|
||||
(let [contacts-list (map #(vector (:public-key %)
|
||||
(if (empty? (:address %))
|
||||
(dissoc % :address)
|
||||
%))
|
||||
all-contacts)
|
||||
contacts (into {} contacts-list)]
|
||||
contacts (into {} contacts-list)]
|
||||
{:db (cond-> (-> db
|
||||
(update :contacts/contacts #(merge contacts %))
|
||||
(assoc :contacts/blocked (contact.db/get-blocked-contacts all-contacts))))}))
|
||||
|
||||
(defn build-contact
|
||||
[{{:keys [multiaccount]
|
||||
:contacts/keys [contacts]} :db} public-key]
|
||||
[{{:keys [multiaccount]
|
||||
:contacts/keys [contacts]}
|
||||
:db} public-key]
|
||||
(cond-> (contact.db/public-key->contact contacts public-key)
|
||||
(= public-key (:public-key multiaccount))
|
||||
(assoc :name (:name multiaccount))))
|
||||
|
||||
(fx/defn ensure-contacts
|
||||
(rf/defn ensure-contacts
|
||||
[{:keys [db]} contacts chats]
|
||||
(let [events
|
||||
(reduce
|
||||
(fn [acc {:keys [public-key] :as contact}]
|
||||
(let [added (:added contact)
|
||||
was-added (contact.db/added? db public-key)
|
||||
blocked (:blocked contact)
|
||||
(let [added (:added contact)
|
||||
was-added (contact.db/added? db public-key)
|
||||
blocked (:blocked contact)
|
||||
was-blocked (contact.db/blocked? db public-key)]
|
||||
(cond-> acc
|
||||
(and added (not was-added))
|
||||
@@ -51,7 +53,8 @@
|
||||
[:activity-center.notifications/fetch-unread-count]]
|
||||
contacts)]
|
||||
(merge
|
||||
{:db (update db :contacts/contacts
|
||||
{:db (update db
|
||||
:contacts/contacts
|
||||
#(reduce (fn [acc {:keys [public-key] :as contact}]
|
||||
(-> acc
|
||||
(update public-key merge contact)
|
||||
@@ -68,15 +71,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]
|
||||
{::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]
|
||||
@@ -90,60 +93,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]
|
||||
{: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}]
|
||||
{:method "wakuext_retractContactRequest"
|
||||
:params [{:contactId public-key}]
|
||||
:on-success #(log/debug "contact removed successfully")}]
|
||||
:dispatch [:offload-messages constants/timeline-chat-id]})
|
||||
: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}]
|
||||
{::json-rpc/call [{:method "wakuext_acceptContactRequest"
|
||||
:params [{:id id}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]})
|
||||
: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}]
|
||||
{::json-rpc/call [{:method "wakuext_dismissContactRequest"
|
||||
:params [{:id id}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]})
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]})
|
||||
|
||||
(fx/defn initialize-contacts [cofx]
|
||||
(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 "")}
|
||||
: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
|
||||
@@ -152,7 +157,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,18 @@
|
||||
(ns status-im.currency.core
|
||||
(:require [status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.wallet.prices :as prices]))
|
||||
[status-im.wallet.prices :as prices]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn get-currency [db]
|
||||
(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
|
||||
:currency
|
||||
currency
|
||||
{})
|
||||
(prices/update-prices)))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(ns status-im.data-store.activities
|
||||
(:require [clojure.set :as set]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.activity-center.notification-types :as notification-types]
|
||||
[status-im2.contexts.activity-center.notification-types :as notification-types]
|
||||
[status-im.data-store.messages :as messages]))
|
||||
|
||||
(defn- rpc->type [{:keys [type name] :as chat}]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(ns status-im.data-store.activities-test
|
||||
(:require [cljs.test :refer [deftest is testing]]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.activity-center.notification-types :as notification-types]
|
||||
[status-im2.contexts.activity-center.notification-types :as notification-types]
|
||||
[status-im.data-store.activities :as store]))
|
||||
|
||||
(def chat-id
|
||||
|
||||
@@ -1,31 +1,34 @@
|
||||
(ns status-im.data-store.chats
|
||||
(: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.constants :as constants]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.types :as types]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.utils.types :as types]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn rpc->type [{:keys [chat-type name] :as chat}]
|
||||
(defn rpc->type
|
||||
[{:keys [chat-type name] :as chat}]
|
||||
(cond
|
||||
(or (= constants/public-chat-type chat-type)
|
||||
(= constants/profile-chat-type chat-type)
|
||||
(= constants/timeline-chat-type chat-type)) (assoc chat
|
||||
:chat-name (str "#" name)
|
||||
:public? true
|
||||
:group-chat true
|
||||
:timeline? (= constants/timeline-chat-type chat-type))
|
||||
(= constants/timeline-chat-type chat-type))
|
||||
(assoc chat
|
||||
:chat-name (str "#" name)
|
||||
:public? true
|
||||
:group-chat true
|
||||
:timeline? (= constants/timeline-chat-type chat-type))
|
||||
(= constants/community-chat-type chat-type) (assoc chat
|
||||
:chat-name name
|
||||
:chat-name name
|
||||
:group-chat true)
|
||||
(= constants/private-group-chat-type chat-type) (assoc chat
|
||||
:chat-name name
|
||||
:public? false
|
||||
:chat-name name
|
||||
:public? false
|
||||
:group-chat true)
|
||||
:else (assoc chat :public? false :group-chat false)))
|
||||
|
||||
(defn members-reducer [acc member]
|
||||
(defn members-reducer
|
||||
[acc member]
|
||||
(cond-> acc
|
||||
(:admin member)
|
||||
(update :admins conj (:id member))
|
||||
@@ -34,45 +37,48 @@
|
||||
:always
|
||||
(update :contacts conj (:id member))))
|
||||
|
||||
(defn- unmarshal-members [{:keys [members chat-type] :as chat}]
|
||||
(defn- unmarshal-members
|
||||
[{:keys [members chat-type] :as chat}]
|
||||
(cond
|
||||
(= constants/public-chat-type chat-type) (assoc chat
|
||||
:contacts #{}
|
||||
:admins #{}
|
||||
:members-joined #{})
|
||||
(= constants/public-chat-type chat-type) (assoc chat
|
||||
:contacts #{}
|
||||
:admins #{}
|
||||
:members-joined #{})
|
||||
(= constants/private-group-chat-type chat-type) (merge chat
|
||||
(reduce members-reducer
|
||||
{:admins #{}
|
||||
{:admins #{}
|
||||
:members-joined #{}
|
||||
:contacts #{}}
|
||||
:contacts #{}}
|
||||
members))
|
||||
:else
|
||||
(assoc chat
|
||||
:contacts #{(:id chat)}
|
||||
:admins #{}
|
||||
:contacts #{(:id chat)}
|
||||
:admins #{}
|
||||
:members-joined #{})))
|
||||
|
||||
(defn <-rpc [chat]
|
||||
(defn <-rpc
|
||||
[chat]
|
||||
(-> chat
|
||||
(clojure.set/rename-keys {:id :chat-id
|
||||
:communityId :community-id
|
||||
:syncedFrom :synced-from
|
||||
:syncedTo :synced-to
|
||||
(clojure.set/rename-keys {:id :chat-id
|
||||
:communityId :community-id
|
||||
:syncedFrom :synced-from
|
||||
:syncedTo :synced-to
|
||||
:membershipUpdateEvents :membership-update-events
|
||||
:deletedAtClockValue :deleted-at-clock-value
|
||||
:chatType :chat-type
|
||||
:unviewedMessagesCount :unviewed-messages-count
|
||||
:unviewedMentionsCount :unviewed-mentions-count
|
||||
:lastMessage :last-message
|
||||
:lastClockValue :last-clock-value
|
||||
:invitationAdmin :invitation-admin
|
||||
:profile :profile-public-key})
|
||||
:deletedAtClockValue :deleted-at-clock-value
|
||||
:chatType :chat-type
|
||||
:unviewedMessagesCount :unviewed-messages-count
|
||||
:unviewedMentionsCount :unviewed-mentions-count
|
||||
:lastMessage :last-message
|
||||
:lastClockValue :last-clock-value
|
||||
:invitationAdmin :invitation-admin
|
||||
:profile :profile-public-key})
|
||||
rpc->type
|
||||
unmarshal-members
|
||||
(update :last-message #(when % (messages/<-rpc %)))
|
||||
(dissoc :members)))
|
||||
|
||||
(defn <-rpc-js [^js chat]
|
||||
(defn <-rpc-js
|
||||
[^js chat]
|
||||
(-> {:name (.-name chat)
|
||||
:description (.-description chat)
|
||||
:color (.-color chat)
|
||||
@@ -103,9 +109,10 @@
|
||||
rpc->type
|
||||
unmarshal-members))
|
||||
|
||||
(fx/defn fetch-chats-rpc [_ {:keys [on-success]}]
|
||||
{::json-rpc/call [{:method "wakuext_chatsPreview"
|
||||
:params []
|
||||
(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 %)}]})
|
||||
:on-success #(on-success ^js %)
|
||||
:on-error #(log/error "failed to fetch chats" 0 -1 %)}]})
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
(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]
|
||||
[taoensso.timbre :as log]))
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn <-rpc [contact]
|
||||
(defn <-rpc
|
||||
[contact]
|
||||
(-> contact
|
||||
(clojure.set/rename-keys
|
||||
{:id :public-key
|
||||
@@ -17,48 +18,54 @@
|
||||
:lastENSClockValue :last-ens-clock-value
|
||||
:lastUpdated :last-updated
|
||||
:localNickname :nickname})
|
||||
(assoc :mutual? (and (:added contact)
|
||||
(:hasAddedUs contact)))))
|
||||
(assoc :mutual?
|
||||
(and (:added contact)
|
||||
(:hasAddedUs contact)))))
|
||||
|
||||
(fx/defn fetch-contacts-rpc
|
||||
(rf/defn fetch-contacts-rpc
|
||||
[_ on-success]
|
||||
{::json-rpc/call [{:method "wakuext_contacts"
|
||||
:params []
|
||||
{::json-rpc/call [{:method "wakuext_contacts"
|
||||
:params []
|
||||
:on-success #(on-success (map <-rpc %))
|
||||
:on-error #(log/error "failed to fetch contacts" %)}]})
|
||||
: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}]
|
||||
{::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 %)}]})
|
||||
: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}]
|
||||
{::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 %)}]})
|
||||
: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 [_ contact-id on-success]
|
||||
{::json-rpc/call [{:method "wakuext_blockContact"
|
||||
:params [contact-id]
|
||||
(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)}]})
|
||||
:on-success on-success
|
||||
:on-error #(log/error "failed to block contact" % contact-id)}]})
|
||||
|
||||
(fx/defn unblock [_ contact-id on-success]
|
||||
{::json-rpc/call [{:method "wakuext_unblockContact"
|
||||
:params [contact-id]
|
||||
:on-success on-success
|
||||
(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)}]})
|
||||
:on-error #(log/error "failed to unblock contact" % contact-id)}]})
|
||||
|
||||
@@ -1,103 +1,118 @@
|
||||
(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]
|
||||
[taoensso.timbre :as log]))
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn ->rpc [{:keys [content] :as message}]
|
||||
(defn ->rpc
|
||||
[{:keys [content] :as message}]
|
||||
(cond-> message
|
||||
content
|
||||
(assoc :text (:text content)
|
||||
(assoc :text (:text content)
|
||||
:sticker (:sticker content))
|
||||
:always
|
||||
(clojure.set/rename-keys {:chat-id :chat_id
|
||||
(clojure.set/rename-keys {:chat-id :chat_id
|
||||
:whisper-timestamp :whisperTimestamp
|
||||
:community-id :communityId
|
||||
:clock-value :clock})))
|
||||
:community-id :communityId
|
||||
:clock-value :clock})))
|
||||
|
||||
(defn <-rpc [message]
|
||||
(defn <-rpc
|
||||
[message]
|
||||
(-> message
|
||||
(clojure.set/rename-keys {:id :message-id
|
||||
:whisperTimestamp :whisper-timestamp
|
||||
:editedAt :edited-at
|
||||
(clojure.set/rename-keys {:id :message-id
|
||||
:whisperTimestamp :whisper-timestamp
|
||||
:editedAt :edited-at
|
||||
:contactVerificationState :contact-verification-state
|
||||
:contactRequestState :contact-request-state
|
||||
:commandParameters :command-parameters
|
||||
:gapParameters :gap-parameters
|
||||
:messageType :message-type
|
||||
:localChatId :chat-id
|
||||
:communityId :community-id
|
||||
:contentType :content-type
|
||||
:clock :clock-value
|
||||
:quotedMessage :quoted-message
|
||||
:outgoingStatus :outgoing-status
|
||||
:audioDurationMs :audio-duration-ms
|
||||
:deleted :deleted?
|
||||
:deletedForMe :deleted-for-me?
|
||||
:new :new?})
|
||||
:contactRequestState :contact-request-state
|
||||
:commandParameters :command-parameters
|
||||
:gapParameters :gap-parameters
|
||||
:messageType :message-type
|
||||
:localChatId :chat-id
|
||||
:communityId :community-id
|
||||
:contentType :content-type
|
||||
:clock :clock-value
|
||||
:quotedMessage :quoted-message
|
||||
:outgoingStatus :outgoing-status
|
||||
:audioDurationMs :audio-duration-ms
|
||||
:deleted :deleted?
|
||||
:deletedForMe :deleted-for-me?
|
||||
:new :new?})
|
||||
|
||||
(update :quoted-message clojure.set/rename-keys {:parsedText :parsed-text :communityId :community-id})
|
||||
(update :quoted-message
|
||||
clojure.set/rename-keys
|
||||
{:parsedText :parsed-text :communityId :community-id})
|
||||
(update :outgoing-status keyword)
|
||||
(update :command-parameters clojure.set/rename-keys {:transactionHash :transaction-hash
|
||||
:commandState :command-state})
|
||||
(assoc :content {:chat-id (:chatId message)
|
||||
:text (:text message)
|
||||
:image (:image message)
|
||||
:sticker (:sticker message)
|
||||
:ens-name (:ensName message)
|
||||
:line-count (:lineCount message)
|
||||
:parsed-text (:parsedText message)
|
||||
:links (:links message)
|
||||
:rtl? (:rtl message)
|
||||
:response-to (:responseTo message)}
|
||||
(update :command-parameters
|
||||
clojure.set/rename-keys
|
||||
{:transactionHash :transaction-hash
|
||||
:commandState :command-state})
|
||||
(assoc :content {:chat-id (:chatId message)
|
||||
:text (:text message)
|
||||
:image (:image message)
|
||||
:sticker (:sticker message)
|
||||
:ens-name (:ensName message)
|
||||
:line-count (:lineCount message)
|
||||
:parsed-text (:parsedText message)
|
||||
:links (:links message)
|
||||
:rtl? (:rtl message)
|
||||
:response-to (:responseTo message)}
|
||||
:outgoing (boolean (:outgoingStatus message)))
|
||||
(dissoc :ensName :chatId :text :rtl :responseTo :image :sticker :lineCount :parsedText :links)))
|
||||
|
||||
(defn messages-by-chat-id-rpc [chat-id
|
||||
cursor
|
||||
limit
|
||||
on-success
|
||||
on-error]
|
||||
(defn messages-by-chat-id-rpc
|
||||
[chat-id
|
||||
cursor
|
||||
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}]})
|
||||
:on-error on-error}]})
|
||||
|
||||
(defn mark-seen-rpc [chat-id ids on-success]
|
||||
{::json-rpc/call [{:method "wakuext_markMessagesSeen"
|
||||
:params [chat-id ids]
|
||||
(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" %)}]})
|
||||
:on-error #(log/error "failed to get messages" %)}]})
|
||||
|
||||
(defn delete-message-rpc [id]
|
||||
{::json-rpc/call [{:method "wakuext_deleteMessage"
|
||||
:params [id]
|
||||
(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)}]})
|
||||
:on-error #(log/error "failed to delete message" % id)}]})
|
||||
|
||||
(defn delete-messages-from-rpc [author]
|
||||
{::json-rpc/call [{:method "wakuext_deleteMessagesFrom"
|
||||
:params [author]
|
||||
(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)}]})
|
||||
: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]
|
||||
(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)}]})
|
||||
:on-error #(log/error "failed to delete messages by chat-id" % chat-id)}]})
|
||||
|
||||
(fx/defn delete-message [cofx id]
|
||||
(rf/defn delete-message
|
||||
[cofx id]
|
||||
(delete-message-rpc id))
|
||||
|
||||
(fx/defn delete-messages-from [cofx author]
|
||||
(rf/defn delete-messages-from
|
||||
[cofx author]
|
||||
(delete-messages-from-rpc author))
|
||||
|
||||
(fx/defn mark-messages-seen [cofx chat-id ids on-success]
|
||||
(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 [cofx chat-id]
|
||||
(rf/defn delete-messages-by-chat-id
|
||||
[cofx chat-id]
|
||||
(delete-messages-by-chat-id-rpc chat-id))
|
||||
|
||||
@@ -1,31 +1,36 @@
|
||||
(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]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.data-store.messages :as messages]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn <-rpc [message]
|
||||
(defn <-rpc
|
||||
[message]
|
||||
(-> message
|
||||
(merge (messages/<-rpc (message :message)))
|
||||
(clojure.set/rename-keys {:pinnedAt :pinned-at
|
||||
:pinnedBy :pinned-by})
|
||||
(dissoc :message)))
|
||||
|
||||
(defn pinned-message-by-chat-id-rpc [chat-id
|
||||
cursor
|
||||
limit
|
||||
on-success
|
||||
on-error]
|
||||
(defn pinned-message-by-chat-id-rpc
|
||||
[chat-id
|
||||
cursor
|
||||
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})]
|
||||
(let [result (clojure.set/rename-keys result
|
||||
{:pinnedMessages
|
||||
:pinned-messages})]
|
||||
(on-success (update result :pinned-messages #(map <-rpc %)))))
|
||||
:on-error on-error}]})
|
||||
:on-error on-error}]})
|
||||
|
||||
(fx/defn send-pin-message [cofx pin-message]
|
||||
{::json-rpc/call [{:method "wakuext_sendPinMessage"
|
||||
:params [(messages/->rpc 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)}]})
|
||||
:on-error #(log/error "failed to pin message" % pin-message)}]})
|
||||
|
||||
@@ -2,23 +2,28 @@
|
||||
(: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]
|
||||
[taoensso.timbre :as log]))
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn <-rpc [visibility-status-update]
|
||||
(clojure.set/rename-keys visibility-status-update {:publicKey :public-key
|
||||
:statusType :status-type}))
|
||||
(defn <-rpc-settings [settings]
|
||||
(defn <-rpc
|
||||
[visibility-status-update]
|
||||
(clojure.set/rename-keys visibility-status-update
|
||||
{:publicKey :public-key
|
||||
:statusType :status-type}))
|
||||
(defn <-rpc-settings
|
||||
[settings]
|
||||
(-> settings
|
||||
(clojure.set/rename-keys
|
||||
{: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" %)}]})
|
||||
:on-error #(log/error
|
||||
"failed to fetch visibility-status-updates"
|
||||
%)}]})
|
||||
|
||||
+104
-74
@@ -2,18 +2,19 @@
|
||||
(:refer-clojure :exclude [name])
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.eip55 :as eip55]
|
||||
[status-im.ethereum.ens :as ens]
|
||||
[status-im.ethereum.stateofus :as stateofus]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.utils.datetime :as datetime]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.bottom-sheet.core :as bottom-sheet]))
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn fullname [custom-domain? username]
|
||||
(defn fullname
|
||||
[custom-domain? username]
|
||||
(if custom-domain?
|
||||
username
|
||||
(stateofus/subdomain username)))
|
||||
@@ -38,14 +39,16 @@
|
||||
(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 [:ens/registrations tx-hash] {:state new-state
|
||||
:username username
|
||||
:custom-domain? custom-domain?})})
|
||||
{:db (assoc-in db
|
||||
[:ens/registrations tx-hash]
|
||||
{:state new-state
|
||||
: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
|
||||
@@ -55,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
|
||||
@@ -76,37 +79,43 @@
|
||||
(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] [])
|
||||
(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
|
||||
:usernames
|
||||
new-names
|
||||
(when redirectToSummary
|
||||
{:on-success #(re-frame/dispatch [::redirect-to-ens-summary])}))
|
||||
(when (empty? names)
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:preferred-name name {})))))
|
||||
:preferred-name
|
||||
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)
|
||||
address (or address (ethereum/default-address db))
|
||||
{:keys [public-key]} (:multiaccount db)
|
||||
chain-id (ethereum/chain-id db)
|
||||
username (fullname custom-domain? username)]
|
||||
address (or address (ethereum/default-address db))
|
||||
{:keys [public-key]} (:multiaccount db)
|
||||
chain-id (ethereum/chain-id db)
|
||||
username (fullname custom-domain? username)]
|
||||
(ens/set-pub-key-prepare-tx
|
||||
chain-id address username public-key
|
||||
chain-id
|
||||
address
|
||||
username
|
||||
public-key
|
||||
#(re-frame/dispatch [:signing.ui/sign
|
||||
{:tx-obj %
|
||||
: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)]
|
||||
@@ -135,14 +144,16 @@
|
||||
(ens/pubkey
|
||||
chain-id
|
||||
(fullname custom-domain? username)
|
||||
#(re-frame/dispatch [::name-resolved username
|
||||
(cond
|
||||
(not public-key) :owned
|
||||
(and (string/ends-with? % "0000000000000000000000000000000000000000000000000000000000000000") (not custom-domain?))
|
||||
:invalid-ens
|
||||
(= % public-key) :connected
|
||||
:else :connected-with-different-key)
|
||||
(eip55/address->checksum response)]))
|
||||
#(re-frame/dispatch
|
||||
[::name-resolved username
|
||||
(cond
|
||||
(not public-key) :owned
|
||||
(and (string/ends-with? % "0000000000000000000000000000000000000000000000000000000000000000")
|
||||
(not custom-domain?))
|
||||
:invalid-ens
|
||||
(= % public-key) :connected
|
||||
:else :connected-with-different-key)
|
||||
(eip55/address->checksum response)]))
|
||||
:else
|
||||
(re-frame/dispatch [::name-resolved username :taken]))))
|
||||
|
||||
@@ -153,33 +164,40 @@
|
||||
5 10
|
||||
1 10))
|
||||
|
||||
(fx/defn register-name
|
||||
(rf/defn register-name
|
||||
{:events [::register-name-pressed]}
|
||||
[{:keys [db]} address]
|
||||
(let [{:keys [username]}
|
||||
(:ens/registration db)
|
||||
{:keys [public-key]} (:multiaccount db)
|
||||
chain-id (ethereum/chain-id db)]
|
||||
chain-id (ethereum/chain-id db)]
|
||||
(ens/register-prepare-tx
|
||||
chain-id address username public-key
|
||||
chain-id
|
||||
address
|
||||
username
|
||||
public-key
|
||||
#(re-frame/dispatch [:signing.ui/sign
|
||||
{:tx-obj %
|
||||
:on-result [:update-ens-tx-state-and-redirect :submitted username false]
|
||||
:on-error [::on-registration-failure]}]))))
|
||||
|
||||
(defn- valid-custom-domain? [username]
|
||||
(defn- valid-custom-domain?
|
||||
[username]
|
||||
(and (ens/is-valid-eth-name? username)
|
||||
(stateofus/lower-case? username)))
|
||||
|
||||
(defn- valid-username? [custom-domain? username]
|
||||
(defn- valid-username?
|
||||
[custom-domain? username]
|
||||
(if custom-domain?
|
||||
(valid-custom-domain? username)
|
||||
(stateofus/valid-username? username)))
|
||||
|
||||
(defn- state [custom-domain? username usernames]
|
||||
(defn- state
|
||||
[custom-domain? username usernames]
|
||||
(cond
|
||||
(or (string/blank? username)
|
||||
(> 4 (count username))) :too-short
|
||||
(> 4 (count username)))
|
||||
:too-short
|
||||
(valid-username? custom-domain? username)
|
||||
(if (usernames (fullname custom-domain? username))
|
||||
:already-added
|
||||
@@ -189,79 +207,88 @@
|
||||
;;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)
|
||||
usernames (into #{} (get-in db [:multiaccount :usernames]))
|
||||
state (state custom-domain? username usernames)]
|
||||
usernames (into #{} (get-in db [:multiaccount :usernames]))
|
||||
state (state custom-domain? username usernames)]
|
||||
(reset! resolve-last-id (random/id))
|
||||
(merge
|
||||
{:db (update db :ens/registration assoc
|
||||
:username username
|
||||
:state state)}
|
||||
{:db (update db
|
||||
:ens/registration assoc
|
||||
:username username
|
||||
:state state)}
|
||||
(when (= state :searching)
|
||||
(let [{:keys [multiaccount]} db
|
||||
{:keys [public-key]} multiaccount
|
||||
addresses (ethereum/addresses-without-watch db)
|
||||
chain-id (ethereum/chain-id db)]
|
||||
{:keys [public-key]} multiaccount
|
||||
addresses (ethereum/addresses-without-watch db)
|
||||
chain-id (ethereum/chain-id db)]
|
||||
{::resolve-owner [chain-id
|
||||
(fullname custom-domain? username)
|
||||
#(on-resolve-owner
|
||||
chain-id custom-domain? username addresses public-key %
|
||||
resolve-last-id @resolve-last-id)]})))))
|
||||
chain-id
|
||||
custom-domain?
|
||||
username
|
||||
addresses
|
||||
public-key
|
||||
%
|
||||
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
|
||||
;; into the registration flow
|
||||
(navigation/set-stack-root :profile-stack [:my-profile
|
||||
:ens-main])))
|
||||
(navigation/set-stack-root :profile-stack
|
||||
[: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
|
||||
:preferred-name name
|
||||
:preferred-name
|
||||
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
|
||||
@@ -269,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)
|
||||
@@ -286,24 +313,27 @@
|
||||
#(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
|
||||
:usernames
|
||||
new-names
|
||||
{})
|
||||
(when (= name preferred-name)
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:preferred-name (first new-names) {}))
|
||||
:preferred-name
|
||||
(first new-names)
|
||||
{}))
|
||||
(navigation/navigate-back))))
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
[status-im.utils.utils :as utils]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
;; NOTE(19/12/22 yqrashawn) this namespace has been moved to the
|
||||
;; status-im2.common.json-rpc.events namespace,
|
||||
;; we keep this only for old (status 1.0) code, can be removed with old code later
|
||||
(defn on-error-retry
|
||||
[call-method {:keys [method number-of-retries delay on-error] :as arg}]
|
||||
(if (pos? number-of-retries)
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
(ns status-im.ethereum.subscriptions
|
||||
(:require [status-im.ethereum.eip55 :as eip55]
|
||||
[status-im.wallet.db :as wallet]
|
||||
[status-im.wallet.core :as wallet.core]
|
||||
[status-im.ethereum.transactions.core :as transactions]
|
||||
[status-im.utils.fx :as fx]
|
||||
[taoensso.timbre :as log]))
|
||||
[status-im.wallet.core :as wallet.core]
|
||||
[status-im.wallet.db :as wallet]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn new-transfers
|
||||
(rf/defn new-transfers
|
||||
[cofx block-number accounts]
|
||||
(log/debug "[wallet-subs] new-transfers"
|
||||
"accounts" accounts
|
||||
"block" block-number)
|
||||
"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" accounts)
|
||||
"accounts"
|
||||
accounts)
|
||||
(let [event (get db :wallet/on-recent-history-fetching)]
|
||||
(cond-> {:db (-> db
|
||||
(transactions/update-fetching-status accounts :recent? true)
|
||||
@@ -25,20 +26,21 @@
|
||||
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
|
||||
"block" blockNumber)
|
||||
{:db (-> db
|
||||
(assoc :ethereum/current-block blockNumber)
|
||||
(update-in [:wallet :accounts]
|
||||
wallet/remove-transactions-since-block blockNumber)
|
||||
(transactions/update-fetching-status accounts :recent? false)
|
||||
(dissoc :wallet/waiting-for-recent-history?
|
||||
:wallet/refreshing-history?
|
||||
:wallet/fetching-error
|
||||
:wallet/recent-history-fetching-started?))
|
||||
"block" blockNumber)
|
||||
{:db (-> db
|
||||
(assoc :ethereum/current-block blockNumber)
|
||||
(update-in [:wallet :accounts]
|
||||
wallet/remove-transactions-since-block
|
||||
blockNumber)
|
||||
(transactions/update-fetching-status accounts :recent? false)
|
||||
(dissoc :wallet/waiting-for-recent-history?
|
||||
:wallet/refreshing-history?
|
||||
:wallet/fetching-error
|
||||
:wallet/recent-history-fetching-started?))
|
||||
:transactions/get-transfers
|
||||
{:chain-tokens (:wallet/all-tokens db)
|
||||
:addresses (reduce
|
||||
@@ -53,27 +55,27 @@
|
||||
: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)}
|
||||
{: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
|
||||
"event-type" type
|
||||
"blockNumber" blockNumber
|
||||
"accounts" accounts)
|
||||
"accounts" accounts)
|
||||
(case type
|
||||
"new-transfers" (new-transfers cofx blockNumber accounts)
|
||||
"recent-history-fetching" (recent-history-fetching-started cofx accounts)
|
||||
"recent-history-ready" (recent-history-fetching-ended cofx event)
|
||||
"fetching-history-error" (fetching-error cofx event)
|
||||
"new-transfers" (new-transfers cofx blockNumber accounts)
|
||||
"recent-history-fetching" (recent-history-fetching-started cofx accounts)
|
||||
"recent-history-ready" (recent-history-fetching-ended cofx event)
|
||||
"fetching-history-error" (fetching-error cofx event)
|
||||
"non-archival-node-detected" (non-archival-node-detected cofx event)
|
||||
(log/warn ::unknown-wallet-event :type type :event event)))
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
[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]
|
||||
[status-im.utils.mobile-sync :as utils.mobile-sync]
|
||||
[status-im.wallet.core :as wallet]
|
||||
[taoensso.timbre :as log]))
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def confirmations-count-threshold 12)
|
||||
|
||||
@@ -23,8 +23,9 @@
|
||||
|
||||
(def network->subdomain {5 "goerli"})
|
||||
|
||||
(defn get-transaction-details-url [chain-id hash]
|
||||
{:pre [(number? chain-id) (string? hash)]
|
||||
(defn get-transaction-details-url
|
||||
[chain-id hash]
|
||||
{:pre [(number? chain-id) (string? hash)]
|
||||
:post [(or (nil? %) (string? %))]}
|
||||
(cond
|
||||
(etherscan-supported? chain-id)
|
||||
@@ -51,15 +52,16 @@
|
||||
|
||||
(defn- parse-token-transfer
|
||||
[chain-tokens contract]
|
||||
(let [{:keys [symbol] :as token} (get chain-tokens contract
|
||||
(let [{:keys [symbol] :as token} (get chain-tokens
|
||||
contract
|
||||
default-erc20-token)]
|
||||
{:symbol symbol
|
||||
:token token
|
||||
{:symbol symbol
|
||||
:token token
|
||||
;; NOTE(goranjovic) - just a flag we need when we merge this entry
|
||||
;; with the existing entry in the app, e.g. transaction info with
|
||||
;; gas details, or a previous transfer entry with old confirmations
|
||||
;; count.
|
||||
:transfer true}))
|
||||
:transfer true}))
|
||||
|
||||
(defn enrich-transfer
|
||||
[chain-tokens
|
||||
@@ -105,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
|
||||
@@ -114,10 +116,11 @@
|
||||
[{:keys [db]} transaction-id {:keys [trigger-fn on-trigger] :as watch-params}]
|
||||
(when (and (fn? trigger-fn)
|
||||
(fn? on-trigger))
|
||||
{:db (assoc-in db [:ethereum/watched-transactions transaction-id]
|
||||
watch-params)}))
|
||||
{:db (assoc-in db
|
||||
[: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}]
|
||||
@@ -125,12 +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
|
||||
{:db (update db :ethereum/watched-transactions
|
||||
dissoc hash)}
|
||||
(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]}]
|
||||
@@ -139,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"
|
||||
@@ -157,25 +162,30 @@
|
||||
(:type transfer-by-hash))))
|
||||
id
|
||||
hash))]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:wallet :accounts address :transactions unique-id]
|
||||
(assoc transfer :hash unique-id))}
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:wallet :accounts address :transactions unique-id]
|
||||
(assoc transfer :hash unique-id))}
|
||||
(check-transaction transfer)))))
|
||||
|
||||
(defn get-min-known-block [db address]
|
||||
(defn get-min-known-block
|
||||
[db address]
|
||||
(get-in db [:wallet :accounts (eip55/address->checksum address) :min-block]))
|
||||
|
||||
(defn get-max-block-with-transfers [db address]
|
||||
(defn get-max-block-with-transfers
|
||||
[db address]
|
||||
(get-in db [:wallet :accounts (eip55/address->checksum address) :max-block]))
|
||||
|
||||
(defn min-block-transfers-count [db address]
|
||||
(get-in db [:wallet :accounts
|
||||
(eip55/address->checksum address)
|
||||
:min-block-transfers-count]))
|
||||
(defn min-block-transfers-count
|
||||
[db address]
|
||||
(get-in db
|
||||
[:wallet :accounts
|
||||
(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)
|
||||
(let [checksum (eip55/address->checksum address)
|
||||
{:keys [min-block min-block-transfers-count]}
|
||||
(reduce
|
||||
(fn [{:keys [min-block] :as acc}
|
||||
@@ -198,43 +208,47 @@
|
||||
(min-block-transfers-count db address)}
|
||||
transfers)]
|
||||
(log/debug "[transactions] set-lowest-fetched-block"
|
||||
"address" address
|
||||
"min-block" min-block
|
||||
"address" address
|
||||
"min-block" min-block
|
||||
"min-block-transfers-count" min-block-transfers-count)
|
||||
{:db (update-in db [:wallet :accounts checksum] assoc
|
||||
:min-block min-block
|
||||
{:db (update-in db
|
||||
[:wallet :accounts checksum]
|
||||
assoc
|
||||
:min-block min-block
|
||||
:min-block-transfers-count min-block-transfers-count)}))
|
||||
|
||||
(defn update-fetching-status
|
||||
[db addresses fetching-type state]
|
||||
(update-in
|
||||
db [:wallet :fetching]
|
||||
db
|
||||
[:wallet :fetching]
|
||||
(fn [accounts]
|
||||
(reduce
|
||||
(fn [accounts address]
|
||||
(assoc-in accounts
|
||||
[(eip55/address->checksum address) fetching-type]
|
||||
state))
|
||||
[(eip55/address->checksum address) fetching-type]
|
||||
state))
|
||||
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 [:wallet :fetching address :all-fetched?]
|
||||
(if syncing-allowed?
|
||||
:all
|
||||
:all-preloaded))}))
|
||||
{:db (assoc-in db
|
||||
[:wallet :fetching address :all-fetched?]
|
||||
(if syncing-allowed?
|
||||
: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])
|
||||
@@ -247,38 +261,38 @@
|
||||
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
|
||||
"count" (count transfers)
|
||||
"limit" limit)
|
||||
(let [checksum (eip55/address->checksum address)
|
||||
"count" (count transfers)
|
||||
"limit" limit)
|
||||
(let [checksum (eip55/address->checksum address)
|
||||
max-known-block (get-max-block-with-transfers db address)
|
||||
effects (cond-> [(when (seq transfers)
|
||||
(set-lowest-fetched-block checksum transfers))
|
||||
(wallet/set-max-block-with-transfers checksum transfers)]
|
||||
effects (cond-> [(when (seq transfers)
|
||||
(set-lowest-fetched-block checksum transfers))
|
||||
(wallet/set-max-block-with-transfers checksum transfers)]
|
||||
|
||||
(seq transfers)
|
||||
(concat
|
||||
[(delete-pending-transactions address transfers)]
|
||||
(mapv add-transfer transfers))
|
||||
(seq transfers)
|
||||
(concat
|
||||
[(delete-pending-transactions address transfers)]
|
||||
(mapv add-transfer transfers))
|
||||
|
||||
(and max-known-block
|
||||
(some #(> (:block %) max-known-block) transfers))
|
||||
(conj (wallet/update-balances
|
||||
[address]
|
||||
(zero? max-known-block)))
|
||||
(and max-known-block
|
||||
(some #(> (:block %) max-known-block) transfers))
|
||||
(conj (wallet/update-balances
|
||||
[address]
|
||||
(zero? max-known-block)))
|
||||
|
||||
(and (zero? max-known-block)
|
||||
(empty? transfers))
|
||||
(conj (wallet/set-zero-balances {:address address}))
|
||||
(and (zero? max-known-block)
|
||||
(empty? transfers))
|
||||
(conj (wallet/set-zero-balances {:address address}))
|
||||
|
||||
(< (count transfers) limit)
|
||||
(conj (tx-history-end-reached checksum)))]
|
||||
(apply fx/merge cofx (tx-fetching-ended [checksum]) effects)))
|
||||
(< (count transfers) limit)
|
||||
(conj (tx-history-end-reached checksum)))]
|
||||
(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
|
||||
@@ -288,12 +302,15 @@
|
||||
(contains? set-of-transactions-hash hash)))
|
||||
(get db :ens/registrations))
|
||||
fxs (map (fn [[hash {:keys [username custom-domain?]}]]
|
||||
(let [transfer (first (filter (fn [transfer] (let [transfer-hash (get transfer :hash)] (= transfer-hash hash))) transfers))
|
||||
type (get transfer :type)
|
||||
(let [transfer (first (filter (fn [transfer]
|
||||
(let [transfer-hash (get transfer :hash)]
|
||||
(= transfer-hash hash)))
|
||||
transfers))
|
||||
type (get transfer :type)
|
||||
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)
|
||||
@@ -301,69 +318,72 @@
|
||||
: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"
|
||||
"address" address
|
||||
"error" error)
|
||||
"error" error)
|
||||
(tx-fetching-ended cofx [address]))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:transactions/get-transfers
|
||||
(fn [{:keys [chain-tokens addresses before-block limit
|
||||
limit-per-address fetch-more?]
|
||||
:as params
|
||||
:or {limit default-transfers-limit
|
||||
(fn
|
||||
[{:keys [chain-tokens addresses before-block limit
|
||||
limit-per-address fetch-more?]
|
||||
:as params
|
||||
:or {limit default-transfers-limit
|
||||
fetch-more? true}}]
|
||||
{:pre [(spec/valid?
|
||||
(spec/coll-of string?)
|
||||
addresses)]}
|
||||
(log/debug "[transactions] get-transfers"
|
||||
"addresses" addresses
|
||||
"block" before-block
|
||||
"limit" limit
|
||||
"addresses" addresses
|
||||
"block" before-block
|
||||
"limit" limit
|
||||
"limit-per-address" limit-per-address
|
||||
"fetch-more?" fetch-more?)
|
||||
"fetch-more?" fetch-more?)
|
||||
(doseq [address addresses]
|
||||
(let [limit (or (get limit-per-address address)
|
||||
limit)]
|
||||
(json-rpc/call
|
||||
{:method "wallet_getTransfersByAddress"
|
||||
:params [address (encode/uint before-block) (encode/uint limit) fetch-more?]
|
||||
{:method "wallet_getTransfersByAddress"
|
||||
:params [address (encode/uint before-block) (encode/uint limit) fetch-more?]
|
||||
:on-success #(re-frame/dispatch
|
||||
[::new-transfers
|
||||
(enrich-transfers chain-tokens %)
|
||||
(assoc params :address address
|
||||
:limit limit)])
|
||||
:on-error #(re-frame/dispatch [::tx-fetching-failed address])})))))
|
||||
(assoc params
|
||||
:address address
|
||||
:limit limit)])
|
||||
:on-error #(re-frame/dispatch [::tx-fetching-failed address])})))))
|
||||
|
||||
(defn some-transactions-loaded? [db address]
|
||||
(defn some-transactions-loaded?
|
||||
[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))
|
||||
(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)
|
||||
:addresses [address]
|
||||
:before-block min-known-block
|
||||
:fetch-more? (utils.mobile-sync/syncing-allowed? cofx)
|
||||
{:chain-tokens (:wallet/all-tokens db)
|
||||
:addresses [address]
|
||||
:before-block min-known-block
|
||||
:fetch-more? (utils.mobile-sync/syncing-allowed? cofx)
|
||||
;; Transfers are requested before and including `min-known-block` because
|
||||
;; there is no guarantee that all transfers from that block are shown
|
||||
;; already. To make sure that we fetch the whole `default-transfers-limit`
|
||||
@@ -373,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
|
||||
|
||||
+137
-122
@@ -1,64 +1,65 @@
|
||||
(ns status-im.events
|
||||
(:require clojure.set
|
||||
[re-frame.core :as re-frame]
|
||||
status-im.add-new.core
|
||||
[status-im.async-storage.core :as async-storage]
|
||||
status-im.backup.core
|
||||
status-im.bootnodes.core
|
||||
status-im.browser.core
|
||||
status-im.browser.permissions
|
||||
[status-im.chat.models :as chat]
|
||||
status-im.chat.models.images
|
||||
status-im.chat.models.input
|
||||
status-im.chat.models.loading
|
||||
status-im.chat.models.transport
|
||||
[status-im.constants :as constants]
|
||||
status-im.contact.block
|
||||
status-im.contact.chat
|
||||
status-im.contact.core
|
||||
status-im.currency.core
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
status-im.ethereum.subscriptions
|
||||
status-im.fleet.core
|
||||
status-im.http.core
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.keycard.core :as keycard]
|
||||
status-im.log-level.core
|
||||
status-im.mailserver.constants
|
||||
[status-im.mailserver.core :as mailserver]
|
||||
[status-im.multiaccounts.biometric.core :as biometric]
|
||||
status-im.multiaccounts.login.core
|
||||
status-im.multiaccounts.logout.core
|
||||
status-im.multiaccounts.update.core
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
status-im.activity-center.core
|
||||
status-im.pairing.core
|
||||
status-im.profile.core
|
||||
status-im.search.core
|
||||
status-im.signals.core
|
||||
status-im.stickers.core
|
||||
status-im.transport.core
|
||||
[status-im.ui.components.permissions :as permissions]
|
||||
[status-im.ui.components.react :as react]
|
||||
status-im.ui.screens.privacy-and-security-settings.events
|
||||
[status-im.utils.dimensions :as dimensions]
|
||||
[status-im.utils.fx :as fx]
|
||||
status-im.utils.logging.core
|
||||
[status-im.utils.universal-links.core :as universal-links]
|
||||
[status-im.utils.utils :as utils]
|
||||
status-im.visibility-status-updates.core
|
||||
status-im.waku.core
|
||||
status-im.wallet.accounts.core
|
||||
status-im.wallet.choose-recipient.core
|
||||
[status-im.wallet.core :as wallet]
|
||||
status-im.wallet.custom-tokens.core
|
||||
status-im.wallet-connect.core
|
||||
status-im.wallet-connect-legacy.core
|
||||
status-im.network.net-info
|
||||
status-im.visibility-status-popover.core
|
||||
status-im2.contexts.shell.events
|
||||
[status-im.multiaccounts.model :as multiaccounts.model]))
|
||||
(:require
|
||||
clojure.set
|
||||
[re-frame.core :as re-frame]
|
||||
status-im.add-new.core
|
||||
[status-im.async-storage.core :as async-storage]
|
||||
status-im.backup.core
|
||||
status-im.bootnodes.core
|
||||
status-im.browser.core
|
||||
status-im.browser.permissions
|
||||
[status-im.chat.models :as chat]
|
||||
status-im.chat.models.images
|
||||
status-im.chat.models.input
|
||||
status-im.chat.models.loading
|
||||
status-im.chat.models.transport
|
||||
[status-im.constants :as constants]
|
||||
status-im.contact.block
|
||||
status-im.contact.chat
|
||||
status-im.contact.core
|
||||
status-im.currency.core
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
status-im.ethereum.subscriptions
|
||||
status-im.fleet.core
|
||||
status-im.http.core
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.keycard.core :as keycard]
|
||||
status-im.log-level.core
|
||||
status-im.mailserver.constants
|
||||
[status-im.mailserver.core :as mailserver]
|
||||
[status-im.multiaccounts.biometric.core :as biometric]
|
||||
status-im.multiaccounts.login.core
|
||||
status-im.multiaccounts.logout.core
|
||||
[status-im.multiaccounts.model :as multiaccounts.model]
|
||||
status-im.multiaccounts.update.core
|
||||
[status-im.native-module.core :as status]
|
||||
status-im.network.net-info
|
||||
status-im.pairing.core
|
||||
status-im.profile.core
|
||||
status-im.search.core
|
||||
status-im.signals.core
|
||||
status-im.stickers.core
|
||||
status-im.transport.core
|
||||
[status-im.ui.components.permissions :as permissions]
|
||||
[status-im.ui.components.react :as react]
|
||||
status-im.ui.screens.privacy-and-security-settings.events
|
||||
[status-im.utils.dimensions :as dimensions]
|
||||
status-im.utils.logging.core
|
||||
[status-im.utils.universal-links.core :as universal-links]
|
||||
[status-im.utils.utils :as utils]
|
||||
status-im.visibility-status-popover.core
|
||||
status-im.visibility-status-updates.core
|
||||
status-im.waku.core
|
||||
status-im.wallet-connect-legacy.core
|
||||
status-im.wallet-connect.core
|
||||
status-im.wallet.accounts.core
|
||||
status-im.wallet.choose-recipient.core
|
||||
[status-im.wallet.core :as wallet]
|
||||
status-im.wallet.custom-tokens.core
|
||||
status-im2.contexts.activity-center.events
|
||||
status-im2.contexts.shell.events
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:dismiss-keyboard
|
||||
@@ -95,53 +96,58 @@
|
||||
(fn []
|
||||
(dimensions/add-event-listener)))
|
||||
|
||||
(fx/defn dismiss-keyboard
|
||||
(rf/defn dismiss-keyboard
|
||||
{:events [:dismiss-keyboard]}
|
||||
[_]
|
||||
{:dismiss-keyboard nil})
|
||||
|
||||
(fx/defn identicon-generated
|
||||
(rf/defn identicon-generated
|
||||
{:events [:identicon-generated]}
|
||||
[{:keys [db]} path identicon]
|
||||
{:db (assoc-in db path identicon)})
|
||||
|
||||
(fx/defn gfycat-generated
|
||||
(rf/defn gfycat-generated
|
||||
{:events [:gfycat-generated]}
|
||||
[{:keys [db]} path gfycat]
|
||||
{:db (assoc-in db path gfycat)})
|
||||
|
||||
(fx/defn system-theme-mode-changed
|
||||
(rf/defn system-theme-mode-changed
|
||||
{:events [:system-theme-mode-changed]}
|
||||
[cofx _]
|
||||
(when (multiaccounts.model/logged-in? cofx)
|
||||
{:multiaccounts.ui/switch-theme (get-in cofx [:db :multiaccount :appearance])
|
||||
:dispatch [:reload-new-ui]}))
|
||||
:dispatch [:reload-new-ui]}))
|
||||
|
||||
(def authentication-options
|
||||
{:reason (i18n/label :t/biometric-auth-reason-login)})
|
||||
|
||||
(defn- on-biometric-auth-result [{:keys [bioauth-success bioauth-code bioauth-message]}]
|
||||
(defn- on-biometric-auth-result
|
||||
[{:keys [bioauth-success bioauth-code bioauth-message]}]
|
||||
(when-not bioauth-success
|
||||
(if (= bioauth-code "USER_FALLBACK")
|
||||
(re-frame/dispatch [:multiaccounts.logout.ui/logout-confirmed])
|
||||
(utils/show-confirmation {:title (i18n/label :t/biometric-auth-confirm-title)
|
||||
:content (or bioauth-message (i18n/label :t/biometric-auth-confirm-message))
|
||||
:confirm-button-text (i18n/label :t/biometric-auth-confirm-try-again)
|
||||
:cancel-button-text (i18n/label :t/biometric-auth-confirm-logout)
|
||||
:on-accept #(biometric/authenticate nil on-biometric-auth-result authentication-options)
|
||||
:on-cancel #(re-frame/dispatch [:multiaccounts.logout.ui/logout-confirmed])}))))
|
||||
(utils/show-confirmation
|
||||
{:title (i18n/label :t/biometric-auth-confirm-title)
|
||||
:content (or bioauth-message (i18n/label :t/biometric-auth-confirm-message))
|
||||
:confirm-button-text (i18n/label :t/biometric-auth-confirm-try-again)
|
||||
:cancel-button-text (i18n/label :t/biometric-auth-confirm-logout)
|
||||
:on-accept #(biometric/authenticate nil
|
||||
on-biometric-auth-result
|
||||
authentication-options)
|
||||
:on-cancel #(re-frame/dispatch [:multiaccounts.logout.ui/logout-confirmed])}))))
|
||||
|
||||
(fx/defn on-return-from-background [{:keys [db now] :as cofx}]
|
||||
(rf/defn on-return-from-background
|
||||
[{:keys [db now] :as cofx}]
|
||||
(let [app-in-background-since (get db :app-in-background-since)
|
||||
signed-up? (get-in db [:multiaccount :signed-up?])
|
||||
biometric-auth? (= (:auth-method db) "biometric")
|
||||
requires-bio-auth (and
|
||||
signed-up?
|
||||
biometric-auth?
|
||||
(some? app-in-background-since)
|
||||
(>= (- now app-in-background-since)
|
||||
constants/ms-in-bg-for-require-bioauth))]
|
||||
(fx/merge cofx
|
||||
signed-up? (get-in db [:multiaccount :signed-up?])
|
||||
biometric-auth? (= (:auth-method db) "biometric")
|
||||
requires-bio-auth (and
|
||||
signed-up?
|
||||
biometric-auth?
|
||||
(some? app-in-background-since)
|
||||
(>= (- now app-in-background-since)
|
||||
constants/ms-in-bg-for-require-bioauth))]
|
||||
(rf/merge cofx
|
||||
{:db (dissoc db :app-in-background-since)}
|
||||
(mailserver/process-next-messages-request)
|
||||
(wallet/restart-wallet-service-after-background app-in-background-since)
|
||||
@@ -151,17 +157,17 @@
|
||||
#(when requires-bio-auth
|
||||
(biometric/authenticate % on-biometric-auth-result authentication-options)))))
|
||||
|
||||
(fx/defn on-going-in-background
|
||||
(rf/defn on-going-in-background
|
||||
[{:keys [db now]}]
|
||||
{:db (assoc db :app-in-background-since now)
|
||||
:dispatch-n [[:audio-recorder/on-background] [:audio-message/on-background]]})
|
||||
|
||||
(fx/defn app-state-change
|
||||
(rf/defn app-state-change
|
||||
{:events [:app-state-change]}
|
||||
[{:keys [db] :as cofx} state]
|
||||
(let [app-coming-from-background? (= state "active")
|
||||
app-going-in-background? (= state "background")]
|
||||
(fx/merge cofx
|
||||
app-going-in-background? (= state "background")]
|
||||
(rf/merge cofx
|
||||
{::app-state-change-fx state
|
||||
:db (assoc db :app-state state)}
|
||||
#(when app-coming-from-background?
|
||||
@@ -169,31 +175,31 @@
|
||||
#(when app-going-in-background?
|
||||
(on-going-in-background %)))))
|
||||
|
||||
(fx/defn request-permissions
|
||||
(rf/defn request-permissions
|
||||
{:events [:request-permissions]}
|
||||
[_ options]
|
||||
{:request-permissions-fx options})
|
||||
|
||||
(fx/defn update-window-dimensions
|
||||
(rf/defn update-window-dimensions
|
||||
{:events [:update-window-dimensions]}
|
||||
[{:keys [db]} dimensions]
|
||||
{:db (assoc db :dimensions/window (dimensions/window dimensions))})
|
||||
|
||||
(fx/defn init-timeline-chat
|
||||
(rf/defn init-timeline-chat
|
||||
{:events [:init-timeline-chat]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(when-not (get-in db [:pagination-info constants/timeline-chat-id :messages-initialized?])
|
||||
(chat/preload-chat-data cofx constants/timeline-chat-id)))
|
||||
|
||||
(fx/defn on-will-focus
|
||||
(rf/defn on-will-focus
|
||||
{:events [:screens/on-will-focus]}
|
||||
[{:keys [db] :as cofx} view-id]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(cond
|
||||
(= :chat view-id)
|
||||
{::async-storage/set! {:chat-id (get-in cofx [:db :current-chat-id])
|
||||
:key-uid (get-in cofx [:db :multiaccount :key-uid])}
|
||||
:db (assoc db :screens/was-focused-once? true)}
|
||||
:db (assoc db :screens/was-focused-once? true)}
|
||||
|
||||
(= :login view-id)
|
||||
{}
|
||||
@@ -204,47 +210,49 @@
|
||||
:else
|
||||
{::async-storage/set! {:chat-id nil
|
||||
:key-uid nil}
|
||||
:db (assoc db :screens/was-focused-once? true)})
|
||||
:db (assoc db :screens/was-focused-once? true)})
|
||||
#(case view-id
|
||||
:keycard-settings (keycard/settings-screen-did-load %)
|
||||
:reset-card (keycard/reset-card-screen-did-load %)
|
||||
:enter-pin-settings (keycard/enter-pin-screen-did-load %)
|
||||
:keycard-login-pin (keycard/login-pin-screen-did-load %)
|
||||
:add-new-account-pin (keycard/enter-pin-screen-did-load %)
|
||||
:keycard-settings (keycard/settings-screen-did-load %)
|
||||
:reset-card (keycard/reset-card-screen-did-load %)
|
||||
:enter-pin-settings (keycard/enter-pin-screen-did-load %)
|
||||
:keycard-login-pin (keycard/login-pin-screen-did-load %)
|
||||
:add-new-account-pin (keycard/enter-pin-screen-did-load %)
|
||||
:keycard-authentication-method (keycard/authentication-method-screen-did-load %)
|
||||
:multiaccounts (keycard/multiaccounts-screen-did-load %)
|
||||
:wallet (wallet/wallet-will-focus %)
|
||||
:multiaccounts (keycard/multiaccounts-screen-did-load %)
|
||||
:wallet (wallet/wallet-will-focus %)
|
||||
nil)))
|
||||
|
||||
;;TODO :replace by named events
|
||||
(fx/defn set-event
|
||||
(rf/defn set-event
|
||||
{:events [:set]}
|
||||
[{:keys [db]} k v]
|
||||
{:db (assoc db k v)})
|
||||
|
||||
(fx/defn set-view-id
|
||||
(rf/defn set-view-id
|
||||
{:events [:set-view-id]}
|
||||
[{:keys [db]} view-id]
|
||||
{:db (assoc db :view-id view-id)})
|
||||
|
||||
;;TODO :replace by named events
|
||||
(fx/defn set-once-event
|
||||
(rf/defn set-once-event
|
||||
{:events [:set-once]}
|
||||
[{:keys [db]} k v]
|
||||
(when-not (get db k)
|
||||
{:db (assoc db k v)}))
|
||||
|
||||
;;TODO :replace by named events
|
||||
(fx/defn set-in-event
|
||||
(rf/defn set-in-event
|
||||
{:events [:set-in]}
|
||||
[{:keys [db]} path v]
|
||||
{:db (assoc-in db path v)})
|
||||
|
||||
(defn on-ramp<-rpc [on-ramp]
|
||||
(clojure.set/rename-keys on-ramp {:logoUrl :logo-url
|
||||
:siteUrl :site-url}))
|
||||
(defn on-ramp<-rpc
|
||||
[on-ramp]
|
||||
(clojure.set/rename-keys on-ramp
|
||||
{:logoUrl :logo-url
|
||||
:siteUrl :site-url}))
|
||||
|
||||
(fx/defn crypto-loaded-event
|
||||
(rf/defn crypto-loaded-event
|
||||
{:events [::crypto-loaded]}
|
||||
[{:keys [db]} on-ramps]
|
||||
{:db (assoc
|
||||
@@ -252,7 +260,7 @@
|
||||
:buy-crypto/on-ramps
|
||||
(map on-ramp<-rpc on-ramps))})
|
||||
|
||||
(fx/defn buy-crypto-ui-loaded
|
||||
(rf/defn buy-crypto-ui-loaded
|
||||
{:events [:buy-crypto.ui/loaded]}
|
||||
[_]
|
||||
{::json-rpc/call [{:method "wallet_getCryptoOnRamps"
|
||||
@@ -260,10 +268,10 @@
|
||||
:on-success (fn [on-ramps]
|
||||
(re-frame/dispatch [::crypto-loaded on-ramps]))}]})
|
||||
|
||||
(fx/defn open-buy-crypto-screen
|
||||
(rf/defn open-buy-crypto-screen
|
||||
{:events [:buy-crypto.ui/open-screen]}
|
||||
[cofx]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
(navigation/open-modal :buy-crypto nil)
|
||||
(wallet/keep-watching-history)))
|
||||
@@ -275,38 +283,45 @@
|
||||
:global? true/false (close information box across all profiles)}]"
|
||||
[])
|
||||
|
||||
(defn information-box-id-hash [id public-key global?]
|
||||
(defn information-box-id-hash
|
||||
[id public-key global?]
|
||||
(if global?
|
||||
(hash id)
|
||||
(hash (str public-key id))))
|
||||
|
||||
(fx/defn close-information-box
|
||||
(rf/defn close-information-box
|
||||
{:events [:close-information-box]}
|
||||
[{:keys [db]} id global?]
|
||||
(let [public-key (get-in db [:multiaccount :public-key])
|
||||
hash (information-box-id-hash id public-key global?)]
|
||||
{::async-storage/set! {hash true}
|
||||
:db (assoc-in db [:information-box-states id] true)}))
|
||||
:db (assoc-in db [:information-box-states id] true)}))
|
||||
|
||||
(fx/defn information-box-states-loaded
|
||||
(rf/defn information-box-states-loaded
|
||||
{:events [:information-box-states-loaded]}
|
||||
[{:keys [db]} hashes states]
|
||||
{:db (assoc db :information-box-states (reduce
|
||||
(fn [acc [id hash]]
|
||||
(assoc acc id (get states hash)))
|
||||
{} hashes))})
|
||||
{:db (assoc db
|
||||
:information-box-states
|
||||
(reduce
|
||||
(fn [acc [id hash]]
|
||||
(assoc acc id (get states hash)))
|
||||
{}
|
||||
hashes))})
|
||||
|
||||
(fx/defn load-information-box-states
|
||||
(rf/defn load-information-box-states
|
||||
{:events [:load-information-box-states]}
|
||||
[{:keys [db]}]
|
||||
(let [public-key (get-in db [:multiaccount :public-key])
|
||||
{:keys [keys hashes]} (reduce (fn [acc {:keys [id global?]}]
|
||||
(let [hash (information-box-id-hash
|
||||
id public-key global?)]
|
||||
id
|
||||
public-key
|
||||
global?)]
|
||||
(-> acc
|
||||
(assoc-in [:hashes id] hash)
|
||||
(update :keys #(conj % hash)))))
|
||||
{} closable-information-boxes)]
|
||||
{}
|
||||
closable-information-boxes)]
|
||||
{::async-storage/get {:keys keys
|
||||
:cb #(re-frame/dispatch
|
||||
[:information-box-states-loaded hashes %])}}))
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.node.core :as node]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.utils.fx :as fx]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn current-fleet-sub
|
||||
[multiaccount]
|
||||
@@ -14,10 +14,10 @@
|
||||
|
||||
(defn format-mailserver
|
||||
[mailserver address]
|
||||
{:id mailserver
|
||||
:name (name mailserver)
|
||||
{:id mailserver
|
||||
:name (name mailserver)
|
||||
:password constants/mailserver-password
|
||||
:address address})
|
||||
:address address})
|
||||
|
||||
(defn format-mailservers
|
||||
[mailservers]
|
||||
@@ -26,13 +26,14 @@
|
||||
{}
|
||||
mailservers))
|
||||
|
||||
(defn default-mailservers [db]
|
||||
(defn default-mailservers
|
||||
[db]
|
||||
(reduce (fn [acc [fleet node-by-type]]
|
||||
(assoc acc fleet (format-mailservers (:mail node-by-type))))
|
||||
{}
|
||||
(node/fleets db)))
|
||||
|
||||
(fx/defn show-save-confirmation
|
||||
(rf/defn show-save-confirmation
|
||||
{:events [:fleet.ui/fleet-selected]}
|
||||
[_ fleet]
|
||||
{:ui/show-confirmation
|
||||
@@ -44,7 +45,8 @@
|
||||
#(re-frame/dispatch [:fleet.ui/save-fleet-confirmed (keyword fleet)])
|
||||
:on-cancel nil}})
|
||||
|
||||
(defn nodes->fleet [nodes]
|
||||
(defn nodes->fleet
|
||||
[nodes]
|
||||
(letfn [(format-nodes [nodes]
|
||||
(reduce (fn [acc n]
|
||||
(assoc acc
|
||||
@@ -52,28 +54,30 @@
|
||||
n))
|
||||
{}
|
||||
nodes))]
|
||||
{:boot (format-nodes nodes)
|
||||
:mail (format-nodes nodes)
|
||||
{:boot (format-nodes nodes)
|
||||
:mail (format-nodes nodes)
|
||||
:whisper (format-nodes nodes)}))
|
||||
|
||||
(fx/defn set-nodes [{:keys [db]} fleet nodes]
|
||||
(rf/defn set-nodes
|
||||
[{:keys [db]} fleet nodes]
|
||||
{:db (-> db
|
||||
(assoc-in [:custom-fleets fleet] (nodes->fleet nodes))
|
||||
(assoc-in [:mailserver/mailservers fleet] (format-mailservers
|
||||
(reduce
|
||||
(fn [acc e]
|
||||
(assoc acc
|
||||
(keyword e)
|
||||
e))
|
||||
{}
|
||||
nodes))))})
|
||||
(assoc-in [:mailserver/mailservers fleet]
|
||||
(format-mailservers
|
||||
(reduce
|
||||
(fn [acc e]
|
||||
(assoc acc
|
||||
(keyword e)
|
||||
e))
|
||||
{}
|
||||
nodes))))})
|
||||
|
||||
(fx/defn save
|
||||
(rf/defn save
|
||||
{:events [:fleet.ui/save-fleet-confirmed]}
|
||||
[{:keys [db now] :as cofx} fleet]
|
||||
(let [old-fleet (get-in db [:multiaccount :fleet])]
|
||||
(when (not= fleet old-fleet)
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
(multiaccounts.update/multiaccount-update :fleet fleet {})
|
||||
(node/prepare-new-config
|
||||
|
||||
@@ -4,35 +4,36 @@
|
||||
[clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.chat.models :as models.chat]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.activity-center.core :as activity-center]))
|
||||
[status-im2.contexts.activity-center.events :as activity-center]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn navigate-chat-updated
|
||||
(rf/defn navigate-chat-updated
|
||||
{:events [:navigate-chat-updated]}
|
||||
[cofx chat-id]
|
||||
(when (get-in cofx [:db :chats chat-id])
|
||||
(models.chat/navigate-to-chat cofx chat-id)))
|
||||
|
||||
(fx/defn handle-chat-removed
|
||||
(rf/defn handle-chat-removed
|
||||
{:events [:chat-removed]}
|
||||
[cofx response]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (dissoc (:db cofx) :current-chat-id)
|
||||
:dispatch-n [[:sanitize-messages-and-process-response response]
|
||||
[:pop-to-root-tab :chat-stack]]}
|
||||
(activity-center/notifications-fetch-unread-count)))
|
||||
|
||||
(fx/defn handle-chat-update
|
||||
(rf/defn handle-chat-update
|
||||
{:events [:chat-updated]}
|
||||
[_ response do-not-navigate?]
|
||||
{:dispatch-n [[:sanitize-messages-and-process-response response]
|
||||
(when-not do-not-navigate? [:navigate-chat-updated (.-id (aget (.-chats response) 0))])]})
|
||||
(when-not do-not-navigate?
|
||||
[:navigate-chat-updated (.-id (aget (.-chats response) 0))])]})
|
||||
|
||||
(fx/defn remove-member
|
||||
(rf/defn remove-member
|
||||
"Format group update message and sign membership"
|
||||
{:events [:group-chats.ui/remove-member-pressed]}
|
||||
[_ chat-id member do-not-navigate?]
|
||||
@@ -41,7 +42,7 @@
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:chat-updated % do-not-navigate?])}]})
|
||||
|
||||
(fx/defn join-chat
|
||||
(rf/defn join-chat
|
||||
{:events [:group-chats.ui/join-pressed]}
|
||||
[_ chat-id]
|
||||
{::json-rpc/call [{:method "wakuext_confirmJoiningGroup"
|
||||
@@ -49,7 +50,7 @@
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:chat-updated %])}]})
|
||||
|
||||
(fx/defn create
|
||||
(rf/defn create
|
||||
{:events [:group-chats.ui/create-pressed]
|
||||
:interceptors [(re-frame/inject-cofx :random-guid-generator)]}
|
||||
[{:keys [db] :as cofx} group-name]
|
||||
@@ -59,7 +60,7 @@
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:chat-updated %])}]}))
|
||||
|
||||
(fx/defn create-from-link
|
||||
(rf/defn create-from-link
|
||||
[cofx {:keys [chat-id invitation-admin chat-name]}]
|
||||
(if (get-in cofx [:db :chats chat-id])
|
||||
{:dispatch [:chat.ui/navigate-to-chat chat-id]}
|
||||
@@ -68,7 +69,7 @@
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:chat-updated %])}]}))
|
||||
|
||||
(fx/defn make-admin
|
||||
(rf/defn make-admin
|
||||
{:events [:group-chats.ui/make-admin-pressed]}
|
||||
[_ chat-id member]
|
||||
{::json-rpc/call [{:method "wakuext_addAdminsToGroupChat"
|
||||
@@ -76,7 +77,7 @@
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:chat-updated %])}]})
|
||||
|
||||
(fx/defn add-members
|
||||
(rf/defn add-members
|
||||
"Add members to a group chat"
|
||||
{:events [:group-chats.ui/add-members-pressed]}
|
||||
[{{:keys [current-chat-id selected-participants]} :db :as cofx}]
|
||||
@@ -85,7 +86,7 @@
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:chat-updated %])}]})
|
||||
|
||||
(fx/defn add-members-from-invitation
|
||||
(rf/defn add-members-from-invitation
|
||||
"Add members to a group chat"
|
||||
{:events [:group-chats.ui/add-members-from-invitation]}
|
||||
[{{:keys [current-chat-id] :as db} :db :as cofx} id participant]
|
||||
@@ -95,7 +96,7 @@
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:chat-updated %])}]})
|
||||
|
||||
(fx/defn leave
|
||||
(rf/defn leave
|
||||
"Leave chat"
|
||||
{:events [:group-chats.ui/leave-chat-confirmed]}
|
||||
[{:keys [db] :as cofx} chat-id]
|
||||
@@ -104,21 +105,22 @@
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:chat-removed %])}]})
|
||||
|
||||
(fx/defn remove
|
||||
(rf/defn remove
|
||||
"Remove chat"
|
||||
{:events [:group-chats.ui/remove-chat-confirmed]}
|
||||
[cofx chat-id]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(models.chat/deactivate-chat chat-id)
|
||||
(navigation/pop-to-root-tab :chat-stack)))
|
||||
|
||||
(def not-blank?
|
||||
(complement string/blank?))
|
||||
|
||||
(defn- valid-name? [name]
|
||||
(defn- valid-name?
|
||||
[name]
|
||||
(spec/valid? not-blank? name))
|
||||
|
||||
(fx/defn name-changed
|
||||
(rf/defn name-changed
|
||||
"Save chat from edited profile"
|
||||
{:events [:group-chats.ui/name-changed]}
|
||||
[{:keys [db] :as cofx} chat-id new-name]
|
||||
@@ -129,29 +131,29 @@
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:chat-updated %])}]}))
|
||||
|
||||
(fx/defn membership-retry
|
||||
(rf/defn membership-retry
|
||||
{:events [:group-chats.ui/membership-retry]}
|
||||
[{{:keys [current-chat-id] :as db} :db}]
|
||||
{:db (assoc-in db [:chat/memberships current-chat-id :retry?] true)})
|
||||
|
||||
(fx/defn membership-message
|
||||
(rf/defn membership-message
|
||||
{:events [:group-chats.ui/update-membership-message]}
|
||||
[{{:keys [current-chat-id] :as db} :db} message]
|
||||
{:db (assoc-in db [:chat/memberships current-chat-id :message] message)})
|
||||
|
||||
(fx/defn send-group-chat-membership-request
|
||||
(rf/defn send-group-chat-membership-request
|
||||
"Send group chat membership request"
|
||||
{:events [:send-group-chat-membership-request]}
|
||||
[{{:keys [current-chat-id chats] :as db} :db :as cofx}]
|
||||
(let [{:keys [invitation-admin]} (get chats current-chat-id)
|
||||
message (get-in db [:chat/memberships current-chat-id :message])]
|
||||
message (get-in db [:chat/memberships current-chat-id :message])]
|
||||
{:db (assoc-in db [:chat/memberships current-chat-id] nil)
|
||||
::json-rpc/call [{:method "wakuext_sendGroupChatInvitationRequest"
|
||||
:params [nil current-chat-id invitation-admin message]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]}))
|
||||
|
||||
(fx/defn send-group-chat-membership-rejection
|
||||
(rf/defn send-group-chat-membership-rejection
|
||||
"Send group chat membership rejection"
|
||||
{:events [:send-group-chat-membership-rejection]}
|
||||
[cofx invitation-id]
|
||||
@@ -160,14 +162,17 @@
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]})
|
||||
|
||||
(fx/defn handle-invitations
|
||||
(rf/defn handle-invitations
|
||||
[{db :db} invitations]
|
||||
{:db (update db :group-chat/invitations #(reduce (fn [acc {:keys [id] :as inv}]
|
||||
(assoc acc id inv))
|
||||
%
|
||||
invitations))})
|
||||
{:db (update db
|
||||
:group-chat/invitations
|
||||
#(reduce (fn [acc {:keys [id] :as inv}]
|
||||
(assoc acc id inv))
|
||||
%
|
||||
invitations))})
|
||||
|
||||
(defn member-removed? [{:keys [membership-update-events]} pk]
|
||||
(defn member-removed?
|
||||
[{:keys [membership-update-events]} pk]
|
||||
(->> membership-update-events
|
||||
(filter #(contains? (set (:members %)) pk))
|
||||
(sort-by :clockValue >)
|
||||
@@ -175,41 +180,41 @@
|
||||
:type
|
||||
(= constants/invitation-state-removed)))
|
||||
|
||||
(fx/defn deselect-contact
|
||||
(rf/defn deselect-contact
|
||||
{:events [:deselect-contact]}
|
||||
[{:keys [db]} id]
|
||||
{:db (update db :group/selected-contacts disj id)})
|
||||
|
||||
(fx/defn select-contact
|
||||
(rf/defn select-contact
|
||||
{:events [:select-contact]}
|
||||
[{:keys [db]} id]
|
||||
{:db (update db :group/selected-contacts conj id)})
|
||||
|
||||
(fx/defn deselect-participant
|
||||
(rf/defn deselect-participant
|
||||
{:events [:deselect-participant]}
|
||||
[{:keys [db]} id]
|
||||
{:db (update db :selected-participants disj id)})
|
||||
|
||||
(fx/defn select-participant
|
||||
(rf/defn select-participant
|
||||
{:events [:select-participant]}
|
||||
[{:keys [db]} id]
|
||||
{:db (update db :selected-participants conj id)})
|
||||
|
||||
(fx/defn add-participants-toggle-list
|
||||
(rf/defn add-participants-toggle-list
|
||||
{:events [:group/add-participants-toggle-list]}
|
||||
[{db :db}]
|
||||
{:db (assoc db :selected-participants #{})})
|
||||
|
||||
(fx/defn show-group-chat-profile
|
||||
(rf/defn show-group-chat-profile
|
||||
{:events [:show-group-chat-profile]}
|
||||
[{:keys [db] :as cofx} chat-id]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc :new-chat-name (get-in db [:chats chat-id :name]))
|
||||
(assoc :current-chat-id chat-id))}
|
||||
(navigation/navigate-to-cofx :group-chat-profile nil)))
|
||||
|
||||
(fx/defn ui-leave-chat-pressed
|
||||
(rf/defn ui-leave-chat-pressed
|
||||
{:events [:group-chats.ui/leave-chat-pressed]}
|
||||
[{:keys [db]} chat-id]
|
||||
(let [chat-name (get-in db [:chats chat-id :name])]
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
status-im.events
|
||||
status-im2.navigation.core
|
||||
[status-im.chat.models :as chat.models]
|
||||
[status-im.utils.security :as security]
|
||||
[utils.security.core :as security]
|
||||
[status-im.multiaccounts.logout.core :as logout]
|
||||
[status-im.transport.core :as transport]
|
||||
status-im2.subs.root ;;so integration tests can run independently
|
||||
@@ -103,7 +103,7 @@
|
||||
(initialize-app!) ; initialize app
|
||||
(rf-test/wait-for
|
||||
[:setup/initialize-view]
|
||||
(generate-and-derive-addresses!) ; generate 5 new keys
|
||||
(generate-and-derive-addresses!) ; generate 5 new keys
|
||||
(rf-test/wait-for
|
||||
[:multiaccount-generate-and-derive-addresses-success]
|
||||
(assert-multiaccount-loaded) ; assert keys are generated
|
||||
|
||||
@@ -1,69 +1,72 @@
|
||||
(ns status-im.keycard.backup-key
|
||||
(:require [status-im.utils.fx :as fx]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.ethereum.mnemonic :as mnemonic]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.keycard.common :as common]
|
||||
[status-im.multiaccounts.recover.core :as multiaccounts.recover]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.signing.core :as signing.core]
|
||||
[taoensso.timbre :as log]))
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn backup-card-pressed
|
||||
(rf/defn backup-card-pressed
|
||||
{:events [:keycard-settings.ui/backup-card-pressed]}
|
||||
[{:keys [db] :as cofx} backup-type]
|
||||
(log/debug "[keycard] start backup")
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :creating-backup?] backup-type))}
|
||||
(when (:multiaccount db)
|
||||
(navigation/change-tab :profile))
|
||||
(navigation/navigate-to-cofx :seed-phrase nil)))
|
||||
|
||||
(fx/defn recovery-card-pressed
|
||||
(rf/defn recovery-card-pressed
|
||||
{:events [:keycard-settings.ui/recovery-card-pressed]}
|
||||
[{:keys [db] :as cofx} show-warning]
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
;setting pin-retry-counter is a workaround for the way the PIN view decides if it should accept PUK or PIN
|
||||
(assoc-in [:keycard :application-info :pin-retry-counter] 3)
|
||||
(assoc-in [:keycard :factory-reset-card?] true)
|
||||
(dissoc :popover/popover))
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
;setting pin-retry-counter is a workaround for the way the PIN view
|
||||
;decides if it should accept PUK or PIN
|
||||
(assoc-in [:keycard :application-info :pin-retry-counter] 3)
|
||||
(assoc-in [:keycard :factory-reset-card?] true)
|
||||
(dissoc :popover/popover))
|
||||
:hide-popover nil}
|
||||
(signing.core/discard)
|
||||
(if show-warning
|
||||
(utils/show-confirmation {:title (i18n/label :t/keycard-recover-title)
|
||||
:content (i18n/label :t/keycard-recover-text)
|
||||
:confirm-button-text (i18n/label :t/yes)
|
||||
:cancel-button-text (i18n/label :t/no)
|
||||
:on-accept #(re-frame/dispatch [:keycard-settings.ui/backup-card-pressed :recovery-card])
|
||||
:on-cancel #()})
|
||||
(utils/show-confirmation
|
||||
{:title (i18n/label :t/keycard-recover-title)
|
||||
:content (i18n/label :t/keycard-recover-text)
|
||||
:confirm-button-text (i18n/label :t/yes)
|
||||
:cancel-button-text (i18n/label :t/no)
|
||||
:on-accept #(re-frame/dispatch [:keycard-settings.ui/backup-card-pressed
|
||||
:recovery-card])
|
||||
:on-cancel #()})
|
||||
(backup-card-pressed :recovery-card))))
|
||||
|
||||
(fx/defn start-keycard-backup
|
||||
(rf/defn start-keycard-backup
|
||||
{:events [::start-keycard-backup]}
|
||||
[{:keys [db] :as cofx}]
|
||||
{::multiaccounts.recover/import-multiaccount {:passphrase (-> db
|
||||
:multiaccounts/key-storage
|
||||
:seed-phrase
|
||||
mnemonic/sanitize-passphrase)
|
||||
:password nil
|
||||
{::multiaccounts.recover/import-multiaccount {:passphrase (-> db
|
||||
:multiaccounts/key-storage
|
||||
:seed-phrase
|
||||
mnemonic/sanitize-passphrase)
|
||||
:password nil
|
||||
:success-event ::create-backup-card}})
|
||||
|
||||
(fx/defn create-backup-card
|
||||
(rf/defn create-backup-card
|
||||
{:events [::create-backup-card]}
|
||||
[{:keys [db] :as cofx} root-data derived-data]
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
(update :intro-wizard
|
||||
assoc
|
||||
:root-key root-data
|
||||
:derived derived-data
|
||||
:recovering? true
|
||||
:selected-storage-type :advanced)
|
||||
(assoc-in [:keycard :flow] :recovery)
|
||||
(update :multiaccounts/key-storage dissoc :seed-phrase))
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(update :intro-wizard
|
||||
assoc
|
||||
:root-key root-data
|
||||
:derived derived-data
|
||||
:recovering? true
|
||||
:selected-storage-type :advanced)
|
||||
(assoc-in [:keycard :flow] :recovery)
|
||||
(update :multiaccounts/key-storage dissoc :seed-phrase))
|
||||
:dismiss-keyboard nil}
|
||||
(common/listen-to-hardware-back-button)
|
||||
(navigation/navigate-to-cofx :keycard-onboarding-intro nil)))
|
||||
|
||||
@@ -1,71 +1,74 @@
|
||||
(ns status-im.keycard.change-pin
|
||||
(:require [status-im.i18n.i18n :as i18n]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.keycard.onboarding :as onboarding]
|
||||
[status-im.utils.fx :as fx]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.keycard.common :as common]
|
||||
[status-im.utils.security :as security]))
|
||||
[status-im.keycard.onboarding :as onboarding]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(fx/defn change-credentials-pressed
|
||||
(rf/defn change-credentials-pressed
|
||||
{:events [:keycard-settings.ui/change-credentials-pressed]}
|
||||
[{:keys [db] :as cofx} changing]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db
|
||||
(assoc-in db [:keycard :pin] {:enter-step :current
|
||||
:current []
|
||||
:puk []
|
||||
:original []
|
||||
:confirmation []
|
||||
:puk-original []
|
||||
:puk-confirmation []
|
||||
:status nil
|
||||
:error-label nil
|
||||
:on-verified (case changing
|
||||
:pin :keycard/proceed-to-change-pin
|
||||
:puk :keycard/proceed-to-change-puk
|
||||
:pairing :keycard/proceed-to-change-pairing)})}
|
||||
(assoc-in db
|
||||
[:keycard :pin]
|
||||
{:enter-step :current
|
||||
:current []
|
||||
:puk []
|
||||
:original []
|
||||
:confirmation []
|
||||
:puk-original []
|
||||
:puk-confirmation []
|
||||
:status nil
|
||||
:error-label nil
|
||||
:on-verified (case changing
|
||||
:pin :keycard/proceed-to-change-pin
|
||||
:puk :keycard/proceed-to-change-puk
|
||||
:pairing :keycard/proceed-to-change-pairing)})}
|
||||
(common/navigate-to-enter-pin-screen)))
|
||||
|
||||
(fx/defn proceed-to-change-pin
|
||||
(rf/defn proceed-to-change-pin
|
||||
{:events [:keycard/proceed-to-change-pin]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :pin :enter-step] :original)
|
||||
(assoc-in [:keycard :pin :status] nil))}
|
||||
(navigation/navigate-replace :enter-pin-settings nil)))
|
||||
|
||||
(fx/defn proceed-to-change-puk
|
||||
(rf/defn proceed-to-change-puk
|
||||
{:events [:keycard/proceed-to-change-puk]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :pin :enter-step] :puk-original)
|
||||
(assoc-in [:keycard :pin :status] nil))}
|
||||
(navigation/navigate-replace :enter-pin-settings nil)))
|
||||
|
||||
(fx/defn proceed-to-change-pairing
|
||||
(rf/defn proceed-to-change-pairing
|
||||
{:events [:keycard/proceed-to-change-pairing]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(navigation/navigate-replace cofx :change-pairing-code nil))
|
||||
|
||||
(fx/defn discard-pin-change
|
||||
(rf/defn discard-pin-change
|
||||
{:events [::on-cancel]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(common/clear-pin)
|
||||
(common/hide-connection-sheet)
|
||||
(if (get-in db [:keycard :pin :puk-restore?])
|
||||
(navigation/navigate-to-cofx :multiaccounts nil)
|
||||
(navigation/set-stack-root :profile-stack [:my-profile :keycard-settings]))))
|
||||
|
||||
(fx/defn change-pin
|
||||
(rf/defn change-pin
|
||||
{:events [:keycard/change-pin]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [setup-step (get-in db [:keycard :setup-step])]
|
||||
(log/debug "[keycard] change-pin"
|
||||
"setup-step" setup-step)
|
||||
"setup-step"
|
||||
setup-step)
|
||||
(if (= setup-step :pin)
|
||||
(onboarding/load-preparing-screen cofx)
|
||||
(common/show-connection-sheet
|
||||
@@ -78,15 +81,15 @@
|
||||
(get-in db [:keycard :pin :original]))
|
||||
current-pin (common/vector->string
|
||||
(get-in db [:keycard :pin :current]))]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (assoc-in db [:keycard :pin :status] :verifying)
|
||||
{:db (assoc-in db [:keycard :pin :status] :verifying)
|
||||
|
||||
:keycard/change-pin
|
||||
{:new-pin new-pin
|
||||
:current-pin current-pin}})))}))))
|
||||
|
||||
(fx/defn change-puk
|
||||
(rf/defn change-puk
|
||||
{:events [:keycard/change-puk]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(common/show-connection-sheet
|
||||
@@ -99,13 +102,13 @@
|
||||
(get-in db [:keycard :pin :puk-original]))
|
||||
pin (common/vector->string
|
||||
(get-in db [:keycard :pin :current]))]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (assoc-in db [:keycard :pin :status] :verifying)
|
||||
:keycard/change-puk {:puk puk
|
||||
:pin pin}})))}))
|
||||
|
||||
(fx/defn change-pairing
|
||||
(rf/defn change-pairing
|
||||
{:events [:keycard/change-pairing]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(common/show-connection-sheet
|
||||
@@ -117,30 +120,32 @@
|
||||
(let [pairing (get-in db [:keycard :pin :pairing-code])
|
||||
pin (common/vector->string
|
||||
(get-in db [:keycard :pin :current]))]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (assoc-in db [:keycard :pin :status] :verifying)
|
||||
:keycard/change-pairing {:pairing pairing
|
||||
:pin pin}})))}))
|
||||
|
||||
(fx/defn change-pairing-code
|
||||
(rf/defn change-pairing-code
|
||||
{:events [:keycard/change-pairing-code]}
|
||||
[{:keys [db] :as cofx} pairing]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (assoc-in db [:keycard :pin :pairing-code] (security/unmask pairing))}
|
||||
(change-pairing)))
|
||||
|
||||
(fx/defn on-change-pin-success
|
||||
(rf/defn on-change-pin-success
|
||||
{:events [:keycard.callback/on-change-pin-success]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [pin (get-in db [:keycard :pin :original])
|
||||
puk-restore? (get-in db [:keycard :pin :puk-restore?])]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:keycard :pin] {:status nil
|
||||
:login pin
|
||||
:confirmation []
|
||||
:error-label nil})
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:keycard :pin]
|
||||
{:status nil
|
||||
:login pin
|
||||
:confirmation []
|
||||
:error-label nil})
|
||||
:utils/show-popup {:title ""
|
||||
:content (i18n/label :t/pin-changed)}}
|
||||
(common/hide-connection-sheet)
|
||||
@@ -150,55 +155,61 @@
|
||||
(when (:multiaccounts/login db)
|
||||
(common/get-keys-from-keycard)))))
|
||||
|
||||
(fx/defn on-change-puk-success
|
||||
(rf/defn on-change-puk-success
|
||||
{:events [:keycard.callback/on-change-puk-success]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:keycard :pin] {:status nil
|
||||
:puk-original []
|
||||
:puk-confirmation []
|
||||
:error-label nil})
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:keycard :pin]
|
||||
{:status nil
|
||||
:puk-original []
|
||||
:puk-confirmation []
|
||||
:error-label nil})
|
||||
:utils/show-popup {:title ""
|
||||
:content (i18n/label :t/puk-changed)}}
|
||||
(common/hide-connection-sheet)
|
||||
(navigation/set-stack-root :profile-stack [:my-profile :keycard-settings])))
|
||||
|
||||
(fx/defn on-change-pairing-success
|
||||
(rf/defn on-change-pairing-success
|
||||
{:events [:keycard.callback/on-change-pairing-success]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:keycard :pin] {:status nil
|
||||
:pairing-code nil
|
||||
:error-label nil})
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:keycard :pin]
|
||||
{:status nil
|
||||
:pairing-code nil
|
||||
:error-label nil})
|
||||
:utils/show-popup {:title ""
|
||||
:content (i18n/label :t/pairing-changed)}}
|
||||
(common/hide-connection-sheet)
|
||||
(navigation/set-stack-root :profile-stack [:my-profile :keycard-settings])))
|
||||
|
||||
(fx/defn on-change-pin-error
|
||||
(rf/defn on-change-pin-error
|
||||
{:events [:keycard.callback/on-change-pin-error]}
|
||||
[{:keys [db] :as cofx} error]
|
||||
(log/debug "[keycard] change pin error" error)
|
||||
(let [tag-was-lost? (common/tag-lost? (:error error))
|
||||
pin-retries (common/pin-retries (:error error))]
|
||||
(fx/merge cofx
|
||||
(if tag-was-lost?
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:keycard :pin :status] nil)}
|
||||
(common/set-on-card-connected :keycard/change-pin))
|
||||
(if-not (nil? pin-retries)
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :application-info :pin-retry-counter] pin-retries)
|
||||
(update-in [:keycard :pin] assoc
|
||||
:status :error
|
||||
:enter-step :current
|
||||
:puk []
|
||||
:current []
|
||||
:original []
|
||||
:confirmation []
|
||||
:sign []
|
||||
:error-label :t/pin-mismatch))}
|
||||
(when (zero? pin-retries) (common/frozen-keycard-popup))
|
||||
(navigation/navigate-to-cofx :enter-pin-settings nil))
|
||||
(common/show-wrong-keycard-alert))))))
|
||||
pin-retries (common/pin-retries (:error error))]
|
||||
(rf/merge
|
||||
cofx
|
||||
(if tag-was-lost?
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :pin :status] nil)}
|
||||
(common/set-on-card-connected :keycard/change-pin))
|
||||
(if-not (nil? pin-retries)
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :application-info :pin-retry-counter] pin-retries)
|
||||
(update-in [:keycard :pin]
|
||||
assoc
|
||||
:status :error
|
||||
:enter-step :current
|
||||
:puk []
|
||||
:current []
|
||||
:original []
|
||||
:confirmation []
|
||||
:sign []
|
||||
:error-label :t/pin-mismatch))}
|
||||
(when (zero? pin-retries) (common/frozen-keycard-popup))
|
||||
(navigation/navigate-to-cofx :enter-pin-settings nil))
|
||||
(common/show-wrong-keycard-alert))))))
|
||||
|
||||
+147
-129
@@ -1,28 +1,30 @@
|
||||
(ns status-im.keycard.common
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.keycard.nfc :as nfc]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.ui.screens.keycard.keycard-interaction :as keycard-sheet]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.keychain.core :as keychain]
|
||||
[status-im.utils.types :as types]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.utils.datetime :as utils.datetime]
|
||||
[status-im.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.keycard.nfc :as nfc]
|
||||
[status-im.popover.core :as popover]
|
||||
[status-im.ui.screens.keycard.keycard-interaction :as keycard-sheet]
|
||||
[status-im.utils.datetime :as utils.datetime]
|
||||
[status-im.utils.keychain.core :as keychain]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.popover.core :as popover]))
|
||||
[status-im.utils.types :as types]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def default-pin "000000")
|
||||
|
||||
(def pin-mismatch-error #"Unexpected error SW, 0x63C(\d+)|wrongPIN\(retryCounter: (\d+)\)")
|
||||
|
||||
(defn pin-retries [error]
|
||||
(when-let [matched-error (re-matches pin-mismatch-error error)] (js/parseInt (second (filter some? matched-error)))))
|
||||
(defn pin-retries
|
||||
[error]
|
||||
(when-let [matched-error (re-matches pin-mismatch-error error)]
|
||||
(js/parseInt (second (filter some? matched-error)))))
|
||||
|
||||
(fx/defn dispatch-event
|
||||
(rf/defn dispatch-event
|
||||
[_ event]
|
||||
{:dispatch [event]})
|
||||
|
||||
@@ -56,7 +58,8 @@
|
||||
(zero? free-pairing-slots))
|
||||
:no-pairing-slots))
|
||||
|
||||
(defn tag-lost? [error]
|
||||
(defn tag-lost?
|
||||
[error]
|
||||
(or
|
||||
(= error "Tag was lost.")
|
||||
(= error "NFCError:100")
|
||||
@@ -94,24 +97,24 @@
|
||||
(fn [supported?]
|
||||
(nfc/set-nfc-supported? supported?)))
|
||||
|
||||
(fx/defn listen-to-hardware-back-button
|
||||
(rf/defn listen-to-hardware-back-button
|
||||
[{:keys [db]}]
|
||||
(when-not (get-in db [:keycard :back-button-listener])
|
||||
{:keycard/listen-to-hardware-back-button nil}))
|
||||
|
||||
(fx/defn remove-listener-to-hardware-back-button
|
||||
(rf/defn remove-listener-to-hardware-back-button
|
||||
[{:keys [db]}]
|
||||
(when-let [listener (get-in db [:keycard :back-button-listener])]
|
||||
{:keycard/remove-listener-to-hardware-back-button listener}))
|
||||
|
||||
(fx/defn set-on-card-connected
|
||||
(rf/defn set-on-card-connected
|
||||
[{:keys [db]} on-connect]
|
||||
(log/debug "[keycard] set-on-card-connected" on-connect)
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :on-card-connected] on-connect)
|
||||
(assoc-in [:keycard :last-on-card-connected] nil))})
|
||||
|
||||
(fx/defn stash-on-card-connected
|
||||
(rf/defn stash-on-card-connected
|
||||
[{:keys [db]}]
|
||||
(let [on-connect (get-in db [:keycard :on-card-connected])]
|
||||
(log/debug "[keycard] stash-on-card-connected" on-connect)
|
||||
@@ -119,7 +122,7 @@
|
||||
(assoc-in [:keycard :last-on-card-connected] on-connect)
|
||||
(assoc-in [:keycard :on-card-connected] nil))}))
|
||||
|
||||
(fx/defn restore-on-card-connected
|
||||
(rf/defn restore-on-card-connected
|
||||
[{:keys [db]}]
|
||||
(let [on-connect (or
|
||||
(get-in db [:keycard :on-card-connected])
|
||||
@@ -129,21 +132,21 @@
|
||||
(assoc-in [:keycard :on-card-connected] on-connect)
|
||||
(assoc-in [:keycard :last-on-card-connect] nil))}))
|
||||
|
||||
(fx/defn clear-on-card-connected
|
||||
(rf/defn clear-on-card-connected
|
||||
[{:keys [db]}]
|
||||
(log/debug "[keycard] clear-on-card-connected")
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :on-card-connected] nil)
|
||||
(assoc-in [:keycard :last-on-card-connected] nil))})
|
||||
|
||||
(fx/defn set-on-card-read
|
||||
(rf/defn set-on-card-read
|
||||
[{:keys [db]} on-connect]
|
||||
(log/debug "[keycard] set-on-card-read" on-connect)
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :on-card-read] on-connect)
|
||||
(assoc-in [:keycard :last-on-card-read] nil))})
|
||||
|
||||
(fx/defn stash-on-card-read
|
||||
(rf/defn stash-on-card-read
|
||||
[{:keys [db]}]
|
||||
(let [on-connect (get-in db [:keycard :on-card-read])]
|
||||
(log/debug "[keycard] stash-on-card-read" on-connect)
|
||||
@@ -151,7 +154,7 @@
|
||||
(assoc-in [:keycard :last-on-card-read] on-connect)
|
||||
(assoc-in [:keycard :on-card-read] nil))}))
|
||||
|
||||
(fx/defn restore-on-card-read
|
||||
(rf/defn restore-on-card-read
|
||||
[{:keys [db]}]
|
||||
(let [on-connect (or
|
||||
(get-in db [:keycard :on-card-read])
|
||||
@@ -161,14 +164,15 @@
|
||||
(assoc-in [:keycard :on-card-read] on-connect)
|
||||
(assoc-in [:keycard :last-on-card-connect] nil))}))
|
||||
|
||||
(fx/defn clear-on-card-read
|
||||
(rf/defn clear-on-card-read
|
||||
[{:keys [db]}]
|
||||
(log/debug "[keycard] clear-on-card-read")
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :on-card-read] nil)
|
||||
(assoc-in [:keycard :last-on-card-read] nil))})
|
||||
|
||||
(defn keycard-sheet-content [on-cancel connected? params]
|
||||
(defn keycard-sheet-content
|
||||
[on-cancel connected? params]
|
||||
(fn []
|
||||
[keycard-sheet/connect-keycard
|
||||
{:on-cancel #(re-frame/dispatch on-cancel)
|
||||
@@ -177,17 +181,19 @@
|
||||
:on-connect ::on-card-connected
|
||||
:on-disconnect ::on-card-disconnected}]))
|
||||
|
||||
(fx/defn show-connection-sheet-component
|
||||
[{:keys [db] :as cofx} {:keys [on-card-connected on-card-read handler]
|
||||
{:keys [on-cancel]
|
||||
:or {on-cancel [::cancel-sheet-confirm]}}
|
||||
:sheet-options}]
|
||||
(rf/defn show-connection-sheet-component
|
||||
[{:keys [db] :as cofx}
|
||||
{:keys [on-card-connected on-card-read handler]
|
||||
{:keys [on-cancel]
|
||||
:or {on-cancel [::cancel-sheet-confirm]}}
|
||||
:sheet-options}]
|
||||
(assert (keyword? on-card-connected))
|
||||
(assert (fn? handler))
|
||||
(let [connected? (get-in db [:keycard :card-connected?])]
|
||||
(log/debug "[keycard] show-sheet-with-connection-check"
|
||||
"card-connected?" connected?)
|
||||
(fx/merge
|
||||
"card-connected?"
|
||||
connected?)
|
||||
(rf/merge
|
||||
cofx
|
||||
{:dismiss-keyboard true}
|
||||
(bottom-sheet/show-bottom-sheet
|
||||
@@ -205,7 +211,7 @@
|
||||
(when connected?
|
||||
handler))))
|
||||
|
||||
(fx/defn show-connection-sheet
|
||||
(rf/defn show-connection-sheet
|
||||
[{:keys [db] :as cofx} args]
|
||||
(let [nfc-running? (get-in db [:keycard :nfc-running?])]
|
||||
(log/debug "show connection; already running?" nfc-running?)
|
||||
@@ -213,59 +219,59 @@
|
||||
(show-connection-sheet-component cofx args)
|
||||
{:keycard/start-nfc-and-show-connection-sheet args})))
|
||||
|
||||
(fx/defn on-nfc-ready-for-sheet
|
||||
(rf/defn on-nfc-ready-for-sheet
|
||||
{:events [:keycard.callback/show-connection-sheet]}
|
||||
[cofx args]
|
||||
(log/debug "on-nfc-ready-for-sheet")
|
||||
(show-connection-sheet-component cofx args))
|
||||
|
||||
(fx/defn hide-connection-sheet-component
|
||||
(rf/defn hide-connection-sheet-component
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :card-read-in-progress?] false)}
|
||||
(restore-on-card-connected)
|
||||
(restore-on-card-read)
|
||||
(bottom-sheet/hide-bottom-sheet)))
|
||||
|
||||
(fx/defn hide-connection-sheet
|
||||
(rf/defn hide-connection-sheet
|
||||
[cofx]
|
||||
(log/debug "hide-connection-sheet")
|
||||
{:keycard/stop-nfc-and-hide-connection-sheet nil})
|
||||
|
||||
(fx/defn on-nfc-ready-to-close-sheet
|
||||
(rf/defn on-nfc-ready-to-close-sheet
|
||||
{:events [:keycard.callback/hide-connection-sheet]}
|
||||
[cofx]
|
||||
(log/debug "on-nfc-ready-to-close-sheet")
|
||||
(hide-connection-sheet-component cofx))
|
||||
|
||||
(fx/defn clear-pin
|
||||
(rf/defn clear-pin
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (assoc-in db
|
||||
[:keycard :pin]
|
||||
{:status nil
|
||||
:login (get-in db [:keycard :pin :original])
|
||||
:export-key []
|
||||
:sign []
|
||||
:puk []
|
||||
:current []
|
||||
:original []
|
||||
:confirmation []
|
||||
:error-label nil
|
||||
:on-verified (get-in db [:keycard :pin :on-verified])
|
||||
:on-verified-failure (get-in db [:keycard :pin :on-verified])})}))
|
||||
[:keycard :pin]
|
||||
{:status nil
|
||||
:login (get-in db [:keycard :pin :original])
|
||||
:export-key []
|
||||
:sign []
|
||||
:puk []
|
||||
:current []
|
||||
:original []
|
||||
:confirmation []
|
||||
:error-label nil
|
||||
:on-verified (get-in db [:keycard :pin :on-verified])
|
||||
:on-verified-failure (get-in db [:keycard :pin :on-verified])})}))
|
||||
|
||||
(fx/defn cancel-sheet-confirm
|
||||
(rf/defn cancel-sheet-confirm
|
||||
{:events [::cancel-sheet-confirm
|
||||
:keycard/back-button-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(when-not (get-in db [:keycard :card-connected?])
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(hide-connection-sheet)
|
||||
(clear-pin))))
|
||||
|
||||
(fx/defn cancel-sheet
|
||||
(rf/defn cancel-sheet
|
||||
{:events [::cancel-sheet]}
|
||||
[_]
|
||||
{:ui/show-confirmation {:title (i18n/label :t/keycard-cancel-setup-title)
|
||||
@@ -275,7 +281,7 @@
|
||||
:on-accept #(re-frame/dispatch [::cancel-sheet-confirm])
|
||||
:on-cancel #()}})
|
||||
|
||||
(fx/defn on-add-listener-to-hardware-back-button
|
||||
(rf/defn on-add-listener-to-hardware-back-button
|
||||
"Adds listener to hardware back button on Android.
|
||||
During keycard setup we show user a warning that setup will be cancelled
|
||||
when back button pressed. This prevents user from going back during setup
|
||||
@@ -284,120 +290,126 @@
|
||||
[{:keys [db]} listener]
|
||||
{:db (assoc-in db [:keycard :back-button-listener] listener)})
|
||||
|
||||
(fx/defn show-wrong-keycard-alert
|
||||
(rf/defn show-wrong-keycard-alert
|
||||
[_]
|
||||
(log/debug "show-wrong-keycard-alert")
|
||||
{:utils/show-popup {:title (i18n/label :t/wrong-card)
|
||||
:content (i18n/label :t/wrong-card-text)}})
|
||||
|
||||
(fx/defn unauthorized-operation
|
||||
(rf/defn unauthorized-operation
|
||||
[cofx]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:utils/show-popup {:title ""
|
||||
:content (i18n/label :t/keycard-unauthorized-operation)}}
|
||||
(clear-on-card-connected)
|
||||
(navigation/set-stack-root :profile-stack [:my-profile :keycard-settings])))
|
||||
|
||||
(fx/defn navigate-to-enter-pin-screen
|
||||
(rf/defn navigate-to-enter-pin-screen
|
||||
{:events [:keycard/navigate-to-enter-pin-screen]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :pin :current] [])}
|
||||
(navigation/navigate-to-cofx :enter-pin-settings nil)))
|
||||
|
||||
(defn- tag-lost-exception? [code error]
|
||||
(defn- tag-lost-exception?
|
||||
[code error]
|
||||
(or
|
||||
(= code "android.nfc.TagLostException")
|
||||
(= error "Tag was lost.")
|
||||
(= error "NFCError:100")))
|
||||
|
||||
(fx/defn process-error [{:keys [db]} code error]
|
||||
(rf/defn process-error
|
||||
[{:keys [db]} code error]
|
||||
(when-not (tag-lost-exception? code error)
|
||||
{:db (assoc-in db [:keycard :setup-step] :error)}))
|
||||
|
||||
(fx/defn get-keys-from-keycard
|
||||
(rf/defn get-keys-from-keycard
|
||||
[{:keys [db]}]
|
||||
(let [key-uid (get-in db [:multiaccounts/login :key-uid])
|
||||
pin (string/join (get-in db [:keycard :pin :login]))]
|
||||
(log/debug "[keycard] get-keys-from-keycard"
|
||||
", not empty pin:" (boolean (seq pin)))
|
||||
", not empty pin:"
|
||||
(boolean (seq pin)))
|
||||
(when (seq pin)
|
||||
{:db (assoc-in db [:keycard :pin :status] :verifying)
|
||||
:keycard/get-keys {:pin pin}})))
|
||||
|
||||
(fx/defn on-get-keys-success
|
||||
(rf/defn on-get-keys-success
|
||||
{:events [:keycard.callback/on-get-keys-success]}
|
||||
[{:keys [db] :as cofx} data]
|
||||
(let [{:keys [key-uid encryption-public-key whisper-private-key]
|
||||
:as account-data} (js->clj data :keywordize-keys true)
|
||||
:as account-data}
|
||||
(js->clj data :keywordize-keys true)
|
||||
{:keys [identicon name]} (get-in db [:multiaccounts/multiaccounts key-uid])
|
||||
key-uid (get-in db [:keycard :application-info :key-uid])
|
||||
multiaccount-data (types/clj->json {:name name
|
||||
:key-uid key-uid
|
||||
:identicon identicon})
|
||||
save-keys? (get-in db [:multiaccounts/login :save-password?])]
|
||||
(fx/merge cofx
|
||||
key-uid (get-in db [:keycard :application-info :key-uid])
|
||||
multiaccount-data (types/clj->json {:name name
|
||||
:key-uid key-uid
|
||||
:identicon identicon})
|
||||
save-keys? (get-in db [:multiaccounts/login :save-password?])]
|
||||
(rf/merge cofx
|
||||
{:db
|
||||
(-> db
|
||||
(assoc-in [:keycard :pin :status] nil)
|
||||
(assoc-in [:keycard :pin :login] [])
|
||||
(update-in [:keycard :application-info] assoc
|
||||
(update-in [:keycard :application-info]
|
||||
assoc
|
||||
:puk-retry-counter 5
|
||||
:pin-retry-counter 3)
|
||||
(assoc-in [:keycard :multiaccount]
|
||||
(update account-data :whisper-public-key ethereum/normalized-hex))
|
||||
(assoc-in [:keycard :flow] nil)
|
||||
(update :multiaccounts/login assoc
|
||||
:password encryption-public-key
|
||||
:key-uid key-uid
|
||||
:identicon identicon
|
||||
:name name))
|
||||
:password encryption-public-key
|
||||
:key-uid key-uid
|
||||
:identicon identicon
|
||||
:name name))
|
||||
|
||||
:keycard/login-with-keycard {:multiaccount-data multiaccount-data
|
||||
:password encryption-public-key
|
||||
:chat-key whisper-private-key
|
||||
:key-uid key-uid}}
|
||||
:keycard/login-with-keycard {:multiaccount-data multiaccount-data
|
||||
:password encryption-public-key
|
||||
:chat-key whisper-private-key
|
||||
:key-uid key-uid}}
|
||||
(when save-keys?
|
||||
(keychain/save-keycard-keys key-uid encryption-public-key whisper-private-key))
|
||||
(clear-on-card-connected)
|
||||
(clear-on-card-read)
|
||||
(hide-connection-sheet))))
|
||||
|
||||
(fx/defn blocked-or-frozen-keycard-popup
|
||||
(rf/defn blocked-or-frozen-keycard-popup
|
||||
[{:keys [db] :as cofx} card-status]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (assoc-in db [:keycard :pin :status] card-status)}
|
||||
(hide-connection-sheet)
|
||||
; do not try to display the popover if it is already open or
|
||||
; we are in the login interface (which has a different handling)
|
||||
; do not try to display the popover if it is already open or
|
||||
; we are in the login interface (which has a different handling)
|
||||
(when-not (or (:multiaccounts/login db) (:popover/popover db))
|
||||
(popover/show-popover {:view card-status}))))
|
||||
|
||||
(fx/defn blocked-keycard-popup
|
||||
(rf/defn blocked-keycard-popup
|
||||
[cofx]
|
||||
(blocked-or-frozen-keycard-popup cofx :blocked-card))
|
||||
|
||||
(fx/defn frozen-keycard-popup
|
||||
(rf/defn frozen-keycard-popup
|
||||
[cofx]
|
||||
(blocked-or-frozen-keycard-popup cofx :frozen-card))
|
||||
|
||||
(fx/defn on-get-keys-error
|
||||
(rf/defn on-get-keys-error
|
||||
{:events [:keycard.callback/on-get-keys-error]}
|
||||
[{:keys [db] :as cofx} error]
|
||||
(log/debug "[keycard] get keys error: " error)
|
||||
(let [tag-was-lost? (tag-lost? (:error error))
|
||||
key-uid (get-in db [:keycard :application-info :key-uid])
|
||||
flow (get-in db [:keycard :flow])
|
||||
pin-retries-count (pin-retries (:error error))]
|
||||
(let [tag-was-lost? (tag-lost? (:error error))
|
||||
key-uid (get-in db [:keycard :application-info :key-uid])
|
||||
flow (get-in db [:keycard :flow])
|
||||
pin-retries-count (pin-retries (:error error))]
|
||||
(if tag-was-lost?
|
||||
{:db (assoc-in db [:keycard :pin :status] nil)}
|
||||
(if-not (nil? pin-retries-count)
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :application-info :pin-retry-counter] pin-retries-count)
|
||||
(update-in [:keycard :pin] assoc
|
||||
(update-in [:keycard :pin]
|
||||
assoc
|
||||
:status :error
|
||||
:login []
|
||||
:import-multiaccount []
|
||||
@@ -406,42 +418,45 @@
|
||||
(when (zero? pin-retries-count) (frozen-keycard-popup)))
|
||||
(show-wrong-keycard-alert)))))
|
||||
|
||||
(fx/defn factory-reset
|
||||
(rf/defn factory-reset
|
||||
{:events [:keycard/factory-reset]}
|
||||
[{:keys [db]} on-card-read]
|
||||
(log/debug "[keycard] factory-reset")
|
||||
{:db (update db :keycard dissoc :factory-reset-card?)
|
||||
{:db (update db :keycard dissoc :factory-reset-card?)
|
||||
:keycard/factory-reset {:on-success on-card-read}})
|
||||
|
||||
;; Get application info
|
||||
|
||||
(fx/defn update-pairings
|
||||
(rf/defn update-pairings
|
||||
[{:keys [db]} instance-uid pairing]
|
||||
(let [paired-on (utils.datetime/timestamp)
|
||||
pairings (-> (get-in db [:keycard :pairings])
|
||||
(assoc instance-uid {:pairing pairing :paired-on paired-on}))]
|
||||
(let [paired-on (utils.datetime/timestamp)
|
||||
pairings (-> (get-in db [:keycard :pairings])
|
||||
(assoc instance-uid {:pairing pairing :paired-on paired-on}))]
|
||||
{:keycard/persist-pairings pairings
|
||||
:db (assoc-in db [:keycard :pairings] pairings)}))
|
||||
:db (assoc-in db [:keycard :pairings] pairings)}))
|
||||
|
||||
(fx/defn get-application-info
|
||||
(rf/defn get-application-info
|
||||
{:events [:keycard/get-application-info]}
|
||||
[{:keys [db]} on-card-read]
|
||||
(log/debug "[keycard] get-application-info")
|
||||
{:keycard/get-application-info {:on-success on-card-read}})
|
||||
|
||||
(fx/defn on-get-application-info-success
|
||||
(rf/defn on-get-application-info-success
|
||||
{:events [:keycard.callback/on-get-application-info-success]}
|
||||
[{:keys [db] :as cofx} info on-success]
|
||||
(let [{:keys [pin-retry-counter puk-retry-counter instance-uid new-pairing]} info
|
||||
view-id (:view-id db)
|
||||
{:keys [on-card-read]} (:keycard db)
|
||||
on-success' (or on-success on-card-read)
|
||||
enter-step (get-in db [:keycard :pin :enter-step])]
|
||||
view-id (:view-id db)
|
||||
{:keys [on-card-read]} (:keycard db)
|
||||
on-success' (or on-success
|
||||
on-card-read)
|
||||
enter-step (get-in db
|
||||
[:keycard :pin
|
||||
:enter-step])]
|
||||
(log/debug "[keycard] on-get-application-info-success"
|
||||
"on-success" on-success'
|
||||
"on-success" on-success'
|
||||
"pin-retry-counter" pin-retry-counter
|
||||
"puk-retry-counter" puk-retry-counter)
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :pin :enter-step] enter-step)
|
||||
@@ -461,7 +476,7 @@
|
||||
(when on-success'
|
||||
(dispatch-event cofx on-success')))))))
|
||||
|
||||
(fx/defn on-get-application-info-error
|
||||
(rf/defn on-get-application-info-error
|
||||
{:events [:keycard.callback/on-get-application-info-error]}
|
||||
[{:keys [db] :as cofx} error]
|
||||
(let [on-card-read (get-in db [:keycard :on-card-read])
|
||||
@@ -475,10 +490,10 @@
|
||||
last-on-card-connected)
|
||||
(when-not tag-was-lost?
|
||||
(if login?
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(clear-on-card-read)
|
||||
(navigation/navigate-to-cofx :not-keycard nil))
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :application-info-error] error)}
|
||||
|
||||
(when (contains?
|
||||
@@ -489,7 +504,7 @@
|
||||
(when on-card-read
|
||||
(dispatch-event on-card-read)))))))
|
||||
|
||||
(fx/defn on-card-connected
|
||||
(rf/defn on-card-connected
|
||||
{:events [::on-card-connected]}
|
||||
[{:keys [db] :as cofx} _]
|
||||
(let [instance-uid (get-in db [:keycard :application-info :instance-uid])
|
||||
@@ -500,9 +515,9 @@
|
||||
should-read-instance-uid? :keycard/get-application-info
|
||||
:else (get-in db [:keycard :on-card-read]))]
|
||||
(log/debug "[keycard] on-card-connected" on-card-connected
|
||||
"on-card-read" on-card-read)
|
||||
"on-card-read" on-card-read)
|
||||
(when on-card-connected
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :card-read-in-progress?] (boolean on-card-read)))}
|
||||
(when on-card-connected
|
||||
@@ -512,20 +527,21 @@
|
||||
(nil? on-card-connected))
|
||||
(get-application-info on-card-read))))))
|
||||
|
||||
(fx/defn on-card-disconnected
|
||||
(rf/defn on-card-disconnected
|
||||
{:events [::on-card-disconnected]}
|
||||
[{:keys [db] :as cofx} _]
|
||||
(log/debug "[keycard] card disconnected")
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :card-read-in-progress?] false))}
|
||||
(restore-on-card-connected)
|
||||
(restore-on-card-read)))
|
||||
|
||||
(defn keycard-multiaccount? [db]
|
||||
(defn keycard-multiaccount?
|
||||
[db]
|
||||
(boolean (get-in db [:multiaccount :keycard-pairing])))
|
||||
|
||||
(fx/defn verify-pin
|
||||
(rf/defn verify-pin
|
||||
{:events [:keycard/verify-pin]}
|
||||
[{:keys [db] :as cofx} {:keys [pin-step on-card-connected on-failure on-success]}]
|
||||
(let [on-success (or on-success
|
||||
@@ -534,23 +550,25 @@
|
||||
(get-in db [:keycard :pin :on-verified-failure]))
|
||||
pin-step (or pin-step
|
||||
(get-in db [:keycard :pin :step]))]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (update-in db [:keycard :pin] assoc
|
||||
:step pin-step
|
||||
:on-verified on-success
|
||||
{:db (update-in db
|
||||
[:keycard :pin]
|
||||
assoc
|
||||
:step pin-step
|
||||
:on-verified on-success
|
||||
:on-verified-failure on-failure)}
|
||||
(show-connection-sheet
|
||||
{:on-card-connected (or on-card-connected :keycard/verify-pin)
|
||||
:handler
|
||||
(fn [{:keys [db] :as cofx}]
|
||||
(let [pin (vector->string (get-in db [:keycard :pin pin-step]))]
|
||||
(fx/merge
|
||||
(let [pin (vector->string (get-in db [:keycard :pin pin-step]))]
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (assoc-in db [:keycard :pin :status] :verifying)
|
||||
{:db (assoc-in db [:keycard :pin :status] :verifying)
|
||||
:keycard/verify-pin {:pin pin}})))}))))
|
||||
|
||||
(fx/defn navigete-to-keycard-settings
|
||||
(rf/defn navigete-to-keycard-settings
|
||||
{:events [::navigate-to-keycard-settings]}
|
||||
[cofx]
|
||||
(navigation/set-stack-root :profile-stack [:my-profile :keycard-settings]))
|
||||
|
||||
+186
-143
@@ -1,70 +1,74 @@
|
||||
(ns status-im.keycard.core
|
||||
(:require [re-frame.db]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
status-im.keycard.backup-key
|
||||
[status-im.keycard.card :as card]
|
||||
[status-im.keycard.change-pin :as change-pin]
|
||||
[status-im.keycard.common :as common]
|
||||
status-im.keycard.delete-key
|
||||
status-im.keycard.export-key
|
||||
status-im.keycard.unpair
|
||||
status-im.keycard.backup-key
|
||||
[status-im.keycard.login :as login]
|
||||
[status-im.keycard.mnemonic :as mnemonic]
|
||||
[status-im.keycard.onboarding :as onboarding]
|
||||
[status-im.keycard.recovery :as recovery]
|
||||
[status-im.keycard.sign :as sign]
|
||||
status-im.keycard.unpair
|
||||
[status-im.keycard.wallet :as wallet]
|
||||
[status-im.keycard.card :as card]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.multiaccounts.recover.core :as multiaccounts.recover]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.utils.datetime :as utils.datetime]
|
||||
[status-im.utils.fx :as fx]
|
||||
[taoensso.timbre :as log]))
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn show-keycard-has-multiaccount-alert
|
||||
(rf/defn show-keycard-has-multiaccount-alert
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :setup-step] nil)
|
||||
:utils/show-confirmation {:title nil
|
||||
:content (i18n/label :t/keycard-has-multiaccount-on-it)
|
||||
:content (i18n/label
|
||||
:t/keycard-has-multiaccount-on-it)
|
||||
:cancel-button-text ""
|
||||
:confirm-button-text :t/okay}}))
|
||||
|
||||
(fx/defn load-pin-screen
|
||||
(rf/defn load-pin-screen
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :setup-step] :pin)
|
||||
(assoc-in [:keycard :pin] {:enter-step :original
|
||||
:original []
|
||||
:confirmation []}))}
|
||||
(assoc-in [:keycard :pin]
|
||||
{:enter-step :original
|
||||
:original []
|
||||
:confirmation []}))}
|
||||
(navigation/navigate-to-cofx :keycard-onboarding-pin nil)))
|
||||
|
||||
(fx/defn load-recovery-pin-screen
|
||||
(rf/defn load-recovery-pin-screen
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :pin] {:enter-step :import-multiaccount
|
||||
:import-multiaccount []
|
||||
:current []}))}
|
||||
(assoc-in [:keycard :pin]
|
||||
{:enter-step :import-multiaccount
|
||||
:import-multiaccount []
|
||||
:current []}))}
|
||||
(common/listen-to-hardware-back-button)
|
||||
(navigation/navigate-replace :keycard-recovery-pin nil)))
|
||||
|
||||
(fx/defn load-pairing
|
||||
(rf/defn load-pairing
|
||||
[{:keys [db]}]
|
||||
(let [instance-uid (get-in db [:keycard :application-info :instance-uid])
|
||||
pairing-data (or (get-in db [:keycard :pairings (keyword instance-uid)])
|
||||
(get-in db [:keycard :pairings instance-uid]))]
|
||||
{:db (update-in db [:keycard :secrets] merge pairing-data)}))
|
||||
|
||||
(fx/defn proceed-setup-with-initialized-card
|
||||
(rf/defn proceed-setup-with-initialized-card
|
||||
[{:keys [db] :as cofx} flow instance-uid paired?]
|
||||
(log/debug "[keycard] proceed-setup-with-initialized-card"
|
||||
"instance-uid" instance-uid)
|
||||
"instance-uid"
|
||||
instance-uid)
|
||||
(if (= flow :import)
|
||||
(navigation/navigate-to-cofx cofx :keycard-recovery-no-key nil)
|
||||
(if paired?
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(common/listen-to-hardware-back-button)
|
||||
(when (= flow :create)
|
||||
(mnemonic/set-mnemonic))
|
||||
@@ -74,25 +78,25 @@
|
||||
(onboarding/load-pairing-screen cofx)
|
||||
(recovery/load-pair-screen cofx)))))
|
||||
|
||||
(fx/defn navigate-to-keycard-settings
|
||||
(rf/defn navigate-to-keycard-settings
|
||||
{:events [:profile.ui/keycard-settings-button-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :pin :on-verified] nil)
|
||||
(assoc-in [:keycard :setup-step] nil))}
|
||||
(common/clear-on-card-connected)
|
||||
(navigation/navigate-to-cofx :keycard-settings nil)))
|
||||
|
||||
(fx/defn password-option-pressed
|
||||
(rf/defn password-option-pressed
|
||||
{:eevents [:keycard.ui/password-option-pressed]}
|
||||
[{:keys [db]}]
|
||||
(when (= (get-in db [:keycard :flow]) :create)
|
||||
#())) ;;TODO with v1 flow
|
||||
|
||||
(fx/defn settings-screen-did-load
|
||||
(rf/defn settings-screen-did-load
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :pin :on-verified] nil)
|
||||
(assoc-in [:keycard :setup-step] nil))}
|
||||
@@ -111,7 +115,7 @@
|
||||
[{:keys [db]}]
|
||||
(let [enter-step (get-in db [:keycard :pin :enter-step])]
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :pin enter-step] [])
|
||||
(assoc-in [:keycard :pin enter-step] [])
|
||||
(dissoc :intro-wizard :recovered-account?))}))
|
||||
|
||||
(defn multiaccounts-screen-did-load
|
||||
@@ -122,44 +126,51 @@
|
||||
[{:keys [db]}]
|
||||
{:db (assoc-in db [:keycard :setup-step] nil)})
|
||||
|
||||
(fx/defn set-nfc-supported
|
||||
(rf/defn set-nfc-supported
|
||||
{:events [:keycard.callback/check-nfc-support-success]}
|
||||
[_ supported?]
|
||||
{:keycard/set-nfc-supported supported?})
|
||||
|
||||
;; TODO: Should be listener and replace the view in bottom sheet to avoid this
|
||||
(fx/defn on-check-nfc-enabled-success
|
||||
(rf/defn on-check-nfc-enabled-success
|
||||
{:events [:keycard.callback/check-nfc-enabled-success]}
|
||||
[{:keys [db]} nfc-enabled?]
|
||||
(log/debug "[keycard] check-nfc-enabled-success"
|
||||
"nfc-enabled?" nfc-enabled?)
|
||||
"nfc-enabled?"
|
||||
nfc-enabled?)
|
||||
{:db (assoc-in db [:keycard :nfc-enabled?] nfc-enabled?)})
|
||||
|
||||
(defn- proceed-to-pin-confirmation [fx]
|
||||
(defn- proceed-to-pin-confirmation
|
||||
[fx]
|
||||
(assoc-in fx [:db :keycard :pin :enter-step] :confirmation))
|
||||
|
||||
(defn- proceed-to-change-puk-confirmation [fx]
|
||||
(defn- proceed-to-change-puk-confirmation
|
||||
[fx]
|
||||
(assoc-in fx [:db :keycard :pin :enter-step] :puk-confirmation))
|
||||
|
||||
(defn- proceed-to-pin-reset-confirmation [fx]
|
||||
(defn- proceed-to-pin-reset-confirmation
|
||||
[fx]
|
||||
(-> fx
|
||||
(update-in [:db :keycard :pin] dissoc :reset-confirmation)
|
||||
(assoc-in [:db :keycard :pin :enter-step] :reset-confirmation)))
|
||||
|
||||
(defn- proceed-to-puk-confirmation [fx]
|
||||
(defn- proceed-to-puk-confirmation
|
||||
[fx]
|
||||
(assoc-in fx [:db :keycard :pin :enter-step] :puk))
|
||||
|
||||
(fx/defn on-unblock-pin-success
|
||||
(rf/defn on-unblock-pin-success
|
||||
{:events [:keycard.callback/on-unblock-pin-success]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [reset-pin (get-in db [:keycard :pin :reset])]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db
|
||||
(-> db
|
||||
(update-in [:keycard :application-info] assoc
|
||||
(update-in [:keycard :application-info]
|
||||
assoc
|
||||
:puk-retry-counter 5
|
||||
:pin-retry-counter 3)
|
||||
(update-in [:keycard :pin] assoc
|
||||
(update-in [:keycard :pin]
|
||||
assoc
|
||||
:status :after-unblocking
|
||||
:enter-step :login
|
||||
:login reset-pin
|
||||
@@ -171,18 +182,19 @@
|
||||
(common/clear-on-card-connected)
|
||||
(common/clear-on-card-read))))
|
||||
|
||||
(fx/defn on-unblock-pin-error
|
||||
(rf/defn on-unblock-pin-error
|
||||
{:events [:keycard.callback/on-unblock-pin-error]}
|
||||
[{:keys [db] :as cofx} error]
|
||||
(let [tag-was-lost? (common/tag-lost? (:error error))
|
||||
puk-retries (common/pin-retries (:error error))]
|
||||
puk-retries (common/pin-retries (:error error))]
|
||||
(log/debug "[keycard] unblock pin error" error)
|
||||
(when-not tag-was-lost?
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db
|
||||
(-> db
|
||||
(assoc-in [:keycard :application-info :puk-retry-counter] puk-retries)
|
||||
(update-in [:keycard :pin] merge
|
||||
(update-in [:keycard :pin]
|
||||
merge
|
||||
{:status (if (zero? puk-retries) :blocked-card :error)
|
||||
:error-label :t/puk-mismatch
|
||||
:enter-step :puk
|
||||
@@ -190,19 +202,25 @@
|
||||
|
||||
(common/hide-connection-sheet)))))
|
||||
|
||||
(fx/defn clear-on-verify-handlers
|
||||
(rf/defn clear-on-verify-handlers
|
||||
[{:keys [db]}]
|
||||
{:db (update-in db [:keycard :pin]
|
||||
dissoc :on-verified-failure :on-verified)})
|
||||
{:db (update-in db
|
||||
[:keycard :pin]
|
||||
dissoc
|
||||
:on-verified-failure
|
||||
:on-verified)})
|
||||
|
||||
(fx/defn on-verify-pin-success
|
||||
(rf/defn on-verify-pin-success
|
||||
{:events [:keycard.callback/on-verify-pin-success]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [on-verified (get-in db [:keycard :pin :on-verified])]
|
||||
(log/debug "[hardwaller] success pin verification. on-verified" on-verified)
|
||||
(fx/merge cofx
|
||||
{:db (update-in db [:keycard :pin] merge {:status nil
|
||||
:error-label nil})}
|
||||
(rf/merge cofx
|
||||
{:db (update-in db
|
||||
[:keycard :pin]
|
||||
merge
|
||||
{:status nil
|
||||
:error-label nil})}
|
||||
(common/clear-on-card-connected)
|
||||
(common/clear-on-card-read)
|
||||
;; TODO(Ferossgp): Each pin input should handle this event on it's own,
|
||||
@@ -211,33 +229,36 @@
|
||||
(when-not (contains? #{:keycard/generate-and-load-key
|
||||
:wallet.accounts/generate-new-keycard-account
|
||||
:keycard/remove-key-with-unpair
|
||||
:keycard/unpair-and-delete} on-verified)
|
||||
:keycard/unpair-and-delete}
|
||||
on-verified)
|
||||
(common/hide-connection-sheet))
|
||||
(when-not (contains? #{:keycard/unpair
|
||||
:keycard/generate-and-load-key
|
||||
:keycard/remove-key-with-unpair
|
||||
:keycard/unpair-and-delete
|
||||
:wallet.accounts/generate-new-keycard-account} on-verified)
|
||||
:wallet.accounts/generate-new-keycard-account}
|
||||
on-verified)
|
||||
(common/get-application-info nil))
|
||||
(when on-verified
|
||||
(common/dispatch-event on-verified))
|
||||
(clear-on-verify-handlers))))
|
||||
|
||||
(fx/defn on-verify-pin-error
|
||||
(rf/defn on-verify-pin-error
|
||||
{:events [:keycard.callback/on-verify-pin-error]}
|
||||
[{:keys [db] :as cofx} error]
|
||||
(let [tag-was-lost? (common/tag-lost? (:error error))
|
||||
setup? (boolean (get-in db [:keycard :setup-step]))
|
||||
on-verified-failure (get-in db [:keycard :pin :on-verified-failure])
|
||||
exporting? (get-in db [:keycard :on-export-success])
|
||||
pin-retries (common/pin-retries (:error error))]
|
||||
pin-retries (common/pin-retries (:error error))]
|
||||
(log/debug "[keycard] verify pin error" error)
|
||||
(when-not tag-was-lost?
|
||||
(if-not (nil? pin-retries)
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :application-info :pin-retry-counter] pin-retries)
|
||||
(update-in [:keycard :pin] assoc
|
||||
(update-in [:keycard :pin]
|
||||
assoc
|
||||
:status :error
|
||||
:enter-step :current
|
||||
:puk []
|
||||
@@ -251,20 +272,21 @@
|
||||
(not on-verified-failure))
|
||||
(when exporting?
|
||||
(navigation/navigate-back)))
|
||||
;(navigation/navigate-to-cofx :enter-pin-settings nil)))
|
||||
;(navigation/navigate-to-cofx :enter-pin-settings nil)))
|
||||
(when (zero? pin-retries) (common/frozen-keycard-popup))
|
||||
(when on-verified-failure
|
||||
(fn [_] {:utils/dispatch-later
|
||||
[{:dispatch [on-verified-failure]
|
||||
:ms 200}]}))
|
||||
(fn [_]
|
||||
{:utils/dispatch-later
|
||||
[{:dispatch [on-verified-failure]
|
||||
:ms 200}]}))
|
||||
#_(clear-on-verify-handlers))
|
||||
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(common/hide-connection-sheet)
|
||||
(common/show-wrong-keycard-alert)
|
||||
(clear-on-verify-handlers))))))
|
||||
|
||||
(fx/defn unblock-pin
|
||||
(rf/defn unblock-pin
|
||||
{:events [:keycard/unblock-pin]}
|
||||
[cofx]
|
||||
(common/show-connection-sheet
|
||||
@@ -275,7 +297,7 @@
|
||||
(let [puk (common/vector->string (get-in db [:keycard :pin :puk]))
|
||||
pin (common/vector->string (get-in db [:keycard :pin :reset]))
|
||||
key-uid (get-in db [:keycard :application-info :key-uid])]
|
||||
{:db (assoc-in db [:keycard :pin :status] :verifying)
|
||||
{:db (assoc-in db [:keycard :pin :status] :verifying)
|
||||
:keycard/unblock-pin
|
||||
{:puk puk
|
||||
:new-pin pin}}))}))
|
||||
@@ -283,22 +305,24 @@
|
||||
(def pin-code-length 6)
|
||||
(def puk-code-length 12)
|
||||
|
||||
(fx/defn handle-pin-input
|
||||
(rf/defn handle-pin-input
|
||||
[{:keys [db]} enter-step]
|
||||
(let [numbers-entered (count (get-in db [:keycard :pin enter-step]))]
|
||||
(when (or (= numbers-entered pin-code-length)
|
||||
(= numbers-entered puk-code-length))
|
||||
{:dispatch [:keycard/process-pin-input]})))
|
||||
|
||||
(fx/defn update-pin
|
||||
(rf/defn update-pin
|
||||
{:events [:keycard.ui/pin-numpad-button-pressed]}
|
||||
[{:keys [db] :as cofx} number enter-step]
|
||||
(log/debug "update-pin" enter-step)
|
||||
(let [numbers-entered (count (get-in db [:keycard :pin enter-step]))
|
||||
need-update? (if (or (= enter-step :puk) (= enter-step :puk-original) (= enter-step :puk-confirmation))
|
||||
(< numbers-entered puk-code-length)
|
||||
(< numbers-entered pin-code-length))]
|
||||
(fx/merge cofx
|
||||
need-update? (if (or (= enter-step :puk)
|
||||
(= enter-step :puk-original)
|
||||
(= enter-step :puk-confirmation))
|
||||
(< numbers-entered puk-code-length)
|
||||
(< numbers-entered pin-code-length))]
|
||||
(rf/merge cofx
|
||||
{:db (cond-> (-> db
|
||||
(assoc-in [:keycard :pin :enter-step] enter-step)
|
||||
(assoc-in [:keycard :pin :status] nil))
|
||||
@@ -306,26 +330,38 @@
|
||||
(when need-update?
|
||||
(handle-pin-input enter-step)))))
|
||||
|
||||
(defn- pin-enter-error [fx error-label]
|
||||
(update-in fx [:db :keycard :pin] merge {:status :error
|
||||
:error-label error-label
|
||||
:enter-step :original
|
||||
:original []
|
||||
:confirmation []}))
|
||||
(defn- pin-enter-error
|
||||
[fx error-label]
|
||||
(update-in fx
|
||||
[:db :keycard :pin]
|
||||
merge
|
||||
{:status :error
|
||||
:error-label error-label
|
||||
:enter-step :original
|
||||
:original []
|
||||
:confirmation []}))
|
||||
|
||||
(defn- puk-enter-error [fx error-label]
|
||||
(update-in fx [:db :keycard :pin] merge {:status :error
|
||||
:error-label error-label
|
||||
:enter-step :puk-original
|
||||
:puk-original []
|
||||
:puk-confirmation []}))
|
||||
(defn- puk-enter-error
|
||||
[fx error-label]
|
||||
(update-in fx
|
||||
[:db :keycard :pin]
|
||||
merge
|
||||
{:status :error
|
||||
:error-label error-label
|
||||
:enter-step :puk-original
|
||||
:puk-original []
|
||||
:puk-confirmation []}))
|
||||
|
||||
(defn- pin-reset-error [fx error-label]
|
||||
(update-in fx [:db :keycard :pin] merge {:status :error
|
||||
:error-label error-label
|
||||
:enter-step :reset
|
||||
:reset []
|
||||
:reset-confirmation []}))
|
||||
(defn- pin-reset-error
|
||||
[fx error-label]
|
||||
(update-in fx
|
||||
[:db :keycard :pin]
|
||||
merge
|
||||
{:status :error
|
||||
:error-label error-label
|
||||
:enter-step :reset
|
||||
:reset []
|
||||
:reset-confirmation []}))
|
||||
|
||||
; PIN enter steps:
|
||||
; login - PIN is used to login
|
||||
@@ -333,14 +369,14 @@
|
||||
; current - current PIN to perform actions which require PIN auth
|
||||
; original - new PIN when user changes it or creates new one
|
||||
; confirmation - confirmation for new PIN
|
||||
(fx/defn process-pin-input
|
||||
(rf/defn process-pin-input
|
||||
{:events [:keycard/process-pin-input]}
|
||||
[{:keys [db]}]
|
||||
(let [enter-step (get-in db [:keycard :pin :enter-step])
|
||||
pin (get-in db [:keycard :pin enter-step])
|
||||
(let [enter-step (get-in db [:keycard :pin :enter-step])
|
||||
pin (get-in db [:keycard :pin enter-step])
|
||||
numbers-entered (count pin)]
|
||||
(log/debug "[keycard] process-pin-input"
|
||||
"enter-step" enter-step
|
||||
"enter-step" enter-step
|
||||
"numbers-entered" numbers-entered)
|
||||
(cond-> {:db (assoc-in db [:keycard :pin :status] nil)}
|
||||
|
||||
@@ -417,15 +453,19 @@
|
||||
(get-in db [:keycard :pin :reset-confirmation])))
|
||||
(pin-reset-error :t/pin-mismatch))))
|
||||
|
||||
(fx/defn set-multiaccount-pairing
|
||||
(rf/defn set-multiaccount-pairing
|
||||
[cofx _ pairing paired-on]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:keycard-pairing pairing {})
|
||||
:keycard-pairing
|
||||
pairing
|
||||
{})
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:keycard-paired-on paired-on {})))
|
||||
:keycard-paired-on
|
||||
paired-on
|
||||
{})))
|
||||
|
||||
(fx/defn on-retrieve-pairings-success
|
||||
(rf/defn on-retrieve-pairings-success
|
||||
{:events [:keycard.callback/on-retrieve-pairings-success]}
|
||||
[{:keys [db]} pairings]
|
||||
(card/set-pairings pairings)
|
||||
@@ -438,7 +478,7 @@
|
||||
;; with setup and skip the pairing step if the pairing was already done during a previous
|
||||
;; unfinished setup.
|
||||
|
||||
(fx/defn on-pair-success
|
||||
(rf/defn on-pair-success
|
||||
{:events [:keycard.callback/on-pair-success]}
|
||||
[{:keys [db] :as cofx} pairing]
|
||||
(let [setup-step (get-in db [:keycard :setup-step])
|
||||
@@ -448,19 +488,20 @@
|
||||
paired-on (utils.datetime/timestamp)
|
||||
pairings (-> (get-in db [:keycard :pairings])
|
||||
(dissoc (keyword instance-uid))
|
||||
(assoc instance-uid {:pairing pairing :paired-on paired-on}))
|
||||
(assoc instance-uid {:pairing pairing :paired-on paired-on}))
|
||||
next-step (if (= setup-step :pair)
|
||||
:begin
|
||||
:card-ready)]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:keycard/persist-pairings pairings
|
||||
:db (-> db
|
||||
(assoc-in [:keycard :pairings] pairings)
|
||||
(assoc-in [:keycard :application-info :paired?] true)
|
||||
(assoc-in [:keycard :setup-step] next-step)
|
||||
(assoc-in [:keycard :secrets :pairing] pairing)
|
||||
(assoc-in [:keycard :secrets :paired-on] paired-on))}
|
||||
(when-not (and (= flow :recovery) (= next-step :card-ready)) (common/hide-connection-sheet))
|
||||
:db (-> db
|
||||
(assoc-in [:keycard :pairings] pairings)
|
||||
(assoc-in [:keycard :application-info :paired?] true)
|
||||
(assoc-in [:keycard :setup-step] next-step)
|
||||
(assoc-in [:keycard :secrets :pairing] pairing)
|
||||
(assoc-in [:keycard :secrets :paired-on] paired-on))}
|
||||
(when-not (and (= flow :recovery) (= next-step :card-ready))
|
||||
(common/hide-connection-sheet))
|
||||
(when multiaccount
|
||||
(set-multiaccount-pairing multiaccount pairing paired-on))
|
||||
(when (= flow :login)
|
||||
@@ -474,7 +515,7 @@
|
||||
(when (= flow :create)
|
||||
(mnemonic/set-mnemonic)))))
|
||||
|
||||
(fx/defn on-pair-error
|
||||
(rf/defn on-pair-error
|
||||
{:events [:keycard.callback/on-pair-error]}
|
||||
[{:keys [db] :as cofx} {:keys [error code]}]
|
||||
(log/debug "[keycard] pair error: " error)
|
||||
@@ -483,7 +524,7 @@
|
||||
flow (get-in db [:keycard :flow])]
|
||||
(log/debug "[keycard] on-pair-error" setup-step "flow:" flow)
|
||||
(when-not tag-was-lost?
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :setup-error] (i18n/label :t/invalid-pairing-password))}
|
||||
(common/set-on-card-connected (if (= setup-step :pairing)
|
||||
:keycard/load-pairing-screen
|
||||
@@ -494,17 +535,19 @@
|
||||
(when (not= setup-step :enter-pair-code)
|
||||
(common/process-error code error))))))
|
||||
|
||||
(fx/defn set-setup-step
|
||||
(rf/defn set-setup-step
|
||||
[{:keys [db]} card-state]
|
||||
{:db (assoc-in db [:keycard :setup-step]
|
||||
(case card-state
|
||||
:not-paired :pair
|
||||
:no-pairing-slots :no-slots
|
||||
:init :card-ready
|
||||
:multiaccount :import-multiaccount
|
||||
:begin))})
|
||||
{:db (assoc-in db
|
||||
[:keycard :setup-step]
|
||||
(case card-state
|
||||
:not-paired :pair
|
||||
:no-pairing-slots :no-slots
|
||||
:init :card-ready
|
||||
:multiaccount :import-multiaccount
|
||||
:begin))})
|
||||
|
||||
(fx/defn show-no-keycard-applet-alert [_]
|
||||
(rf/defn show-no-keycard-applet-alert
|
||||
[_]
|
||||
{:utils/show-confirmation {:title (i18n/label :t/no-keycard-applet-on-card)
|
||||
:content (i18n/label :t/keycard-applet-install-instructions)
|
||||
:cancel-button-text ""
|
||||
@@ -512,17 +555,17 @@
|
||||
|
||||
;; NOTE: Maybe replaced by multiple events based on on flow to make it easier to maintain.
|
||||
;; Because there are many execution paths it is harder to follow all possible states.
|
||||
(fx/defn check-card-state
|
||||
(rf/defn check-card-state
|
||||
{:events [:keycard/check-card-state]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [app-info (get-in db [:keycard :application-info])
|
||||
flow (get-in db [:keycard :flow])
|
||||
(let [app-info (get-in db [:keycard :application-info])
|
||||
flow (get-in db [:keycard :flow])
|
||||
{:keys [instance-uid key-uid paired?]} app-info
|
||||
card-state (common/get-card-state app-info)]
|
||||
card-state (common/get-card-state app-info)]
|
||||
(log/debug "[keycard] check-card-state"
|
||||
"card-state" card-state
|
||||
"flow" flow)
|
||||
(fx/merge cofx
|
||||
"flow" flow)
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :card-state] card-state)}
|
||||
(set-setup-step card-state)
|
||||
|
||||
@@ -538,7 +581,7 @@
|
||||
(if (= flow :import)
|
||||
(navigation/navigate-to-cofx :keycard-recovery-no-key nil)
|
||||
(fn [cofx]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
(common/clear-on-card-read)
|
||||
(load-pin-screen)))))
|
||||
@@ -560,72 +603,72 @@
|
||||
(#{:create :recovery} flow))
|
||||
(show-keycard-has-multiaccount-alert)))))
|
||||
|
||||
(fx/defn on-card-connected
|
||||
(rf/defn on-card-connected
|
||||
{:events [:keycard.callback/on-card-connected]}
|
||||
[{:keys [db]} _]
|
||||
(log/debug "[keycard] card globally connected")
|
||||
{:db (assoc-in db [:keycard :card-connected?] true)})
|
||||
|
||||
(fx/defn on-card-disconnected
|
||||
(rf/defn on-card-disconnected
|
||||
{:events [:keycard.callback/on-card-disconnected]}
|
||||
[{:keys [db]} _]
|
||||
(log/debug "[keycard] card disconnected")
|
||||
{:db (assoc-in db [:keycard :card-connected?] false)})
|
||||
|
||||
(fx/defn on-nfc-user-cancelled
|
||||
(rf/defn on-nfc-user-cancelled
|
||||
{:events [:keycard.callback/on-nfc-user-cancelled]}
|
||||
[{:keys [db]} _]
|
||||
(log/debug "[keycard] nfc user cancelled")
|
||||
{:dispatch [:signing.ui/cancel-is-pressed]})
|
||||
|
||||
(fx/defn on-nfc-timeout
|
||||
(rf/defn on-nfc-timeout
|
||||
{:events [:keycard.callback/on-nfc-timeout]}
|
||||
[{:keys [db]} _]
|
||||
(log/debug "[keycard] nfc timeout")
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :nfc-running?] false)
|
||||
(assoc-in [:keycard :card-connected?] false))
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :nfc-running?] false)
|
||||
(assoc-in [:keycard :card-connected?] false))
|
||||
:dispatch-later [{:ms 500 :dispatch [:keycard.ui/start-nfc]}]})
|
||||
|
||||
(fx/defn on-register-card-events
|
||||
(rf/defn on-register-card-events
|
||||
{:events [:keycard.callback/on-register-card-events]}
|
||||
[{:keys [db]} listeners]
|
||||
{:db (update-in db [:keycard :listeners] merge listeners)})
|
||||
|
||||
(fx/defn ui-recovery-phrase-cancel-pressed
|
||||
(rf/defn ui-recovery-phrase-cancel-pressed
|
||||
{:events [:keycard.ui/recovery-phrase-cancel-pressed]}
|
||||
[{:keys [db]}]
|
||||
{:db (assoc-in db [:keycard :setup-step] :recovery-phrase)})
|
||||
|
||||
(fx/defn ui-pin-numpad-delete-button-pressed
|
||||
(rf/defn ui-pin-numpad-delete-button-pressed
|
||||
{:events [:keycard.ui/pin-numpad-delete-button-pressed]}
|
||||
[{:keys [db]} step]
|
||||
(when-not (empty? (get-in db [:keycard :pin step]))
|
||||
{:db (update-in db [:keycard :pin step] pop)}))
|
||||
|
||||
(fx/defn start-nfc
|
||||
(rf/defn start-nfc
|
||||
{:events [:keycard.ui/start-nfc]}
|
||||
[cofx]
|
||||
{:keycard/start-nfc nil})
|
||||
|
||||
(fx/defn stop-nfc
|
||||
(rf/defn stop-nfc
|
||||
{:events [:keycard.ui/stop-nfc]}
|
||||
[cofx]
|
||||
{:keycard/stop-nfc nil
|
||||
{:keycard/stop-nfc nil
|
||||
:keycard.callback/on-card-disconnected nil})
|
||||
|
||||
(fx/defn start-nfc-success
|
||||
(rf/defn start-nfc-success
|
||||
{:events [:keycard.callback/start-nfc-success]}
|
||||
[{:keys [db]} _]
|
||||
(log/debug "[keycard] nfc started success")
|
||||
{:db (assoc-in db [:keycard :nfc-running?] true)})
|
||||
|
||||
(fx/defn start-nfc-failure
|
||||
(rf/defn start-nfc-failure
|
||||
{:events [:keycard.callback/start-nfc-failure]}
|
||||
[{:keys [db]} _]
|
||||
(log/debug "[keycard] nfc failed starting")) ;; leave current value on :nfc-running
|
||||
|
||||
(fx/defn stop-nfc-success
|
||||
(rf/defn stop-nfc-success
|
||||
{:events [:keycard.callback/stop-nfc-success]}
|
||||
[{:keys [db]} _]
|
||||
(log/debug "[keycard] nfc stopped success")
|
||||
@@ -634,7 +677,7 @@
|
||||
(assoc-in [:keycard :nfc-running?] false)
|
||||
(assoc-in [:keycard :card-connected?] false))})
|
||||
|
||||
(fx/defn stop-nfc-failure
|
||||
(rf/defn stop-nfc-failure
|
||||
{:events [:keycard.callback/stop-nfc-failure]}
|
||||
[{:keys [db]} _]
|
||||
(log/debug "[keycard] nfc failed stopping")) ;; leave current value on :nfc-running
|
||||
|
||||
@@ -1,44 +1,46 @@
|
||||
(ns status-im.keycard.delete-key
|
||||
(:require [status-im2.navigation.events :as navigation]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.keycard.common :as common]))
|
||||
(:require [status-im.keycard.common :as common]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn reset-card-pressed
|
||||
(rf/defn reset-card-pressed
|
||||
{:events [:keycard-settings.ui/reset-card-pressed]}
|
||||
[cofx]
|
||||
(navigation/navigate-to-cofx cofx :reset-card nil))
|
||||
|
||||
(fx/defn delete-card
|
||||
(rf/defn delete-card
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [key-uid (get-in db [:keycard :application-info :key-uid])
|
||||
(let [key-uid (get-in db [:keycard :application-info :key-uid])
|
||||
multiaccount-key-uid (get-in db [:multiaccount :key-uid])]
|
||||
(if (and key-uid
|
||||
(= key-uid multiaccount-key-uid))
|
||||
{:keycard/delete nil}
|
||||
(common/unauthorized-operation cofx))))
|
||||
|
||||
(fx/defn navigate-to-reset-card-screen
|
||||
(rf/defn navigate-to-reset-card-screen
|
||||
{:events [:keycard/navigate-to-reset-card-screen]}
|
||||
[cofx]
|
||||
(navigation/navigate-to-cofx cofx :reset-card nil))
|
||||
|
||||
(fx/defn reset-card-next-button-pressed
|
||||
(rf/defn reset-card-next-button-pressed
|
||||
{:events [:keycard-settings.ui/reset-card-next-button-pressed]}
|
||||
[{:keys [db]}]
|
||||
{:db (assoc-in db [:keycard :reset-card :disabled?] true)
|
||||
:dispatch [:keycard/proceed-to-reset-card false]})
|
||||
|
||||
(fx/defn proceed-to-reset-card
|
||||
(rf/defn proceed-to-reset-card
|
||||
{:events [:keycard/proceed-to-reset-card]}
|
||||
[{:keys [db] :as cofx} keep-keys-on-keycard?]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:keycard :pin] {:enter-step :current
|
||||
:current []
|
||||
:puk []
|
||||
:status nil
|
||||
:error-label nil
|
||||
:on-verified (if keep-keys-on-keycard?
|
||||
:keycard/unpair-and-delete
|
||||
:keycard/remove-key-with-unpair)})}
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:keycard :pin]
|
||||
{:enter-step :current
|
||||
:current []
|
||||
:puk []
|
||||
:status nil
|
||||
:error-label nil
|
||||
:on-verified (if keep-keys-on-keycard?
|
||||
:keycard/unpair-and-delete
|
||||
:keycard/remove-key-with-unpair)})}
|
||||
(common/set-on-card-connected :keycard/navigate-to-enter-pin-screen)
|
||||
(common/navigate-to-enter-pin-screen)))
|
||||
|
||||
@@ -1,47 +1,49 @@
|
||||
(ns status-im.keycard.export-key
|
||||
(:require [status-im.utils.fx :as fx]
|
||||
[taoensso.timbre :as log]
|
||||
(:require [status-im.keycard.common :as common]
|
||||
[status-im.keycard.wallet :as wallet]
|
||||
[status-im.keycard.common :as common]))
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn on-export-key-error
|
||||
(rf/defn on-export-key-error
|
||||
{:events [:keycard.callback/on-export-key-error]}
|
||||
[{:keys [db] :as cofx} error]
|
||||
(log/debug "[keycard] export key error" error)
|
||||
(let [tag-was-lost? (common/tag-lost? (:error error))
|
||||
pin-retries (common/pin-retries (:error error))]
|
||||
(cond tag-was-lost?
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:keycard :pin :status] nil)}
|
||||
(common/set-on-card-connected :wallet.accounts/generate-new-keycard-account))
|
||||
pin-retries (common/pin-retries (:error error))]
|
||||
(cond
|
||||
tag-was-lost?
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :pin :status] nil)}
|
||||
(common/set-on-card-connected :wallet.accounts/generate-new-keycard-account))
|
||||
|
||||
(not (nil? pin-retries))
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :application-info :pin-retry-counter] pin-retries)
|
||||
(update-in [:keycard :pin] assoc
|
||||
:status :error
|
||||
:enter-step :export-key
|
||||
:puk []
|
||||
:current []
|
||||
:original []
|
||||
:confirmation []
|
||||
:sign []
|
||||
:export-key []
|
||||
:error-label :t/pin-mismatch))}
|
||||
(common/hide-connection-sheet)
|
||||
(when (zero? pin-retries) (common/frozen-keycard-popup)))
|
||||
:else
|
||||
(fx/merge cofx
|
||||
(common/show-wrong-keycard-alert)
|
||||
(common/clear-pin)
|
||||
(common/hide-connection-sheet)))))
|
||||
(not (nil? pin-retries))
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :application-info :pin-retry-counter] pin-retries)
|
||||
(update-in [:keycard :pin]
|
||||
assoc
|
||||
:status :error
|
||||
:enter-step :export-key
|
||||
:puk []
|
||||
:current []
|
||||
:original []
|
||||
:confirmation []
|
||||
:sign []
|
||||
:export-key []
|
||||
:error-label :t/pin-mismatch))}
|
||||
(common/hide-connection-sheet)
|
||||
(when (zero? pin-retries) (common/frozen-keycard-popup)))
|
||||
:else
|
||||
(rf/merge cofx
|
||||
(common/show-wrong-keycard-alert)
|
||||
(common/clear-pin)
|
||||
(common/hide-connection-sheet)))))
|
||||
|
||||
(fx/defn on-export-key-success
|
||||
(rf/defn on-export-key-success
|
||||
{:events [:keycard.callback/on-export-key-success]}
|
||||
[{:keys [db] :as cofx} pubkey]
|
||||
(let [callback-fn (get-in db [:keycard :on-export-success])]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:dispatch (callback-fn pubkey)}
|
||||
(wallet/hide-pin-sheet)
|
||||
(common/clear-pin)
|
||||
|
||||
@@ -1,70 +1,73 @@
|
||||
(ns status-im.keycard.login
|
||||
(:require [status-im.ethereum.core :as ethereum]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.types :as types]
|
||||
[taoensso.timbre :as log]
|
||||
(:require [status-im.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.keycard.common :as common]
|
||||
[status-im.keycard.recovery :as recovery]
|
||||
[status-im.keycard.onboarding :as onboarding]
|
||||
status-im.keycard.fx
|
||||
[status-im.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.signing.core :as signing.core]))
|
||||
[status-im.keycard.onboarding :as onboarding]
|
||||
[status-im.keycard.recovery :as recovery]
|
||||
[status-im.signing.core :as signing.core]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn login-got-it-pressed
|
||||
(rf/defn login-got-it-pressed
|
||||
{:events [:keycard.login.pin.ui/got-it-pressed
|
||||
:keycard.login.pin.ui/cancel-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db db}
|
||||
(navigation/pop-to-root-tab :multiaccounts-stack)))
|
||||
|
||||
(fx/defn login-pin-more-icon-pressed
|
||||
(rf/defn login-pin-more-icon-pressed
|
||||
{:events [:keycard.login.pin.ui/more-icon-pressed]}
|
||||
[cofx]
|
||||
(bottom-sheet/show-bottom-sheet cofx {:view :keycard.login/more}))
|
||||
|
||||
(fx/defn login-create-key-pressed
|
||||
(rf/defn login-create-key-pressed
|
||||
{:events [:keycard.login.ui/create-new-key-pressed]}
|
||||
[cofx]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(bottom-sheet/hide-bottom-sheet)
|
||||
(onboarding/start-onboarding-flow)))
|
||||
|
||||
(fx/defn login-add-key-pressed
|
||||
(rf/defn login-add-key-pressed
|
||||
{:events [:keycard.login.ui/add-key-pressed]}
|
||||
[cofx]
|
||||
(recovery/start-import-flow cofx))
|
||||
|
||||
(fx/defn login-remember-me-changed
|
||||
(rf/defn login-remember-me-changed
|
||||
{:events [:keycard.login.ui/remember-me-changed]}
|
||||
[{:keys [db] :as cofx} value]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :remember-me?] value)}))
|
||||
|
||||
(fx/defn login-pair-card-pressed
|
||||
(rf/defn login-pair-card-pressed
|
||||
{:events [:keycard.login.ui/pair-card-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(log/debug "[keycard] load-pair-card-pressed")
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :flow] :login)}
|
||||
(navigation/navigate-to-cofx :keycard-recovery-pair nil)))
|
||||
|
||||
(fx/defn reset-pin
|
||||
(rf/defn reset-pin
|
||||
{:events [::reset-pin]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
(signing.core/discard)
|
||||
(fn [{:keys [db]}]
|
||||
{:db (-> db
|
||||
(dissoc :popover/popover)
|
||||
(update-in [:keycard :pin] dissoc
|
||||
:reset :puk)
|
||||
(update-in [:keycard :pin] assoc
|
||||
:enter-step :reset
|
||||
:error nil
|
||||
:status nil))
|
||||
{:db (-> db
|
||||
(dissoc :popover/popover)
|
||||
(update-in [:keycard :pin]
|
||||
dissoc
|
||||
:reset
|
||||
:puk)
|
||||
(update-in [:keycard :pin]
|
||||
assoc
|
||||
:enter-step :reset
|
||||
:error nil
|
||||
:status nil))
|
||||
:hide-popover nil})
|
||||
(when (:multiaccount db)
|
||||
(navigation/change-tab :profile))
|
||||
@@ -73,50 +76,51 @@
|
||||
(navigation/navigate-replace :keycard-pin nil)
|
||||
(navigation/navigate-to-cofx :keycard-pin nil)))))
|
||||
|
||||
(fx/defn dismiss-frozen-keycard-popover
|
||||
(rf/defn dismiss-frozen-keycard-popover
|
||||
{:events [::frozen-keycard-popover-dismissed]}
|
||||
[{:keys [db]}]
|
||||
{:db (-> db
|
||||
(dissoc :popover/popover)
|
||||
(update :keycard dissoc :setup-step))
|
||||
{:db (-> db
|
||||
(dissoc :popover/popover)
|
||||
(update :keycard dissoc :setup-step))
|
||||
:hide-popover nil})
|
||||
|
||||
(fx/defn login-with-keycard
|
||||
(rf/defn login-with-keycard
|
||||
{:events [:keycard/login-with-keycard]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [:pin-retry-counter :puk-retry-counter]
|
||||
:as application-info}
|
||||
:as application-info}
|
||||
(get-in db [:keycard :application-info])
|
||||
|
||||
key-uid (get-in db [:keycard :application-info :key-uid])
|
||||
paired? (get-in db [:keycard :application-info :paired?])
|
||||
multiaccount (get-in db [:multiaccounts/multiaccounts (get-in db [:multiaccounts/login :key-uid])])
|
||||
multiaccount-key-uid (get multiaccount :key-uid)
|
||||
key-uid (get-in db [:keycard :application-info :key-uid])
|
||||
paired? (get-in db [:keycard :application-info :paired?])
|
||||
multiaccount (get-in db
|
||||
[:multiaccounts/multiaccounts (get-in db [:multiaccounts/login :key-uid])])
|
||||
multiaccount-key-uid (get multiaccount :key-uid)
|
||||
multiaccount-mismatch? (or (nil? multiaccount)
|
||||
(not= multiaccount-key-uid key-uid))]
|
||||
(log/debug "[keycard] login-with-keycard"
|
||||
"empty application info" (empty? application-info)
|
||||
"no key-uid" (empty? key-uid)
|
||||
"no key-uid" (empty? key-uid)
|
||||
"multiaccount-mismatch?" multiaccount-mismatch?
|
||||
"no pairing" paired?)
|
||||
"no pairing" paired?)
|
||||
(cond
|
||||
(empty? application-info)
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(common/hide-connection-sheet)
|
||||
(navigation/navigate-to-cofx :not-keycard nil))
|
||||
|
||||
(empty? key-uid)
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(common/hide-connection-sheet)
|
||||
(navigation/navigate-to-cofx :keycard-blank nil))
|
||||
|
||||
multiaccount-mismatch?
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(common/hide-connection-sheet)
|
||||
(navigation/navigate-to-cofx :keycard-wrong nil))
|
||||
|
||||
(not paired?)
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(common/hide-connection-sheet)
|
||||
(navigation/navigate-to-cofx :keycard-unpaired nil))
|
||||
|
||||
@@ -128,7 +132,7 @@
|
||||
:else
|
||||
(common/get-keys-from-keycard cofx))))
|
||||
|
||||
(fx/defn proceed-to-login
|
||||
(rf/defn proceed-to-login
|
||||
{:events [::login-after-reset]}
|
||||
[cofx]
|
||||
(log/debug "[keycard] proceed-to-login")
|
||||
@@ -139,12 +143,14 @@
|
||||
:on-card-read :keycard/login-with-keycard
|
||||
:handler (common/get-application-info :keycard/login-with-keycard)}))
|
||||
|
||||
(fx/defn on-keycard-keychain-keys
|
||||
(rf/defn on-keycard-keychain-keys
|
||||
{:events [:multiaccounts.login.callback/get-keycard-keys-success]}
|
||||
[{:keys [db] :as cofx} key-uid [encryption-public-key whisper-private-key :as creds]]
|
||||
(if (nil? creds)
|
||||
(navigation/set-stack-root cofx :multiaccounts-stack [:multiaccounts
|
||||
:keycard-login-pin])
|
||||
(navigation/set-stack-root cofx
|
||||
:multiaccounts-stack
|
||||
[:multiaccounts
|
||||
:keycard-login-pin])
|
||||
(let [{:keys [identicon name]} (get-in db [:multiaccounts/multiaccounts key-uid])
|
||||
multiaccount-data (types/clj->json {:name name
|
||||
:key-uid key-uid
|
||||
@@ -160,18 +166,18 @@
|
||||
(update account-data :whisper-public-key ethereum/normalized-hex))
|
||||
(assoc-in [:keycard :flow] nil)
|
||||
(update :multiaccounts/login assoc
|
||||
:password encryption-public-key
|
||||
:key-uid key-uid
|
||||
:identicon identicon
|
||||
:name name
|
||||
:save-password? true))
|
||||
:password encryption-public-key
|
||||
:key-uid key-uid
|
||||
:identicon identicon
|
||||
:name name
|
||||
:save-password? true))
|
||||
:keycard/login-with-keycard
|
||||
{:multiaccount-data multiaccount-data
|
||||
:key-uid key-uid
|
||||
:password encryption-public-key
|
||||
:chat-key whisper-private-key}})))
|
||||
|
||||
(fx/defn on-login-success
|
||||
(rf/defn on-login-success
|
||||
{:events [:keycard.login.callback/login-success]}
|
||||
[_ result]
|
||||
(log/debug "loginWithKeycard success: " result))
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
(ns status-im.keycard.mnemonic
|
||||
(:require [status-im2.navigation.events :as navigation]
|
||||
[status-im.utils.fx :as fx]
|
||||
(:require [status-im.keycard.common :as common]
|
||||
status-im.keycard.fx
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.keycard.common :as common]
|
||||
status-im.keycard.fx))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn set-mnemonic
|
||||
(rf/defn set-mnemonic
|
||||
[{:keys [db] :as cofx}]
|
||||
(log/debug "[keycard] set-mnemonic")
|
||||
(let [selected-id (get-in db [:intro-wizard :selected-id])
|
||||
mnemonic (reduce
|
||||
(fn [_ {:keys [id mnemonic]}]
|
||||
(when (= selected-id id)
|
||||
(reduced mnemonic)))
|
||||
nil
|
||||
(get-in db [:intro-wizard :multiaccounts]))]
|
||||
(fx/merge
|
||||
mnemonic (reduce
|
||||
(fn [_ {:keys [id mnemonic]}]
|
||||
(when (= selected-id id)
|
||||
(reduced mnemonic)))
|
||||
nil
|
||||
(get-in db [:intro-wizard :multiaccounts]))]
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :setup-step] :recovery-phrase)
|
||||
@@ -24,11 +24,11 @@
|
||||
(common/hide-connection-sheet)
|
||||
(navigation/navigate-replace :keycard-onboarding-recovery-phrase nil))))
|
||||
|
||||
(fx/defn load-loading-keys-screen
|
||||
(rf/defn load-loading-keys-screen
|
||||
{:events [:keycard.ui/recovery-phrase-confirm-pressed
|
||||
:keycard/load-loading-keys-screen]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (assoc-in db [:keycard :setup-step] :loading-keys)}
|
||||
(common/show-connection-sheet
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
(ns status-im.keycard.onboarding
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.keycard.common :as common]
|
||||
[status-im.keycard.mnemonic :as mnemonic]
|
||||
[taoensso.timbre :as log]
|
||||
status-im.keycard.fx
|
||||
[status-im.keycard.mnemonic :as mnemonic]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.constants :as constants]))
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn begin-setup-button-pressed
|
||||
(rf/defn begin-setup-button-pressed
|
||||
{:keys [:keycard.ui/begin-setup-button-pressed]}
|
||||
[{:keys [db]}]
|
||||
{:db (-> db
|
||||
@@ -21,7 +21,7 @@
|
||||
(assoc-in [:keycard :pin :original] [])
|
||||
(assoc-in [:keycard :pin :confirmation] []))})
|
||||
|
||||
(fx/defn start-installation
|
||||
(rf/defn start-installation
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [card-state (get-in db [:keycard :card-state])
|
||||
pin (common/vector->string (get-in db [:keycard :pin :original]))]
|
||||
@@ -33,12 +33,12 @@
|
||||
|
||||
(do
|
||||
(log/debug (str "Cannot start keycard installation from state: " card-state))
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:utils/show-popup {:title (i18n/label :t/error)
|
||||
:content (i18n/label :t/something-went-wrong)}}
|
||||
(navigation/navigate-to-cofx :keycard-authentication-method nil))))))
|
||||
|
||||
(fx/defn load-preparing-screen
|
||||
(rf/defn load-preparing-screen
|
||||
{:events [:keycard/load-preparing-screen]}
|
||||
[cofx]
|
||||
(common/show-connection-sheet
|
||||
@@ -47,11 +47,11 @@
|
||||
:on-card-connected :keycard/load-preparing-screen
|
||||
:handler start-installation}))
|
||||
|
||||
(fx/defn load-pairing-screen
|
||||
(rf/defn load-pairing-screen
|
||||
{:events [:keycard/load-pairing-screen
|
||||
:keycard.onboarding.puk-code.ui/confirm-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (assoc-in db [:keycard :setup-step] :pairing)}
|
||||
(common/show-connection-sheet
|
||||
@@ -59,21 +59,22 @@
|
||||
:on-card-connected :keycard/load-pairing-screen
|
||||
:handler (common/dispatch-event :keycard/pair)})))
|
||||
|
||||
(fx/defn puk-code-next-pressed
|
||||
(rf/defn puk-code-next-pressed
|
||||
{:events [:keycard.onboarding.puk-code.ui/next-pressed]}
|
||||
[_]
|
||||
{:ui/show-confirmation {:title (i18n/label :t/secret-keys-confirmation-title)
|
||||
:content (i18n/label :t/secret-keys-confirmation-text)
|
||||
:confirm-button-text (i18n/label :t/yes)
|
||||
:cancel-button-text (i18n/label :t/cancel)
|
||||
:on-accept #(re-frame/dispatch [:keycard.onboarding.puk-code.ui/confirm-pressed])
|
||||
:on-accept #(re-frame/dispatch
|
||||
[:keycard.onboarding.puk-code.ui/confirm-pressed])
|
||||
:on-cancel #()}})
|
||||
|
||||
(fx/defn load-finishing-screen
|
||||
(rf/defn load-finishing-screen
|
||||
{:events [:keycard.onboarding.recovery-phrase-confirm-word2.ui/next-pressed
|
||||
:keycard/load-finishing-screen]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (assoc-in db [:keycard :setup-step] :loading-keys)}
|
||||
(common/show-connection-sheet
|
||||
@@ -81,29 +82,30 @@
|
||||
:on-card-connected :keycard/load-finishing-screen
|
||||
:handler (common/dispatch-event :keycard/generate-and-load-key)})))
|
||||
|
||||
(fx/defn recovery-phrase-learn-more-pressed
|
||||
(rf/defn recovery-phrase-learn-more-pressed
|
||||
{:events [:keycard.onboarding.recovery-phrase.ui/learn-more-pressed]}
|
||||
[_]
|
||||
(.openURL ^js react/linking constants/keycard-integration-link))
|
||||
|
||||
(fx/defn recovery-phrase-next-pressed
|
||||
(rf/defn recovery-phrase-next-pressed
|
||||
{:events [:keycard.onboarding.recovery-phrase.ui/next-pressed
|
||||
:keycard.ui/recovery-phrase-next-button-pressed]}
|
||||
[_]
|
||||
{:ui/show-confirmation {:title (i18n/label :t/keycard-recovery-phrase-confirmation-title)
|
||||
:content (i18n/label :t/keycard-recovery-phrase-confirmation-text)
|
||||
{:ui/show-confirmation {:title (i18n/label :t/keycard-recovery-phrase-confirmation-title)
|
||||
:content (i18n/label :t/keycard-recovery-phrase-confirmation-text)
|
||||
:confirm-button-text (i18n/label :t/yes)
|
||||
:cancel-button-text (i18n/label :t/cancel)
|
||||
:on-accept #(re-frame/dispatch [:keycard.onboarding.recovery-phrase.ui/confirm-pressed])
|
||||
:on-cancel #()}})
|
||||
:cancel-button-text (i18n/label :t/cancel)
|
||||
:on-accept #(re-frame/dispatch
|
||||
[:keycard.onboarding.recovery-phrase.ui/confirm-pressed])
|
||||
:on-cancel #()}})
|
||||
|
||||
(fx/defn recovery-phrase-start-confirmation
|
||||
(rf/defn recovery-phrase-start-confirmation
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [mnemonic (get-in db [:keycard :secrets :mnemonic])
|
||||
[word1 word2] (shuffle (map-indexed vector (clojure.string/split mnemonic #" ")))
|
||||
word1 (zipmap [:idx :word] word1)
|
||||
word2 (zipmap [:idx :word] word2)]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :setup-step] :recovery-phrase-confirm-word1)
|
||||
(assoc-in [:keycard :recovery-phrase :step] :word1)
|
||||
@@ -113,14 +115,14 @@
|
||||
(assoc-in [:keycard :recovery-phrase :word2] word2))}
|
||||
(common/remove-listener-to-hardware-back-button))))
|
||||
|
||||
(fx/defn recovery-phrase-confirm-pressed
|
||||
(rf/defn recovery-phrase-confirm-pressed
|
||||
{:events [:keycard.onboarding.recovery-phrase.ui/confirm-pressed]}
|
||||
[cofx]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(recovery-phrase-start-confirmation)
|
||||
(navigation/navigate-to-cofx :keycard-onboarding-recovery-phrase-confirm-word1 nil)))
|
||||
|
||||
(fx/defn recovery-phrase-next-word
|
||||
(rf/defn recovery-phrase-next-word
|
||||
[{:keys [db]}]
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :recovery-phrase :step] :word2)
|
||||
@@ -128,50 +130,52 @@
|
||||
(assoc-in [:keycard :recovery-phrase :input-word] nil)
|
||||
(assoc-in [:keycard :setup-step] :recovery-phrase-confirm-word2))})
|
||||
|
||||
(fx/defn proceed-with-generating-key
|
||||
(rf/defn proceed-with-generating-key
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [pin (get-in db [:keycard :secrets :pin]
|
||||
(let [pin (get-in db
|
||||
[:keycard :secrets :pin]
|
||||
(common/vector->string (get-in db [:keycard :pin :current])))]
|
||||
(if (empty? pin)
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :pin] {:enter-step :current
|
||||
:on-verified :keycard/generate-and-load-key
|
||||
:current []})
|
||||
(assoc-in [:keycard :pin]
|
||||
{:enter-step :current
|
||||
:on-verified :keycard/generate-and-load-key
|
||||
:current []})
|
||||
(assoc-in [:keycard :setup-step] :loading-keys))}
|
||||
(navigation/navigate-to-cofx :keycard-onboarding-pin nil))
|
||||
(load-finishing-screen cofx))))
|
||||
|
||||
(fx/defn recovery-phrase-confirm-word-next-pressed
|
||||
(rf/defn recovery-phrase-confirm-word-next-pressed
|
||||
{:events [:keycard.onboarding.recovery-phrase-confirm-word.ui/next-pressed
|
||||
:keycard.onboarding.recovery-phrase-confirm-word.ui/input-submitted]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [step (get-in db [:keycard :recovery-phrase :step])
|
||||
input-word (get-in db [:keycard :recovery-phrase :input-word])
|
||||
(let [step (get-in db [:keycard :recovery-phrase :step])
|
||||
input-word (get-in db [:keycard :recovery-phrase :input-word])
|
||||
{:keys [word]} (get-in db [:keycard :recovery-phrase step])]
|
||||
(if (= word input-word)
|
||||
(if (= (:view-id db) :keycard-onboarding-recovery-phrase-confirm-word1)
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(recovery-phrase-next-word)
|
||||
(navigation/navigate-replace :keycard-onboarding-recovery-phrase-confirm-word2 nil))
|
||||
(proceed-with-generating-key cofx))
|
||||
{:db (assoc-in db [:keycard :recovery-phrase :confirm-error] (i18n/label :t/wrong-word))})))
|
||||
|
||||
(fx/defn recovery-phrase-confirm-word-input-changed
|
||||
(rf/defn recovery-phrase-confirm-word-input-changed
|
||||
{:events [:keycard.onboarding.recovery-phrase-confirm-word.ui/input-changed]}
|
||||
[{:keys [db]} input]
|
||||
{:db (assoc-in db [:keycard :recovery-phrase :input-word] input)})
|
||||
|
||||
(fx/defn pair-code-input-changed
|
||||
(rf/defn pair-code-input-changed
|
||||
{:events [:keycard.onboarding.pair.ui/input-changed]}
|
||||
[{:keys [db]} input]
|
||||
{:db (assoc-in db [:keycard :secrets :password] input)})
|
||||
|
||||
(fx/defn keycard-option-pressed
|
||||
(rf/defn keycard-option-pressed
|
||||
{:events [:onboarding.ui/keycard-option-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [flow (get-in db [:keycard :flow])]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:keycard/check-nfc-enabled nil}
|
||||
(if (= flow :import)
|
||||
(navigation/navigate-to-cofx :keycard-recovery-intro nil)
|
||||
@@ -179,33 +183,36 @@
|
||||
(common/listen-to-hardware-back-button)
|
||||
(navigation/navigate-to-cofx :keycard-onboarding-intro nil))))))
|
||||
|
||||
(fx/defn start-onboarding-flow
|
||||
(rf/defn start-onboarding-flow
|
||||
{:events [:keycard/start-onboarding-flow]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:keycard :flow] :create)
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :flow] :create)
|
||||
:keycard/check-nfc-enabled nil}
|
||||
(common/listen-to-hardware-back-button)
|
||||
(navigation/navigate-to-cofx :keycard-onboarding-intro nil)))
|
||||
|
||||
(fx/defn open-nfc-settings-pressed
|
||||
(rf/defn open-nfc-settings-pressed
|
||||
{:events [:keycard.onboarding.nfc-on/open-nfc-settings-pressed]}
|
||||
[_]
|
||||
{:keycard/open-nfc-settings nil})
|
||||
|
||||
(defn- show-recover-confirmation []
|
||||
(defn- show-recover-confirmation
|
||||
[]
|
||||
{:ui/show-confirmation {:title (i18n/label :t/are-you-sure?)
|
||||
:content (i18n/label :t/are-you-sure-description)
|
||||
:confirm-button-text (clojure.string/upper-case (i18n/label :t/yes))
|
||||
:cancel-button-text (i18n/label :t/see-it-again)
|
||||
:on-accept #(re-frame/dispatch [:keycard.ui/recovery-phrase-confirm-pressed])
|
||||
:on-cancel #(re-frame/dispatch [:keycard.ui/recovery-phrase-cancel-pressed])}})
|
||||
:on-accept #(re-frame/dispatch
|
||||
[:keycard.ui/recovery-phrase-confirm-pressed])
|
||||
:on-cancel #(re-frame/dispatch
|
||||
[:keycard.ui/recovery-phrase-cancel-pressed])}})
|
||||
|
||||
(fx/defn recovery-phrase-confirm-word
|
||||
(rf/defn recovery-phrase-confirm-word
|
||||
{:events [:keycard.ui/recovery-phrase-confirm-word-next-button-pressed]}
|
||||
[{:keys [db]}]
|
||||
(let [step (get-in db [:keycard :recovery-phrase :step])
|
||||
input-word (get-in db [:keycard :recovery-phrase :input-word])
|
||||
(let [step (get-in db [:keycard :recovery-phrase :step])
|
||||
input-word (get-in db [:keycard :recovery-phrase :input-word])
|
||||
{:keys [word]} (get-in db [:keycard :recovery-phrase step])]
|
||||
(if (= word input-word)
|
||||
(if (= step :word1)
|
||||
@@ -213,21 +220,21 @@
|
||||
(show-recover-confirmation))
|
||||
{:db (assoc-in db [:keycard :recovery-phrase :confirm-error] (i18n/label :t/wrong-word))})))
|
||||
|
||||
(fx/defn recovery-phrase-next-button-pressed
|
||||
(rf/defn recovery-phrase-next-button-pressed
|
||||
[{:keys [db] :as cofx}]
|
||||
(if (= (get-in db [:keycard :flow]) :create)
|
||||
(recovery-phrase-start-confirmation cofx)
|
||||
(let [mnemonic (get-in db [:multiaccounts/recover :passphrase])]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :secrets :mnemonic] mnemonic)}
|
||||
(mnemonic/load-loading-keys-screen)))))
|
||||
|
||||
(fx/defn on-install-applet-and-init-card-success
|
||||
(rf/defn on-install-applet-and-init-card-success
|
||||
{:events [:keycard.callback/on-install-applet-and-init-card-success
|
||||
:keycard.callback/on-init-card-success]}
|
||||
[{:keys [db] :as cofx} secrets]
|
||||
(let [secrets' (js->clj secrets :keywordize-keys true)]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :card-state] :init)
|
||||
(assoc-in [:keycard :setup-step] :secret-keys)
|
||||
@@ -237,17 +244,17 @@
|
||||
:on-card-read :keycard/check-card-state
|
||||
:handler (common/get-application-info :keycard/check-card-state)}))))
|
||||
|
||||
(fx/defn on-install-applet-and-init-card-error
|
||||
(rf/defn on-install-applet-and-init-card-error
|
||||
{:events [:keycard.callback/on-install-applet-and-init-card-error
|
||||
:keycard.callback/on-init-card-error]}
|
||||
[{:keys [db] :as cofx} {:keys [code error]}]
|
||||
(log/debug "[keycard] install applet and init card error: " error)
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :setup-error] error)}
|
||||
(common/set-on-card-connected :keycard/load-preparing-screen)
|
||||
(common/process-error code error)))
|
||||
|
||||
(fx/defn generate-and-load-key
|
||||
(rf/defn generate-and-load-key
|
||||
{:events [:keycard/generate-and-load-key]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [pin]}
|
||||
@@ -256,36 +263,41 @@
|
||||
{:keys [selected-id multiaccounts]}
|
||||
(:intro-wizard db)
|
||||
|
||||
multiaccount (or (->> multiaccounts
|
||||
(filter #(= (:id %) selected-id))
|
||||
first)
|
||||
(assoc (get-in db [:intro-wizard :root-key])
|
||||
:derived
|
||||
(get-in db [:intro-wizard :derived])))
|
||||
recovery-mnemonic (get-in db [:intro-wizard :passphrase])
|
||||
mnemonic (or (:mnemonic multiaccount)
|
||||
recovery-mnemonic)
|
||||
pin' (or pin (common/vector->string (get-in db [:keycard :pin :current])))]
|
||||
(fx/merge cofx
|
||||
multiaccount (or (->> multiaccounts
|
||||
(filter #(= (:id %) selected-id))
|
||||
first)
|
||||
(assoc (get-in db [:intro-wizard :root-key])
|
||||
:derived
|
||||
(get-in db [:intro-wizard :derived])))
|
||||
recovery-mnemonic (get-in db [:intro-wizard :passphrase])
|
||||
mnemonic (or (:mnemonic multiaccount)
|
||||
recovery-mnemonic)
|
||||
pin' (or pin
|
||||
(common/vector->string (get-in db
|
||||
[:keycard :pin
|
||||
:current])))]
|
||||
(rf/merge cofx
|
||||
{:keycard/generate-and-load-key
|
||||
{:mnemonic mnemonic
|
||||
:pin pin'
|
||||
:key-uid (:key-uid multiaccount)
|
||||
:delete-multiaccount? (get-in db [:keycard :delete-account?])}})))
|
||||
|
||||
(fx/defn factory-reset-card-toggle
|
||||
(rf/defn factory-reset-card-toggle
|
||||
{:events [:keycard.onboarding.intro.ui/factory-reset-card-toggle]}
|
||||
[{:keys [db] :as cofx} checked?]
|
||||
{:db (assoc-in db [:keycard :factory-reset-card?] checked?)})
|
||||
|
||||
(fx/defn begin-setup-pressed
|
||||
(rf/defn begin-setup-pressed
|
||||
{:events [:keycard.onboarding.intro.ui/begin-setup-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(update :keycard
|
||||
dissoc :secrets :card-state :multiaccount-wallet-address
|
||||
dissoc
|
||||
:secrets
|
||||
:card-state :multiaccount-wallet-address
|
||||
:multiaccount-whisper-public-key :application-info)
|
||||
(assoc-in [:keycard :setup-step] :begin)
|
||||
(assoc-in [:keycard :pin :on-verified] nil))}
|
||||
@@ -301,7 +313,7 @@
|
||||
:on-card-read :keycard/check-card-state
|
||||
:handler (common/get-application-info :keycard/check-card-state)}))))
|
||||
|
||||
(fx/defn factory-reset
|
||||
(rf/defn factory-reset
|
||||
{:events [::factory-reset]}
|
||||
[cofx]
|
||||
(common/show-connection-sheet
|
||||
@@ -310,14 +322,14 @@
|
||||
:on-card-read :keycard/check-card-state
|
||||
:handler (common/factory-reset :keycard/check-card-state)}))
|
||||
|
||||
(fx/defn factory-reset-cancel
|
||||
(rf/defn factory-reset-cancel
|
||||
{:events [::factory-reset-cancel]}
|
||||
[{:keys [db] :as cofx}]
|
||||
{:db (update db :keycard dissoc :factory-reset-card?)})
|
||||
|
||||
(fx/defn cancel-pressed
|
||||
(rf/defn cancel-pressed
|
||||
{:events [::cancel-pressed]}
|
||||
[cofx]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(navigation/navigate-back)
|
||||
(common/cancel-sheet-confirm)))
|
||||
|
||||
+156
-136
@@ -1,30 +1,31 @@
|
||||
(ns status-im.keycard.recovery
|
||||
(:require [status-im2.navigation.events :as navigation]
|
||||
[status-im.utils.datetime :as utils.datetime]
|
||||
[status-im.multiaccounts.create.core :as multiaccounts.create]
|
||||
[status-im.multiaccounts.model :as multiaccounts.model]
|
||||
[status-im.utils.fx :as fx]
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[clojure.string :as string]
|
||||
[status-im.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.eip55 :as eip55]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.keycard.common :as common]
|
||||
status-im.keycard.fx
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ethereum.eip55 :as eip55]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.multiaccounts.create.core :as multiaccounts.create]
|
||||
[status-im.multiaccounts.model :as multiaccounts.model]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.popover.core :as popover]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.utils.security :as security]
|
||||
[status-im.utils.datetime :as utils.datetime]
|
||||
[status-im.utils.keychain.core :as keychain]
|
||||
[status-im.utils.platform :as platform]))
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(fx/defn pair* [_ password]
|
||||
(rf/defn pair*
|
||||
[_ password]
|
||||
{:keycard/pair {:password password}})
|
||||
|
||||
(fx/defn pair
|
||||
(rf/defn pair
|
||||
{:events [:keycard/pair]}
|
||||
[cofx]
|
||||
(let [{:keys [password]} (get-in cofx [:db :keycard :secrets])]
|
||||
@@ -33,41 +34,41 @@
|
||||
{:on-card-connected :keycard/pair
|
||||
:handler (pair* password)})))
|
||||
|
||||
(fx/defn pair-code-next-button-pressed
|
||||
(rf/defn pair-code-next-button-pressed
|
||||
{:events [:keycard.onboarding.pair.ui/input-submitted
|
||||
:keycard.ui/pair-code-next-button-pressed
|
||||
:keycard.onboarding.pair.ui/next-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [pairing (get-in db [:keycard :secrets :pairing])
|
||||
(let [pairing (get-in db [:keycard :secrets :pairing])
|
||||
paired-on (get-in db [:keycard :secrets :paired-on] (utils.datetime/timestamp))]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(if pairing
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :setup-step] :import-multiaccount)
|
||||
(assoc-in [:keycard :secrets :paired-on] paired-on))}
|
||||
(pair)))))
|
||||
|
||||
(fx/defn load-pair-screen
|
||||
(rf/defn load-pair-screen
|
||||
[{:keys [db] :as cofx}]
|
||||
(log/debug "[keycard] load-pair-screen")
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :setup-step] :pair))
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :setup-step] :pair))
|
||||
:dispatch [:bottom-sheet/hide]}
|
||||
(common/listen-to-hardware-back-button)
|
||||
(navigation/navigate-to-cofx :keycard-recovery-pair nil)))
|
||||
|
||||
(fx/defn keycard-storage-selected-for-recovery
|
||||
(rf/defn keycard-storage-selected-for-recovery
|
||||
{:events [:recovery.ui/keycard-storage-selected]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :flow] :recovery)}
|
||||
(navigation/navigate-to-cofx :keycard-recovery-enter-mnemonic nil)))
|
||||
|
||||
(fx/defn start-import-flow
|
||||
(rf/defn start-import-flow
|
||||
{:events [::recover-with-keycard-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db
|
||||
(-> db
|
||||
(assoc-in [:keycard :flow] :import)
|
||||
@@ -76,35 +77,37 @@
|
||||
(bottom-sheet/hide-bottom-sheet)
|
||||
(navigation/navigate-to-cofx :keycard-recovery-intro nil)))
|
||||
|
||||
(fx/defn access-key-pressed
|
||||
(rf/defn access-key-pressed
|
||||
{:events [:multiaccounts.recover.ui/recover-multiaccount-button-pressed]}
|
||||
[_]
|
||||
{:dispatch [:bottom-sheet/show-sheet :recover-sheet]})
|
||||
|
||||
(fx/defn recovery-keycard-selected
|
||||
(rf/defn recovery-keycard-selected
|
||||
{:events [:recovery.ui/keycard-option-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:keycard :flow] :recovery)
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :flow] :recovery)
|
||||
:keycard/check-nfc-enabled nil}
|
||||
(common/listen-to-hardware-back-button)
|
||||
(navigation/navigate-to-cofx :keycard-onboarding-intro nil)))
|
||||
|
||||
(fx/defn cancel-pressed
|
||||
(rf/defn cancel-pressed
|
||||
{:events [::cancel-pressed]}
|
||||
[cofx]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(common/cancel-sheet-confirm)
|
||||
(navigation/navigate-back)))
|
||||
|
||||
(fx/defn begin-setup-pressed
|
||||
(rf/defn begin-setup-pressed
|
||||
{:events [:keycard.recovery.intro.ui/begin-recovery-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(update :keycard
|
||||
dissoc :secrets :card-state :multiaccount-wallet-address
|
||||
dissoc
|
||||
:secrets
|
||||
:card-state :multiaccount-wallet-address
|
||||
:multiaccount-whisper-public-key
|
||||
:application-info)
|
||||
(assoc-in [:keycard :setup-step] :begin)
|
||||
@@ -115,21 +118,24 @@
|
||||
:sheet-options {:on-cancel [::cancel-pressed]}
|
||||
:handler (common/get-application-info :keycard/check-card-state)})))
|
||||
|
||||
(fx/defn recovery-success-finish-pressed
|
||||
(rf/defn recovery-success-finish-pressed
|
||||
{:events [:keycard.recovery.success/finish-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
{:db (update db :keycard dissoc
|
||||
(rf/merge cofx
|
||||
{:db (update db
|
||||
:keycard dissoc
|
||||
:multiaccount-wallet-address
|
||||
:multiaccount-whisper-public-key)}
|
||||
(navigation/navigate-to-cofx (if platform/android?
|
||||
:notifications-settings :welcome) nil)))
|
||||
:notifications-settings
|
||||
:welcome)
|
||||
nil)))
|
||||
|
||||
(fx/defn intro-wizard
|
||||
(rf/defn intro-wizard
|
||||
{:events [:multiaccounts.create.ui/intro-wizard]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [accs (get db :multiaccounts/multiaccounts)]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(update :keycard dissoc :flow)
|
||||
(dissoc :restored-account?))}
|
||||
@@ -138,16 +144,16 @@
|
||||
(navigation/navigate-to-cofx :get-your-keys nil)
|
||||
(navigation/set-stack-root :onboarding [:get-your-keys])))))
|
||||
|
||||
(fx/defn recovery-no-key
|
||||
(rf/defn recovery-no-key
|
||||
{:events [:keycard.recovery.no-key.ui/generate-key-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:keycard :flow] :create)
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :flow] :create)
|
||||
:keycard/check-nfc-enabled nil}
|
||||
(intro-wizard)))
|
||||
|
||||
(fx/defn create-keycard-multiaccount
|
||||
{:events [::create-keycard-multiaccount]
|
||||
(rf/defn create-keycard-multiaccount
|
||||
{:events [::create-keycard-multiaccount]
|
||||
:interceptors [(re-frame/inject-cofx :random-guid-generator)
|
||||
(re-frame/inject-cofx ::multiaccounts.create/get-signing-phrase)]}
|
||||
[{:keys [db] :as cofx}]
|
||||
@@ -166,13 +172,14 @@
|
||||
encryption-public-key
|
||||
instance-uid
|
||||
key-uid
|
||||
recovered]} multiaccount
|
||||
{:keys [pairing paired-on]} secrets
|
||||
recovered]}
|
||||
multiaccount
|
||||
{:keys [pairing paired-on]} secrets
|
||||
{:keys [name identicon]}
|
||||
(if (nil? name)
|
||||
;; name might have been generated during recovery via passphrase
|
||||
(get-in db [:intro-wizard :derived constants/path-whisper-keyword])
|
||||
{:name name
|
||||
{:name name
|
||||
:identicon identicon})]
|
||||
;; if a name is still `nil` we have to generate it before multiaccount's
|
||||
;; creation otherwise spec validation will fail
|
||||
@@ -180,7 +187,7 @@
|
||||
{:keycard/generate-name-and-photo
|
||||
{:public-key whisper-public-key
|
||||
:on-success ::on-name-and-photo-generated}}
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :setup-step] nil)
|
||||
(dissoc :intro-wizard))}
|
||||
@@ -193,7 +200,7 @@
|
||||
{:public-key whisper-public-key
|
||||
:address (eip55/address->checksum whisper-address)
|
||||
:name name
|
||||
:identicon identicon}
|
||||
:identicon identicon}
|
||||
constants/path-default-wallet-keyword
|
||||
{:public-key wallet-public-key
|
||||
:address (eip55/address->checksum wallet-address)}}
|
||||
@@ -207,24 +214,29 @@
|
||||
encryption-public-key
|
||||
{})))))
|
||||
|
||||
(fx/defn return-to-keycard-login
|
||||
(rf/defn return-to-keycard-login
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(update-in [:keycard :pin] assoc :enter-step :login
|
||||
:status nil
|
||||
:login [])
|
||||
(update-in [:keycard :pin]
|
||||
assoc
|
||||
:enter-step :login
|
||||
:status nil
|
||||
:login [])
|
||||
(update :keycard dissoc :application-info))}
|
||||
(navigation/set-stack-root :multiaccounts-stack [:multiaccounts
|
||||
:keycard-login-pin])))
|
||||
(navigation/set-stack-root :multiaccounts-stack
|
||||
[:multiaccounts
|
||||
:keycard-login-pin])))
|
||||
|
||||
(fx/defn on-backup-success
|
||||
(rf/defn on-backup-success
|
||||
[{:keys [db] :as cofx} backup-type]
|
||||
(fx/merge cofx
|
||||
{:utils/show-popup {:title (i18n/label (if (= backup-type :recovery-card)
|
||||
:t/keycard-access-reset :t/keycard-backup-success-title))
|
||||
:content (i18n/label (if (= backup-type :recovery-card)
|
||||
:t/keycard-can-use-with-new-passcode :t/keycard-backup-success-body))}}
|
||||
(rf/merge cofx
|
||||
{:utils/show-popup {:title (i18n/label (if (= backup-type :recovery-card)
|
||||
:t/keycard-access-reset
|
||||
:t/keycard-backup-success-title))
|
||||
:content (i18n/label (if (= backup-type :recovery-card)
|
||||
:t/keycard-can-use-with-new-passcode
|
||||
:t/keycard-backup-success-body))}}
|
||||
(cond
|
||||
(multiaccounts.model/logged-in? cofx)
|
||||
(navigation/set-stack-root :profile-stack [:my-profile :keycard-settings])
|
||||
@@ -246,36 +258,40 @@
|
||||
#(let [{:keys [error]} (types/json->clj %)]
|
||||
(if (string/blank? error)
|
||||
(status/login-with-keycard login-params)
|
||||
(throw (js/Error. "Please shake the phone to report this error and restart the app. Migration failed unexpectedly.")))))))
|
||||
(throw
|
||||
(js/Error.
|
||||
"Please shake the phone to report this error and restart the app. Migration failed unexpectedly.")))))))
|
||||
|
||||
(fx/defn migrate-account
|
||||
(rf/defn migrate-account
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [pairing (get-in db [:keycard :secrets :pairing])
|
||||
paired-on (get-in db [:keycard :secrets :paired-on])
|
||||
instance-uid (get-in db [:keycard :multiaccount :instance-uid])
|
||||
account (-> db
|
||||
:multiaccounts/login
|
||||
(assoc :keycard-pairing pairing)
|
||||
(assoc :save-password? false))
|
||||
key-uid (-> account :key-uid)
|
||||
settings {:keycard-instance-uid instance-uid
|
||||
:keycard-paired-on paired-on
|
||||
:keycard-pairing pairing}
|
||||
password (ethereum/sha3 (security/safe-unmask-data (get-in db [:keycard :migration-password])))
|
||||
(let [pairing (get-in db [:keycard :secrets :pairing])
|
||||
paired-on (get-in db [:keycard :secrets :paired-on])
|
||||
instance-uid (get-in db [:keycard :multiaccount :instance-uid])
|
||||
account (-> db
|
||||
:multiaccounts/login
|
||||
(assoc :keycard-pairing pairing)
|
||||
(assoc :save-password? false))
|
||||
key-uid (-> account :key-uid)
|
||||
settings {:keycard-instance-uid instance-uid
|
||||
:keycard-paired-on paired-on
|
||||
:keycard-pairing pairing}
|
||||
password (ethereum/sha3 (security/safe-unmask-data (get-in db
|
||||
[:keycard
|
||||
:migration-password])))
|
||||
encryption-pass (get-in db [:keycard :multiaccount :encryption-public-key])
|
||||
login-params {:key-uid key-uid
|
||||
:multiaccount-data (types/clj->json account)
|
||||
:password encryption-pass
|
||||
:chat-key (get-in db [:keycard :multiaccount :whisper-private-key])}]
|
||||
{:db (-> db
|
||||
(assoc-in [:multiaccounts/multiaccounts key-uid :keycard-pairing] pairing)
|
||||
(assoc :multiaccounts/login account)
|
||||
(assoc :auth-method keychain/auth-method-none)
|
||||
(update :keycard dissoc :flow :migration-password)
|
||||
(dissoc :recovered-account?))
|
||||
login-params {:key-uid key-uid
|
||||
:multiaccount-data (types/clj->json account)
|
||||
:password encryption-pass
|
||||
:chat-key (get-in db [:keycard :multiaccount :whisper-private-key])}]
|
||||
{:db (-> db
|
||||
(assoc-in [:multiaccounts/multiaccounts key-uid :keycard-pairing] pairing)
|
||||
(assoc :multiaccounts/login account)
|
||||
(assoc :auth-method keychain/auth-method-none)
|
||||
(update :keycard dissoc :flow :migration-password)
|
||||
(dissoc :recovered-account?))
|
||||
::finish-migration [account settings password encryption-pass login-params]}))
|
||||
|
||||
(fx/defn delete-multiaccount
|
||||
(rf/defn delete-multiaccount
|
||||
[{:keys [db]}]
|
||||
(let [key-uid (get-in db [:multiaccounts/login :key-uid])]
|
||||
{:keycard/delete-multiaccount-before-migration
|
||||
@@ -283,61 +299,63 @@
|
||||
:on-error #(re-frame/dispatch [::delete-multiaccount-error %])
|
||||
:on-success #(re-frame/dispatch [::create-keycard-multiaccount])}}))
|
||||
|
||||
(fx/defn handle-delete-multiaccount-error
|
||||
(rf/defn handle-delete-multiaccount-error
|
||||
{:events [::delete-multiaccount-error]}
|
||||
[cofx _]
|
||||
(popover/show-popover cofx {:view :transfer-multiaccount-unknown-error}))
|
||||
|
||||
(fx/defn on-generate-and-load-key-success
|
||||
(rf/defn on-generate-and-load-key-success
|
||||
{:events [:keycard.callback/on-generate-and-load-key-success]
|
||||
:interceptors [(re-frame/inject-cofx :random-guid-generator)
|
||||
(re-frame/inject-cofx ::multiaccounts.create/get-signing-phrase)]}
|
||||
[{:keys [db random-guid-generator] :as cofx} data]
|
||||
(let [account-data (js->clj data :keywordize-keys true)
|
||||
backup? (get-in db [:keycard :creating-backup?])
|
||||
migration? (get-in db [:keycard :converting-account?])]
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :multiaccount]
|
||||
(-> account-data
|
||||
(update :address ethereum/normalized-hex)
|
||||
(update :whisper-address ethereum/normalized-hex)
|
||||
(update :wallet-address ethereum/normalized-hex)
|
||||
(update :wallet-root-address ethereum/normalized-hex)
|
||||
(update :public-key ethereum/normalized-hex)
|
||||
(update :whisper-public-key ethereum/normalized-hex)
|
||||
(update :wallet-public-key ethereum/normalized-hex)
|
||||
(update :wallet-root-public-key ethereum/normalized-hex)
|
||||
(update :instance-uid #(get-in db [:keycard :multiaccount :instance-uid] %))))
|
||||
(assoc-in [:keycard :multiaccount-wallet-address] (:wallet-address account-data))
|
||||
(assoc-in [:keycard :multiaccount-whisper-public-key] (:whisper-public-key account-data))
|
||||
(assoc-in [:keycard :pin :status] nil)
|
||||
(assoc-in [:keycard :application-info :key-uid]
|
||||
(ethereum/normalized-hex (:key-uid account-data)))
|
||||
(update :keycard dissoc :recovery-phrase :creating-backup? :converting-account?)
|
||||
(update-in [:keycard :secrets] dissoc :pin :puk :password :mnemonic)
|
||||
(assoc :multiaccounts/new-installation-id (random-guid-generator)))}
|
||||
(common/remove-listener-to-hardware-back-button)
|
||||
(common/hide-connection-sheet)
|
||||
(cond backup? (on-backup-success backup?)
|
||||
migration? (migrate-account)
|
||||
backup? (get-in db [:keycard :creating-backup?])
|
||||
migration? (get-in db [:keycard :converting-account?])]
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(assoc-in
|
||||
[:keycard :multiaccount]
|
||||
(-> account-data
|
||||
(update :address ethereum/normalized-hex)
|
||||
(update :whisper-address ethereum/normalized-hex)
|
||||
(update :wallet-address ethereum/normalized-hex)
|
||||
(update :wallet-root-address ethereum/normalized-hex)
|
||||
(update :public-key ethereum/normalized-hex)
|
||||
(update :whisper-public-key ethereum/normalized-hex)
|
||||
(update :wallet-public-key ethereum/normalized-hex)
|
||||
(update :wallet-root-public-key ethereum/normalized-hex)
|
||||
(update :instance-uid #(get-in db [:keycard :multiaccount :instance-uid] %))))
|
||||
(assoc-in [:keycard :multiaccount-wallet-address] (:wallet-address account-data))
|
||||
(assoc-in [:keycard :multiaccount-whisper-public-key] (:whisper-public-key account-data))
|
||||
(assoc-in [:keycard :pin :status] nil)
|
||||
(assoc-in [:keycard :application-info :key-uid]
|
||||
(ethereum/normalized-hex (:key-uid account-data)))
|
||||
(update :keycard dissoc :recovery-phrase :creating-backup? :converting-account?)
|
||||
(update-in [:keycard :secrets] dissoc :pin :puk :password :mnemonic)
|
||||
(assoc :multiaccounts/new-installation-id (random-guid-generator)))}
|
||||
(common/remove-listener-to-hardware-back-button)
|
||||
(common/hide-connection-sheet)
|
||||
(cond backup? (on-backup-success backup?)
|
||||
migration? (migrate-account)
|
||||
|
||||
(get-in db [:keycard :delete-account?])
|
||||
(delete-multiaccount)
|
||||
(get-in db [:keycard :delete-account?])
|
||||
(delete-multiaccount)
|
||||
|
||||
:else (create-keycard-multiaccount)))))
|
||||
:else (create-keycard-multiaccount)))))
|
||||
|
||||
(fx/defn on-generate-and-load-key-error
|
||||
(rf/defn on-generate-and-load-key-error
|
||||
{:events [:keycard.callback/on-generate-and-load-key-error]}
|
||||
[{:keys [db] :as cofx} {:keys [error code]}]
|
||||
(log/debug "[keycard] generate and load key error: " error)
|
||||
(when-not (common/tag-lost? error)
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :setup-error] error)}
|
||||
(common/set-on-card-connected :keycard/load-loading-keys-screen)
|
||||
(common/process-error code error))))
|
||||
|
||||
(fx/defn import-multiaccount
|
||||
(rf/defn import-multiaccount
|
||||
{:events [:keycard/import-multiaccount]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [pairing]} (get-in db [:keycard :secrets])
|
||||
@@ -345,17 +363,18 @@
|
||||
key-uid (get-in db [:keycard :application-info :key-uid])
|
||||
pairing' (or pairing (common/get-pairing db key-uid))
|
||||
pin (common/vector->string (get-in db [:keycard :pin :import-multiaccount]))]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :multiaccount :instance-uid] instance-uid)
|
||||
(assoc-in [:keycard :pin :status] :verifying)
|
||||
(assoc-in [:keycard :secrets] {:pairing pairing'
|
||||
:paired-on (utils.datetime/timestamp)}))
|
||||
(assoc-in [:keycard :secrets]
|
||||
{:pairing pairing'
|
||||
:paired-on (utils.datetime/timestamp)}))
|
||||
:keycard/import-keys
|
||||
{:pin pin
|
||||
:on-success :keycard.callback/on-generate-and-load-key-success}})))
|
||||
{:pin pin
|
||||
:on-success :keycard.callback/on-generate-and-load-key-success}})))
|
||||
|
||||
(fx/defn load-recovering-key-screen
|
||||
(rf/defn load-recovering-key-screen
|
||||
{:events [:keycard/load-recovering-key-screen]}
|
||||
[cofx]
|
||||
(common/show-connection-sheet
|
||||
@@ -363,17 +382,18 @@
|
||||
{:on-card-connected :keycard/load-recovering-key-screen
|
||||
:handler (common/dispatch-event :keycard/import-multiaccount)}))
|
||||
|
||||
(fx/defn on-name-and-photo-generated
|
||||
{:events [::on-name-and-photo-generated]
|
||||
(rf/defn on-name-and-photo-generated
|
||||
{:events [::on-name-and-photo-generated]
|
||||
:interceptors [(re-frame/inject-cofx :random-guid-generator)
|
||||
(re-frame/inject-cofx ::multiaccounts.create/get-signing-phrase)]}
|
||||
[{:keys [db] :as cofx} whisper-name identicon]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (update-in db [:keycard :multiaccount]
|
||||
{:db (update-in db
|
||||
[:keycard :multiaccount]
|
||||
(fn [multiacc]
|
||||
(assoc multiacc
|
||||
:recovered (get db :recovered-account?)
|
||||
:name whisper-name
|
||||
:name whisper-name
|
||||
:identicon identicon)))}
|
||||
(create-keycard-multiaccount)))
|
||||
|
||||
@@ -1,46 +1,49 @@
|
||||
(ns status-im.keycard.sign
|
||||
(:require [re-frame.core :as re-frame]
|
||||
(:require [clojure.string :as string]
|
||||
[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]
|
||||
[status-im.keycard.common :as common]
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.utils.types :as types]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.keycard.common :as common]
|
||||
[clojure.string :as string]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn sign
|
||||
(rf/defn sign
|
||||
{:events [:keycard/sign]}
|
||||
[{:keys [db] :as cofx} hash on-success]
|
||||
(let [card-connected? (get-in db [:keycard :card-connected?])
|
||||
key-uid (get-in db [:multiaccount :key-uid])
|
||||
keycard-key-uid (get-in db [:keycard :application-info :key-uid])
|
||||
keycard-pin-retries (get-in db [:keycard :application-info :pin-retry-counter])
|
||||
keycard-match? (= key-uid keycard-key-uid)
|
||||
hash (or hash (get-in db [:keycard :hash]))
|
||||
data (get-in db [:keycard :data])
|
||||
typed? (get-in db [:keycard :typed?])
|
||||
pin (common/vector->string (get-in db [:keycard :pin :sign]))
|
||||
from (or (get-in db [:signing/tx :from :address]) (get-in db [:signing/tx :message :from]) (ethereum/default-address db))
|
||||
path (reduce
|
||||
(fn [_ {:keys [address path]}]
|
||||
(when (ethereum/address= from address)
|
||||
(reduced path)))
|
||||
nil
|
||||
(:multiaccount/accounts db))]
|
||||
(let [card-connected? (get-in db [:keycard :card-connected?])
|
||||
key-uid (get-in db [:multiaccount :key-uid])
|
||||
keycard-key-uid (get-in db [:keycard :application-info :key-uid])
|
||||
keycard-pin-retries (get-in db [:keycard :application-info :pin-retry-counter])
|
||||
keycard-match? (= key-uid keycard-key-uid)
|
||||
hash (or hash (get-in db [:keycard :hash]))
|
||||
data (get-in db [:keycard :data])
|
||||
typed? (get-in db [:keycard :typed?])
|
||||
pin (common/vector->string (get-in db [:keycard :pin :sign]))
|
||||
from (or (get-in db [:signing/tx :from :address])
|
||||
(get-in db [:signing/tx :message :from])
|
||||
(ethereum/default-address db))
|
||||
path (reduce
|
||||
(fn [_ {:keys [address path]}]
|
||||
(when (ethereum/address= from address)
|
||||
(reduced path)))
|
||||
nil
|
||||
(:multiaccount/accounts db))]
|
||||
(cond
|
||||
(not keycard-match?)
|
||||
(common/show-wrong-keycard-alert cofx)
|
||||
|
||||
(not card-connected?)
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:signing/sign :keycard-step] :signing)}
|
||||
(common/set-on-card-connected :keycard/sign))
|
||||
|
||||
(pos? keycard-pin-retries) ; if 0, get-application-info will have already closed the connection sheet and opened the frozen card popup
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :card-read-in-progress?] true)
|
||||
(assoc-in [:keycard :pin :status] :verifying))
|
||||
(pos? keycard-pin-retries) ; if 0, get-application-info will have already closed the connection
|
||||
; sheet and opened the frozen card popup
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :card-read-in-progress?] true)
|
||||
(assoc-in [:keycard :pin :status] :verifying))
|
||||
:keycard/sign {:hash (ethereum/naked-address hash)
|
||||
:data data
|
||||
:typed? typed? ; this parameter is for e2e
|
||||
@@ -48,76 +51,80 @@
|
||||
:pin pin
|
||||
:path path}})))
|
||||
|
||||
(defn normalize-signature [signature]
|
||||
(defn normalize-signature
|
||||
[signature]
|
||||
(-> signature
|
||||
(string/replace-first #"00$", "1b")
|
||||
(string/replace-first #"01$", "1c")
|
||||
(string/replace-first #"00$" "1b")
|
||||
(string/replace-first #"01$" "1c")
|
||||
ethereum/normalized-hex))
|
||||
|
||||
(fx/defn sign-message
|
||||
(rf/defn sign-message
|
||||
{:events [:keycard/sign-message]}
|
||||
[cofx params result]
|
||||
(let [{:keys [result error]} (types/json->clj result)
|
||||
on-success #(re-frame/dispatch [:keycard/on-sign-message-success params
|
||||
(normalize-signature %)])
|
||||
hash (ethereum/naked-address result)]
|
||||
on-success #(re-frame/dispatch [:keycard/on-sign-message-success params
|
||||
(normalize-signature %)])
|
||||
hash (ethereum/naked-address result)]
|
||||
(sign cofx hash on-success)))
|
||||
|
||||
(fx/defn on-sign-message-success
|
||||
(rf/defn on-sign-message-success
|
||||
{:events [:keycard/on-sign-message-success]}
|
||||
[{:keys [db] :as cofx} {:keys [tx-hash message-id chat-id value contract]} signature]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:dispatch
|
||||
(if message-id
|
||||
[:sign/send-accept-transaction-message message-id tx-hash signature]
|
||||
[:sign/send-transaction-message chat-id value contract tx-hash signature])
|
||||
:signing/show-transaction-result nil
|
||||
:db (-> db
|
||||
(assoc-in [:keycard :pin :sign] [])
|
||||
(assoc-in [:keycard :pin :status] nil))}
|
||||
:db (-> db
|
||||
(assoc-in [:keycard :pin :sign] [])
|
||||
(assoc-in [:keycard :pin :status] nil))}
|
||||
(common/clear-on-card-connected)
|
||||
(common/get-application-info nil)
|
||||
(common/hide-connection-sheet)))
|
||||
|
||||
(fx/defn sign-typed-data
|
||||
(rf/defn sign-typed-data
|
||||
{:events [:keycard/sign-typed-data]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [card-connected? (get-in db [:keycard :card-connected?])
|
||||
hash (get-in db [:keycard :hash])]
|
||||
hash (get-in db [:keycard :hash])]
|
||||
(if card-connected?
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :card-read-in-progress?] true)
|
||||
(assoc-in [:signing/sign :keycard-step] :signing))
|
||||
:keycard/sign-typed-data {:hash (ethereum/naked-address hash)}}
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(common/set-on-card-connected :keycard/sign-typed-data)
|
||||
{:db (assoc-in db [:signing/sign :keycard-step] :signing)}))))
|
||||
|
||||
(fx/defn fetch-currency-token-on-success
|
||||
(rf/defn fetch-currency-token-on-success
|
||||
{:events [:keycard/fetch-currency-token-on-success]}
|
||||
[{:keys [db]} {:keys [decimals symbol]}]
|
||||
{:db (-> db
|
||||
(assoc-in [:signing/sign :formatted-data :message :formatted-currency] symbol)
|
||||
(update-in [:signing/sign :formatted-data :message]
|
||||
#(assoc % :formatted-amount (.dividedBy ^js (money/bignumber (:amount %))
|
||||
(money/bignumber (money/from-decimal decimals))))))})
|
||||
#(assoc %
|
||||
:formatted-amount
|
||||
(.dividedBy ^js (money/bignumber (:amount %))
|
||||
(money/bignumber (money/from-decimal decimals))))))})
|
||||
|
||||
(fx/defn store-hash-and-sign-typed
|
||||
(rf/defn store-hash-and-sign-typed
|
||||
{:events [:keycard/store-hash-and-sign-typed]}
|
||||
[{:keys [db] :as cofx} result]
|
||||
(let [{:keys [result]} (types/json->clj result)
|
||||
message (get-in db [:signing/sign :formatted-data :message])
|
||||
(let [{:keys [result]} (types/json->clj result)
|
||||
message (get-in db [:signing/sign :formatted-data :message])
|
||||
currency-contract (:currency message)]
|
||||
(when currency-contract
|
||||
{::json-rpc/call [{:method "wallet_discoverToken"
|
||||
:params [(ethereum/chain-id db) currency-contract]
|
||||
:on-success #(re-frame/dispatch [:keycard/fetch-currency-token-on-success %])}]})
|
||||
(fx/merge cofx
|
||||
{::json-rpc/call [{:method "wallet_discoverToken"
|
||||
:params [(ethereum/chain-id db) currency-contract]
|
||||
:on-success #(re-frame/dispatch [:keycard/fetch-currency-token-on-success
|
||||
%])}]})
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :hash] result)}
|
||||
sign-typed-data)))
|
||||
|
||||
(fx/defn prepare-to-sign
|
||||
(rf/defn prepare-to-sign
|
||||
{:events [:keycard/prepare-to-sign]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(common/show-connection-sheet
|
||||
@@ -125,30 +132,31 @@
|
||||
{:on-card-connected :keycard/prepare-to-sign
|
||||
:handler (common/get-application-info :keycard/sign)}))
|
||||
|
||||
(fx/defn sign-message-completed
|
||||
(rf/defn sign-message-completed
|
||||
[_ signature]
|
||||
{:dispatch
|
||||
[:signing/sign-message-completed signature]})
|
||||
|
||||
(fx/defn send-transaction-with-signature
|
||||
(rf/defn send-transaction-with-signature
|
||||
[_ data]
|
||||
{:send-transaction-with-signature data})
|
||||
|
||||
(fx/defn on-sign-success
|
||||
(rf/defn on-sign-success
|
||||
{:events [:keycard.callback/on-sign-success]}
|
||||
[{:keys [db] :as cofx} signature]
|
||||
(log/debug "[keycard] sign success: " signature)
|
||||
(let [signature-json (types/clj->json {:result (normalize-signature signature)})
|
||||
transaction (get-in db [:keycard :transaction])
|
||||
tx-obj (select-keys transaction [:from :to :value :gas :gasPrice :command? :chat-id :message-id])
|
||||
tx-obj (select-keys transaction
|
||||
[:from :to :value :gas :gasPrice :command? :chat-id :message-id])
|
||||
command? (:command? transaction)]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :hash] nil)
|
||||
(assoc-in [:keycard :transaction] nil))}
|
||||
(when-not command?
|
||||
(fn [{:keys [db] :as cofx}]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :pin :sign] [])
|
||||
@@ -163,18 +171,19 @@
|
||||
:on-completed #(re-frame/dispatch [:signing/transaction-completed % tx-obj])})
|
||||
(sign-message-completed signature-json)))))
|
||||
|
||||
(fx/defn on-sign-error
|
||||
(rf/defn on-sign-error
|
||||
{:events [:keycard.callback/on-sign-error]}
|
||||
[{:keys [db] :as cofx} error]
|
||||
(log/debug "[keycard] sign error: " error)
|
||||
(let [tag-was-lost? (common/tag-lost? (:error error))
|
||||
pin-retries (common/pin-retries (:error error))]
|
||||
pin-retries (common/pin-retries (:error error))]
|
||||
(when-not tag-was-lost?
|
||||
(if (not (nil? pin-retries))
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :application-info :pin-retry-counter] pin-retries)
|
||||
(update-in [:keycard :pin] assoc
|
||||
(update-in [:keycard :pin]
|
||||
assoc
|
||||
:status :error
|
||||
:sign []
|
||||
:error-label :t/pin-mismatch)
|
||||
@@ -182,6 +191,6 @@
|
||||
(common/hide-connection-sheet)
|
||||
(when (zero? pin-retries) (common/frozen-keycard-popup)))
|
||||
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(common/hide-connection-sheet)
|
||||
(common/show-wrong-keycard-alert))))))
|
||||
|
||||
@@ -1,42 +1,45 @@
|
||||
(ns status-im.keycard.unpair
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.utils.fx :as fx]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.keycard.common :as common]
|
||||
[status-im.multiaccounts.key-storage.core :as key-storage]))
|
||||
[status-im.multiaccounts.key-storage.core :as key-storage]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn unpair-card-pressed
|
||||
(rf/defn unpair-card-pressed
|
||||
{:events [:keycard-settings.ui/unpair-card-pressed]}
|
||||
[_]
|
||||
{:ui/show-confirmation {:title (i18n/label :t/unpair-card)
|
||||
:content (i18n/label :t/unpair-card-confirmation)
|
||||
:confirm-button-text (i18n/label :t/yes)
|
||||
:cancel-button-text (i18n/label :t/no)
|
||||
:on-accept #(re-frame/dispatch [:keycard-settings.ui/unpair-card-confirmed])
|
||||
:on-accept #(re-frame/dispatch
|
||||
[:keycard-settings.ui/unpair-card-confirmed])
|
||||
:on-cancel #()}})
|
||||
|
||||
(fx/defn unpair-card-confirmed
|
||||
(rf/defn unpair-card-confirmed
|
||||
{:events [:keycard-settings.ui/unpair-card-confirmed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:keycard :pin] {:enter-step :current
|
||||
:current []
|
||||
:puk []
|
||||
:status nil
|
||||
:error-label nil
|
||||
:on-verified :keycard/unpair})}
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:keycard :pin]
|
||||
{:enter-step :current
|
||||
:current []
|
||||
:puk []
|
||||
:status nil
|
||||
:error-label nil
|
||||
:on-verified :keycard/unpair})}
|
||||
(common/navigate-to-enter-pin-screen)))
|
||||
|
||||
(fx/defn unpair
|
||||
(rf/defn unpair
|
||||
{:events [:keycard/unpair]}
|
||||
[{:keys [db]}]
|
||||
(let [pin (common/vector->string (get-in db [:keycard :pin :current]))]
|
||||
(let [pin (common/vector->string (get-in db [:keycard :pin :current]))]
|
||||
{:keycard/unpair {:pin pin}}))
|
||||
|
||||
(fx/defn unpair-and-delete
|
||||
(rf/defn unpair-and-delete
|
||||
{:events [:keycard/unpair-and-delete]}
|
||||
[cofx]
|
||||
(common/show-connection-sheet
|
||||
@@ -44,55 +47,65 @@
|
||||
{:on-card-connected :keycard/unpair-and-delete
|
||||
:handler
|
||||
(fn [{:keys [db]}]
|
||||
(let [pin (common/vector->string (get-in db [:keycard :pin :current]))]
|
||||
(let [pin (common/vector->string (get-in db [:keycard :pin :current]))]
|
||||
{:keycard/unpair-and-delete
|
||||
{:pin pin}}))}))
|
||||
|
||||
(fx/defn remove-pairing-from-multiaccount
|
||||
(rf/defn remove-pairing-from-multiaccount
|
||||
[cofx {:keys [remove-instance-uid?]}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:keycard-pairing nil {})
|
||||
:keycard-pairing
|
||||
nil
|
||||
{})
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:keycard-paired-on nil {})
|
||||
:keycard-paired-on
|
||||
nil
|
||||
{})
|
||||
(when remove-instance-uid?
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:keycard-instance-uid nil {}))))
|
||||
:keycard-instance-uid
|
||||
nil
|
||||
{}))))
|
||||
|
||||
(fx/defn on-unpair-success
|
||||
(rf/defn on-unpair-success
|
||||
{:events [:keycard.callback/on-unpair-success]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [instance-uid (get-in db [:keycard :application-info :instance-uid])
|
||||
pairings (get-in db [:keycard :pairings])]
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :secrets] nil)
|
||||
(update-in [:keycard :pairings] dissoc (keyword instance-uid))
|
||||
(assoc-in [:keycard :pin] {:status nil
|
||||
:error-label nil
|
||||
:on-verified nil}))
|
||||
:keycard/persist-pairings (dissoc pairings (keyword instance-uid))
|
||||
:utils/show-popup {:title ""
|
||||
:content (i18n/label :t/card-unpaired)}}
|
||||
(common/clear-on-card-connected)
|
||||
(remove-pairing-from-multiaccount nil)
|
||||
(navigation/navigate-to-cofx :keycard-settings nil))))
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :secrets] nil)
|
||||
(update-in [:keycard :pairings] dissoc (keyword instance-uid))
|
||||
(assoc-in [:keycard :pin]
|
||||
{:status nil
|
||||
:error-label nil
|
||||
:on-verified nil}))
|
||||
:keycard/persist-pairings (dissoc pairings (keyword instance-uid))
|
||||
:utils/show-popup {:title ""
|
||||
:content (i18n/label :t/card-unpaired)}}
|
||||
(common/clear-on-card-connected)
|
||||
(remove-pairing-from-multiaccount nil)
|
||||
(navigation/navigate-to-cofx :keycard-settings nil))))
|
||||
|
||||
(fx/defn on-unpair-error
|
||||
(rf/defn on-unpair-error
|
||||
{:events [:keycard.callback/on-unpair-error]}
|
||||
[{:keys [db] :as cofx} error]
|
||||
(log/debug "[keycard] unpair error" error)
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:keycard :pin] {:status nil
|
||||
:error-label nil
|
||||
:on-verified nil})
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:keycard :pin]
|
||||
{:status nil
|
||||
:error-label nil
|
||||
:on-verified nil})
|
||||
:keycard/get-application-info nil
|
||||
:utils/show-popup {:title ""
|
||||
:content (i18n/label :t/something-went-wrong)}}
|
||||
:utils/show-popup {:title ""
|
||||
:content (i18n/label :t/something-went-wrong)}}
|
||||
(common/clear-on-card-connected)
|
||||
(navigation/navigate-to-cofx :keycard-settings nil)))
|
||||
|
||||
(fx/defn remove-key-with-unpair
|
||||
(rf/defn remove-key-with-unpair
|
||||
{:events [:keycard/remove-key-with-unpair]}
|
||||
[cofx]
|
||||
(common/show-connection-sheet
|
||||
@@ -100,66 +113,75 @@
|
||||
{:on-card-connected :keycard/remove-key-with-unpair
|
||||
:handler
|
||||
(fn [{:keys [db]}]
|
||||
(let [pin (common/vector->string (get-in db [:keycard :pin :current]))]
|
||||
(let [pin (common/vector->string (get-in db [:keycard :pin :current]))]
|
||||
{:keycard/remove-key-with-unpair
|
||||
{:pin pin}}))}))
|
||||
|
||||
(defn handle-account-removal [{:keys [db] :as cofx} keys-removed-from-card?]
|
||||
(let [key-uid (get-in db [:multiaccount :key-uid])
|
||||
(defn handle-account-removal
|
||||
[{:keys [db] :as cofx} keys-removed-from-card?]
|
||||
(let [key-uid (get-in db [:multiaccount :key-uid])
|
||||
instance-uid (get-in db [:keycard :application-info :instance-uid])
|
||||
pairings (get-in db [:keycard :pairings])]
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
(update :multiaccounts/multiaccounts dissoc key-uid)
|
||||
(assoc-in [:keycard :secrets] nil)
|
||||
(update-in [:keycard :pairings] dissoc (keyword instance-uid))
|
||||
(update-in [:keycard :pairings] dissoc instance-uid)
|
||||
(assoc-in [:keycard :whisper-public-key] nil)
|
||||
(assoc-in [:keycard :wallet-address] nil)
|
||||
(assoc-in [:keycard :application-info] nil)
|
||||
(assoc-in [:keycard :pin] {:status nil
|
||||
:error-label nil
|
||||
:on-verified nil}))
|
||||
:keycard/persist-pairings (dissoc pairings (keyword instance-uid))
|
||||
:utils/show-popup {:title (i18n/label (if keys-removed-from-card? :t/profile-deleted-title :t/database-reset-title))
|
||||
:content (i18n/label (if keys-removed-from-card? :t/profile-deleted-keycard :t/database-reset-content))
|
||||
:on-dismiss #(re-frame/dispatch [:logout])}
|
||||
::key-storage/delete-multiaccount {:key-uid key-uid
|
||||
:on-success #(log/debug "[keycard] remove account ok")
|
||||
:on-error #(log/warn "[keycard] remove account: " %)}}
|
||||
(common/clear-on-card-connected)
|
||||
(common/hide-connection-sheet))))
|
||||
pairings (get-in db [:keycard :pairings])]
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(update :multiaccounts/multiaccounts dissoc key-uid)
|
||||
(assoc-in [:keycard :secrets] nil)
|
||||
(update-in [:keycard :pairings]
|
||||
dissoc
|
||||
(keyword instance-uid))
|
||||
(update-in [:keycard :pairings] dissoc instance-uid)
|
||||
(assoc-in [:keycard :whisper-public-key] nil)
|
||||
(assoc-in [:keycard :wallet-address] nil)
|
||||
(assoc-in [:keycard :application-info] nil)
|
||||
(assoc-in [:keycard :pin]
|
||||
{:status nil
|
||||
:error-label nil
|
||||
:on-verified nil}))
|
||||
:keycard/persist-pairings (dissoc pairings (keyword instance-uid))
|
||||
:utils/show-popup {:title (i18n/label (if keys-removed-from-card?
|
||||
:t/profile-deleted-title
|
||||
:t/database-reset-title))
|
||||
:content (i18n/label (if keys-removed-from-card?
|
||||
:t/profile-deleted-keycard
|
||||
:t/database-reset-content))
|
||||
:on-dismiss #(re-frame/dispatch [:logout])}
|
||||
::key-storage/delete-multiaccount {:key-uid key-uid
|
||||
:on-success #(log/debug "[keycard] remove account ok")
|
||||
:on-error #(log/warn "[keycard] remove account: " %)}}
|
||||
(common/clear-on-card-connected)
|
||||
(common/hide-connection-sheet))))
|
||||
|
||||
(fx/defn on-remove-key-success
|
||||
(rf/defn on-remove-key-success
|
||||
{:events [:keycard.callback/on-remove-key-success]}
|
||||
[cofx]
|
||||
(handle-account-removal cofx true))
|
||||
|
||||
(fx/defn on-remove-key-error
|
||||
(rf/defn on-remove-key-error
|
||||
{:events [:keycard.callback/on-remove-key-error]}
|
||||
[{:keys [db] :as cofx} error]
|
||||
(log/debug "[keycard] remove key error" error)
|
||||
(let [tag-was-lost? (common/tag-lost? (:error error))]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(if tag-was-lost?
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :pin :status] nil)}
|
||||
(common/set-on-card-connected :keycard/remove-key-with-unpair))
|
||||
(common/show-wrong-keycard-alert)))))
|
||||
|
||||
(fx/defn on-unpair-and-delete-success
|
||||
(rf/defn on-unpair-and-delete-success
|
||||
{:events [:keycard.callback/on-unpair-and-delete-success]}
|
||||
[cofx]
|
||||
(handle-account-removal cofx false))
|
||||
|
||||
(fx/defn on-unpair-and-delete-error
|
||||
(rf/defn on-unpair-and-delete-error
|
||||
{:events [:keycard.callback/on-unpair-and-delete-error]}
|
||||
[{:keys [db] :as cofx} error]
|
||||
(log/debug "[keycard] unpair and delete error" error)
|
||||
(let [tag-was-lost? (common/tag-lost? (:error error))]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(if tag-was-lost?
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db [:keycard :pin :status] nil)}
|
||||
(common/set-on-card-connected :keycard/unpair-and-delete))
|
||||
(common/show-wrong-keycard-alert)))))
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
(ns status-im.keycard.wallet
|
||||
(:require [status-im.ethereum.core :as ethereum]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.keycard.common :as common]
|
||||
(:require [status-im.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.eip55 :as eip55]
|
||||
[status-im.utils.hex :as utils.hex]
|
||||
[status-im.keycard.common :as common]
|
||||
[status-im.ui.screens.wallet.add-new.views :as add-new.views]
|
||||
[status-im.bottom-sheet.core :as bottom-sheet]))
|
||||
[status-im.utils.hex :as utils.hex]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn show-pin-sheet
|
||||
(rf/defn show-pin-sheet
|
||||
{:events [:keycard/new-account-pin-sheet]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :pin :enter-step] :export-key)
|
||||
(update-in [:keycard :pin] dissoc :export-key))
|
||||
{:db (-> db
|
||||
(assoc-in [:keycard :pin :enter-step] :export-key)
|
||||
(update-in [:keycard :pin] dissoc :export-key))
|
||||
:dismiss-keyboard nil}
|
||||
(bottom-sheet/show-bottom-sheet {:view {:content add-new.views/pin}})))
|
||||
|
||||
(fx/defn verify-pin-with-delay
|
||||
(rf/defn verify-pin-with-delay
|
||||
[cofx]
|
||||
{:utils/dispatch-later
|
||||
;; We need to give previous sheet some time to be fully hidden
|
||||
[{:ms 200
|
||||
[{:ms 200
|
||||
:dispatch [:wallet.accounts/verify-pin]}]})
|
||||
|
||||
(fx/defn hide-pin-sheet
|
||||
(rf/defn hide-pin-sheet
|
||||
{:events [:keycard/new-account-pin-sheet-hide]}
|
||||
[cofx]
|
||||
(bottom-sheet/hide-bottom-sheet cofx))
|
||||
|
||||
(fx/defn generate-new-keycard-account
|
||||
(rf/defn generate-new-keycard-account
|
||||
{:events [:wallet.accounts/generate-new-keycard-account]}
|
||||
[{:keys [db]}]
|
||||
(let [path-num (inc (get-in db [:multiaccount :latest-derived-path]))
|
||||
@@ -39,7 +39,8 @@
|
||||
pin (common/vector->string (get-in db [:keycard :pin :export-key]))]
|
||||
{:db
|
||||
(assoc-in
|
||||
db [:keycard :on-export-success]
|
||||
db
|
||||
[:keycard :on-export-success]
|
||||
#(vector :wallet.accounts/account-stored
|
||||
(let [public-key (utils.hex/normalize-hex %)]
|
||||
{;; Strip leading 04 prefix denoting uncompressed key format
|
||||
@@ -52,7 +53,7 @@
|
||||
|
||||
:keycard/export-key {:pin pin :path path}}))
|
||||
|
||||
(fx/defn verify-pin
|
||||
(rf/defn verify-pin
|
||||
{:events [:wallet.accounts/verify-pin]}
|
||||
[cofx]
|
||||
(common/verify-pin
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
(ns status-im.log-level.core
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.node.core :as node]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.utils.fx :as fx]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn save-log-level
|
||||
(rf/defn save-log-level
|
||||
{:events [:log-level.ui/change-log-level-confirmed]}
|
||||
[{:keys [db now] :as cofx} log-level]
|
||||
(let [old-log-level (get-in db [:multiaccount :log-level])]
|
||||
(when (not= old-log-level log-level)
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:log-level log-level
|
||||
:log-level
|
||||
log-level
|
||||
{})
|
||||
(node/prepare-new-config
|
||||
{:on-success #(re-frame/dispatch [:logout])})))))
|
||||
|
||||
(fx/defn show-change-log-level-confirmation
|
||||
(rf/defn show-change-log-level-confirmation
|
||||
{:events [:log-level.ui/log-level-selected]}
|
||||
[_ {:keys [name value]}]
|
||||
{:ui/show-confirmation
|
||||
|
||||
+142
-119
@@ -1,5 +1,4 @@
|
||||
(ns ^{:doc "Mailserver events and API"}
|
||||
status-im.mailserver.core
|
||||
(ns ^{:doc "Mailserver events and API"} status-im.mailserver.core
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
@@ -8,8 +7,8 @@
|
||||
[status-im.node.core :as node]
|
||||
[status-im.utils.mobile-sync :as mobile-network-utils]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.utils.fx :as fx]
|
||||
[taoensso.timbre :as log]))
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
;; How do mailserver work ?
|
||||
;;
|
||||
@@ -24,22 +23,28 @@
|
||||
;; as soon as the mailserver becomes available
|
||||
|
||||
|
||||
(defn connected? [db id]
|
||||
(defn connected?
|
||||
[db id]
|
||||
(= (:mailserver/current-id db) id))
|
||||
|
||||
(defn fetch [db id]
|
||||
(defn fetch
|
||||
[db id]
|
||||
(get-in db [:mailserver/mailservers (node/current-fleet-key db) id]))
|
||||
|
||||
(defn fetch-current [db]
|
||||
(defn fetch-current
|
||||
[db]
|
||||
(fetch db (:mailserver/current-id db)))
|
||||
|
||||
(defn preferred-mailserver-id [db]
|
||||
(defn preferred-mailserver-id
|
||||
[db]
|
||||
(get-in db [:multiaccount :pinned-mailservers (node/current-fleet-key db)]))
|
||||
|
||||
(defn connection-error-dismissed [db]
|
||||
(defn connection-error-dismissed
|
||||
[db]
|
||||
(get-in db [:mailserver/connection-error-dismissed]))
|
||||
|
||||
(defn mailserver-address->id [db address]
|
||||
(defn mailserver-address->id
|
||||
[db address]
|
||||
(let [current-fleet (node/current-fleet-key db)]
|
||||
(:id (some #(when (= address (:address %))
|
||||
%)
|
||||
@@ -48,19 +53,21 @@
|
||||
current-fleet
|
||||
vals)))))
|
||||
|
||||
(fx/defn disconnect-from-mailserver
|
||||
(rf/defn disconnect-from-mailserver
|
||||
{:events [::disconnect-from-mailserver]}
|
||||
[{:keys [db] :as cofx}]
|
||||
{:db (-> db
|
||||
(assoc :mailserver/state nil)
|
||||
(dissoc :mailserver/current-request :mailserver/fetching-gaps-in-progress))})
|
||||
|
||||
(defn fetch-use-mailservers? [{:keys [db]}]
|
||||
(defn fetch-use-mailservers?
|
||||
[{:keys [db]}]
|
||||
(get-in db [:multiaccount :use-mailservers?]))
|
||||
|
||||
(defonce showing-connection-error-popup? (atom false))
|
||||
|
||||
(defn cancel-connection-popup! []
|
||||
(defn cancel-connection-popup!
|
||||
[]
|
||||
(reset! showing-connection-error-popup? false)
|
||||
(re-frame/dispatch [:mailserver.ui/dismiss-connection-error true]))
|
||||
|
||||
@@ -68,7 +75,8 @@
|
||||
::cancel-connection-popup
|
||||
cancel-connection-popup!)
|
||||
|
||||
(fx/defn show-connection-error! [cofx current-fleet preferred-mailserver]
|
||||
(rf/defn show-connection-error!
|
||||
[cofx current-fleet preferred-mailserver]
|
||||
(reset! showing-connection-error-popup? true)
|
||||
{:ui/show-confirmation
|
||||
{:title (i18n/label :t/mailserver-error-title)
|
||||
@@ -88,27 +96,28 @@
|
||||
preferred-mailserver]))
|
||||
:style "default"}]}})
|
||||
|
||||
(fx/defn handle-successful-request
|
||||
(rf/defn handle-successful-request
|
||||
{:events [::request-success]}
|
||||
[{:keys [db] :as cofx} response-js]
|
||||
{:db (dissoc db :mailserver/current-request)
|
||||
:dispatch [:sanitize-messages-and-process-response response-js]})
|
||||
|
||||
(fx/defn handle-mailserver-not-working [{:keys [db] :as cofx}]
|
||||
(let [current-fleet (node/current-fleet-key db)
|
||||
error-dismissed? (connection-error-dismissed db)
|
||||
pinned-mailserver (get-in db [:multiaccount :pinned-mailservers current-fleet])]
|
||||
(rf/defn handle-mailserver-not-working
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [current-fleet (node/current-fleet-key db)
|
||||
error-dismissed? (connection-error-dismissed db)
|
||||
pinned-mailserver (get-in db [:multiaccount :pinned-mailservers current-fleet])]
|
||||
(when (and pinned-mailserver
|
||||
(not error-dismissed?)
|
||||
(not @showing-connection-error-popup?))
|
||||
(show-connection-error! cofx current-fleet pinned-mailserver))))
|
||||
|
||||
(fx/defn handle-request-error
|
||||
(rf/defn handle-request-error
|
||||
{:events [::request-error]}
|
||||
[{:keys [db] :as cofx}]
|
||||
{:db (dissoc db :mailserver/current-request)})
|
||||
|
||||
(fx/defn process-next-messages-request
|
||||
(rf/defn process-next-messages-request
|
||||
{:events [::request-messages]}
|
||||
[{:keys [db now] :as cofx}]
|
||||
(when (and
|
||||
@@ -116,93 +125,99 @@
|
||||
(mobile-network-utils/syncing-allowed? cofx)
|
||||
(fetch-use-mailservers? cofx)
|
||||
(not (:mailserver/current-request db)))
|
||||
{:db (assoc db :mailserver/current-request true)
|
||||
::json-rpc/call [{:method "wakuext_requestAllHistoricMessagesWithRetries"
|
||||
:params []
|
||||
{:db (assoc db :mailserver/current-request true)
|
||||
::json-rpc/call [{:method "wakuext_requestAllHistoricMessagesWithRetries"
|
||||
:params []
|
||||
:js-response true
|
||||
:on-success #(do
|
||||
(log/info "fetched historical messages")
|
||||
(re-frame/dispatch [::request-success %]))
|
||||
:on-error #(do
|
||||
(log/error "failed retrieve historical messages" %)
|
||||
(re-frame/dispatch [::request-error]))}]}))
|
||||
:on-success #(do
|
||||
(log/info "fetched historical messages")
|
||||
(re-frame/dispatch [::request-success %]))
|
||||
:on-error #(do
|
||||
(log/error "failed retrieve historical messages" %)
|
||||
(re-frame/dispatch [::request-error]))}]}))
|
||||
|
||||
(fx/defn handle-mailserver-changed
|
||||
(rf/defn handle-mailserver-changed
|
||||
[{:keys [db] :as cofx} ms]
|
||||
(if (seq ms)
|
||||
{:db (assoc db :mailserver/state :connecting
|
||||
{:db (assoc db
|
||||
:mailserver/state :connecting
|
||||
:mailserver/current-id (keyword ms))}
|
||||
{:db (assoc db :mailserver/state nil)}))
|
||||
|
||||
(fx/defn handle-mailserver-available
|
||||
(rf/defn handle-mailserver-available
|
||||
[{:keys [db] :as cofx} ms]
|
||||
{::cancel-connection-popup []
|
||||
:db (assoc db :mailserver/state :connected
|
||||
:mailserver/current-id (keyword ms))})
|
||||
:db (assoc db
|
||||
:mailserver/state :connected
|
||||
:mailserver/current-id (keyword ms))})
|
||||
|
||||
(fx/defn connected-to-mailserver
|
||||
(rf/defn connected-to-mailserver
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [address]} (fetch-current db)]
|
||||
(fx/merge
|
||||
(let [{:keys [address]} (fetch-current db)]
|
||||
(rf/merge
|
||||
cofx
|
||||
{:mailserver/update-mailservers [[address] #(re-frame/dispatch [::request-messages])]})))
|
||||
|
||||
(fx/defn handle-request-success
|
||||
(rf/defn handle-request-success
|
||||
{:events [:mailserver.callback/request-success]}
|
||||
[{{:keys [chats] :as db} :db} {:keys [request-id topics]}]
|
||||
(when (:mailserver/current-request db)
|
||||
{:db (assoc-in db [:mailserver/current-request :request-id]
|
||||
request-id)}))
|
||||
{:db (assoc-in db
|
||||
[:mailserver/current-request :request-id]
|
||||
request-id)}))
|
||||
|
||||
(fx/defn toggle-use-mailservers
|
||||
(rf/defn toggle-use-mailservers
|
||||
[cofx value]
|
||||
{::json-rpc/call
|
||||
[{:method "wakuext_toggleUseMailservers"
|
||||
:params [value]
|
||||
[{:method "wakuext_toggleUseMailservers"
|
||||
:params [value]
|
||||
:on-success #(log/info "successfully toggled use-mailservers" value)
|
||||
:on-failure #(log/error "failed to toggle use-mailserver" value %)}]})
|
||||
|
||||
(fx/defn update-use-mailservers
|
||||
(rf/defn update-use-mailservers
|
||||
{:events [:mailserver.ui/use-history-switch-pressed]}
|
||||
[cofx use-mailservers?]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(multiaccounts.update/optimistic :use-mailservers? use-mailservers?)
|
||||
(toggle-use-mailservers use-mailservers?)
|
||||
(when use-mailservers?
|
||||
(disconnect-from-mailserver))))
|
||||
|
||||
(fx/defn retry-next-messages-request
|
||||
(rf/defn retry-next-messages-request
|
||||
{:events [:mailserver.ui/retry-request-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (dissoc db :mailserver/request-error)}
|
||||
(process-next-messages-request)))
|
||||
|
||||
(fx/defn show-request-error-popup
|
||||
(rf/defn show-request-error-popup
|
||||
{:events [:mailserver.ui/request-error-pressed]}
|
||||
[{:keys [db]}]
|
||||
(let [mailserver-error (:mailserver/request-error db)]
|
||||
{:utils/show-confirmation
|
||||
{:title (i18n/label :t/mailserver-request-error-title)
|
||||
:content (i18n/label :t/mailserver-request-error-content
|
||||
{:error mailserver-error})
|
||||
:on-accept #(re-frame/dispatch [:mailserver.ui/retry-request-pressed])
|
||||
{:title (i18n/label :t/mailserver-request-error-title)
|
||||
:content (i18n/label :t/mailserver-request-error-content
|
||||
{:error mailserver-error})
|
||||
:on-accept #(re-frame/dispatch [:mailserver.ui/retry-request-pressed])
|
||||
:confirm-button-text (i18n/label :t/mailserver-request-retry)}}))
|
||||
|
||||
(def enode-url-regex
|
||||
#"enode://[a-zA-Z0-9]+\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})")
|
||||
|
||||
(defn- extract-url-components [address]
|
||||
(defn- extract-url-components
|
||||
[address]
|
||||
(rest (re-matches #"enode://(.*)@(.*)" address)))
|
||||
|
||||
(defn valid-enode-url? [address]
|
||||
(defn valid-enode-url?
|
||||
[address]
|
||||
(re-matches enode-url-regex address))
|
||||
|
||||
(defn build-url [address]
|
||||
(defn build-url
|
||||
[address]
|
||||
(let [[initial host] (extract-url-components address)]
|
||||
(str "enode://" initial "@" host)))
|
||||
|
||||
(fx/defn set-input
|
||||
(rf/defn set-input
|
||||
{:events [:mailserver.ui/input-changed]}
|
||||
[{:keys [db]} input-key value]
|
||||
{:db (update
|
||||
@@ -216,26 +231,28 @@
|
||||
:name (string/blank? value)
|
||||
:url (not (valid-enode-url? value)))})})
|
||||
|
||||
(defn- address->mailserver [address]
|
||||
(defn- address->mailserver
|
||||
[address]
|
||||
(let [[enode url :as response] (extract-url-components address)]
|
||||
{:address (if (seq response)
|
||||
(str "enode://" enode "@" url)
|
||||
address)
|
||||
:custom true}))
|
||||
:custom true}))
|
||||
|
||||
(defn- build [id mailserver-name address]
|
||||
(defn- build
|
||||
[id mailserver-name address]
|
||||
(assoc (address->mailserver address)
|
||||
:id id
|
||||
:id id
|
||||
:name mailserver-name))
|
||||
|
||||
(def default? (comp not :custom fetch))
|
||||
|
||||
(fx/defn edit
|
||||
(rf/defn edit
|
||||
{:events [:mailserver.ui/custom-mailserver-selected]}
|
||||
[{:keys [db] :as cofx} id]
|
||||
(let [{:keys [id address name]} (fetch db id)
|
||||
url (when address (build-url address))]
|
||||
(fx/merge cofx
|
||||
url (when address (build-url address))]
|
||||
(rf/merge cofx
|
||||
(set-input :id id)
|
||||
(set-input :url (str url))
|
||||
(set-input :name (str name))
|
||||
@@ -247,14 +264,15 @@
|
||||
(assoc :fleet (name current-fleet))
|
||||
(update :id name)))
|
||||
|
||||
(fx/defn upsert
|
||||
{:events [:mailserver.ui/save-pressed]
|
||||
(rf/defn upsert
|
||||
{:events [:mailserver.ui/save-pressed]
|
||||
:interceptors [(re-frame/inject-cofx :random-id-generator)]}
|
||||
[{{:mailserver.edit/keys [mailserver] :keys [multiaccount] :as db} :db
|
||||
random-id-generator :random-id-generator :as cofx}]
|
||||
random-id-generator :random-id-generator
|
||||
:as cofx}]
|
||||
|
||||
(let [{:keys [name url id]} mailserver
|
||||
current-fleet (node/current-fleet-key db)]
|
||||
current-fleet (node/current-fleet-key db)]
|
||||
(when (and (not (string/blank? (:value name)))
|
||||
(valid-enode-url? (:value url)))
|
||||
|
||||
@@ -263,14 +281,14 @@
|
||||
(keyword (string/replace (random-id-generator) "-" "")))
|
||||
(:value name)
|
||||
(:value url))
|
||||
current (connected? db (:id mailserver))]
|
||||
{:db (-> db
|
||||
(dissoc :mailserver.edit/mailserver)
|
||||
(assoc-in [:mailserver/mailservers current-fleet (:id mailserver)]
|
||||
mailserver))
|
||||
current (connected? db (:id mailserver))]
|
||||
{:db (-> db
|
||||
(dissoc :mailserver.edit/mailserver)
|
||||
(assoc-in [:mailserver/mailservers current-fleet (:id mailserver)]
|
||||
mailserver))
|
||||
::json-rpc/call
|
||||
[{:method "mailservers_addMailserver"
|
||||
:params [(mailserver->rpc mailserver current-fleet)]
|
||||
[{:method "mailservers_addMailserver"
|
||||
:params [(mailserver->rpc mailserver current-fleet)]
|
||||
:on-success (fn []
|
||||
;; we naively logout if the user is connected to
|
||||
;; the edited mailserver
|
||||
@@ -279,47 +297,49 @@
|
||||
[:multiaccounts.logout.ui/logout-confirmed]))
|
||||
(log/debug "saved mailserver" id "successfuly"))
|
||||
:on-failure #(log/error "failed to save mailserver" id %)}]
|
||||
:dispatch [:navigate-back]}))))
|
||||
:dispatch [:navigate-back]}))))
|
||||
|
||||
(defn can-delete?
|
||||
[db id]
|
||||
(not (or (default? db id)
|
||||
(connected? db id))))
|
||||
|
||||
(fx/defn delete
|
||||
(rf/defn delete
|
||||
{:events [:mailserver.ui/delete-confirmed]}
|
||||
[{:keys [db] :as cofx} id]
|
||||
(if (can-delete? db id)
|
||||
{:db (-> db
|
||||
(update-in
|
||||
[:mailserver/mailservers (node/current-fleet-key db)]
|
||||
dissoc id)
|
||||
(dissoc :mailserver.edit/mailserver))
|
||||
{:db (-> db
|
||||
(update-in
|
||||
[:mailserver/mailservers (node/current-fleet-key db)]
|
||||
dissoc
|
||||
id)
|
||||
(dissoc :mailserver.edit/mailserver))
|
||||
::json-rpc/call
|
||||
[{:method "mailservers_deleteMailserver"
|
||||
:params [(name id)]
|
||||
[{:method "mailservers_deleteMailserver"
|
||||
:params [(name id)]
|
||||
:on-success #(log/debug "deleted mailserver" id)
|
||||
:on-failure #(log/error "failed to delete mailserver" id %)}]
|
||||
:dispatch [:navigate-back]}
|
||||
:dispatch [:navigate-back]}
|
||||
{:dispatch [:navigate-back]}))
|
||||
|
||||
(fx/defn show-connection-confirmation
|
||||
(rf/defn show-connection-confirmation
|
||||
{:events [:mailserver.ui/default-mailserver-selected :mailserver.ui/connect-pressed]}
|
||||
[{:keys [db]} mailserver-id]
|
||||
(let [current-fleet (node/current-fleet-key db)]
|
||||
{:ui/show-confirmation
|
||||
{:title (i18n/label :t/close-app-title)
|
||||
{:title (i18n/label :t/close-app-title)
|
||||
:content
|
||||
(i18n/label :t/connect-mailserver-content
|
||||
{:name (get-in db [:mailserver/mailservers
|
||||
current-fleet mailserver-id :name])})
|
||||
{:name (get-in db
|
||||
[:mailserver/mailservers
|
||||
current-fleet mailserver-id :name])})
|
||||
:confirm-button-text (i18n/label :t/close-app-button)
|
||||
:on-accept
|
||||
#(re-frame/dispatch
|
||||
[:mailserver.ui/connect-confirmed current-fleet mailserver-id])
|
||||
:on-cancel nil}}))
|
||||
:on-cancel nil}}))
|
||||
|
||||
(fx/defn show-delete-confirmation
|
||||
(rf/defn show-delete-confirmation
|
||||
{:events [:mailserver.ui/delete-pressed]}
|
||||
[{:keys [db]} mailserver-id]
|
||||
{:ui/show-confirmation
|
||||
@@ -329,64 +349,67 @@
|
||||
:on-accept #(re-frame/dispatch
|
||||
[:mailserver.ui/delete-confirmed mailserver-id])}})
|
||||
|
||||
(fx/defn set-url-from-qr
|
||||
(rf/defn set-url-from-qr
|
||||
{:events [:mailserver.callback/qr-code-scanned]}
|
||||
[cofx url]
|
||||
(assoc (set-input cofx :url url)
|
||||
:dispatch [:navigate-back]))
|
||||
:dispatch
|
||||
[:navigate-back]))
|
||||
|
||||
(fx/defn dismiss-connection-error
|
||||
(rf/defn dismiss-connection-error
|
||||
{:events [:mailserver.ui/dismiss-connection-error]}
|
||||
[{:keys [db]} new-state]
|
||||
{:db (assoc db :mailserver/connection-error-dismissed new-state)})
|
||||
|
||||
(fx/defn pin-mailserver
|
||||
(rf/defn pin-mailserver
|
||||
{:events [:mailserver.ui/connect-confirmed]}
|
||||
[{:keys [db] :as cofx} current-fleet mailserver-id]
|
||||
(let [pinned-mailservers (-> db
|
||||
(get-in [:multiaccount :pinned-mailservers])
|
||||
(assoc current-fleet mailserver-id))]
|
||||
(fx/merge cofx
|
||||
{:db (assoc db :mailserver/current-id mailserver-id)
|
||||
::json-rpc/call [{:method "wakuext_setPinnedMailservers"
|
||||
:params [pinned-mailservers]
|
||||
(rf/merge cofx
|
||||
{:db (assoc db :mailserver/current-id mailserver-id)
|
||||
::json-rpc/call [{:method "wakuext_setPinnedMailservers"
|
||||
:params [pinned-mailservers]
|
||||
:on-success #(log/info "successfully pinned mailserver")
|
||||
:on-error #(log/error "failed to pin mailserver" %)}]}
|
||||
:on-error #(log/error "failed to pin mailserver" %)}]}
|
||||
(multiaccounts.update/optimistic :pinned-mailservers pinned-mailservers))))
|
||||
|
||||
(fx/defn unpin
|
||||
(rf/defn unpin
|
||||
{:events [:mailserver.ui/unpin-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [current-fleet (node/current-fleet-key db)
|
||||
pinned-mailservers (-> db
|
||||
(get-in [:multiaccount :pinned-mailservers])
|
||||
(dissoc current-fleet))]
|
||||
(fx/merge cofx
|
||||
{::json-rpc/call [{:method "wakuext_setPinnedMailservers"
|
||||
:params [pinned-mailservers]
|
||||
(let [current-fleet (node/current-fleet-key db)
|
||||
pinned-mailservers (-> db
|
||||
(get-in [:multiaccount :pinned-mailservers])
|
||||
(dissoc current-fleet))]
|
||||
(rf/merge cofx
|
||||
{::json-rpc/call [{:method "wakuext_setPinnedMailservers"
|
||||
:params [pinned-mailservers]
|
||||
:on-success #(log/info "successfully unpinned mailserver")
|
||||
:on-error #(log/error "failed to unpin mailserver" %)}]}
|
||||
:on-error #(log/error "failed to unpin mailserver" %)}]}
|
||||
(multiaccounts.update/optimistic
|
||||
:pinned-mailservers pinned-mailservers)
|
||||
:pinned-mailservers
|
||||
pinned-mailservers)
|
||||
(dismiss-connection-error false))))
|
||||
|
||||
(fx/defn pin
|
||||
(rf/defn pin
|
||||
{:events [:mailserver.ui/pin-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [current-fleet (node/current-fleet-key db)
|
||||
mailserver-id (:mailserver/current-id db)
|
||||
(let [current-fleet (node/current-fleet-key db)
|
||||
mailserver-id (:mailserver/current-id db)
|
||||
pinned-mailservers (get-in db [:multiaccount :pinned-mailservers])]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:pinned-mailservers (assoc pinned-mailservers
|
||||
current-fleet
|
||||
mailserver-id)
|
||||
:pinned-mailservers
|
||||
(assoc pinned-mailservers
|
||||
current-fleet
|
||||
mailserver-id)
|
||||
{})
|
||||
(dismiss-connection-error false))))
|
||||
|
||||
(fx/defn mailserver-ui-add-pressed
|
||||
(rf/defn mailserver-ui-add-pressed
|
||||
{:events [:mailserver.ui/add-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (dissoc db :mailserver.edit/mailserver)}
|
||||
(navigation/navigate-to-cofx :edit-mailserver nil)))
|
||||
|
||||
@@ -1,28 +1,29 @@
|
||||
(ns status-im.mobile-sync-settings.core
|
||||
(:require
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.wallet.core :as wallet]
|
||||
[status-im.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.multiaccounts.model :as multiaccounts.model]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.mailserver.core :as mailserver]
|
||||
[status-im.utils.mobile-sync :as utils]
|
||||
[taoensso.timbre :as log]))
|
||||
(:require [status-im.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.mailserver.core :as mailserver]
|
||||
[status-im.multiaccounts.model :as multiaccounts.model]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.utils.mobile-sync :as utils]
|
||||
[status-im.wallet.core :as wallet]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn sheet-defaults
|
||||
(rf/defn sheet-defaults
|
||||
[{:keys [db]}]
|
||||
(let [remember-choice? (get-in db [:multiaccount :remember-syncing-choice?])]
|
||||
{:db (assoc db :mobile-network/remember-choice? (or (nil? remember-choice?)
|
||||
remember-choice?))}))
|
||||
{:db (assoc db
|
||||
:mobile-network/remember-choice?
|
||||
(or (nil? remember-choice?)
|
||||
remember-choice?))}))
|
||||
|
||||
(fx/defn on-network-status-change
|
||||
(rf/defn on-network-status-change
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [initialized? (get db :network-status/initialized?)
|
||||
logged-in? (multiaccounts.model/logged-in? cofx)
|
||||
(let [initialized? (get db :network-status/initialized?)
|
||||
logged-in? (multiaccounts.model/logged-in? cofx)
|
||||
{:keys [remember-syncing-choice?]} (:multiaccount db)]
|
||||
(apply
|
||||
fx/merge
|
||||
rf/merge
|
||||
cofx
|
||||
{:db (assoc db :network-status/initialized? true)}
|
||||
(cond
|
||||
@@ -51,67 +52,71 @@
|
||||
([sync?] (apply-settings sync? :default))
|
||||
([sync? remember?]
|
||||
(fn [{:keys [db] :as cofx}]
|
||||
(let [network (:network/type db)
|
||||
(let [network (:network/type db)
|
||||
remember-choice?
|
||||
(if (not= :default remember?)
|
||||
remember?
|
||||
(:mobile-network/remember-choice? db))
|
||||
cellular? (utils/cellular? network)]
|
||||
cellular? (utils/cellular? network)]
|
||||
(log/info "apply mobile network settings"
|
||||
"sunc?" sync?
|
||||
"sunc?" sync?
|
||||
"remember?" remember?
|
||||
"cellular?" cellular?)
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:syncing-on-mobile-network? (boolean sync?) {})
|
||||
:syncing-on-mobile-network?
|
||||
(boolean sync?)
|
||||
{})
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:remember-syncing-choice? (boolean remember-choice?) {})
|
||||
:remember-syncing-choice?
|
||||
(boolean remember-choice?)
|
||||
{})
|
||||
(when (and cellular? sync?)
|
||||
(mailserver/process-next-messages-request))
|
||||
(wallet/restart-wallet-service nil))))))
|
||||
|
||||
(fx/defn mobile-network-continue-syncing
|
||||
(rf/defn mobile-network-continue-syncing
|
||||
{:events [:mobile-network/continue-syncing]}
|
||||
[cofx]
|
||||
((apply-settings true) cofx))
|
||||
|
||||
(fx/defn mobile-network-stop-syncing
|
||||
(rf/defn mobile-network-stop-syncing
|
||||
{:events [:mobile-network/stop-syncing]}
|
||||
[cofx]
|
||||
((apply-settings false) cofx))
|
||||
|
||||
(fx/defn mobile-network-set-syncing
|
||||
(rf/defn mobile-network-set-syncing
|
||||
{:events [:mobile-network/set-syncing]}
|
||||
[{:keys [db] :as cofx} syncing?]
|
||||
(let [{:keys [remember-syncing-choice?]} (:multiaccount db)]
|
||||
((apply-settings syncing? remember-syncing-choice?) cofx)))
|
||||
|
||||
(fx/defn mobile-network-ask-on-mobile-network?
|
||||
(rf/defn mobile-network-ask-on-mobile-network?
|
||||
{:events [:mobile-network/ask-on-mobile-network?]}
|
||||
[{:keys [db] :as cofx} ask?]
|
||||
(let [{:keys [syncing-on-mobile-network?]} (:multiaccount db)]
|
||||
((apply-settings syncing-on-mobile-network? (not ask?)) cofx)))
|
||||
|
||||
(fx/defn mobile-network-restore-defaults
|
||||
(rf/defn mobile-network-restore-defaults
|
||||
{:events [:mobile-network/restore-defaults]}
|
||||
[cofx]
|
||||
((apply-settings false false) cofx))
|
||||
|
||||
(fx/defn mobile-network-remember-choice?
|
||||
(rf/defn mobile-network-remember-choice?
|
||||
{:events [:mobile-network/remember-choice?]}
|
||||
[{:keys [db]} remember-choice?]
|
||||
{:db (assoc db :mobile-network/remember-choice? remember-choice?)})
|
||||
|
||||
(fx/defn mobile-network-navigate-to-settings
|
||||
(rf/defn mobile-network-navigate-to-settings
|
||||
{:events [:mobile-network/navigate-to-settings]}
|
||||
[cofx]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
(bottom-sheet/hide-bottom-sheet)
|
||||
(navigation/navigate-to-cofx :mobile-network-settings nil)))
|
||||
|
||||
(fx/defn mobile-network-show-offline-sheet
|
||||
(rf/defn mobile-network-show-offline-sheet
|
||||
{:events [:mobile-network/show-offline-sheet]}
|
||||
[cofx]
|
||||
(bottom-sheet/show-bottom-sheet
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
(ns status-im.multiaccounts.biometric.core
|
||||
(:require [re-frame.core :as re-frame]
|
||||
(:require ["react-native-touch-id" :default touchid]
|
||||
[quo.design-system.colors :as colors]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.popover.core :as popover]
|
||||
[quo.design-system.colors :as colors]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.keychain.core :as keychain]
|
||||
[status-im.utils.platform :as platform]
|
||||
[taoensso.timbre :as log]
|
||||
["react-native-touch-id" :default touchid]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
;; currently, for android, react-native-touch-id
|
||||
;; is not returning supported biometric type
|
||||
@@ -28,11 +28,12 @@
|
||||
(def android-device-blacklisted?
|
||||
(cond
|
||||
(= (:brand deviceinfo) "bannedbrand") true
|
||||
:else false))
|
||||
:else false))
|
||||
|
||||
;; biometric auth config
|
||||
;; https://github.com/naoufal/react-native-touch-id#authenticatereason-config
|
||||
(defn- authenticate-options [ios-fallback-label]
|
||||
(defn- authenticate-options
|
||||
[ios-fallback-label]
|
||||
(clj->js (merge
|
||||
{:unifiedErrors true}
|
||||
(when platform/ios?
|
||||
@@ -46,7 +47,8 @@
|
||||
:sensorErrorDescription (i18n/label :t/biometric-auth-android-sensor-error-desc)
|
||||
:cancelText (i18n/label :cancel)}))))
|
||||
|
||||
(defn get-label [supported-biometric-auth]
|
||||
(defn get-label
|
||||
[supported-biometric-auth]
|
||||
(case supported-biometric-auth
|
||||
:fingerprint (i18n/label :t/biometric-fingerprint)
|
||||
:FaceID (i18n/label :t/biometric-faceid)
|
||||
@@ -61,29 +63,33 @@
|
||||
(= touchid-error-code "USER_FALLBACK") nil
|
||||
;; add here more specific errors if needed
|
||||
;; https://github.com/naoufal/react-native-touch-id#unified-errors
|
||||
:else (i18n/label :t/biometric-auth-error {:code touchid-error-code})))
|
||||
:else (i18n/label :t/biometric-auth-error
|
||||
{:code touchid-error-code})))
|
||||
|
||||
(def success-result
|
||||
{:bioauth-success true})
|
||||
|
||||
(defn- generate-error-result [touchid-error-obj]
|
||||
(defn- generate-error-result
|
||||
[touchid-error-obj]
|
||||
(let [code (aget touchid-error-obj "code")]
|
||||
{:bioauth-success false
|
||||
:bioauth-code code
|
||||
:bioauth-message (get-error-message code)}))
|
||||
|
||||
(defn- do-get-supported [callback]
|
||||
(defn- do-get-supported
|
||||
[callback]
|
||||
(-> (.isSupported touchid)
|
||||
(.then #(callback (or (keyword %) android-default-support)))
|
||||
(.catch #(callback nil))))
|
||||
|
||||
(defn get-supported [callback]
|
||||
(defn get-supported
|
||||
[callback]
|
||||
(log/debug "[biometric] get-supported")
|
||||
(cond platform/ios? (do-get-supported callback)
|
||||
(cond platform/ios? (do-get-supported callback)
|
||||
platform/android? (if android-device-blacklisted?
|
||||
(callback nil)
|
||||
(do-get-supported callback))
|
||||
:else (callback nil)))
|
||||
:else (callback nil)))
|
||||
|
||||
(defn authenticate-fx
|
||||
([cb]
|
||||
@@ -105,12 +111,12 @@
|
||||
(get-supported callback)
|
||||
(callback nil)))))))
|
||||
|
||||
(fx/defn set-supported-biometric-auth
|
||||
(rf/defn set-supported-biometric-auth
|
||||
{:events [:init.callback/get-supported-biometric-auth-success]}
|
||||
[{:keys [db]} supported-biometric-auth]
|
||||
{:db (assoc db :supported-biometric-auth supported-biometric-auth)})
|
||||
|
||||
(fx/defn authenticate
|
||||
(rf/defn authenticate
|
||||
[_ cb options]
|
||||
{:biometric-auth/authenticate [cb options]})
|
||||
|
||||
@@ -119,10 +125,11 @@
|
||||
(fn [[cb options]]
|
||||
(authenticate-fx #(cb %) options)))
|
||||
|
||||
(fx/defn update-biometric [{db :db :as cofx} biometric-auth?]
|
||||
(rf/defn update-biometric
|
||||
[{db :db :as cofx} biometric-auth?]
|
||||
(let [key-uid (or (get-in db [:multiaccount :key-uid])
|
||||
(get-in db [:multiaccounts/login :key-uid]))]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(keychain/save-auth-method
|
||||
key-uid
|
||||
(if biometric-auth?
|
||||
@@ -131,7 +138,7 @@
|
||||
#(when-not biometric-auth?
|
||||
{:keychain/clear-user-password key-uid}))))
|
||||
|
||||
(fx/defn biometric-auth-switched
|
||||
(rf/defn biometric-auth-switched
|
||||
{:events [:multiaccounts.ui/biometric-auth-switched]}
|
||||
[cofx biometric-auth?]
|
||||
(if biometric-auth?
|
||||
@@ -141,17 +148,17 @@
|
||||
{})
|
||||
(update-biometric cofx false)))
|
||||
|
||||
(fx/defn show-message
|
||||
(rf/defn show-message
|
||||
[cofx bioauth-message bioauth-code]
|
||||
(let [content (or (when (get #{"NOT_AVAILABLE" "NOT_ENROLLED"} bioauth-code)
|
||||
(i18n/label :t/grant-face-id-permissions))
|
||||
bioauth-message)]
|
||||
(when content
|
||||
{:utils/show-popup
|
||||
{:title (i18n/label :t/biometric-auth-login-error-title)
|
||||
{:title (i18n/label :t/biometric-auth-login-error-title)
|
||||
:content content}})))
|
||||
|
||||
(fx/defn biometric-init-done
|
||||
(rf/defn biometric-init-done
|
||||
{:events [:biometric-init-done]}
|
||||
[cofx {:keys [bioauth-success bioauth-message bioauth-code]}]
|
||||
(if bioauth-success
|
||||
@@ -161,7 +168,7 @@
|
||||
(popover/show-popover cofx {:view :enable-biometric}))
|
||||
(show-message cofx bioauth-message bioauth-code)))
|
||||
|
||||
(fx/defn biometric-auth
|
||||
(rf/defn biometric-auth
|
||||
{:events [:biometric-authenticate]}
|
||||
[cofx]
|
||||
(authenticate
|
||||
@@ -170,31 +177,31 @@
|
||||
{:reason (i18n/label :t/biometric-auth-reason-login)
|
||||
:ios-fallback-label (i18n/label :t/biometric-auth-login-ios-fallback-label)}))
|
||||
|
||||
(fx/defn enable
|
||||
(rf/defn enable
|
||||
{:events [:biometric/enable]}
|
||||
[cofx]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
(popover/hide-popover)
|
||||
(authenticate #(re-frame/dispatch [:biometric/setup-done %]) {})))
|
||||
|
||||
(fx/defn disable
|
||||
(rf/defn disable
|
||||
{:events [:biometric/disable]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(assoc :auth-method keychain/auth-method-none)
|
||||
(assoc-in [:multiaccounts/login :save-password?] false))}
|
||||
(popover/hide-popover)))
|
||||
|
||||
(fx/defn setup-done
|
||||
(rf/defn setup-done
|
||||
{:events [:biometric/setup-done]}
|
||||
[{:keys [db] :as cofx} {:keys [bioauth-success bioauth-message bioauth-code]}]
|
||||
(log/debug "[biometric] setup-done"
|
||||
"bioauth-success" bioauth-success
|
||||
"bioauth-message" bioauth-message
|
||||
"bioauth-code" bioauth-code)
|
||||
"bioauth-code" bioauth-code)
|
||||
(if bioauth-success
|
||||
{:db (assoc db :auth-method keychain/auth-method-biometric-prepare)}
|
||||
(show-message cofx bioauth-message bioauth-code)))
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
(ns status-im.multiaccounts.core
|
||||
(:require [re-frame.core :as re-frame]
|
||||
(:require [clojure.string :as string]
|
||||
[quo.platform :as platform]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.ethereum.stateofus :as stateofus]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.native-module.core :as native-module]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.theme.core :as theme]
|
||||
[status-im.utils.gfycat.core :as gfycat]
|
||||
[status-im.utils.identicon :as identicon]
|
||||
[status-im.theme.core :as theme]
|
||||
[status-im.utils.utils :as utils]
|
||||
[quo.platform :as platform]
|
||||
[status-im2.common.theme.core :as utils.theme]
|
||||
[taoensso.timbre :as log]
|
||||
[clojure.string :as string]
|
||||
[status-im2.common.theme.core :as utils.theme]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
;; validate that the given mnemonic was generated from Status Dictionary
|
||||
(re-frame/reg-fx
|
||||
@@ -35,7 +35,7 @@
|
||||
(cond-> {:nickname nickname
|
||||
:display-name display-name
|
||||
:three-words-name (or alias (gfycat/generate-gfy public-key))}
|
||||
;; Preferred name is our own otherwise we make sure it's verified
|
||||
;; Preferred name is our own otherwise we make sure it's verified
|
||||
(or preferred-name (and ens-verified name))
|
||||
(assoc :ens-name (str "@" (or (stateofus/username ens-name) ens-name))))))
|
||||
|
||||
@@ -48,7 +48,8 @@
|
||||
(let [{:keys [nickname
|
||||
ens-name
|
||||
display-name
|
||||
three-words-name]} (or names (contact-names contact))
|
||||
three-words-name]}
|
||||
(or names (contact-names contact))
|
||||
short-public-key (when public-key? (utils/get-shortened-address public-key))]
|
||||
(->> [nickname ens-name display-name three-words-name short-public-key]
|
||||
(remove string/blank?)
|
||||
@@ -70,11 +71,13 @@
|
||||
(str "@" (or username ens-name)))
|
||||
(or alias (gfycat/generate-gfy public-key)))))
|
||||
|
||||
(defn contact-by-identity [contacts identity]
|
||||
(defn contact-by-identity
|
||||
[contacts identity]
|
||||
(or (get contacts identity)
|
||||
(contact-with-names {:public-key identity})))
|
||||
|
||||
(defn contact-two-names-by-identity [contact current-multiaccount identity]
|
||||
(defn contact-two-names-by-identity
|
||||
[contact current-multiaccount identity]
|
||||
(let [me? (= (:public-key current-multiaccount) identity)]
|
||||
(if me?
|
||||
[(or (:preferred-name current-multiaccount)
|
||||
@@ -110,53 +113,61 @@
|
||||
(fn [flag]
|
||||
(native-module/set-blank-preview-flag flag)))
|
||||
|
||||
(fx/defn confirm-wallet-set-up
|
||||
(rf/defn confirm-wallet-set-up
|
||||
{:events [:multiaccounts.ui/wallet-set-up-confirmed]}
|
||||
[cofx]
|
||||
(multiaccounts.update/multiaccount-update cofx
|
||||
:wallet-set-up-passed? true {}))
|
||||
:wallet-set-up-passed?
|
||||
true
|
||||
{}))
|
||||
|
||||
(fx/defn confirm-home-tooltip
|
||||
(rf/defn confirm-home-tooltip
|
||||
{:events [:multiaccounts.ui/hide-home-tooltip]}
|
||||
[cofx]
|
||||
(multiaccounts.update/multiaccount-update cofx
|
||||
:hide-home-tooltip? true {}))
|
||||
:hide-home-tooltip?
|
||||
true
|
||||
{}))
|
||||
|
||||
(fx/defn switch-webview-debug
|
||||
(rf/defn switch-webview-debug
|
||||
{:events [:multiaccounts.ui/switch-webview-debug]}
|
||||
[{:keys [db] :as cofx} value]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{::webview-debug-changed value}
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:webview-debug (boolean value)
|
||||
:webview-debug
|
||||
(boolean value)
|
||||
{})))
|
||||
|
||||
(fx/defn switch-preview-privacy-mode
|
||||
(rf/defn switch-preview-privacy-mode
|
||||
{:events [:multiaccounts.ui/preview-privacy-mode-switched]}
|
||||
[{:keys [db] :as cofx} private?]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{::blank-preview-flag-changed private?}
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:preview-privacy? (boolean private?)
|
||||
:preview-privacy?
|
||||
(boolean private?)
|
||||
{})))
|
||||
|
||||
(fx/defn switch-webview-permission-requests?
|
||||
(rf/defn switch-webview-permission-requests?
|
||||
{:events [:multiaccounts.ui/webview-permission-requests-switched]}
|
||||
[cofx enabled?]
|
||||
(multiaccounts.update/multiaccount-update
|
||||
cofx
|
||||
:webview-allow-permission-requests? (boolean enabled?)
|
||||
:webview-allow-permission-requests?
|
||||
(boolean enabled?)
|
||||
{}))
|
||||
|
||||
(fx/defn switch-default-sync-period
|
||||
(rf/defn switch-default-sync-period
|
||||
{:events [:multiaccounts.ui/default-sync-period-switched]}
|
||||
[cofx value]
|
||||
(multiaccounts.update/multiaccount-update
|
||||
cofx
|
||||
:default-sync-period value
|
||||
:default-sync-period
|
||||
value
|
||||
{}))
|
||||
|
||||
(fx/defn switch-preview-privacy-mode-flag
|
||||
(rf/defn switch-preview-privacy-mode-flag
|
||||
[{:keys [db]}]
|
||||
(let [private? (get-in db [:multiaccount :preview-privacy?])]
|
||||
{::blank-preview-flag-changed private?}))
|
||||
@@ -169,48 +180,49 @@
|
||||
:light)]
|
||||
(theme/change-theme theme))))
|
||||
|
||||
(fx/defn switch-appearance
|
||||
(rf/defn switch-appearance
|
||||
{:events [:multiaccounts.ui/appearance-switched]}
|
||||
[cofx theme]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:multiaccounts.ui/switch-theme theme}
|
||||
(multiaccounts.update/multiaccount-update :appearance theme {})))
|
||||
|
||||
(fx/defn switch-profile-picture-show-to
|
||||
(rf/defn switch-profile-picture-show-to
|
||||
{:events [:multiaccounts.ui/profile-picture-show-to-switched]}
|
||||
[cofx id]
|
||||
(fx/merge cofx
|
||||
{::json-rpc/call [{:method "wakuext_changeIdentityImageShowTo"
|
||||
:params [id]
|
||||
(rf/merge cofx
|
||||
{::json-rpc/call [{:method "wakuext_changeIdentityImageShowTo"
|
||||
:params [id]
|
||||
:on-success #(log/debug "picture settings changed successfully")}]}
|
||||
(multiaccounts.update/optimistic :profile-pictures-show-to id)))
|
||||
|
||||
(fx/defn switch-appearance-profile
|
||||
(rf/defn switch-appearance-profile
|
||||
{:events [:multiaccounts.ui/appearance-profile-switched]}
|
||||
[cofx id]
|
||||
(multiaccounts.update/multiaccount-update cofx :profile-pictures-visibility id {}))
|
||||
|
||||
(defn clean-path [path]
|
||||
(defn clean-path
|
||||
[path]
|
||||
(if path
|
||||
(string/replace-first path #"file://" "")
|
||||
(log/warn "[native-module] Empty path was provided")))
|
||||
|
||||
(fx/defn save-profile-picture
|
||||
(rf/defn save-profile-picture
|
||||
{:events [::save-profile-picture]}
|
||||
[cofx path ax ay bx by]
|
||||
(let [key-uid (get-in cofx [:db :multiaccount :key-uid])]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{::json-rpc/call [{:method "multiaccounts_storeIdentityImage"
|
||||
:params [key-uid (clean-path path) ax ay bx by]
|
||||
;; NOTE: In case of an error we can show a toast error
|
||||
:on-success #(re-frame/dispatch [::update-local-picture %])}]}
|
||||
(bottom-sheet/hide-bottom-sheet))))
|
||||
|
||||
(fx/defn save-profile-picture-from-url
|
||||
(rf/defn save-profile-picture-from-url
|
||||
{:events [::save-profile-picture-from-url]}
|
||||
[cofx url]
|
||||
(let [key-uid (get-in cofx [:db :multiaccount :key-uid])]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{::json-rpc/call [{:method "multiaccounts_storeIdentityImageFromURL"
|
||||
:params [key-uid url]
|
||||
:on-error #(log/error "::save-profile-picture-from-url error" %)
|
||||
@@ -218,32 +230,37 @@
|
||||
(bottom-sheet/hide-bottom-sheet))))
|
||||
|
||||
(comment
|
||||
(re-frame/dispatch [::save-profile-picture-from-url "https://lh3.googleusercontent.com/XuKjNm3HydsaxbPkbpGs9YyCKhn5QQk5oDC8XF2jzmPyYXeZofxFtfUDZuQ3EVmacS_BlBKzbX2ypm37YNX3n1fDJA3WndeFcPsp7Z0=w600"]))
|
||||
(re-frame/dispatch
|
||||
[::save-profile-picture-from-url
|
||||
"https://lh3.googleusercontent.com/XuKjNm3HydsaxbPkbpGs9YyCKhn5QQk5oDC8XF2jzmPyYXeZofxFtfUDZuQ3EVmacS_BlBKzbX2ypm37YNX3n1fDJA3WndeFcPsp7Z0=w600"]))
|
||||
|
||||
(fx/defn delete-profile-picture
|
||||
(rf/defn delete-profile-picture
|
||||
{:events [::delete-profile-picture]}
|
||||
[cofx name]
|
||||
(let [key-uid (get-in cofx [:db :multiaccount :key-uid])]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{::json-rpc/call [{:method "multiaccounts_deleteIdentityImage"
|
||||
:params [key-uid]
|
||||
;; NOTE: In case of an error we could fallback to previous image in UI with a toast error
|
||||
;; NOTE: In case of an error we could fallback to previous image in UI
|
||||
;; with a toast error
|
||||
:on-success #(log/info "[multiaccount] Delete profile image" %)}]}
|
||||
(multiaccounts.update/optimistic :images nil)
|
||||
(bottom-sheet/hide-bottom-sheet))))
|
||||
|
||||
(fx/defn get-profile-picture
|
||||
(rf/defn get-profile-picture
|
||||
[cofx]
|
||||
(let [key-uid (get-in cofx [:db :multiaccount :key-uid])]
|
||||
{::json-rpc/call [{:method "multiaccounts_getIdentityImages"
|
||||
:params [key-uid]
|
||||
:on-success #(re-frame/dispatch [::update-local-picture %])}]}))
|
||||
|
||||
(fx/defn store-profile-picture
|
||||
(rf/defn store-profile-picture
|
||||
{:events [::update-local-picture]}
|
||||
[cofx pics]
|
||||
(multiaccounts.update/optimistic cofx :images pics))
|
||||
|
||||
(comment
|
||||
;; Test seed for Dim Venerated Yaffle, it's not here by mistake, this is just a test account
|
||||
(native-module/validate-mnemonic "rocket mixed rebel affair umbrella legal resemble scene virus park deposit cargo" prn))
|
||||
(native-module/validate-mnemonic
|
||||
"rocket mixed rebel affair umbrella legal resemble scene virus park deposit cargo"
|
||||
prn))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns status-im.multiaccounts.create.core
|
||||
(:require [re-frame.core :as re-frame]
|
||||
(:require [quo.design-system.colors :as colors]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.data-store.settings :as data-store.settings]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
@@ -7,26 +8,27 @@
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.node.core :as node]
|
||||
[quo.design-system.colors :as colors]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.security :as security]
|
||||
[status-im.utils.signing-phrase.core :as signing-phrase]
|
||||
[status-im.utils.types :as types]))
|
||||
[status-im.utils.types :as types]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(defn normalize-derived-data-keys [derived-data]
|
||||
(defn normalize-derived-data-keys
|
||||
[derived-data]
|
||||
(->> derived-data
|
||||
(map (fn [[path {:keys [publicKey] :as data}]]
|
||||
[path (cond-> (-> data
|
||||
(dissoc :publicKey)
|
||||
(assoc :public-key publicKey)))]))
|
||||
[path
|
||||
(cond-> (-> data
|
||||
(dissoc :publicKey)
|
||||
(assoc :public-key publicKey)))]))
|
||||
(into {})))
|
||||
|
||||
(defn normalize-multiaccount-data-keys
|
||||
[{:keys [publicKey keyUid derived] :as data}]
|
||||
(cond-> (-> data
|
||||
(dissoc :keyUid :publicKey)
|
||||
(assoc :key-uid keyUid
|
||||
(assoc :key-uid keyUid
|
||||
:public-key publicKey))
|
||||
derived
|
||||
(update :derived normalize-derived-data-keys)))
|
||||
@@ -49,7 +51,7 @@
|
||||
hashed-password
|
||||
callback)))
|
||||
|
||||
(fx/defn create-multiaccount
|
||||
(rf/defn create-multiaccount
|
||||
{:events [:create-multiaccount]}
|
||||
[{:keys [db]} key-code]
|
||||
(let [{:keys [selected-id]} (:intro-wizard db)]
|
||||
@@ -63,14 +65,14 @@
|
||||
(ethereum/sha3 (security/safe-unmask-data key-code))
|
||||
(fn [result]
|
||||
(let [derived-data (normalize-derived-data-keys (types/json->clj result))
|
||||
public-key (get-in derived-data [constants/path-whisper-keyword :public-key])]
|
||||
public-key (get-in derived-data [constants/path-whisper-keyword :public-key])]
|
||||
(status/gfycat-identicon-async
|
||||
public-key
|
||||
(fn [name identicon]
|
||||
(let [derived-whisper (derived-data constants/path-whisper-keyword)
|
||||
(let [derived-whisper (derived-data constants/path-whisper-keyword)
|
||||
derived-data-extended (assoc-in derived-data
|
||||
[constants/path-whisper-keyword]
|
||||
(merge derived-whisper {:name name :identicon identicon}))]
|
||||
[constants/path-whisper-keyword]
|
||||
(merge derived-whisper {:name name :identicon identicon}))]
|
||||
(re-frame/dispatch [::store-multiaccount-success key-code derived-data-extended]))))))]}))
|
||||
|
||||
(re-frame/reg-fx
|
||||
@@ -86,32 +88,36 @@
|
||||
(mapv normalize-multiaccount-data-keys
|
||||
(types/json->clj %))]))))
|
||||
|
||||
(fx/defn multiaccount-generate-and-derive-addresses-success
|
||||
(rf/defn multiaccount-generate-and-derive-addresses-success
|
||||
{:events [:multiaccount-generate-and-derive-addresses-success]}
|
||||
[{:keys [db]} result]
|
||||
{:db (update db :intro-wizard
|
||||
(fn [data]
|
||||
(-> data
|
||||
(dissoc :processing?)
|
||||
(assoc :multiaccounts result
|
||||
:selected-storage-type :default
|
||||
:selected-id (-> result first :id)
|
||||
:step :choose-key))))
|
||||
{:db (update db
|
||||
:intro-wizard
|
||||
(fn [data]
|
||||
(-> data
|
||||
(dissoc :processing?)
|
||||
(assoc :multiaccounts result
|
||||
:selected-storage-type :default
|
||||
:selected-id (-> result first :id)
|
||||
:step :choose-key))))
|
||||
:navigate-to-fx :choose-name})
|
||||
|
||||
(fx/defn generate-and-derive-addresses
|
||||
(rf/defn generate-and-derive-addresses
|
||||
{:events [:generate-and-derive-addresses]}
|
||||
[{:keys [db]}]
|
||||
{:db (-> db
|
||||
(update :intro-wizard #(-> % (assoc :processing? true) (dissoc :recovering?)))
|
||||
(dissoc :recovered-account?))
|
||||
{:db (-> db
|
||||
(update :intro-wizard
|
||||
#(-> %
|
||||
(assoc :processing? true)
|
||||
(dissoc :recovering?)))
|
||||
(dissoc :recovered-account?))
|
||||
:multiaccount-generate-and-derive-addresses nil})
|
||||
|
||||
(fx/defn prepare-intro-wizard
|
||||
(rf/defn prepare-intro-wizard
|
||||
[{:keys [db]}]
|
||||
{:db (assoc db :intro-wizard {})})
|
||||
|
||||
(fx/defn save-multiaccount-and-login-with-keycard
|
||||
(rf/defn save-multiaccount-and-login-with-keycard
|
||||
[_ args]
|
||||
{:keycard/save-multiaccount-and-login args})
|
||||
|
||||
@@ -126,7 +132,7 @@
|
||||
config
|
||||
accounts-data)))
|
||||
|
||||
(fx/defn save-account-and-login
|
||||
(rf/defn save-account-and-login
|
||||
[_ key-uid multiaccount-data password settings node-config accounts-data]
|
||||
{::save-account-and-login [key-uid
|
||||
(types/clj->json multiaccount-data)
|
||||
@@ -150,53 +156,57 @@
|
||||
{:public-key public-key
|
||||
:address (eip55/address->checksum address)
|
||||
:name name
|
||||
:identicon identicon
|
||||
:identicon identicon
|
||||
:path constants/path-whisper
|
||||
:chat true})])
|
||||
|
||||
(fx/defn on-multiaccount-created
|
||||
(rf/defn on-multiaccount-created
|
||||
[{:keys [signing-phrase random-guid-generator db] :as cofx}
|
||||
{:keys [address chat-key keycard-instance-uid key-uid
|
||||
keycard-pairing keycard-paired-on mnemonic recovered]
|
||||
:as multiaccount}
|
||||
:as multiaccount}
|
||||
password
|
||||
{:keys [save-mnemonic? login?] :or {login? true save-mnemonic? false}}]
|
||||
(let [[wallet-account {:keys [public-key identicon name]} :as accounts-data] (prepare-accounts-data multiaccount)
|
||||
multiaccount-data {:name name
|
||||
:address address
|
||||
:identicon identicon
|
||||
:key-uid key-uid
|
||||
(let [[wallet-account {:keys [public-key identicon name]} :as accounts-data] (prepare-accounts-data
|
||||
multiaccount)
|
||||
multiaccount-data {:name name
|
||||
:address address
|
||||
:identicon identicon
|
||||
:key-uid key-uid
|
||||
:keycard-pairing keycard-pairing}
|
||||
keycard-multiaccount? (boolean keycard-pairing)
|
||||
eip1581-address (get-in multiaccount [:derived
|
||||
constants/path-eip1581-keyword
|
||||
:address])
|
||||
eip1581-address (get-in multiaccount
|
||||
[:derived
|
||||
constants/path-eip1581-keyword
|
||||
:address])
|
||||
new-multiaccount
|
||||
(cond-> (merge
|
||||
{;; address of the master key
|
||||
:address address
|
||||
;; sha256 of master public key
|
||||
:key-uid key-uid
|
||||
;; The address from which we derive any wallet
|
||||
:wallet-root-address
|
||||
(get-in multiaccount [:derived
|
||||
constants/path-wallet-root-keyword
|
||||
:address])
|
||||
:name name
|
||||
:identicon identicon
|
||||
;; public key of the chat account
|
||||
:public-key public-key
|
||||
;; default address for Dapps
|
||||
:dapps-address (:address wallet-account)
|
||||
:latest-derived-path 0
|
||||
:signing-phrase signing-phrase
|
||||
:send-push-notifications? true
|
||||
:backup-enabled? true
|
||||
:installation-id (random-guid-generator)
|
||||
;; default mailserver (history node) setting
|
||||
:use-mailservers? true
|
||||
:recovered recovered}
|
||||
config/default-multiaccount)
|
||||
(cond->
|
||||
(merge
|
||||
{;; address of the master key
|
||||
:address address
|
||||
;; sha256 of master public key
|
||||
:key-uid key-uid
|
||||
;; The address from which we derive any wallet
|
||||
:wallet-root-address
|
||||
(get-in multiaccount
|
||||
[:derived
|
||||
constants/path-wallet-root-keyword
|
||||
:address])
|
||||
:name name
|
||||
:identicon identicon
|
||||
;; public key of the chat account
|
||||
:public-key public-key
|
||||
;; default address for Dapps
|
||||
:dapps-address (:address wallet-account)
|
||||
:latest-derived-path 0
|
||||
:signing-phrase signing-phrase
|
||||
:send-push-notifications? true
|
||||
:backup-enabled? true
|
||||
:installation-id (random-guid-generator)
|
||||
;; default mailserver (history node) setting
|
||||
:use-mailservers? true
|
||||
:recovered recovered}
|
||||
config/default-multiaccount)
|
||||
;; The address from which we derive any chat
|
||||
;; account/encryption keys
|
||||
eip1581-address
|
||||
@@ -205,23 +215,23 @@
|
||||
(assoc :mnemonic mnemonic)
|
||||
keycard-multiaccount?
|
||||
(assoc :keycard-instance-uid keycard-instance-uid
|
||||
:keycard-pairing keycard-pairing
|
||||
:keycard-paired-on keycard-paired-on))
|
||||
:keycard-pairing keycard-pairing
|
||||
:keycard-paired-on keycard-paired-on))
|
||||
db (assoc db
|
||||
:multiaccounts/login {:key-uid key-uid
|
||||
:name name
|
||||
:identicon identicon
|
||||
:password password
|
||||
:creating? true
|
||||
:processing true}
|
||||
:multiaccount new-multiaccount
|
||||
:multiaccount/accounts [wallet-account]
|
||||
:multiaccounts/login {:key-uid key-uid
|
||||
:name name
|
||||
:identicon identicon
|
||||
:password password
|
||||
:creating? true
|
||||
:processing true}
|
||||
:multiaccount new-multiaccount
|
||||
:multiaccount/accounts [wallet-account]
|
||||
:networks/current-network config/default-network
|
||||
:networks/networks (data-store.settings/rpc->networks config/default-networks))
|
||||
:networks/networks (data-store.settings/rpc->networks config/default-networks))
|
||||
settings (assoc new-multiaccount
|
||||
:networks/current-network config/default-network
|
||||
:networks/networks config/default-networks)]
|
||||
(fx/merge cofx
|
||||
:networks/networks config/default-networks)]
|
||||
(rf/merge cofx
|
||||
{:db db}
|
||||
(if keycard-multiaccount?
|
||||
(save-multiaccount-and-login-with-keycard
|
||||
@@ -240,26 +250,26 @@
|
||||
(node/get-new-config db)
|
||||
accounts-data)))))
|
||||
|
||||
(fx/defn store-multiaccount-success
|
||||
{:events [::store-multiaccount-success]
|
||||
(rf/defn store-multiaccount-success
|
||||
{:events [::store-multiaccount-success]
|
||||
:interceptors [(re-frame/inject-cofx :random-guid-generator)
|
||||
(re-frame/inject-cofx ::get-signing-phrase)]}
|
||||
[{:keys [db] :as cofx} password derived]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (dissoc db :intro-wizard)}
|
||||
(on-multiaccount-created (assoc (let [{:keys [selected-id multiaccounts]} (:intro-wizard db)]
|
||||
(some #(when (= selected-id (:id %)) %) multiaccounts))
|
||||
:derived derived
|
||||
:derived derived
|
||||
:recovered (get-in db [:intro-wizard :recovering?]))
|
||||
password
|
||||
{:save-mnemonic? true})))
|
||||
|
||||
(fx/defn on-key-selected
|
||||
(rf/defn on-key-selected
|
||||
{:events [:intro-wizard/on-key-selected]}
|
||||
[{:keys [db]} id]
|
||||
{:db (assoc-in db [:intro-wizard :selected-id] id)})
|
||||
|
||||
(fx/defn on-key-storage-selected
|
||||
(rf/defn on-key-storage-selected
|
||||
{:events [:intro-wizard/on-key-storage-selected]}
|
||||
[{:keys [db]} storage-type]
|
||||
{:db (assoc-in db [:intro-wizard :selected-storage-type] storage-type)})
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
(ns status-im.multiaccounts.key-storage.core
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.mnemonic :as mnemonic]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.keycard.backup-key :as keycard.backup]
|
||||
[status-im.keycard.common :as common]
|
||||
[status-im.multiaccounts.core :as multiaccounts]
|
||||
[status-im.multiaccounts.recover.core :as multiaccounts.recover]
|
||||
[status-im.multiaccounts.model :as multiaccounts.model]
|
||||
[status-im.multiaccounts.logout.core :as multiaccounts.logout]
|
||||
[status-im.multiaccounts.model :as multiaccounts.model]
|
||||
[status-im.multiaccounts.recover.core :as multiaccounts.recover]
|
||||
[status-im.native-module.core :as native-module]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.popover.core :as popover]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.security :as security]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.keycard.backup-key :as keycard.backup]
|
||||
[status-im.bottom-sheet.core :as bottom-sheet]))
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(fx/defn key-and-storage-management-pressed
|
||||
(rf/defn key-and-storage-management-pressed
|
||||
"This event can be dispatched before login and from profile and needs to redirect accordingly"
|
||||
{:events [::key-and-storage-management-pressed]}
|
||||
[cofx]
|
||||
@@ -29,52 +29,57 @@
|
||||
:actions-not-logged-in)
|
||||
nil))
|
||||
|
||||
(fx/defn move-keystore-checked
|
||||
(rf/defn move-keystore-checked
|
||||
{:events [::move-keystore-checked]}
|
||||
[{:keys [db] :as cofx} checked?]
|
||||
{:db (assoc-in db [:multiaccounts/key-storage :move-keystore-checked?] checked?)})
|
||||
|
||||
(fx/defn reset-db-checked
|
||||
(rf/defn reset-db-checked
|
||||
{:events [::reset-db-checked]}
|
||||
[{:keys [db] :as cofx} checked?]
|
||||
{:db (assoc-in db [:multiaccounts/key-storage :reset-db-checked?] checked?)})
|
||||
|
||||
(fx/defn navigate-back
|
||||
(rf/defn navigate-back
|
||||
{:events [::navigate-back]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(dissoc :recovered-account?)
|
||||
(update :keycard dissoc :from-key-storage-and-migration? :creating-backup? :factory-reset-card?))}
|
||||
(update :keycard
|
||||
dissoc
|
||||
:from-key-storage-and-migration?
|
||||
:creating-backup?
|
||||
:factory-reset-card?))}
|
||||
(navigation/navigate-back)))
|
||||
|
||||
(fx/defn enter-seed-pressed
|
||||
(rf/defn enter-seed-pressed
|
||||
"User is logged out and probably wants to move multiaccount to Keycard. Navigate to enter seed phrase screen"
|
||||
{:events [::enter-seed-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (assoc db :recovered-account? true)}
|
||||
(navigation/navigate-to-cofx :seed-phrase nil)))
|
||||
|
||||
(fx/defn seed-phrase-input-changed
|
||||
(rf/defn seed-phrase-input-changed
|
||||
{:events [::seed-phrase-input-changed]}
|
||||
[{:keys [db] :as cofx} masked-seed-phrase]
|
||||
(let [seed-phrase (security/safe-unmask-data masked-seed-phrase)]
|
||||
{:db (update db :multiaccounts/key-storage assoc
|
||||
:seed-phrase (when seed-phrase
|
||||
(string/lower-case seed-phrase))
|
||||
:seed-shape-invalid? (or (empty? seed-phrase)
|
||||
(not (mnemonic/valid-length? seed-phrase)))
|
||||
:seed-word-count (mnemonic/words-count seed-phrase))}))
|
||||
{:db (update db
|
||||
:multiaccounts/key-storage assoc
|
||||
:seed-phrase (when seed-phrase
|
||||
(string/lower-case seed-phrase))
|
||||
:seed-shape-invalid? (or (empty? seed-phrase)
|
||||
(not (mnemonic/valid-length? seed-phrase)))
|
||||
:seed-word-count (mnemonic/words-count seed-phrase))}))
|
||||
|
||||
(fx/defn key-uid-seed-mismatch
|
||||
(rf/defn key-uid-seed-mismatch
|
||||
{:events [::show-seed-key-uid-mismatch-error-popup]}
|
||||
[cofx _]
|
||||
(popover/show-popover cofx {:view :seed-key-uid-mismatch}))
|
||||
|
||||
(fx/defn key-uid-matches
|
||||
(rf/defn key-uid-matches
|
||||
{:events [::key-uid-matches]}
|
||||
[{:keys [db] :as cofx} _]
|
||||
(let [backup? (get-in db [:keycard :creating-backup?])]
|
||||
@@ -100,27 +105,32 @@
|
||||
::validate-seed-against-key-uid
|
||||
(partial validate-seed-against-key-uid
|
||||
{:import-mnemonic-fn native-module/multiaccount-import-mnemonic
|
||||
:on-success #(re-frame/dispatch [::key-uid-matches])
|
||||
:on-error #(re-frame/dispatch [::show-seed-key-uid-mismatch-error-popup])}))
|
||||
:on-success #(re-frame/dispatch [::key-uid-matches])
|
||||
:on-error #(re-frame/dispatch [::show-seed-key-uid-mismatch-error-popup])}))
|
||||
|
||||
(fx/defn seed-phrase-validated
|
||||
(rf/defn seed-phrase-validated
|
||||
{:events [::seed-phrase-validated]}
|
||||
[{:keys [db] :as cofx} validation-error]
|
||||
(let [error? (-> validation-error
|
||||
types/json->clj
|
||||
:error
|
||||
string/blank?
|
||||
not)
|
||||
(let [error? (-> validation-error
|
||||
types/json->clj
|
||||
:error
|
||||
string/blank?
|
||||
not)
|
||||
onboarding? (not (or (:multiaccounts/login db) (:multiaccount db)))]
|
||||
(if error?
|
||||
(popover/show-popover cofx {:view :custom-seed-phrase})
|
||||
{::validate-seed-against-key-uid {:seed-phrase (-> db :multiaccounts/key-storage :seed-phrase)
|
||||
;; Unique key-uid of the account for which we are going to move keys
|
||||
:key-uid (or (-> db :multiaccounts/login :key-uid)
|
||||
(-> db :multiaccount :key-uid)
|
||||
(and onboarding? (-> db :keycard :application-info :key-uid)))}})))
|
||||
;; Unique key-uid of the account for which we are going to move
|
||||
;; keys
|
||||
:key-uid (or (-> db :multiaccounts/login :key-uid)
|
||||
(-> db :multiaccount :key-uid)
|
||||
(and onboarding?
|
||||
(-> db
|
||||
:keycard
|
||||
:application-info
|
||||
:key-uid)))}})))
|
||||
|
||||
(fx/defn choose-storage-pressed
|
||||
(rf/defn choose-storage-pressed
|
||||
{:events [::choose-storage-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [seed-phrase]} (:multiaccounts/key-storage db)]
|
||||
@@ -128,7 +138,7 @@
|
||||
[(mnemonic/sanitize-passphrase seed-phrase)
|
||||
#(re-frame/dispatch [::seed-phrase-validated %])]}))
|
||||
|
||||
(fx/defn keycard-storage-pressed
|
||||
(rf/defn keycard-storage-pressed
|
||||
{:events [::keycard-storage-pressed]}
|
||||
[{:keys [db]} selected?]
|
||||
{:db (assoc-in db [:multiaccounts/key-storage :keycard-storage-selected?] selected?)})
|
||||
@@ -161,55 +171,56 @@ The exact events dispatched for this flow if consumed from the UI are:
|
||||
|
||||
We don't need to take the exact steps, just set the required state and redirect to correct screen
|
||||
"
|
||||
(fx/defn import-multiaccount
|
||||
(rf/defn import-multiaccount
|
||||
[{:keys [db] :as cofx}]
|
||||
{:dispatch [:bottom-sheet/hide]
|
||||
{:dispatch [:bottom-sheet/hide]
|
||||
::multiaccounts.recover/import-multiaccount
|
||||
{:passphrase (get-in db [:multiaccounts/key-storage :seed-phrase])
|
||||
:password nil
|
||||
:success-event ::import-multiaccount-success}})
|
||||
|
||||
(fx/defn delete-multiaccount-and-init-keycard-onboarding
|
||||
(rf/defn delete-multiaccount-and-init-keycard-onboarding
|
||||
{:events [::delete-multiaccount-and-init-keycard-onboarding]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
{:dispatch [:bottom-sheet/hide]
|
||||
:db (assoc-in db [:multiaccounts/key-storage :reset-db-checked?] true)}
|
||||
(import-multiaccount)))
|
||||
|
||||
(fx/defn storage-selected
|
||||
(rf/defn storage-selected
|
||||
{:events [::storage-selected]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(if (get-in db [:multiaccounts/key-storage :reset-db-checked?])
|
||||
(popover/show-popover cofx {:view :transfer-multiaccount-to-keycard-warning})
|
||||
(bottom-sheet/show-bottom-sheet cofx {:view :migrate-account-password})))
|
||||
|
||||
(fx/defn skip-password-pressed
|
||||
(rf/defn skip-password-pressed
|
||||
{:events [::skip-password-pressed]}
|
||||
[cofx]
|
||||
(popover/show-popover cofx {:view :transfer-multiaccount-to-keycard-warning}))
|
||||
|
||||
(fx/defn password-changed
|
||||
(rf/defn password-changed
|
||||
{:events [::password-changed]}
|
||||
[{db :db} password]
|
||||
(let [unmasked-pass (security/safe-unmask-data password)]
|
||||
{:db (update db :keycard assoc
|
||||
:migration-password password
|
||||
:migration-password-error nil
|
||||
{:db (update db
|
||||
:keycard assoc
|
||||
:migration-password password
|
||||
:migration-password-error nil
|
||||
:migration-password-valid? (and unmasked-pass (> (count unmasked-pass) 5)))}))
|
||||
|
||||
(fx/defn verify-password-result
|
||||
(rf/defn verify-password-result
|
||||
{:events [::verify-password-result]}
|
||||
[{:keys [db] :as cofx} result]
|
||||
(let [{:keys [error]} (types/json->clj result)]
|
||||
(if (string/blank? error)
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (update db :keycard dissoc :migration-password-error :migration-password-valid?)}
|
||||
(import-multiaccount))
|
||||
{:db (assoc-in db [:keycard :migration-password-error] (i18n/label :t/wrong-password))})))
|
||||
|
||||
(fx/defn verify-password
|
||||
(rf/defn verify-password
|
||||
{:events [::verify-password]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(native-module/verify-database-password
|
||||
@@ -217,42 +228,43 @@ We don't need to take the exact steps, just set the required state and redirect
|
||||
(ethereum/sha3 (security/safe-unmask-data (get-in db [:keycard :migration-password])))
|
||||
#(re-frame/dispatch [::verify-password-result %])))
|
||||
|
||||
(fx/defn handle-multiaccount-import
|
||||
(rf/defn handle-multiaccount-import
|
||||
{:events [::import-multiaccount-success]}
|
||||
[{:keys [db] :as cofx} root-data derived-data]
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
(update :intro-wizard
|
||||
assoc
|
||||
:root-key root-data
|
||||
:derived derived-data
|
||||
:recovering? true
|
||||
:selected-storage-type :advanced)
|
||||
(assoc-in [:keycard :flow] :recovery)
|
||||
(assoc-in [:keycard :from-key-storage-and-migration?] true)
|
||||
(assoc-in [:keycard :converting-account?] (not (get-in db [:multiaccounts/key-storage :reset-db-checked?])))
|
||||
(assoc-in [:keycard :delete-account?]
|
||||
(true? (get-in db [:multiaccounts/key-storage :reset-db-checked?])))
|
||||
(dissoc :multiaccounts/key-storage))}
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(update :intro-wizard
|
||||
assoc
|
||||
:root-key root-data
|
||||
:derived derived-data
|
||||
:recovering? true
|
||||
:selected-storage-type :advanced)
|
||||
(assoc-in [:keycard :flow] :recovery)
|
||||
(assoc-in [:keycard :from-key-storage-and-migration?] true)
|
||||
(assoc-in [:keycard :converting-account?]
|
||||
(not (get-in db [:multiaccounts/key-storage :reset-db-checked?])))
|
||||
(assoc-in [:keycard :delete-account?]
|
||||
(true? (get-in db [:multiaccounts/key-storage :reset-db-checked?])))
|
||||
(dissoc :multiaccounts/key-storage))}
|
||||
(popover/hide-popover)
|
||||
(common/listen-to-hardware-back-button)
|
||||
(navigation/navigate-to-cofx :keycard-onboarding-intro nil)))
|
||||
|
||||
(fx/defn goto-multiaccounts-screen
|
||||
(rf/defn goto-multiaccounts-screen
|
||||
{:events [::hide-popover-and-goto-multiaccounts-screen]}
|
||||
[cofx _]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(popover/hide-popover)
|
||||
(navigation/navigate-to-cofx :multiaccounts nil)))
|
||||
|
||||
(fx/defn confirm-logout-and-goto-key-storage
|
||||
(rf/defn confirm-logout-and-goto-key-storage
|
||||
{:events [::confirm-logout-and-goto-key-storage]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc db :goto-key-storage? true)}
|
||||
(multiaccounts.logout/logout)))
|
||||
|
||||
(fx/defn logout-and-goto-key-storage
|
||||
(rf/defn logout-and-goto-key-storage
|
||||
{:events [::logout-and-goto-key-storage]}
|
||||
[_]
|
||||
{:ui/show-confirmation
|
||||
@@ -264,9 +276,11 @@ We don't need to take the exact steps, just set the required state and redirect
|
||||
|
||||
(comment
|
||||
;; check import mnemonic output
|
||||
(native-module/multiaccount-import-mnemonic "rocket mixed rebel affair umbrella legal resemble scene virus park deposit cargo" nil
|
||||
(fn [result]
|
||||
(prn (types/json->clj result))))
|
||||
(native-module/multiaccount-import-mnemonic
|
||||
"rocket mixed rebel affair umbrella legal resemble scene virus park deposit cargo"
|
||||
nil
|
||||
(fn [result]
|
||||
(prn (types/json->clj result))))
|
||||
;; check delete account output
|
||||
(native-module/delete-multiaccount "0x3831d0f22996a65970a214f0a94bfa9a63a21dac235d8dadb91be8e32e7d3ab7"
|
||||
(fn [result]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[clojure.string :as string]
|
||||
[status-im.multiaccounts.key-storage.core :as models]
|
||||
[status-im.utils.security :as security]))
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(deftest move-keystore-checked
|
||||
(testing "Checks checkbox on-press"
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
(ns status-im.multiaccounts.login.core
|
||||
(:require [re-frame.core :as re-frame]
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.async-storage.core :as async-storage]
|
||||
[status-im.chat.models.link-preview :as link-preview]
|
||||
[status-im.communities.core :as communities]
|
||||
[status-im.contact.core :as contact]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.data-store.chats :as data-store.chats]
|
||||
[status-im.data-store.invitations :as data-store.invitations]
|
||||
[status-im.data-store.settings :as data-store.settings]
|
||||
[status-im.data-store.visibility-status-updates :as visibility-status-updates-store]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.transactions.core :as transactions]
|
||||
[status-im.ethereum.eip55 :as eip55]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.keycard.common :as keycard.common]
|
||||
[status-im.ethereum.tokens :as tokens]
|
||||
[status-im.ethereum.transactions.core :as transactions]
|
||||
[status-im.fleet.core :as fleet]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.keycard.common :as keycard.common]
|
||||
[status-im.mobile-sync-settings.core :as mobile-network]
|
||||
[status-im.multiaccounts.biometric.core :as biometric]
|
||||
[status-im.multiaccounts.core :as multiaccounts]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.node.core :as node]
|
||||
[status-im.notifications.core :as notifications]
|
||||
[status-im.popover.core :as popover]
|
||||
[status-im.communities.core :as communities]
|
||||
[status-im.signing.eip1559 :as eip1559]
|
||||
[status-im.transport.core :as transport]
|
||||
[status-im.mobile-sync-settings.core :as mobile-network]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.utils.keychain.core :as keychain]
|
||||
[status-im2.setup.log :as logging]
|
||||
[status-im.utils.security :as security]
|
||||
[status-im.utils.mobile-sync :as utils.mobile-sync]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.wallet.core :as wallet]
|
||||
[status-im.wallet-connect-legacy.core :as wallet-connect-legacy]
|
||||
[status-im.wallet.prices :as prices]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.data-store.invitations :as data-store.invitations]
|
||||
[status-im.chat.models.link-preview :as link-preview]
|
||||
[status-im.utils.mobile-sync :as utils.mobile-sync]
|
||||
[status-im.async-storage.core :as async-storage]
|
||||
[status-im.activity-center.core :as activity-center]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.signing.eip1559 :as eip1559]
|
||||
[status-im.data-store.chats :as data-store.chats]
|
||||
[status-im.data-store.visibility-status-updates :as visibility-status-updates-store]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.ethereum.tokens :as tokens]
|
||||
[clojure.string :as string]
|
||||
[status-im.utils.wallet-connect :as wallet-connect]
|
||||
[status-im.node.core :as node]))
|
||||
[status-im.wallet-connect-legacy.core :as wallet-connect-legacy]
|
||||
[status-im.wallet.core :as wallet]
|
||||
[status-im.wallet.prices :as prices]
|
||||
[status-im2.contexts.activity-center.events :as activity-center]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im2.setup.log :as logging]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::initialize-communities-enabled
|
||||
@@ -89,11 +89,13 @@
|
||||
#(re-frame/dispatch [:wallet-connect/client-init %])
|
||||
#(log/error "[wallet-connect]" %))))
|
||||
|
||||
(defn rpc->accounts [accounts]
|
||||
(defn rpc->accounts
|
||||
[accounts]
|
||||
(reduce (fn [acc {:keys [chat type wallet] :as account}]
|
||||
(if chat
|
||||
acc
|
||||
(let [account (cond-> (update account :address
|
||||
(let [account (cond-> (update account
|
||||
:address
|
||||
eip55/address->checksum)
|
||||
type
|
||||
(update :type keyword))]
|
||||
@@ -119,25 +121,28 @@
|
||||
"0x86a12d91c813f69a53349ff640e32af97d5f5c1f8d42d54cf4c8aa8dea231955"
|
||||
"0x0011a30f5b2023bc228f6dd5608b3e7149646fa83f33350926ceb1925af78f08"})
|
||||
|
||||
(fx/defn check-invalid-ens [{:keys [db]}]
|
||||
(rf/defn check-invalid-ens
|
||||
[{:keys [db]}]
|
||||
(async-storage/get-item
|
||||
:invalid-ens-name-seen
|
||||
(fn [already-seen]
|
||||
(when (and (not already-seen)
|
||||
(boolean (get invalid-addrr (ethereum/sha3 (string/lower-case (ethereum/default-address db))))))
|
||||
(boolean (get invalid-addrr
|
||||
(ethereum/sha3 (string/lower-case (ethereum/default-address db))))))
|
||||
(utils/show-popup
|
||||
(i18n/label :t/warning)
|
||||
(i18n/label :t/ens-username-invalid-name-warning)
|
||||
#(async-storage/set-item! :invalid-ens-name-seen true)))))
|
||||
nil)
|
||||
|
||||
(fx/defn initialize-wallet
|
||||
(rf/defn initialize-wallet
|
||||
{:events [::initialize-wallet]}
|
||||
[{:keys [db] :as cofx} accounts tokens custom-tokens
|
||||
favourites scan-all-tokens? new-account?]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (assoc db :multiaccount/accounts
|
||||
{:db (assoc db
|
||||
:multiaccount/accounts
|
||||
(rpc->accounts accounts))
|
||||
;; NOTE: Local notifications should be enabled only after wallet was started
|
||||
::enable-local-notifications nil}
|
||||
@@ -146,16 +151,18 @@
|
||||
(wallet/initialize-favourites favourites)
|
||||
(wallet/get-pending-transactions)
|
||||
(wallet/fetch-collectibles-collection)
|
||||
(cond (and new-account?
|
||||
(not scan-all-tokens?))
|
||||
(wallet/set-zero-balances (first accounts))
|
||||
(cond
|
||||
(and new-account?
|
||||
(not scan-all-tokens?))
|
||||
(wallet/set-zero-balances (first accounts))
|
||||
|
||||
(and new-account? scan-all-tokens?
|
||||
(not (utils.mobile-sync/cellular? (:network/type db))))
|
||||
(wallet/set-max-block (get (first accounts) :address) 0)
|
||||
(and new-account?
|
||||
scan-all-tokens?
|
||||
(not (utils.mobile-sync/cellular? (:network/type db))))
|
||||
(wallet/set-max-block (get (first accounts) :address) 0)
|
||||
|
||||
:else
|
||||
(wallet/get-cached-balances scan-all-tokens?))
|
||||
:else
|
||||
(wallet/get-cached-balances scan-all-tokens?))
|
||||
(when-not (get db :wallet/new-account)
|
||||
(wallet/restart-wallet-service nil))
|
||||
(when (or (not (utils.mobile-sync/syncing-allowed? cofx))
|
||||
@@ -166,21 +173,21 @@
|
||||
(prices/update-prices)
|
||||
(wallet-connect-legacy/get-connector-session-from-db)))
|
||||
|
||||
(fx/defn login
|
||||
(rf/defn login
|
||||
{:events [:multiaccounts.login.ui/password-input-submitted]}
|
||||
[{:keys [db]}]
|
||||
(let [{:keys [key-uid password name identicon]} (:multiaccounts/login db)]
|
||||
{:db (-> db
|
||||
(assoc-in [:multiaccounts/login :processing] true)
|
||||
(dissoc :intro-wizard :recovered-account?)
|
||||
(update :keycard dissoc :flow))
|
||||
{:db (-> db
|
||||
(assoc-in [:multiaccounts/login :processing] true)
|
||||
(dissoc :intro-wizard :recovered-account?)
|
||||
(update :keycard dissoc :flow))
|
||||
::login [key-uid
|
||||
(types/clj->json {:name name
|
||||
:key-uid key-uid
|
||||
:identicon identicon})
|
||||
(types/clj->json {:name name
|
||||
:key-uid key-uid
|
||||
:identicon identicon})
|
||||
(ethereum/sha3 (security/safe-unmask-data password))]}))
|
||||
|
||||
(fx/defn export-db-submitted
|
||||
(rf/defn export-db-submitted
|
||||
{:events [:multiaccounts.login.ui/export-db-submitted]}
|
||||
[{:keys [db]}]
|
||||
(let [{:keys [key-uid password name identicon]} (:multiaccounts/login db)]
|
||||
@@ -192,24 +199,25 @@
|
||||
(fn [path]
|
||||
(when platform/ios?
|
||||
(let [uri (str "file://" path)]
|
||||
(.share ^js react/sharing (clj->js {:title "Unencrypted database"
|
||||
:url uri})))))]}))
|
||||
(.share ^js react/sharing
|
||||
(clj->js {:title "Unencrypted database"
|
||||
:url uri})))))]}))
|
||||
|
||||
(fx/defn import-db-submitted
|
||||
(rf/defn import-db-submitted
|
||||
{:events [:multiaccounts.login.ui/import-db-submitted]}
|
||||
[{:keys [db]}]
|
||||
(let [{:keys [key-uid password name identicon]} (:multiaccounts/login db)]
|
||||
{::import-db [key-uid
|
||||
(types/clj->json {:name name
|
||||
:key-uid key-uid
|
||||
:identicon identicon})
|
||||
(types/clj->json {:name name
|
||||
:key-uid key-uid
|
||||
:identicon identicon})
|
||||
(ethereum/sha3 (security/safe-unmask-data password))]}))
|
||||
|
||||
(fx/defn finish-keycard-setup
|
||||
(rf/defn finish-keycard-setup
|
||||
[{:keys [db] :as cofx}]
|
||||
{:db (update db :keycard dissoc :flow)})
|
||||
|
||||
(fx/defn initialize-dapp-permissions
|
||||
(rf/defn initialize-dapp-permissions
|
||||
{:events [::initialize-dapp-permissions]}
|
||||
[{:keys [db]} all-dapp-permissions]
|
||||
(let [dapp-permissions (reduce (fn [acc {:keys [dapp] :as dapp-permissions}]
|
||||
@@ -218,7 +226,7 @@
|
||||
all-dapp-permissions)]
|
||||
{:db (assoc db :dapps/permissions dapp-permissions)}))
|
||||
|
||||
(fx/defn initialize-browsers
|
||||
(rf/defn initialize-browsers
|
||||
{:events [::initialize-browsers]}
|
||||
[{:keys [db]} all-stored-browsers]
|
||||
(let [browsers (reduce (fn [acc {:keys [browser-id] :as browser}]
|
||||
@@ -227,7 +235,7 @@
|
||||
all-stored-browsers)]
|
||||
{:db (assoc db :browser/browsers browsers)}))
|
||||
|
||||
(fx/defn initialize-bookmarks
|
||||
(rf/defn initialize-bookmarks
|
||||
{:events [::initialize-bookmarks]}
|
||||
[{:keys [db]} stored-bookmarks]
|
||||
(let [bookmarks (reduce (fn [acc {:keys [url] :as bookmark}]
|
||||
@@ -236,28 +244,30 @@
|
||||
stored-bookmarks)]
|
||||
{:db (assoc db :bookmarks/bookmarks bookmarks)}))
|
||||
|
||||
(fx/defn initialize-invitations
|
||||
(rf/defn initialize-invitations
|
||||
{:events [::initialize-invitations]}
|
||||
[{:keys [db]} invitations]
|
||||
{:db (assoc db :group-chat/invitations (reduce (fn [acc {:keys [id] :as inv}]
|
||||
(assoc acc id (data-store.invitations/<-rpc inv)))
|
||||
{}
|
||||
invitations))})
|
||||
{:db (assoc db
|
||||
:group-chat/invitations
|
||||
(reduce (fn [acc {:keys [id] :as inv}]
|
||||
(assoc acc id (data-store.invitations/<-rpc inv)))
|
||||
{}
|
||||
invitations))})
|
||||
|
||||
(fx/defn initialize-web3-client-version
|
||||
(rf/defn initialize-web3-client-version
|
||||
{:events [::initialize-web3-client-version]}
|
||||
[{:keys [db]} node-version]
|
||||
{:db (assoc db :web3-node-version node-version)})
|
||||
|
||||
(fx/defn handle-close-app-confirmed
|
||||
(rf/defn handle-close-app-confirmed
|
||||
{:events [::close-app-confirmed]}
|
||||
[_]
|
||||
{:ui/close-application nil})
|
||||
|
||||
(fx/defn check-network-version
|
||||
(rf/defn check-network-version
|
||||
[_ network-id]
|
||||
{::json-rpc/call
|
||||
[{:method "net_version"
|
||||
[{:method "net_version"
|
||||
:on-success
|
||||
(fn [fetched-network-id]
|
||||
(when (not= network-id (str (int fetched-network-id)))
|
||||
@@ -270,7 +280,8 @@
|
||||
:fetched-network-id fetched-network-id})
|
||||
#(re-frame/dispatch [::close-app-confirmed]))))}]})
|
||||
|
||||
(defn normalize-tokens [network-id tokens]
|
||||
(defn normalize-tokens
|
||||
[network-id tokens]
|
||||
(mapv #(-> %
|
||||
(update :symbol keyword)
|
||||
((partial tokens/update-icon (ethereum/chain-id->chain-keyword (int network-id)))))
|
||||
@@ -281,8 +292,8 @@
|
||||
(fn [[network-id accounts recovered-account?]]
|
||||
(utils/set-timeout
|
||||
(fn []
|
||||
(json-rpc/call {:method "wallet_getTokens"
|
||||
:params [(int network-id)]
|
||||
(json-rpc/call {:method "wallet_getTokens"
|
||||
:params [(int network-id)]
|
||||
:on-success #(re-frame/dispatch [::initialize-wallet
|
||||
accounts
|
||||
(normalize-tokens network-id %)
|
||||
@@ -299,25 +310,25 @@
|
||||
(clj->js
|
||||
[(js/Promise.
|
||||
(fn [resolve reject]
|
||||
(json-rpc/call {:method "accounts_getAccounts"
|
||||
(json-rpc/call {:method "accounts_getAccounts"
|
||||
:on-success resolve
|
||||
:on-error reject})))
|
||||
:on-error reject})))
|
||||
(js/Promise.
|
||||
(fn [resolve _]
|
||||
(json-rpc/call {:method "wallet_getTokens"
|
||||
:params [(int network-id)]
|
||||
(json-rpc/call {:method "wallet_getTokens"
|
||||
:params [(int network-id)]
|
||||
:on-success resolve
|
||||
:on-error #(resolve nil)})))
|
||||
:on-error #(resolve nil)})))
|
||||
(js/Promise.
|
||||
(fn [resolve reject]
|
||||
(json-rpc/call {:method "wallet_getCustomTokens"
|
||||
(json-rpc/call {:method "wallet_getCustomTokens"
|
||||
:on-success resolve
|
||||
:on-error reject})))
|
||||
:on-error reject})))
|
||||
(js/Promise.
|
||||
(fn [resolve reject]
|
||||
(json-rpc/call {:method "wallet_getSavedAddresses"
|
||||
(json-rpc/call {:method "wallet_getSavedAddresses"
|
||||
:on-success resolve
|
||||
:on-error reject})))]))
|
||||
:on-error reject})))]))
|
||||
(.then (fn [[accounts tokens custom-tokens favourites]]
|
||||
(callback accounts
|
||||
(normalize-tokens network-id tokens)
|
||||
@@ -326,7 +337,8 @@
|
||||
(.catch (fn [_]
|
||||
(log/error "Failed to initialize wallet"))))))
|
||||
|
||||
(fx/defn initialize-browser [_]
|
||||
(rf/defn initialize-browser
|
||||
[_]
|
||||
{::json-rpc/call
|
||||
[{:method "wakuext_getBrowsers"
|
||||
:on-success #(re-frame/dispatch [::initialize-browsers %])}
|
||||
@@ -335,53 +347,57 @@
|
||||
{:method "permissions_getDappPermissions"
|
||||
:on-success #(re-frame/dispatch [::initialize-dapp-permissions %])}]})
|
||||
|
||||
(fx/defn initialize-appearance [cofx]
|
||||
(rf/defn initialize-appearance
|
||||
[cofx]
|
||||
{:multiaccounts.ui/switch-theme (get-in cofx [:db :multiaccount :appearance])})
|
||||
|
||||
(fx/defn get-group-chat-invitations [_]
|
||||
(rf/defn get-group-chat-invitations
|
||||
[_]
|
||||
{::json-rpc/call
|
||||
[{:method "wakuext_getGroupChatInvitations"
|
||||
:on-success #(re-frame/dispatch [::initialize-invitations %])}]})
|
||||
|
||||
(fx/defn initialize-communities-enabled
|
||||
(rf/defn initialize-communities-enabled
|
||||
[cofx]
|
||||
{::initialize-communities-enabled nil})
|
||||
|
||||
(fx/defn initialize-transactions-management-enabled
|
||||
(rf/defn initialize-transactions-management-enabled
|
||||
[cofx]
|
||||
{::initialize-transactions-management-enabled nil})
|
||||
|
||||
(fx/defn initialize-wallet-connect
|
||||
(rf/defn initialize-wallet-connect
|
||||
[cofx]
|
||||
{::initialize-wallet-connect nil})
|
||||
|
||||
(fx/defn get-node-config-callback
|
||||
(rf/defn get-node-config-callback
|
||||
{:events [::get-node-config-callback]}
|
||||
[{:keys [db] :as cofx} node-config-json]
|
||||
(let [node-config (types/json->clj node-config-json)]
|
||||
{:db (assoc-in db [:multiaccount :wakuv2-config]
|
||||
(get node-config :WakuV2Config))}))
|
||||
{:db (assoc-in db
|
||||
[:multiaccount :wakuv2-config]
|
||||
(get node-config :WakuV2Config))}))
|
||||
|
||||
(fx/defn get-node-config
|
||||
(rf/defn get-node-config
|
||||
[_]
|
||||
(status/get-node-config #(re-frame/dispatch [::get-node-config-callback %])))
|
||||
|
||||
(fx/defn get-settings-callback
|
||||
(rf/defn get-settings-callback
|
||||
{:events [::get-settings-callback]}
|
||||
[{:keys [db] :as cofx} settings]
|
||||
(let [{:networks/keys [current-network networks]
|
||||
:as settings}
|
||||
(data-store.settings/rpc->settings settings)
|
||||
multiaccount (dissoc settings :networks/current-network :networks/networks)
|
||||
;;for some reason we save default networks in db, in case when we want to modify default-networks for
|
||||
;;for some reason we save default networks in db, in case when we want to modify default-networks
|
||||
;;for
|
||||
;; existing accounts we have to merge them again into networks
|
||||
merged-networks (merge networks config/default-networks-by-id)]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(dissoc :multiaccounts/login)
|
||||
(assoc :networks/current-network current-network
|
||||
:networks/networks merged-networks
|
||||
:multiaccount multiaccount))}
|
||||
:networks/networks merged-networks
|
||||
:multiaccount multiaccount))}
|
||||
(data-store.chats/fetch-chats-rpc
|
||||
{:on-success
|
||||
#(do (re-frame/dispatch [:chats-list/load-success %])
|
||||
@@ -408,31 +424,32 @@
|
||||
(when (= stored-key-uid key-uid)
|
||||
(re-frame/dispatch [:chat.ui/navigate-to-chat chat-id])))))))))
|
||||
|
||||
(fx/defn check-last-chat
|
||||
(rf/defn check-last-chat
|
||||
{:events [::check-last-chat]}
|
||||
[{:keys [db]}]
|
||||
{::open-last-chat (get-in db [:multiaccount :key-uid])})
|
||||
|
||||
(fx/defn update-wallet-accounts
|
||||
(rf/defn update-wallet-accounts
|
||||
[{:keys [db]} accounts]
|
||||
(let [existing-accounts (into {} (map #(vector (:address %1) %1) (:multiaccount/accounts db)))
|
||||
reduce-fn (fn [existing-accs new-acc]
|
||||
(let [address (:address new-acc)]
|
||||
(if (:removed new-acc)
|
||||
(dissoc existing-accs address)
|
||||
(assoc existing-accs address new-acc))))
|
||||
new-accounts (reduce reduce-fn existing-accounts (rpc->accounts accounts))]
|
||||
reduce-fn (fn [existing-accs new-acc]
|
||||
(let [address (:address new-acc)]
|
||||
(if (:removed new-acc)
|
||||
(dissoc existing-accs address)
|
||||
(assoc existing-accs address new-acc))))
|
||||
new-accounts (reduce reduce-fn existing-accounts (rpc->accounts accounts))]
|
||||
{:db (assoc db :multiaccount/accounts (vals new-accounts))}))
|
||||
|
||||
(fx/defn get-chats-callback
|
||||
(rf/defn get-chats-callback
|
||||
{:events [::get-chats-callback]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:networks/keys [current-network networks]} db
|
||||
notifications-enabled? (get-in db [:multiaccount :notifications-enabled?])
|
||||
network-id (str (get-in networks [current-network :config :NetworkId]))
|
||||
notifications-enabled? (get-in db [:multiaccount :notifications-enabled?])
|
||||
network-id (str (get-in networks
|
||||
[current-network :config :NetworkId]))
|
||||
remote-push-notifications-enabled?
|
||||
(get-in db [:multiaccount :remote-push-notifications-enabled?])]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(cond-> {::eip1559/check-eip1559-activation
|
||||
{:network-id network-id
|
||||
:on-enabled #(log/info "eip1550 is activated")
|
||||
@@ -442,7 +459,7 @@
|
||||
(fn [accounts tokens custom-tokens favourites]
|
||||
(re-frame/dispatch [::initialize-wallet
|
||||
accounts tokens custom-tokens favourites]))]
|
||||
::open-last-chat (get-in db [:multiaccount :key-uid])}
|
||||
::open-last-chat (get-in db [:multiaccount :key-uid])}
|
||||
(or notifications-enabled? remote-push-notifications-enabled?)
|
||||
(assoc ::notifications/enable remote-push-notifications-enabled?))
|
||||
(transport/start-messenger)
|
||||
@@ -457,7 +474,8 @@
|
||||
(link-preview/request-link-preview-whitelist)
|
||||
(visibility-status-updates-store/fetch-visibility-status-updates-rpc))))
|
||||
|
||||
(defn get-new-auth-method [auth-method save-password?]
|
||||
(defn get-new-auth-method
|
||||
[auth-method save-password?]
|
||||
(when save-password?
|
||||
(when-not (or (= keychain/auth-method-biometric auth-method)
|
||||
(= keychain/auth-method-password auth-method))
|
||||
@@ -472,15 +490,15 @@
|
||||
(re-frame/dispatch [:init-root (if config/new-ui-enabled? :shell-stack :chat-stack)])
|
||||
(re-frame/dispatch [:init-root :tos])))
|
||||
|
||||
(fx/defn login-only-events
|
||||
(rf/defn login-only-events
|
||||
[{:keys [db] :as cofx} key-uid password save-password?]
|
||||
(let [auth-method (:auth-method db)
|
||||
new-auth-method (get-new-auth-method auth-method save-password?)]
|
||||
(log/debug "[login] login-only-events"
|
||||
"auth-method" auth-method
|
||||
"auth-method" auth-method
|
||||
"new-auth-method" new-auth-method)
|
||||
(fx/merge cofx
|
||||
{:db (assoc db :chats/loading? true)
|
||||
(rf/merge cofx
|
||||
{:db (assoc db :chats/loading? true)
|
||||
::json-rpc/call
|
||||
[{:method "settings_getSettings"
|
||||
:on-success #(do (re-frame/dispatch [::get-settings-callback %])
|
||||
@@ -488,24 +506,26 @@
|
||||
(notifications/load-notification-preferences)
|
||||
(when save-password?
|
||||
(keychain/save-user-password key-uid password))
|
||||
(keychain/save-auth-method key-uid (or new-auth-method auth-method keychain/auth-method-none)))))
|
||||
(keychain/save-auth-method key-uid
|
||||
(or new-auth-method auth-method keychain/auth-method-none)))))
|
||||
|
||||
(fx/defn create-only-events
|
||||
(rf/defn create-only-events
|
||||
[{:keys [db] :as cofx} recovered-account?]
|
||||
(let [{:keys [multiaccount
|
||||
:multiaccounts/multiaccounts
|
||||
:multiaccount/accounts]} db
|
||||
{:keys [creating?]} (:multiaccounts/login db)
|
||||
first-account? (and creating?
|
||||
(empty? multiaccounts))
|
||||
tos-accepted? (get db :tos/accepted?)
|
||||
:multiaccount/accounts]}
|
||||
db
|
||||
{:keys [creating?]} (:multiaccounts/login db)
|
||||
first-account? (and creating?
|
||||
(empty? multiaccounts))
|
||||
tos-accepted? (get db :tos/accepted?)
|
||||
{:networks/keys [current-network networks]} db
|
||||
network-id (str (get-in networks [current-network :config :NetworkId]))]
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
(dissoc :multiaccounts/login)
|
||||
(assoc :tos/next-root :onboarding-notification :chats/loading? false)
|
||||
(assoc-in [:multiaccount :multiaccounts/first-account] first-account?))
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(dissoc :multiaccounts/login)
|
||||
(assoc :tos/next-root :onboarding-notification :chats/loading? false)
|
||||
(assoc-in [:multiaccount :multiaccounts/first-account] first-account?))
|
||||
::get-tokens [network-id accounts recovered-account?]}
|
||||
(finish-keycard-setup)
|
||||
(transport/start-messenger)
|
||||
@@ -525,14 +545,16 @@
|
||||
(navigation/init-root :onboarding-notification)
|
||||
(navigation/init-root :tos))))))
|
||||
|
||||
(defn- keycard-setup? [cofx]
|
||||
(defn- keycard-setup?
|
||||
[cofx]
|
||||
(boolean (get-in cofx [:db :keycard :flow])))
|
||||
|
||||
(defn on-login-update-db [db login-only? now]
|
||||
(defn on-login-update-db
|
||||
[db login-only? now]
|
||||
(-> db
|
||||
(dissoc :connectivity/ui-status-properties)
|
||||
(update :keycard dissoc :from-key-storage-and-migration?)
|
||||
(update :keycard dissoc
|
||||
(update :keycard dissoc
|
||||
:on-card-read
|
||||
:card-read-in-progress?
|
||||
:pin
|
||||
@@ -544,23 +566,25 @@
|
||||
(assoc :logged-in-since now)
|
||||
(assoc :view-id :home)))
|
||||
|
||||
(fx/defn multiaccount-login-success
|
||||
(rf/defn multiaccount-login-success
|
||||
[{:keys [db now] :as cofx}]
|
||||
(let [{:keys [key-uid password save-password? creating?]}
|
||||
(:multiaccounts/login db)
|
||||
|
||||
multiaccounts (:multiaccounts/multiaccounts db)
|
||||
recovered-account? (get db :recovered-account?)
|
||||
login-only? (not (or creating?
|
||||
recovered-account?
|
||||
(keycard-setup? cofx)))
|
||||
from-migration? (get-in db [:keycard :from-key-storage-and-migration?])
|
||||
nodes nil]
|
||||
multiaccounts (:multiaccounts/multiaccounts db)
|
||||
recovered-account? (get db :recovered-account?)
|
||||
login-only? (not (or creating?
|
||||
recovered-account?
|
||||
(keycard-setup? cofx)))
|
||||
from-migration? (get-in db
|
||||
[:keycard
|
||||
:from-key-storage-and-migration?])
|
||||
nodes nil]
|
||||
(log/debug "[multiaccount] multiaccount-login-success"
|
||||
"login-only?" login-only?
|
||||
"login-only?" login-only?
|
||||
"recovered-account?" recovered-account?)
|
||||
(fx/merge cofx
|
||||
{:db (on-login-update-db db login-only? now)
|
||||
(rf/merge cofx
|
||||
{:db (on-login-update-db db login-only? now)
|
||||
::json-rpc/call
|
||||
[{:method "web3_clientVersion"
|
||||
:on-success #(re-frame/dispatch [::initialize-web3-client-version %])}]}
|
||||
@@ -571,7 +595,8 @@
|
||||
(not recovered-account?))
|
||||
(wallet/set-initial-blocks-range))
|
||||
(when from-migration?
|
||||
(utils/show-popup (i18n/label :t/migration-successful) (i18n/label :t/migration-successful-text)))
|
||||
(utils/show-popup (i18n/label :t/migration-successful)
|
||||
(i18n/label :t/migration-successful-text)))
|
||||
(if login-only?
|
||||
(login-only-events key-uid password save-password?)
|
||||
(create-only-events recovered-account?)))))
|
||||
@@ -582,7 +607,7 @@
|
||||
;; are alreayd in `multiaccounts/login` and should not be overriden, as they come from
|
||||
;; the keychain (save-password), this is not very explicit and we should probably
|
||||
;; make it clearer
|
||||
(fx/defn open-login
|
||||
(rf/defn open-login
|
||||
[{:keys [db]} override-multiaccount]
|
||||
{:db (-> db
|
||||
(update :multiaccounts/login
|
||||
@@ -593,23 +618,26 @@
|
||||
:error
|
||||
:password))})
|
||||
|
||||
(fx/defn open-login-callback
|
||||
(rf/defn open-login-callback
|
||||
{:events [:multiaccounts.login.callback/get-user-password-success]}
|
||||
[{:keys [db] :as cofx} password]
|
||||
(let [key-uid (get-in db [:multiaccounts/login :key-uid])
|
||||
keycard-account? (boolean (get-in db [:multiaccounts/multiaccounts
|
||||
key-uid
|
||||
:keycard-pairing]))
|
||||
(let [key-uid (get-in db [:multiaccounts/login :key-uid])
|
||||
keycard-account? (boolean (get-in db
|
||||
[:multiaccounts/multiaccounts
|
||||
key-uid
|
||||
:keycard-pairing]))
|
||||
goto-key-storage? (:goto-key-storage? db)]
|
||||
(if password
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (update-in db [:multiaccounts/login] assoc
|
||||
:password password
|
||||
:save-password? true)
|
||||
{:db (update-in db
|
||||
[:multiaccounts/login]
|
||||
assoc
|
||||
:password password
|
||||
:save-password? true)
|
||||
:init-root-fx :progress}
|
||||
login)
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (dissoc db :goto-key-storage?)}
|
||||
(when keycard-account?
|
||||
@@ -622,25 +650,28 @@
|
||||
#(when goto-key-storage?
|
||||
(navigation/navigate-to-cofx % :actions-not-logged-in nil))))))
|
||||
|
||||
(fx/defn get-credentials
|
||||
(rf/defn get-credentials
|
||||
[{:keys [db] :as cofx} key-uid]
|
||||
(let [keycard-multiaccount? (boolean (get-in db [:multiaccounts/multiaccounts key-uid :keycard-pairing]))]
|
||||
(let [keycard-multiaccount? (boolean (get-in db
|
||||
[:multiaccounts/multiaccounts key-uid :keycard-pairing]))]
|
||||
(log/debug "[login] get-credentials"
|
||||
"keycard-multiacc?" keycard-multiaccount?)
|
||||
"keycard-multiacc?"
|
||||
keycard-multiaccount?)
|
||||
(if keycard-multiaccount?
|
||||
(keychain/get-keycard-keys cofx key-uid)
|
||||
(keychain/get-user-password cofx key-uid))))
|
||||
|
||||
(fx/defn get-auth-method-success
|
||||
(rf/defn get-auth-method-success
|
||||
"Auth method: nil - not supported, \"none\" - not selected, \"password\", \"biometric\", \"biometric-prepare\""
|
||||
{:events [:multiaccounts.login/get-auth-method-success]}
|
||||
[{:keys [db] :as cofx} auth-method]
|
||||
(let [key-uid (get-in db [:multiaccounts/login :key-uid])
|
||||
keycard-multiaccount? (boolean (get-in db [:multiaccounts/multiaccounts key-uid :keycard-pairing]))]
|
||||
keycard-multiaccount? (boolean (get-in db
|
||||
[:multiaccounts/multiaccounts key-uid :keycard-pairing]))]
|
||||
(log/debug "[login] get-auth-method-success"
|
||||
"auth-method" auth-method
|
||||
"auth-method" auth-method
|
||||
"keycard-multiacc?" keycard-multiaccount?)
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (assoc db :auth-method auth-method)}
|
||||
#(cond
|
||||
@@ -653,7 +684,7 @@
|
||||
(keycard.common/get-application-info % nil))
|
||||
(open-login-callback nil))))
|
||||
|
||||
(fx/defn biometric-auth-done
|
||||
(rf/defn biometric-auth-done
|
||||
{:events [:biometric-auth-done]}
|
||||
[{:keys [db] :as cofx} {:keys [bioauth-success bioauth-message bioauth-code]}]
|
||||
(let [key-uid (get-in db [:multiaccounts/login :key-uid])
|
||||
@@ -661,28 +692,28 @@
|
||||
(log/debug "[biometric] biometric-auth-done"
|
||||
"bioauth-success" bioauth-success
|
||||
"bioauth-message" bioauth-message
|
||||
"bioauth-code" bioauth-code)
|
||||
"bioauth-code" bioauth-code)
|
||||
(if bioauth-success
|
||||
(get-credentials cofx key-uid)
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:multiaccounts/login :save-password?]
|
||||
(= auth-method keychain/auth-method-biometric))}
|
||||
[:multiaccounts/login :save-password?]
|
||||
(= auth-method keychain/auth-method-biometric))}
|
||||
(when-not (= auth-method keychain/auth-method-biometric)
|
||||
(keychain/save-auth-method key-uid keychain/auth-method-none))
|
||||
(biometric/show-message bioauth-message bioauth-code)
|
||||
(open-login-callback nil)))))
|
||||
|
||||
(fx/defn save-password
|
||||
(rf/defn save-password
|
||||
{:events [:multiaccounts/save-password]}
|
||||
[{:keys [db] :as cofx} save-password?]
|
||||
(let [bioauth-supported? (boolean (get db :supported-biometric-auth))
|
||||
previous-auth-method (get db :auth-method)]
|
||||
(log/debug "[login] save-password"
|
||||
"save-password?" save-password?
|
||||
"bioauth-supported?" bioauth-supported?
|
||||
"save-password?" save-password?
|
||||
"bioauth-supported?" bioauth-supported?
|
||||
"previous-auth-method" previous-auth-method)
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (cond-> db
|
||||
(not= previous-auth-method
|
||||
@@ -700,54 +731,54 @@
|
||||
(when-not (= previous-auth-method keychain/auth-method-none)
|
||||
(popover/show-popover {:view :disable-password-saving})))))))
|
||||
|
||||
(fx/defn welcome-lets-go
|
||||
(rf/defn welcome-lets-go
|
||||
{:events [:welcome-lets-go]}
|
||||
[_]
|
||||
{:init-root-fx :chat-stack})
|
||||
|
||||
(fx/defn multiaccount-selected
|
||||
(rf/defn multiaccount-selected
|
||||
{:events [:multiaccounts.login.ui/multiaccount-selected]}
|
||||
[{:keys [db] :as cofx} key-uid]
|
||||
;; We specifically pass a bunch of fields instead of the whole multiaccount
|
||||
;; as we want store some fields in multiaccount that are not here
|
||||
(let [multiaccount (get-in db [:multiaccounts/multiaccounts key-uid])
|
||||
(let [multiaccount (get-in db [:multiaccounts/multiaccounts key-uid])
|
||||
keycard-multiaccount? (boolean (:keycard-pairing multiaccount))]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (update db :keycard dissoc :application-info)
|
||||
{:db (update db :keycard dissoc :application-info)
|
||||
:navigate-to-fx (if keycard-multiaccount? :keycard-login-pin :login)}
|
||||
(open-login (select-keys multiaccount [:key-uid :name :public-key :identicon :images])))))
|
||||
|
||||
(fx/defn hide-keycard-banner
|
||||
(rf/defn hide-keycard-banner
|
||||
{:events [:hide-keycard-banner]}
|
||||
[{:keys [db]}]
|
||||
{:db (assoc db :keycard/banner-hidden true)
|
||||
::async-storage/set! {:keycard-banner-hidden true}})
|
||||
|
||||
(fx/defn get-keycard-banner-preference-cb
|
||||
(rf/defn get-keycard-banner-preference-cb
|
||||
{:events [:get-keycard-banner-preference-cb]}
|
||||
[{:keys [db]} {:keys [keycard-banner-hidden]}]
|
||||
{:db (assoc db :keycard/banner-hidden keycard-banner-hidden)})
|
||||
|
||||
(fx/defn get-keycard-banner-preference
|
||||
(rf/defn get-keycard-banner-preference
|
||||
{:events [:get-keycard-banner-preference]}
|
||||
[_]
|
||||
{::async-storage/get {:keys [:keycard-banner-hidden]
|
||||
:cb #(re-frame/dispatch [:get-keycard-banner-preference-cb %])}})
|
||||
|
||||
(fx/defn get-opted-in-to-new-terms-of-service-cb
|
||||
(rf/defn get-opted-in-to-new-terms-of-service-cb
|
||||
{:events [:get-opted-in-to-new-terms-of-service-cb]}
|
||||
[{:keys [db]} {:keys [new-terms-of-service-accepted]}]
|
||||
{:db (assoc db :tos/accepted? new-terms-of-service-accepted)})
|
||||
|
||||
(fx/defn get-opted-in-to-new-terms-of-service
|
||||
(rf/defn get-opted-in-to-new-terms-of-service
|
||||
"New TOS sprint https://github.com/status-im/status-mobile/pull/12240"
|
||||
{:events [:get-opted-in-to-new-terms-of-service]}
|
||||
[{:keys [db]}]
|
||||
{::async-storage/get {:keys [:new-terms-of-service-accepted]
|
||||
:cb #(re-frame/dispatch [:get-opted-in-to-new-terms-of-service-cb %])}})
|
||||
|
||||
(fx/defn hide-terms-of-services-opt-in-screen
|
||||
(rf/defn hide-terms-of-services-opt-in-screen
|
||||
{:events [:hide-terms-of-services-opt-in-screen]}
|
||||
[{:keys [db]}]
|
||||
{::async-storage/set! {:new-terms-of-service-accepted true}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
(:require [cljs.test :as test]
|
||||
[status-im.multiaccounts.biometric.core :as biometric]
|
||||
[status-im.multiaccounts.login.core :as login]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.keychain.core :as keychain]))
|
||||
[status-im.utils.keychain.core :as keychain]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(test/deftest save-password-test
|
||||
(test/testing "check save password, biometric unavailable"
|
||||
@@ -44,7 +44,7 @@
|
||||
"uncheck save password")
|
||||
(let [initial-cofx {:db {:auth-method keychain/auth-method-none
|
||||
:supported-biometric-auth true}}
|
||||
{:keys [db]} (login/save-password (fx/merge
|
||||
{:keys [db]} (login/save-password (rf/merge
|
||||
initial-cofx
|
||||
(login/save-password true)
|
||||
(biometric/enable)
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
(ns status-im.multiaccounts.logout.core
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.multiaccounts.core :as multiaccounts]
|
||||
[status-im.utils.keychain.core :as keychain]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.notifications.core :as notifications]
|
||||
[status-im.utils.keychain.core :as keychain]
|
||||
[status-im.wallet.core :as wallet]
|
||||
[status-im2.setup.events :as init]))
|
||||
[status-im2.setup.events :as init]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(fx/defn logout-method
|
||||
(rf/defn logout-method
|
||||
{:events [::logout-method]}
|
||||
[{:keys [db] :as cofx} {:keys [auth-method logout?]}]
|
||||
(let [key-uid (get-in db [:multiaccount :key-uid])]
|
||||
(fx/merge cofx
|
||||
(let [key-uid (get-in db [:multiaccount :key-uid])]
|
||||
(rf/merge cofx
|
||||
{:init-root-fx :progress
|
||||
:chat.ui/clear-inputs nil
|
||||
:chat.ui/clear-inputs-old nil
|
||||
@@ -22,24 +22,26 @@
|
||||
::logout nil
|
||||
::multiaccounts/webview-debug-changed false
|
||||
:keychain/clear-user-password key-uid
|
||||
:setup/open-multiaccounts #(re-frame/dispatch [:setup/initialize-multiaccounts % {:logout? logout?}])}
|
||||
:setup/open-multiaccounts #(re-frame/dispatch [:setup/initialize-multiaccounts
|
||||
% {:logout? logout?}])}
|
||||
(keychain/save-auth-method key-uid auth-method)
|
||||
(wallet/clear-timeouts)
|
||||
(init/initialize-app-db))))
|
||||
|
||||
(fx/defn logout
|
||||
{:events [:logout :multiaccounts.logout.ui/logout-confirmed :multiaccounts.update.callback/save-settings-success]}
|
||||
(rf/defn logout
|
||||
{:events [:logout :multiaccounts.logout.ui/logout-confirmed
|
||||
:multiaccounts.update.callback/save-settings-success]}
|
||||
[cofx]
|
||||
;; we need to disable notifications before starting the logout process
|
||||
(fx/merge cofx
|
||||
{:dispatch [:wallet-connect-legacy/clean-up-sessions]
|
||||
(rf/merge cofx
|
||||
{:dispatch [:wallet-connect-legacy/clean-up-sessions]
|
||||
:dispatch-later [{:ms 100
|
||||
:dispatch [::logout-method
|
||||
{:auth-method keychain/auth-method-none
|
||||
:logout? true}]}]}
|
||||
(notifications/logout-disable)))
|
||||
|
||||
(fx/defn show-logout-confirmation
|
||||
(rf/defn show-logout-confirmation
|
||||
{:events [:multiaccounts.logout.ui/logout-pressed]}
|
||||
[_]
|
||||
{:ui/show-confirmation
|
||||
@@ -49,10 +51,10 @@
|
||||
:on-accept #(re-frame/dispatch [:multiaccounts.logout.ui/logout-confirmed])
|
||||
:on-cancel nil}})
|
||||
|
||||
(fx/defn biometric-logout
|
||||
(rf/defn biometric-logout
|
||||
{:events [:biometric-logout]}
|
||||
[cofx]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(logout-method {:auth-method keychain/auth-method-biometric-prepare
|
||||
:logout? false})
|
||||
(fn [{:keys [db]}]
|
||||
|
||||
@@ -1,49 +1,52 @@
|
||||
(ns status-im.multiaccounts.recover.core
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.mnemonic :as mnemonic]
|
||||
[status-im.keycard.nfc :as nfc]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.keycard.nfc :as nfc]
|
||||
[status-im.multiaccounts.core :as multiaccounts]
|
||||
[status-im.multiaccounts.create.core :as multiaccounts.create]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.popover.core :as popover]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.security :as security]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.bottom-sheet.core :as bottom-sheet]
|
||||
[taoensso.timbre :as log]))
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(defn existing-account?
|
||||
[multiaccounts key-uid]
|
||||
{:pre [(not (nil? key-uid))]}
|
||||
(contains? multiaccounts key-uid))
|
||||
|
||||
(defn check-phrase-warnings [recovery-phrase]
|
||||
(defn check-phrase-warnings
|
||||
[recovery-phrase]
|
||||
(cond (string/blank? recovery-phrase) :t/required-field))
|
||||
|
||||
(fx/defn set-phrase
|
||||
(rf/defn set-phrase
|
||||
{:events [:multiaccounts.recover/passphrase-input-changed]}
|
||||
[{:keys [db]} masked-recovery-phrase]
|
||||
(let [recovery-phrase (security/safe-unmask-data masked-recovery-phrase)]
|
||||
(fx/merge
|
||||
{:db (update db :intro-wizard assoc
|
||||
:passphrase (string/lower-case recovery-phrase)
|
||||
:passphrase-error nil
|
||||
(rf/merge
|
||||
{:db (update db
|
||||
:intro-wizard assoc
|
||||
:passphrase (string/lower-case recovery-phrase)
|
||||
:passphrase-error nil
|
||||
:next-button-disabled? (or (empty? recovery-phrase)
|
||||
(not (mnemonic/valid-length? recovery-phrase))))})))
|
||||
|
||||
(fx/defn validate-phrase-for-warnings
|
||||
(rf/defn validate-phrase-for-warnings
|
||||
[{:keys [db]}]
|
||||
(let [recovery-phrase (get-in db [:intro-wizard :passphrase])]
|
||||
{:db (update db :intro-wizard assoc
|
||||
{:db (update db
|
||||
:intro-wizard assoc
|
||||
:passphrase-error (check-phrase-warnings recovery-phrase))}))
|
||||
|
||||
(fx/defn on-store-multiaccount-success
|
||||
(rf/defn on-store-multiaccount-success
|
||||
{:events [::store-multiaccount-success]
|
||||
:interceptors [(re-frame/inject-cofx :random-guid-generator)
|
||||
(re-frame/inject-cofx ::multiaccounts.create/get-signing-phrase)]}
|
||||
@@ -54,29 +57,32 @@
|
||||
:content (i18n/label :t/multiaccount-exists-title)
|
||||
:on-dismiss #(re-frame/dispatch [:pop-to-root-tab :multiaccounts])}}
|
||||
(let [{:keys [key-uid] :as multiaccount} (get-in db [:intro-wizard :root-key])
|
||||
keycard-multiaccount? (boolean (get-in db [:multiaccounts/multiaccounts key-uid :keycard-pairing]))]
|
||||
keycard-multiaccount? (boolean (get-in db
|
||||
[:multiaccounts/multiaccounts key-uid
|
||||
:keycard-pairing]))]
|
||||
(if keycard-multiaccount?
|
||||
;; trying to recover multiaccount created with keycard
|
||||
{:db (-> db
|
||||
(update :intro-wizard assoc
|
||||
:processing? false
|
||||
:passphrase-error :recover-keycard-multiaccount-not-supported)
|
||||
(update :intro-wizard dissoc
|
||||
:passphrase-valid?))}
|
||||
{:db (-> db
|
||||
(update :intro-wizard assoc
|
||||
:processing? false
|
||||
:passphrase-error :recover-keycard-multiaccount-not-supported)
|
||||
(update :intro-wizard
|
||||
dissoc
|
||||
:passphrase-valid?))}
|
||||
(let [multiaccount (assoc multiaccount :derived (get-in db [:intro-wizard :derived]))]
|
||||
(multiaccounts.create/on-multiaccount-created cofx
|
||||
multiaccount
|
||||
password
|
||||
{})))))))
|
||||
|
||||
(fx/defn store-multiaccount
|
||||
(rf/defn store-multiaccount
|
||||
{:events [::recover-multiaccount-confirmed]}
|
||||
[{:keys [db]} password]
|
||||
(let [{:keys [root-key]} (:intro-wizard db)
|
||||
(let [{:keys [root-key]} (:intro-wizard db)
|
||||
{:keys [id key-uid]} root-key
|
||||
callback #(re-frame/dispatch [::store-multiaccount-success % password])
|
||||
hashed-password (ethereum/sha3 (security/safe-unmask-data password))]
|
||||
{:db (assoc-in db [:intro-wizard :processing?] true)
|
||||
callback #(re-frame/dispatch [::store-multiaccount-success % password])
|
||||
hashed-password (ethereum/sha3 (security/safe-unmask-data password))]
|
||||
{:db (assoc-in db [:intro-wizard :processing?] true)
|
||||
::multiaccounts.create/store-multiaccount [id key-uid hashed-password callback]}))
|
||||
|
||||
(re-frame/reg-fx
|
||||
@@ -99,17 +105,18 @@
|
||||
(fn [result]
|
||||
(let [derived-data (multiaccounts.create/normalize-derived-data-keys
|
||||
(types/json->clj result))
|
||||
public-key (get-in derived-data [constants/path-whisper-keyword :public-key])]
|
||||
public-key (get-in derived-data [constants/path-whisper-keyword :public-key])]
|
||||
(status/gfycat-identicon-async
|
||||
public-key
|
||||
(fn [name identicon]
|
||||
(let [derived-data-extended
|
||||
(update derived-data
|
||||
constants/path-whisper-keyword
|
||||
merge {:name name :identicon identicon})]
|
||||
merge
|
||||
{:name name :identicon identicon})]
|
||||
(re-frame/dispatch [success-event root-data derived-data-extended]))))))))))))
|
||||
|
||||
(fx/defn show-existing-multiaccount-alert
|
||||
(rf/defn show-existing-multiaccount-alert
|
||||
[_ key-uid]
|
||||
{:utils/show-confirmation
|
||||
{:title (i18n/label :t/multiaccount-exists-title)
|
||||
@@ -121,24 +128,26 @@
|
||||
[:multiaccounts.login.ui/multiaccount-selected key-uid]))
|
||||
:on-cancel #(re-frame/dispatch [:pop-to-root-tab :multiaccounts])}})
|
||||
|
||||
(fx/defn on-import-multiaccount-success
|
||||
(rf/defn on-import-multiaccount-success
|
||||
{:events [::import-multiaccount-success]}
|
||||
[{:keys [db] :as cofx} {:keys [key-uid] :as root-data} derived-data]
|
||||
(let [multiaccounts (:multiaccounts/multiaccounts db)]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (update db :intro-wizard
|
||||
assoc :root-key root-data
|
||||
:derived derived-data
|
||||
:step :recovery-success)}
|
||||
{:db (update db
|
||||
:intro-wizard
|
||||
assoc
|
||||
:root-key root-data
|
||||
:derived derived-data
|
||||
:step :recovery-success)}
|
||||
(when (existing-account? multiaccounts key-uid)
|
||||
(show-existing-multiaccount-alert key-uid))
|
||||
(navigation/navigate-to-cofx :recover-multiaccount-success nil))))
|
||||
|
||||
(fx/defn enter-phrase-pressed
|
||||
(rf/defn enter-phrase-pressed
|
||||
{:events [::enter-phrase-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(assoc :intro-wizard
|
||||
@@ -153,7 +162,7 @@
|
||||
(bottom-sheet/hide-bottom-sheet)
|
||||
(navigation/navigate-to-cofx :recover-multiaccount-enter-phrase nil)))
|
||||
|
||||
(fx/defn proceed-to-import-mnemonic
|
||||
(rf/defn proceed-to-import-mnemonic
|
||||
{:events [:multiaccounts.recover/phrase-validated]}
|
||||
[{:keys [db] :as cofx} phrase-warnings]
|
||||
(let [{:keys [password passphrase]} (:intro-wizard db)]
|
||||
@@ -165,37 +174,41 @@
|
||||
(security/safe-unmask-data password))
|
||||
:success-event ::import-multiaccount-success}}))))
|
||||
|
||||
(fx/defn seed-phrase-next-pressed
|
||||
(rf/defn seed-phrase-next-pressed
|
||||
{:events [:multiaccounts.recover/enter-phrase-next-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [passphrase]} (:intro-wizard db)]
|
||||
{::multiaccounts/validate-mnemonic [passphrase #(re-frame/dispatch [:multiaccounts.recover/phrase-validated %])]}))
|
||||
{::multiaccounts/validate-mnemonic [passphrase
|
||||
#(re-frame/dispatch [:multiaccounts.recover/phrase-validated
|
||||
%])]}))
|
||||
|
||||
(fx/defn continue-to-import-mnemonic
|
||||
(rf/defn continue-to-import-mnemonic
|
||||
{:events [::continue-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [password passphrase]} (:multiaccounts/recover db)]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{::import-multiaccount {:passphrase passphrase
|
||||
:password password
|
||||
:success-event ::import-multiaccount-success}}
|
||||
(popover/hide-popover))))
|
||||
|
||||
(fx/defn dec-step
|
||||
(rf/defn dec-step
|
||||
{:events [:multiaccounts.recover/dec-step]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [step (get-in db [:intro-wizard :step])]
|
||||
(if (= step :enter-phrase)
|
||||
{:db (dissoc db :intro-wizard)}
|
||||
{:db (update db :intro-wizard assoc :step
|
||||
{:db (update db
|
||||
:intro-wizard assoc
|
||||
:step
|
||||
(case step
|
||||
:recovery-success :enter-phrase
|
||||
:recovery-success :enter-phrase
|
||||
:select-key-storage :recovery-success
|
||||
:create-code :select-key-storage)
|
||||
:create-code :select-key-storage)
|
||||
:confirm-failure? false
|
||||
:key-code nil)})))
|
||||
:key-code nil)})))
|
||||
|
||||
(fx/defn cancel-pressed
|
||||
(rf/defn cancel-pressed
|
||||
{:events [:multiaccounts.recover/cancel-pressed]}
|
||||
[{:keys [db] :as cofx} skip-alert?]
|
||||
;; Workaround for multiple Cancel button clicks
|
||||
@@ -207,11 +220,11 @@
|
||||
(i18n/label :t/are-you-sure-to-cancel)
|
||||
(i18n/label :t/you-will-start-from-scratch)
|
||||
#(re-frame/dispatch [:multiaccounts.recover/cancel-pressed true]))
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
dec-step
|
||||
navigation/navigate-back)))))
|
||||
|
||||
(fx/defn select-storage-next-pressed
|
||||
(rf/defn select-storage-next-pressed
|
||||
{:events [:multiaccounts.recover/select-storage-next-pressed]
|
||||
:interceptors [(re-frame/inject-cofx :random-guid-generator)]}
|
||||
[{:keys [db] :as cofx}]
|
||||
@@ -219,51 +232,55 @@
|
||||
(if (= storage-type :advanced)
|
||||
;;TODO: fix circular dependency to remove dispatch here
|
||||
{:dispatch [:recovery.ui/keycard-option-pressed]}
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
{:db (update db :intro-wizard assoc :step :create-code)}
|
||||
(navigation/navigate-to-cofx :create-password nil)))))
|
||||
|
||||
(fx/defn re-encrypt-pressed
|
||||
(rf/defn re-encrypt-pressed
|
||||
{:events [:multiaccounts.recover/re-encrypt-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
{:db (update db :intro-wizard
|
||||
assoc :step :select-key-storage
|
||||
(rf/merge cofx
|
||||
{:db (update db
|
||||
:intro-wizard
|
||||
assoc
|
||||
:step :select-key-storage
|
||||
:selected-storage-type :default)}
|
||||
(if (nfc/nfc-supported?)
|
||||
(navigation/navigate-to-cofx :select-key-storage nil)
|
||||
(select-storage-next-pressed))))
|
||||
|
||||
(fx/defn confirm-password-next-button-pressed
|
||||
{:events [:multiaccounts.recover/enter-password-next-pressed]
|
||||
(rf/defn confirm-password-next-button-pressed
|
||||
{:events [:multiaccounts.recover/enter-password-next-pressed]
|
||||
:interceptors [(re-frame/inject-cofx :random-guid-generator)]}
|
||||
[cofx key-code]
|
||||
(store-multiaccount cofx key-code))
|
||||
|
||||
(fx/defn count-words
|
||||
(rf/defn count-words
|
||||
[{:keys [db]}]
|
||||
(let [passphrase (get-in db [:intro-wizard :passphrase])]
|
||||
{:db (assoc-in db [:intro-wizard :passphrase-word-count]
|
||||
(mnemonic/words-count passphrase))}))
|
||||
{:db (assoc-in db
|
||||
[:intro-wizard :passphrase-word-count]
|
||||
(mnemonic/words-count passphrase))}))
|
||||
|
||||
(fx/defn run-validation
|
||||
(rf/defn run-validation
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [passphrase (get-in db [:intro-wizard :passphrase])]
|
||||
(when (= (last passphrase) " ")
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(validate-phrase-for-warnings)))))
|
||||
|
||||
(fx/defn enter-phrase-input-changed
|
||||
(rf/defn enter-phrase-input-changed
|
||||
{:events [:multiaccounts.recover/enter-phrase-input-changed]}
|
||||
[cofx input]
|
||||
(fx/merge cofx
|
||||
(rf/merge cofx
|
||||
(set-phrase input)
|
||||
(count-words)
|
||||
(run-validation)))
|
||||
|
||||
(fx/defn enter-passphrase-input-changed
|
||||
(rf/defn enter-passphrase-input-changed
|
||||
{:events [:multiaccounts.recover/enter-passphrase-input-changed]}
|
||||
[{:keys [db]} masked-passphrase]
|
||||
{:db (update db :intro-wizard assoc
|
||||
:password masked-passphrase
|
||||
{:db (update db
|
||||
:intro-wizard assoc
|
||||
:password masked-passphrase
|
||||
:password-error nil)})
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user