Compare commits
21
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef1aafa644 | ||
|
|
54e4b597ed | ||
|
|
0b5dac0ad0 | ||
|
|
180065129f | ||
|
|
866b854ee0 | ||
|
|
072370b0d6 | ||
|
|
d74edff9b9 | ||
|
|
0a0591f67a | ||
|
|
7a8db689f4 | ||
|
|
311fde9409 | ||
|
|
f89b66f562 | ||
|
|
d179cbf59b | ||
|
|
7ff7e78691 | ||
|
|
6c352397ab | ||
|
|
3521421098 | ||
|
|
f70a743a8c | ||
|
|
a2178951d7 | ||
|
|
7774c4eac1 | ||
|
|
4c4a8b65d4 | ||
|
|
de6d9a6c3b | ||
|
|
da16d1f69e |
@@ -26,7 +26,6 @@ APN_TOPIC=im.status.ethereum.pr
|
||||
COMMUNITIES_ENABLED=1
|
||||
DATABASE_MANAGEMENT_ENABLED=1
|
||||
DELETE_MESSAGE_ENABLED=1
|
||||
COLLECTIBLES_ENABLED=1
|
||||
COMMANDS_ENABLED=1
|
||||
TWO_MINUTES_SYNCING=1
|
||||
SWAP_ENABLED=1
|
||||
|
||||
@@ -18,6 +18,5 @@ PARTITIONED_TOPIC=0
|
||||
ENABLE_ROOT_ALERT=1
|
||||
MAX_IMAGES_BATCH=1
|
||||
DELETE_MESSAGE_ENABLED=1
|
||||
COLLECTIBLES_ENABLED=1
|
||||
FAST_CREATE_COMMUNITY_ENABLED=0
|
||||
TEST_NETWORKS_ENABLED=0
|
||||
|
||||
@@ -457,6 +457,12 @@ android-tail-geth: export VERSION ?= debug
|
||||
android-tail-geth:
|
||||
adb shell 'while true; do cat; sleep 1; done < /storage/emulated/0/Android/data/im.status.ethereum$$( [ "$(VERSION)" = "release" ] || echo ".$(VERSION)" )/files/Download/geth.log'
|
||||
|
||||
android-clean-geth: export TARGET := android-sdk
|
||||
android-clean-geth: export VERSION ?= debug
|
||||
android-clean-geth:
|
||||
adb shell 'rm /storage/emulated/0/Android/data/im.status.ethereum$$( [ "$(VERSION)" = "release" ] || echo ".$(VERSION)" )/files/Download/geth.log'
|
||||
|
||||
|
||||
android-logcat: export TARGET := android-sdk
|
||||
android-logcat: ##@other Read status-mobile logs from Android phone using adb
|
||||
adb logcat | grep -e RNBootstrap -e ReactNativeJS -e ReactNative -e StatusModule -e StatusNativeLogs -e 'F DEBUG :' -e 'Go :' -e 'GoLog :' -e 'libc :'
|
||||
|
||||
+8
@@ -246,6 +246,14 @@ class AccountManager(private val reactContext: ReactApplicationContext) : ReactC
|
||||
utils.executeRunnableStatusGoMethod({ Statusgo.openAccounts(rootDir) }, callback)
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
private fun initializeApplication(request: String, callback: Callback) {
|
||||
Log.d(TAG, "initializeApplication")
|
||||
Log.d(TAG, "[Initializing application $request")
|
||||
utils.executeRunnableStatusGoMethod({ Statusgo.initializeApplication(request) }, callback)
|
||||
}
|
||||
|
||||
|
||||
@ReactMethod
|
||||
fun logout() {
|
||||
Log.d(TAG, "logout")
|
||||
|
||||
+10
@@ -76,6 +76,16 @@ class StatusModule(private val reactContext: ReactApplicationContext, private va
|
||||
utils.executeRunnableStatusGoMethod({ Statusgo.getNodeConfig() }, callback)
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
fun addCentralizedMetric(request: String, callback: Callback) {
|
||||
utils.executeRunnableStatusGoMethod({ Statusgo.addCentralizedMetric(request) }, callback)
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
fun toggleCentralizedMetrics(request: String, callback: Callback) {
|
||||
utils.executeRunnableStatusGoMethod({ Statusgo.toggleCentralizedMetrics(request) }, callback)
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
fun deleteImportedKey(keyUID: String, address: String, password: String, callback: Callback) {
|
||||
val keyStoreDir = utils.getKeyStorePath(keyUID)
|
||||
|
||||
@@ -153,4 +153,9 @@ class Utils(private val reactContext: ReactApplicationContext) : ReactContextBas
|
||||
|
||||
return strArray
|
||||
}
|
||||
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
fun validateConnectionString(connectionString: String): String {
|
||||
return Statusgo.validateConnectionString(connectionString)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,6 +195,15 @@ RCT_EXPORT_METHOD(verifyDatabasePassword:(NSString *)keyUID
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(initializeApplication:(NSString *)request
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
NSLog(@"initializeApplication() method called");
|
||||
#endif
|
||||
NSString *result = StatusgoInitializeApplication(request);
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(openAccounts:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
NSLog(@"OpenAccounts() method called");
|
||||
|
||||
@@ -176,6 +176,24 @@ RCT_EXPORT_METHOD(appStateChange:(NSString *)type) {
|
||||
StatusgoAppStateChange(type);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(addCentralizedMetric:(NSString *)request
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
NSLog(@"addCentralizedMetric() method called");
|
||||
#endif
|
||||
NSString *result = StatusgoAddCentralizedMetric(request);
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(toggleCentralizedMetrics:(NSString *)request
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
NSLog(@"toggleCentralizedMetrics() method called");
|
||||
#endif
|
||||
NSString *result = StatusgoToggleCentralizedMetrics(request);
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(startLocalNotifications) {
|
||||
#if DEBUG
|
||||
NSLog(@"StartLocalNotifications() method called");
|
||||
|
||||
@@ -128,4 +128,8 @@ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(toChecksumAddress:(NSString *)address) {
|
||||
return StatusgoToChecksumAddress(address);
|
||||
}
|
||||
|
||||
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(validateConnectionString:(NSString *)cs) {
|
||||
return StatusgoValidateConnectionString(cs);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -302,6 +302,36 @@ void _MultiAccountStoreAccount(const FunctionCallbackInfo<Value>& args) {
|
||||
delete c;
|
||||
}
|
||||
|
||||
void _InitializeApplication(const FunctionCallbackInfo<Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
Local<Context> context = isolate->GetCurrentContext();
|
||||
|
||||
if (args.Length() != 1) {
|
||||
// Throw an Error that is passed back to JavaScript
|
||||
isolate->ThrowException(Exception::TypeError(
|
||||
String::NewFromUtf8Literal(isolate, "Wrong number of arguments for InitializeApplication")));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the argument types
|
||||
|
||||
if (!args[0]->IsString()) {
|
||||
isolate->ThrowException(Exception::TypeError(
|
||||
String::NewFromUtf8Literal(isolate, "Wrong argument type for request")));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
String::Utf8Value arg0Obj(isolate, args[0]->ToString(context).ToLocalChecked());
|
||||
char *arg0 = *arg0Obj;
|
||||
|
||||
// Call exported Go function, which returns a C string
|
||||
char *c = InitializeApplication(arg0);
|
||||
|
||||
Local<String> ret = String::NewFromUtf8(isolate, c).ToLocalChecked();
|
||||
args.GetReturnValue().Set(ret);
|
||||
delete c;
|
||||
}
|
||||
|
||||
void _InitKeystore(const FunctionCallbackInfo<Value>& args) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
@@ -1935,6 +1965,7 @@ void init(Local<Object> exports) {
|
||||
NODE_SET_METHOD(exports, "multiAccountStoreDerivedAccounts", _MultiAccountStoreDerivedAccounts);
|
||||
NODE_SET_METHOD(exports, "multiAccountStoreAccount", _MultiAccountStoreAccount);
|
||||
NODE_SET_METHOD(exports, "initKeystore", _InitKeystore);
|
||||
NODE_SET_METHOD(exports, "initializeApplication", _InitializeApplication);
|
||||
NODE_SET_METHOD(exports, "fleets", _Fleets);
|
||||
NODE_SET_METHOD(exports, "stopCPUProfiling", _StopCPUProfiling);
|
||||
NODE_SET_METHOD(exports, "encodeTransfer", _EncodeTransfer);
|
||||
@@ -1972,7 +2003,7 @@ void init(Local<Object> exports) {
|
||||
NODE_SET_METHOD(exports, "signTypedData", _SignTypedData);
|
||||
NODE_SET_METHOD(exports, "sendTransaction", _SendTransaction);
|
||||
NODE_SET_METHOD(exports, "appStateChange", _AppStateChange);
|
||||
NODE_SET_METHOD(exports, "setSignalEventCallback", _SetSignalEventCallback);
|
||||
NODE_SET_METHOD(exports, "setSignalEventCallback", _SetSignalEventCallback);
|
||||
NODE_SET_METHOD(exports, "validateNodeConfig", _ValidateNodeConfig);
|
||||
NODE_SET_METHOD(exports, "hashTypedData", _HashTypedData);
|
||||
NODE_SET_METHOD(exports, "recover", _Recover);
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -45,6 +45,8 @@ SECRETS_ENV_VARS=(
|
||||
'INFURA_TOKEN'
|
||||
'INFURA_TOKEN_SECRET'
|
||||
'OPENSEA_API_KEY'
|
||||
'MIXPANEL_APP_ID'
|
||||
'MIXPANEL_TOKEN'
|
||||
'POKT_TOKEN'
|
||||
)
|
||||
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
:closure-defines
|
||||
{status-im.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
|
||||
status-im.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
|
||||
status-im.config/MIXPANEL_APP_ID #shadow/env "MIXPANEL_APP_ID"
|
||||
status-im.config/MIXPANEL_TOKEN #shadow/env "MIXPANEL_TOKEN"
|
||||
status-im.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"
|
||||
status-im.config/RARIBLE_MAINNET_API_KEY #shadow/env "RARIBLE_MAINNET_API_KEY"
|
||||
status-im.config/RARIBLE_TESTNET_API_KEY #shadow/env "RARIBLE_TESTNET_API_KEY"
|
||||
@@ -102,6 +104,8 @@
|
||||
{status-im.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
|
||||
status-im.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
|
||||
status-im.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"
|
||||
status-im.config/MIXPANEL_APP_ID #shadow/env "MIXPANEL_APP_ID"
|
||||
status-im.config/MIXPANEL_TOKEN #shadow/env "MIXPANEL_TOKEN"
|
||||
status-im.config/RARIBLE_MAINNET_API_KEY #shadow/env "RARIBLE_MAINNET_API_KEY"
|
||||
status-im.config/RARIBLE_TESTNET_API_KEY #shadow/env "RARIBLE_TESTNET_API_KEY"
|
||||
status-im.config/ALCHEMY_ETHEREUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ETHEREUM_MAINNET_TOKEN"
|
||||
@@ -143,6 +147,8 @@
|
||||
status-im.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
|
||||
status-im.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
|
||||
status-im.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"
|
||||
status-im.config/MIXPANEL_APP_ID #shadow/env "MIXPANEL_APP_ID"
|
||||
status-im.config/MIXPANEL_TOKEN #shadow/env "MIXPANEL_TOKEN"
|
||||
status-im.config/RARIBLE_MAINNET_API_KEY #shadow/env "RARIBLE_MAINNET_API_KEY"
|
||||
status-im.config/RARIBLE_TESTNET_API_KEY #shadow/env "RARIBLE_TESTNET_API_KEY"
|
||||
status-im.config/ALCHEMY_ETHEREUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ETHEREUM_MAINNET_TOKEN"
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
legacy.status-im.ui.components.invite.events
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
legacy.status-im.ui.screens.notifications-settings.events
|
||||
legacy.status-im.ui.screens.privacy-and-security-settings.events
|
||||
[legacy.status-im.utils.dimensions :as dimensions]
|
||||
legacy.status-im.utils.logging.core
|
||||
[legacy.status-im.utils.utils :as utils]
|
||||
@@ -108,8 +107,7 @@
|
||||
(when (and (multiaccounts.model/logged-in? db)
|
||||
(= current-theme-type status-im.constants/theme-type-system))
|
||||
{:profile.settings/switch-theme-fx
|
||||
[(get-in db [:profile/profile :appearance])
|
||||
(:view-id db) true]})))
|
||||
[(get-in db [:profile/profile :appearance]) (:view-id db)]})))
|
||||
|
||||
(defn- on-biometric-auth-fail
|
||||
[{:keys [code]}]
|
||||
|
||||
@@ -120,12 +120,3 @@
|
||||
{:events [:multiaccounts.ui/switch-backup-enabled]}
|
||||
[cofx enabled?]
|
||||
(multiaccount-update cofx :backup-enabled? enabled? {}))
|
||||
|
||||
(rf/defn toggle-opensea-nfts-visibility
|
||||
{:events [::toggle-opensea-nfts-visiblity]}
|
||||
[cofx visible?]
|
||||
(rf/merge cofx
|
||||
{:db (assoc-in (:db cofx) [:profile/profile :opensea-enabled?] visible?)
|
||||
;; need to add fully qualified namespace to counter circular deps
|
||||
:dispatch [:legacy.status-im.wallet.core/fetch-collectibles-collection]}
|
||||
(multiaccount-update :opensea-enabled? visible? {})))
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
(ns legacy.status-im.ui.screens.dapps-permissions.styles
|
||||
(:require
|
||||
[legacy.status-im.ui.components.colors :as colors]))
|
||||
|
||||
(def icon-container
|
||||
{:width 40
|
||||
:height 40
|
||||
:border-radius 20
|
||||
:background-color colors/gray-lighter
|
||||
:align-items :center
|
||||
:justify-content :center})
|
||||
@@ -1,64 +0,0 @@
|
||||
(ns legacy.status-im.ui.screens.dapps-permissions.views
|
||||
(:require-macros [legacy.status-im.utils.views :as views])
|
||||
(:require
|
||||
[legacy.status-im.ui.components.colors :as colors]
|
||||
[legacy.status-im.ui.components.core :as quo]
|
||||
[legacy.status-im.ui.components.icons.icons :as icons]
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.components.list.views :as list]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.components.topbar :as topbar]
|
||||
[legacy.status-im.ui.screens.dapps-permissions.styles :as styles]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn d-icon
|
||||
[]
|
||||
[react/view styles/icon-container
|
||||
[icons/icon :main-icons/dapp {:color colors/gray}]])
|
||||
|
||||
(defn prepare-items
|
||||
[{:keys [dapp permissions]}]
|
||||
{:title dapp
|
||||
:chevron true
|
||||
:on-press #(re-frame/dispatch [:navigate-to :manage-dapps-permissions
|
||||
{:dapp dapp :permissions permissions}])
|
||||
:icon [d-icon]})
|
||||
|
||||
(defn prepare-items-manage
|
||||
[name]
|
||||
(fn [permission]
|
||||
{:title (cond
|
||||
(= permission constants/dapp-permission-web3)
|
||||
name
|
||||
(= permission constants/dapp-permission-contact-code)
|
||||
(i18n/label :t/contact-code))
|
||||
:size :small
|
||||
:accessory [icons/icon :main-icons/check {}]}))
|
||||
|
||||
(views/defview dapps-permissions
|
||||
[]
|
||||
(views/letsubs [permissions [:dapps/permissions]]
|
||||
[list/flat-list
|
||||
{:data (vec (map prepare-items (vals permissions)))
|
||||
:key-fn (fn [_ i] (str i))
|
||||
:render-fn list.item/list-item}]))
|
||||
|
||||
(views/defview manage
|
||||
[]
|
||||
(views/letsubs [{:keys [dapp permissions]} [:get-screen-params]
|
||||
{:keys [name]} [:dapps-account]]
|
||||
[:<>
|
||||
[topbar/topbar {:title dapp}]
|
||||
[list/flat-list
|
||||
{:data (vec (map (prepare-items-manage name) permissions))
|
||||
:key-fn (fn [_ i] (str i))
|
||||
:render-fn list.item/list-item}]
|
||||
[react/view
|
||||
{:padding-vertical 16
|
||||
:padding-horizontal 16}
|
||||
[quo/button
|
||||
{:theme :negative
|
||||
:on-press #(re-frame/dispatch [:dapps/revoke-access dapp])}
|
||||
(i18n/label :t/revoke-access)]]]))
|
||||
@@ -1,13 +0,0 @@
|
||||
(ns legacy.status-im.ui.screens.link-previews-settings.styles)
|
||||
|
||||
(def link-preview-settings-image
|
||||
{:height 100
|
||||
:align-self :center
|
||||
:margin-top 16})
|
||||
|
||||
(def whitelist-container
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between})
|
||||
|
||||
(def enable-all
|
||||
{:align-self :flex-end})
|
||||
@@ -1,67 +0,0 @@
|
||||
(ns legacy.status-im.ui.screens.link-previews-settings.views
|
||||
(:require-macros [legacy.status-im.utils.views :as views])
|
||||
(:require
|
||||
[legacy.status-im.react-native.resources :as resources]
|
||||
[legacy.status-im.ui.components.core :as components]
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.components.list.views :as list]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.screens.link-previews-settings.styles :as styles]
|
||||
[quo.core :as quo]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.contexts.chat.messenger.messages.link-preview.events]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn prepare-urls-items-data
|
||||
[link-previews-enabled-sites]
|
||||
(fn [{:keys [title address]}]
|
||||
(let [enabled? (contains? link-previews-enabled-sites title)]
|
||||
{:title title
|
||||
:subtitle address
|
||||
:size :small
|
||||
:accessory :switch
|
||||
:active (contains? link-previews-enabled-sites title)
|
||||
:on-press #(re-frame/dispatch
|
||||
[:chat.ui/enable-link-previews title ((complement boolean) enabled?)])})))
|
||||
|
||||
(views/defview link-previews-settings
|
||||
[]
|
||||
(views/letsubs [link-previews-whitelist [:link-previews-whitelist]
|
||||
link-previews-enabled-sites [:link-preview/enabled-sites]]
|
||||
(let [all-enabled (= (count link-previews-whitelist) (count link-previews-enabled-sites))]
|
||||
[:<>
|
||||
[quo/page-nav
|
||||
{:type :title
|
||||
:title (i18n/label :t/chat-link-previews)
|
||||
:background :blur
|
||||
:icon-name :i/close
|
||||
:on-press #(rf/dispatch [:navigate-back])}]
|
||||
[react/image
|
||||
{:source (resources/get-theme-image :unfurl)
|
||||
:style styles/link-preview-settings-image}]
|
||||
[components/text {:style {:margin 16}}
|
||||
(i18n/label :t/you-can-choose-preview-websites)]
|
||||
[components/separator {:style {:margin-vertical 8}}]
|
||||
|
||||
[react/view styles/whitelist-container
|
||||
[components/list-header (i18n/label :t/websites)]
|
||||
|
||||
(when (> (count link-previews-whitelist) 1)
|
||||
[components/button
|
||||
{:on-press #(re-frame/dispatch [:chat.ui/enable-all-link-previews
|
||||
link-previews-whitelist
|
||||
(not all-enabled)])
|
||||
:type :secondary
|
||||
:style styles/enable-all}
|
||||
(if all-enabled
|
||||
(i18n/label :t/disable-all)
|
||||
(i18n/label :t/enable-all))])]
|
||||
[list/flat-list
|
||||
{:data (vec (map (prepare-urls-items-data link-previews-enabled-sites)
|
||||
link-previews-whitelist))
|
||||
:key-fn (fn [_ i] (str i))
|
||||
:render-fn list.item/list-item
|
||||
:footer [quo/text
|
||||
{:color :secondary
|
||||
:style {:margin 16}} (i18n/label :t/previewing-may-share-metadata)]}]])))
|
||||
@@ -1,81 +0,0 @@
|
||||
(ns legacy.status-im.ui.screens.privacy-and-security-settings.delete-profile
|
||||
(:require
|
||||
[legacy.status-im.ui.components.chat-icon.screen :as chat-icon.screen]
|
||||
[legacy.status-im.ui.components.core :as quo]
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[legacy.status-im.ui.screens.privacy-and-security-settings.events :as delete-profile]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.contexts.profile.utils :as profile.utils]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(defn valid-password?
|
||||
[password]
|
||||
(>= (count password) 6))
|
||||
|
||||
(defn on-delete-profile
|
||||
[password]
|
||||
#(do
|
||||
(re-frame/dispatch
|
||||
[::delete-profile/delete-profile @password])
|
||||
(reset! password nil)))
|
||||
|
||||
(defn delete-profile
|
||||
[]
|
||||
(let [password (reagent/atom nil)
|
||||
text-input-ref (atom nil)]
|
||||
(fn []
|
||||
(let [profile @(re-frame/subscribe [:profile/profile])
|
||||
error @(re-frame/subscribe [:delete-profile/error])
|
||||
keep-keys-on-keycard? @(re-frame/subscribe
|
||||
[:delete-profile/keep-keys-on-keycard?])]
|
||||
(when (and @text-input-ref error (not @password))
|
||||
(.clear ^js @text-input-ref))
|
||||
[react/keyboard-avoiding-view {:style {:flex 1}}
|
||||
[react/scroll-view {:style {:flex 1}}
|
||||
[react/view {:style {:align-items :center}}
|
||||
[quo/text
|
||||
{:weight :bold
|
||||
:size :x-large}
|
||||
(i18n/label :t/delete-profile)]]
|
||||
[list.item/list-item
|
||||
{:title (profile.utils/displayed-name profile)
|
||||
:icon [chat-icon.screen/contact-icon-contacts-tab profile]}]
|
||||
[quo/text
|
||||
{:style {:margin-horizontal 24}
|
||||
:align :center
|
||||
:color :negative}
|
||||
(i18n/label :t/delete-profile-warning)]
|
||||
[quo/text-input
|
||||
{:style {:margin-horizontal 36
|
||||
:margin-top 36}
|
||||
:show-cancel false
|
||||
:secure-text-entry true
|
||||
:return-key-type :next
|
||||
:on-submit-editing nil
|
||||
:auto-focus true
|
||||
:on-change-text #(reset! password (security/mask-data %))
|
||||
:bottom-value 36
|
||||
:get-ref #(reset! text-input-ref %)
|
||||
:error (when (and error (not @password))
|
||||
(if (= :wrong-password error)
|
||||
(i18n/label :t/wrong-password)
|
||||
(str error)))}]]
|
||||
[react/view {:style {:align-items :center}}
|
||||
[quo/separator]
|
||||
(when (not keep-keys-on-keycard?)
|
||||
[quo/text
|
||||
{:style {:margin-horizontal 24 :margin-bottom 16}
|
||||
:align :center
|
||||
:color :negative}
|
||||
(i18n/label :t/delete-profile-warning)])
|
||||
[react/view
|
||||
{:style {:margin-vertical 8}}
|
||||
[quo/button
|
||||
{:on-press (on-delete-profile password)
|
||||
:theme :negative
|
||||
:accessibility-label :delete-profile-confirm
|
||||
:disabled ((complement valid-password?) @password)}
|
||||
(i18n/label :t/delete-profile)]]]]))))
|
||||
@@ -1,73 +0,0 @@
|
||||
(ns legacy.status-im.ui.screens.privacy-and-security-settings.events
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.utils.deprecated-types :as types]
|
||||
[native-module.core :as native-module]
|
||||
[re-frame.core :as re-frame]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(defn safe-blank?
|
||||
[s]
|
||||
(or (not s)
|
||||
(string/blank? s)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::delete-profile
|
||||
(fn [{:keys [address key-uid callback masked-password]}]
|
||||
(let [hashed-password
|
||||
(-> masked-password
|
||||
security/safe-unmask-data
|
||||
native-module/sha3)]
|
||||
(native-module/verify
|
||||
address
|
||||
hashed-password
|
||||
(fn [result]
|
||||
(let [{:keys [error]} (types/json->clj result)]
|
||||
(log/info "[delete-profile] verify-password" result error)
|
||||
(if-not (safe-blank? error)
|
||||
(callback :wrong-password nil)
|
||||
(native-module/delete-multiaccount
|
||||
key-uid
|
||||
(fn [result]
|
||||
(let [{:keys [error]} (types/json->clj result)]
|
||||
(callback error nil)))))))))))
|
||||
|
||||
(rf/defn delete-profile
|
||||
{:events [::delete-profile]}
|
||||
[{:keys [db] :as cofx} masked-password]
|
||||
(log/info "[delete-profile] delete")
|
||||
(let [{:keys [key-uid wallet-root-address]} (:profile/profile db)]
|
||||
{:db (dissoc db :delete-profile/error)
|
||||
::delete-profile
|
||||
{:masked-password masked-password
|
||||
:key-uid key-uid
|
||||
:address wallet-root-address
|
||||
:callback
|
||||
(fn [error result]
|
||||
(log/info "[delete-profile] callback" error)
|
||||
(if (safe-blank? error)
|
||||
(re-frame/dispatch [::on-delete-profile-success result])
|
||||
(re-frame/dispatch [::on-delete-profile-failure error])))}}))
|
||||
|
||||
(rf/defn on-delete-profile-success
|
||||
{:events [::on-delete-profile-success]}
|
||||
[cofx]
|
||||
(log/info "[delete-profile] on-success")
|
||||
{:effects.utils/show-popup
|
||||
{:title (i18n/label :t/profile-deleted-title)
|
||||
:content (i18n/label :t/profile-deleted-content)
|
||||
:on-dismiss #(re-frame/dispatch [:logout])}})
|
||||
|
||||
(rf/defn on-delete-profile-failure
|
||||
{:events [::on-delete-profile-failure]}
|
||||
[{:keys [db]} error]
|
||||
(log/info "[delete-profile] on-failure" error)
|
||||
{:db (assoc db :delete-profile/error error)})
|
||||
|
||||
(rf/defn keep-keys-on-keycard
|
||||
{:events [::keep-keys-on-keycard]}
|
||||
[{:keys [db] :as cofx} checked?]
|
||||
{:db (assoc-in db [:delete-profile/keep-keys-on-keycard?] checked?)})
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
(ns legacy.status-im.ui.screens.privacy-and-security-settings.messages-from-contacts-only
|
||||
(:require-macros [legacy.status-im.utils.views :as views])
|
||||
(:require
|
||||
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[re-frame.core :as re-frame]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/defn handle-messages-from-contacts-only-switched
|
||||
{:events [::messages-from-contacts-only-switched]}
|
||||
[cofx value]
|
||||
(multiaccounts.update/multiaccount-update cofx
|
||||
:messages-from-contacts-only
|
||||
value
|
||||
{}))
|
||||
|
||||
(views/defview messages-from-contacts-only-view
|
||||
[]
|
||||
(views/letsubs [{:keys [messages-from-contacts-only]} [:profile/profile]]
|
||||
[react/view {:margin-top 8}
|
||||
[list.item/list-item
|
||||
{:active (not messages-from-contacts-only)
|
||||
:accessory :radio
|
||||
:title (i18n/label :t/anyone)
|
||||
:on-press #(re-frame/dispatch [::messages-from-contacts-only-switched false])}]
|
||||
[list.item/list-item
|
||||
{:active messages-from-contacts-only
|
||||
:accessory :radio
|
||||
:title (i18n/label :t/contacts)
|
||||
:subtitle (i18n/label :t/messages-from-contacts-only-subtitle)
|
||||
:subtitle-max-lines 4
|
||||
:on-press #(re-frame/dispatch [::messages-from-contacts-only-switched true])}]]))
|
||||
@@ -1,175 +0,0 @@
|
||||
(ns legacy.status-im.ui.screens.privacy-and-security-settings.views
|
||||
(:require
|
||||
[legacy.status-im.multiaccounts.reset-password.core :as reset-password]
|
||||
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[legacy.status-im.ui.components.core :as components]
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.components.react :as react]
|
||||
[quo.core :as quo]
|
||||
[re-frame.core :as re-frame]
|
||||
[react-native.platform :as platform]
|
||||
[status-im.config :as config]
|
||||
[status-im.constants :as constants]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf])
|
||||
(:require-macros [legacy.status-im.utils.views :as views]))
|
||||
|
||||
(defn separator
|
||||
[]
|
||||
[components/separator {:style {:margin-vertical 8}}])
|
||||
|
||||
(def titles
|
||||
{constants/profile-pictures-visibility-contacts-only (i18n/label :t/recent-recipients)
|
||||
constants/profile-pictures-visibility-everyone (i18n/label :t/everyone)
|
||||
constants/profile-pictures-visibility-none (i18n/label :t/none)
|
||||
constants/profile-pictures-show-to-contacts-only (i18n/label :t/recent-recipients)
|
||||
constants/profile-pictures-show-to-everyone (i18n/label :t/everyone)
|
||||
constants/profile-pictures-show-to-none (i18n/label :t/none)})
|
||||
|
||||
(views/defview privacy-and-security
|
||||
[]
|
||||
(views/letsubs [{:keys [preview-privacy?
|
||||
messages-from-contacts-only
|
||||
webview-allow-permission-requests?
|
||||
opensea-enabled?
|
||||
profile-pictures-visibility]}
|
||||
[:profile/profile]
|
||||
has-picture [:profile/has-picture]
|
||||
profile-pictures-show-to [:multiaccount/profile-pictures-show-to]]
|
||||
[:<>
|
||||
[quo/page-nav
|
||||
{:type :no-title
|
||||
:background :blur
|
||||
:icon-name :i/close
|
||||
:on-press #(rf/dispatch [:navigate-back])}]
|
||||
[react/scroll-view {:padding-vertical 8}
|
||||
[components/list-header (i18n/label :t/privacy)]
|
||||
[list.item/list-item
|
||||
{:size :small
|
||||
:title (i18n/label :t/set-dapp-access-permissions)
|
||||
:on-press #(re-frame/dispatch [:navigate-to :dapps-permissions])
|
||||
:accessibility-label :dapps-permissions-button
|
||||
:chevron true}]
|
||||
[list.item/list-item
|
||||
{:size :small
|
||||
:title (if platform/android?
|
||||
(i18n/label :t/hide-content-when-switching-apps)
|
||||
(i18n/label :t/hide-content-when-switching-apps-ios))
|
||||
:container-margin-bottom 8
|
||||
:active preview-privacy?
|
||||
:accessory :switch
|
||||
:on-press #(re-frame/dispatch
|
||||
[:profile.settings/change-preview-privacy
|
||||
((complement boolean) preview-privacy?)])}]
|
||||
(when config/collectibles-enabled?
|
||||
[list.item/list-item
|
||||
{:size :small
|
||||
:title (i18n/label :t/display-collectibles)
|
||||
:container-margin-bottom 8
|
||||
:active opensea-enabled?
|
||||
:accessory :switch
|
||||
:on-press #(re-frame/dispatch
|
||||
[::multiaccounts.update/toggle-opensea-nfts-visiblity
|
||||
(not opensea-enabled?)])}])
|
||||
[list.item/list-item
|
||||
{:size :small
|
||||
:title (i18n/label :t/chat-link-previews)
|
||||
:chevron true
|
||||
:on-press #(re-frame/dispatch [:open-modal :legacy-link-previews-settings])
|
||||
:accessibility-label :chat-link-previews}]
|
||||
[list.item/list-item
|
||||
{:size :small
|
||||
:title (i18n/label :t/accept-new-chats-from)
|
||||
:chevron true
|
||||
:accessory :text
|
||||
:accessory-text (i18n/label (if messages-from-contacts-only
|
||||
:t/contacts
|
||||
:t/anyone))
|
||||
:on-press #(re-frame/dispatch [:navigate-to :messages-from-contacts-only])
|
||||
:accessibility-label :accept-new-chats-from}]
|
||||
[list.item/list-item
|
||||
{:size :small
|
||||
:title (i18n/label :t/reset-password)
|
||||
:chevron true
|
||||
:accessory :text
|
||||
:on-press #(do
|
||||
(re-frame/dispatch [::reset-password/clear-form-vals])
|
||||
(re-frame/dispatch [:navigate-to :reset-password]))
|
||||
:accessibility-label :reset-password}]
|
||||
(when platform/android?
|
||||
[list.item/list-item
|
||||
{:size :small
|
||||
:title (i18n/label :t/webview-camera-permission-requests)
|
||||
:active webview-allow-permission-requests?
|
||||
:accessory :switch
|
||||
:subtitle (i18n/label :t/webview-camera-permission-requests-subtitle)
|
||||
:subtitle-max-lines 2
|
||||
:on-press #(re-frame/dispatch
|
||||
[:profile.settings/profile-update
|
||||
:webview-allow-permission-requests?
|
||||
((complement boolean) webview-allow-permission-requests?)])}])
|
||||
[separator]
|
||||
[components/list-header (i18n/label :t/privacy-photos)]
|
||||
[list.item/list-item
|
||||
{:size :small
|
||||
:title (i18n/label :t/show-profile-pictures)
|
||||
:accessibility-label :show-profile-pictures
|
||||
:accessory :text
|
||||
:accessory-text (get titles profile-pictures-visibility)
|
||||
:on-press #(re-frame/dispatch [:navigate-to :privacy-and-security-profile-pic])
|
||||
:chevron true}]
|
||||
[list.item/list-item
|
||||
{:size :small
|
||||
:title (i18n/label :t/show-profile-pictures-to)
|
||||
:disabled (not has-picture)
|
||||
:accessibility-label :show-profile-pictures-to
|
||||
:accessory :text
|
||||
:accessory-text (get titles profile-pictures-show-to)
|
||||
:on-press #(re-frame/dispatch [:navigate-to
|
||||
:privacy-and-security-profile-pic-show-to])
|
||||
:chevron true}]
|
||||
|
||||
[separator]
|
||||
[list.item/list-item
|
||||
{:size :small
|
||||
:theme :negative
|
||||
:title (i18n/label :t/delete-my-profile)
|
||||
:on-press #(re-frame/dispatch [:navigate-to :delete-profile])
|
||||
:accessibility-label :dapps-permissions-button
|
||||
:chevron true}]]]))
|
||||
|
||||
(defn ppst-radio-item
|
||||
[id value]
|
||||
[list.item/list-item
|
||||
{:active (= value id)
|
||||
:accessory :radio
|
||||
:title (get titles id)
|
||||
:on-press #(re-frame/dispatch [:profile.settings/change-profile-pictures-show-to id])}])
|
||||
|
||||
(views/defview profile-pic-show-to
|
||||
[]
|
||||
(views/letsubs [{:keys [profile-pictures-show-to]} [:profile/profile]]
|
||||
[react/view {:margin-top 8}
|
||||
[ppst-radio-item constants/profile-pictures-show-to-everyone profile-pictures-show-to]
|
||||
[ppst-radio-item constants/profile-pictures-show-to-contacts-only profile-pictures-show-to]
|
||||
[ppst-radio-item constants/profile-pictures-show-to-none profile-pictures-show-to]
|
||||
|
||||
[react/view {:style {:margin-horizontal 16}}
|
||||
[components/text {:color :secondary}
|
||||
(i18n/label :t/privacy-show-to-warning)]]]))
|
||||
|
||||
(defn ppvf-radio-item
|
||||
[id value]
|
||||
[list.item/list-item
|
||||
{:active (= value id)
|
||||
:accessory :radio
|
||||
:title (get titles id)
|
||||
:on-press #(re-frame/dispatch [:profile.settings/profile-update :profile-pictures-visibility id])}])
|
||||
|
||||
(views/defview profile-pic
|
||||
[]
|
||||
(views/letsubs [{:keys [profile-pictures-visibility]} [:profile/profile]]
|
||||
[react/view {:margin-top 8}
|
||||
[ppvf-radio-item constants/profile-pictures-visibility-everyone profile-pictures-visibility]
|
||||
[ppvf-radio-item constants/profile-pictures-visibility-contacts-only profile-pictures-visibility]
|
||||
[ppvf-radio-item constants/profile-pictures-visibility-none profile-pictures-visibility]]))
|
||||
@@ -13,12 +13,6 @@
|
||||
[]
|
||||
[rn/scroll-view {:flex 1}
|
||||
[components/list-header "Legacy settings"]
|
||||
[list.item/list-item
|
||||
{:icon :main-icons/security
|
||||
:title (i18n/label :t/privacy-and-security)
|
||||
:accessibility-label :privacy-and-security-settings-button
|
||||
:chevron true
|
||||
:on-press #(re-frame/dispatch [:open-modal :legacy-privacy-and-security])}]
|
||||
[list.item/list-item
|
||||
{:icon :main-icons/mobile
|
||||
:title (i18n/label :t/sync-settings)
|
||||
|
||||
@@ -8,12 +8,10 @@
|
||||
[legacy.status-im.ui.screens.bug-report :as bug-report]
|
||||
[legacy.status-im.ui.screens.communities.invite :as communities.invite]
|
||||
[legacy.status-im.ui.screens.communities.members :as members]
|
||||
[legacy.status-im.ui.screens.dapps-permissions.views :as dapps-permissions]
|
||||
[legacy.status-im.ui.screens.default-sync-period-settings.view :as default-sync-period-settings]
|
||||
[legacy.status-im.ui.screens.fleet-settings.views :as fleet-settings]
|
||||
[legacy.status-im.ui.screens.glossary.view :as glossary]
|
||||
[legacy.status-im.ui.screens.help-center.views :as help-center]
|
||||
[legacy.status-im.ui.screens.link-previews-settings.views :as link-previews-settings]
|
||||
[legacy.status-im.ui.screens.log-level-settings.views :as log-level-settings]
|
||||
[legacy.status-im.ui.screens.mobile-network-settings.view :as mobile-network-settings]
|
||||
[legacy.status-im.ui.screens.notifications-settings.views :as notifications-settings]
|
||||
@@ -21,10 +19,6 @@
|
||||
[legacy.status-im.ui.screens.offline-messaging-settings.views :as offline-messaging-settings]
|
||||
[legacy.status-im.ui.screens.pairing.views :as pairing]
|
||||
[legacy.status-im.ui.screens.peers-stats :as peers-stats]
|
||||
[legacy.status-im.ui.screens.privacy-and-security-settings.delete-profile :as delete-profile]
|
||||
[legacy.status-im.ui.screens.privacy-and-security-settings.messages-from-contacts-only :as
|
||||
messages-from-contacts-only]
|
||||
[legacy.status-im.ui.screens.privacy-and-security-settings.views :as privacy-and-security]
|
||||
[legacy.status-im.ui.screens.profile.seed.views :as profile.seed]
|
||||
[legacy.status-im.ui.screens.profile.user.views :as profile.user]
|
||||
[legacy.status-im.ui.screens.progress.views :as progress]
|
||||
@@ -94,17 +88,6 @@
|
||||
:insets {:top? platform/android?}}
|
||||
:component profile.user/legacy-settings}
|
||||
|
||||
;; PRIVACY AND SECURITY
|
||||
{:name :legacy-privacy-and-security
|
||||
:options {:topBar {:visible false}
|
||||
:insets {:top? platform/android?}}
|
||||
:component privacy-and-security/privacy-and-security}
|
||||
|
||||
{:name :legacy-link-previews-settings
|
||||
:options {:topBar {:visible false}
|
||||
:insets {:top? platform/android?}}
|
||||
:component link-previews-settings/link-previews-settings}
|
||||
|
||||
;; SYNC
|
||||
{:name :legacy-sync-settings
|
||||
:options {:topBar {:visible false}
|
||||
@@ -150,25 +133,6 @@
|
||||
{:name :edit-mailserver
|
||||
:options {:insets {:top? true}}
|
||||
:component edit-mailserver/edit-mailserver}
|
||||
{:name :dapps-permissions
|
||||
:options {:topBar (topbar-options :t/dapps-permissions)
|
||||
:insets {:top? true}}
|
||||
:component dapps-permissions/dapps-permissions}
|
||||
{:name :messages-from-contacts-only
|
||||
:options {:topBar (topbar-options :t/accept-new-chats-from)
|
||||
:insets {:top? true}}
|
||||
:component messages-from-contacts-only/messages-from-contacts-only-view}
|
||||
{:name :privacy-and-security-profile-pic-show-to
|
||||
:options {:topbar (topbar-options :t/show-profile-pictures-to)
|
||||
:insets {:top? true}}
|
||||
:component privacy-and-security/profile-pic-show-to}
|
||||
{:name :privacy-and-security-profile-pic
|
||||
:options {:topBar (topbar-options :t/show-profile-pictures)
|
||||
:insets {:top? true}}
|
||||
:component privacy-and-security/profile-pic}
|
||||
{:name :manage-dapps-permissions
|
||||
:options {:insets {:top? true}}
|
||||
:component dapps-permissions/manage}
|
||||
{:name :rpc-usage-info
|
||||
:options {:topBar (topbar-options :t/rpc-usage-info)
|
||||
:insets {:top? true}}
|
||||
@@ -196,9 +160,6 @@
|
||||
:options {:topBar (topbar-options :t/reset-password)
|
||||
:insets {:top? true}}
|
||||
:component reset-password/reset-password}
|
||||
{:name :delete-profile
|
||||
:insets {:bottom? true}
|
||||
:component delete-profile/delete-profile}
|
||||
{:name :default-sync-period-settings
|
||||
:options {:topBar (topbar-options :t/default-sync-period)
|
||||
:insets {:top? true}}
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
(ns legacy.status-im.utils.test
|
||||
(:require
|
||||
[legacy.status-im.utils.deprecated-types :as types]
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
(def native-status (js/require "../../modules/react-native-status/nodejs/bindings"))
|
||||
|
||||
(def fs (js/require "fs"))
|
||||
(def path (js/require "path"))
|
||||
(def os (js/require "os"))
|
||||
|
||||
(def tmpdir (.tmpdir os))
|
||||
|
||||
(def test-dir-prefix (.join path tmpdir "status-mobile-tests"))
|
||||
|
||||
(def test-dir (.mkdtempSync fs test-dir-prefix))
|
||||
|
||||
(def initialized? (atom false))
|
||||
|
||||
(defn signal-received-callback
|
||||
[a]
|
||||
(re-frame/dispatch [:signals/signal-received a]))
|
||||
|
||||
;; We poll for signals, could not get callback working
|
||||
(defn init!
|
||||
[]
|
||||
(when-not @initialized?
|
||||
(.setSignalEventCallback native-status)
|
||||
(reset! initialized? true)
|
||||
(js/setInterval (fn []
|
||||
(.pollSignal native-status signal-received-callback)
|
||||
100))))
|
||||
|
||||
(def ui-helper
|
||||
(clj->js
|
||||
{:clearCookies identity
|
||||
:clearStorageAPIs identity}))
|
||||
|
||||
(def encryption-utils
|
||||
(clj->js
|
||||
{:sha3
|
||||
(fn [s] (.sha3 native-status s))
|
||||
:setBlankPreviewFlag
|
||||
identity
|
||||
:encodeTransfer
|
||||
(fn [to-norm amount-hex]
|
||||
(.encodeTransfer native-status to-norm amount-hex))
|
||||
:hexToNumber
|
||||
(fn [hex] (.hexToNumber native-status hex))
|
||||
:decodeParameters
|
||||
(fn [decode-param-json]
|
||||
(.decodeParameters native-status decode-param-json))
|
||||
:numberToHex
|
||||
(fn [num-str] (.numberToHex native-status num-str))
|
||||
:initKeystore
|
||||
(fn [key-uid callback]
|
||||
(callback (.initKeystore native-status
|
||||
(str test-dir "/keystore/" key-uid))))
|
||||
:multiformatDeserializePublicKey
|
||||
(fn [public-key deserialization-key callback]
|
||||
(callback (.multiformatDeserializePublicKey
|
||||
native-status
|
||||
public-key
|
||||
deserialization-key)))}))
|
||||
|
||||
(def account-manager
|
||||
(clj->js
|
||||
{:openAccounts
|
||||
(fn [callback]
|
||||
(callback (.openAccounts native-status test-dir)))
|
||||
:createAccountAndLogin
|
||||
(fn [request] (.createAccountAndLogin native-status request))
|
||||
:logout
|
||||
(fn [] (.logout native-status))
|
||||
:multiAccountImportMnemonic
|
||||
(fn [json callback]
|
||||
(callback (.multiAccountImportMnemonic native-status json)))
|
||||
:multiAccountLoadAccount
|
||||
(fn [json callback]
|
||||
(callback (.multiAccountLoadAccount native-status json)))
|
||||
:multiAccountDeriveAddresses
|
||||
(fn [json callback]
|
||||
(callback (.multiAccountDeriveAddresses native-status json)))
|
||||
:multiAccountGenerateAndDeriveAddresses
|
||||
(fn [json callback]
|
||||
(callback (.multiAccountGenerateAndDeriveAddresses native-status json)))
|
||||
:multiAccountStoreDerived
|
||||
(fn [json callback]
|
||||
(callback (.multiAccountStoreDerivedAccounts native-status json)))}))
|
||||
|
||||
(def utils
|
||||
(clj->js
|
||||
{:backupDisabledDataDir
|
||||
(fn [] (str test-dir "/backup"))
|
||||
:keystoreDir (fn [] "")
|
||||
:toChecksumAddress
|
||||
(fn [address] (.toChecksumAddress native-status address))
|
||||
:checkAddressChecksum
|
||||
(fn [address] (.checkAddressChecksum native-status address))
|
||||
:validateMnemonic
|
||||
(fn [json callback] (callback (.validateMnemonic native-status json)))
|
||||
:isAddress
|
||||
(fn [address] (.isAddress native-status address))}))
|
||||
|
||||
(def log-manager
|
||||
(clj->js
|
||||
{:logFileDirectory
|
||||
(fn [] (str test-dir "/log"))
|
||||
:initLogging
|
||||
(fn [enabled mobile-system log-level callback]
|
||||
(callback (.initLogging native-status
|
||||
(types/clj->json {:Enabled enabled
|
||||
:MobileSystem mobile-system
|
||||
:Level log-level
|
||||
:File (str test-dir "/geth.log")}))))}))
|
||||
|
||||
(def network
|
||||
(clj->js
|
||||
{:callPrivateRPC
|
||||
(fn [payload callback]
|
||||
(callback (.callPrivateRPC native-status payload)))}))
|
||||
|
||||
(def status
|
||||
(clj->js
|
||||
{:getNodeConfig
|
||||
(fn [] (types/clj->json {:WakuV2Config ""}))
|
||||
:fleets
|
||||
(fn [] (.fleets native-status))
|
||||
:startLocalNotifications
|
||||
identity}))
|
||||
@@ -72,10 +72,12 @@
|
||||
(log/debug "[native-module] init-keystore" key-uid)
|
||||
(.initKeystore ^js (encryption) key-uid callback))
|
||||
|
||||
(defn open-accounts
|
||||
[callback]
|
||||
(log/debug "[native-module] open-accounts")
|
||||
(.openAccounts ^js (account-manager) #(callback (types/json->clj %))))
|
||||
(defn initialize-application
|
||||
[request callback]
|
||||
(log/debug "[native-module] initialize-application")
|
||||
(.initializeApplication ^js (account-manager)
|
||||
(types/clj->json request)
|
||||
#(callback (types/json->clj %))))
|
||||
|
||||
(defn prepare-dir-and-update-config
|
||||
[key-uid config callback]
|
||||
@@ -513,6 +515,14 @@
|
||||
(let [result (.checkAddressChecksum ^js (utils) address)]
|
||||
(types/json->clj result)))
|
||||
|
||||
(defn toggle-centralized-metrics
|
||||
[enabled callback]
|
||||
(.toggleCentralizedMetrics ^js (status) (types/clj->json {:enabled enabled}) callback))
|
||||
|
||||
(defn add-centralized-metric
|
||||
[metric]
|
||||
(.addCentralizedMetric ^js (status) (types/clj->json metric) #(log/debug "pushed metric" % metric)))
|
||||
|
||||
(defn address?
|
||||
[address]
|
||||
(log/debug "[native-module] address?")
|
||||
@@ -533,6 +543,13 @@
|
||||
(log/debug "[native-module] validate-mnemonic")
|
||||
(.validateMnemonic ^js (utils) mnemonic callback)))
|
||||
|
||||
(defn validate-connection-string
|
||||
[connection-string]
|
||||
(log/debug "[native-module] validate-connection-string")
|
||||
(->> connection-string
|
||||
(.validateConnectionString ^js (utils))
|
||||
types/json->clj))
|
||||
|
||||
(defn delete-multiaccount
|
||||
"Delete multiaccount from database, deletes multiaccount's database and
|
||||
key files."
|
||||
@@ -643,7 +660,6 @@
|
||||
(native-utils/promisify-native-module-call create-account-from-private-key private-key))
|
||||
([private-key callback]
|
||||
(log/debug "[native-module] create-account-from-private-key")
|
||||
|
||||
(.createAccountFromPrivateKey ^js (account-manager)
|
||||
(types/clj->json {:privateKey private-key})
|
||||
callback)))
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
(defn fallback
|
||||
[{:keys [theme opacity]}]
|
||||
[{:opacity opacity}
|
||||
{:opacity default-opacity-for-image
|
||||
{:opacity 1
|
||||
:background-color (colors/theme-colors colors/neutral-2_5 colors/neutral-90 theme)
|
||||
:border-style :dashed
|
||||
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
|
||||
@@ -60,8 +60,13 @@
|
||||
:padding-right 0
|
||||
:padding-top 4})
|
||||
|
||||
(def card-detail-text
|
||||
{:flex 1})
|
||||
(defn card-detail-text
|
||||
[empty-name? theme]
|
||||
{:flex 1
|
||||
:margin-right 8
|
||||
:color (if empty-name?
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
|
||||
(colors/theme-colors colors/neutral-100 colors/white theme))})
|
||||
|
||||
(defn card-loader
|
||||
[opacity]
|
||||
@@ -115,6 +120,7 @@
|
||||
[{:opacity opacity}
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:column-gap 8
|
||||
:opacity default-opacity-for-image}])
|
||||
|
||||
(defn supported-file
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns quo.components.profile.collectible-list-item.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[quo.components.avatars.collection-avatar.view :as collection-avatar]
|
||||
[quo.components.counter.collectible-counter.view :as collectible-counter]
|
||||
[quo.components.icon :as icon]
|
||||
@@ -21,7 +22,7 @@
|
||||
(def cached-load-time 200)
|
||||
(def error-wait-time 800)
|
||||
|
||||
(defn on-load-end
|
||||
(defn animate-loading-image
|
||||
[{:keys [load-time set-state loader-opacity image-opacity]}]
|
||||
(reanimated/animate loader-opacity 0 timing-options-out)
|
||||
(reanimated/animate image-opacity 1 timing-options-in)
|
||||
@@ -60,12 +61,12 @@
|
||||
(assoc prev-state :avatar-loaded? true)))))
|
||||
|
||||
(defn- fallback-view
|
||||
[{:keys [label theme image-opacity]}]
|
||||
[reanimated/view
|
||||
{:style (style/fallback {:opacity image-opacity
|
||||
:theme theme})}
|
||||
[{:keys [label theme image-opacity on-load-end]}]
|
||||
(rn/use-mount on-load-end)
|
||||
[reanimated/view {:style (style/fallback {:opacity image-opacity :theme theme})}
|
||||
[rn/view
|
||||
[icon/icon :i/sad {:color (colors/theme-colors colors/neutral-40 colors/neutral-50 theme)}]]
|
||||
[icon/icon :i/sad
|
||||
{:color (colors/theme-colors colors/neutral-40 colors/neutral-50 theme)}]]
|
||||
[rn/view {:style {:height 4}}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
@@ -93,31 +94,43 @@
|
||||
[{:keys [community? avatar-image-src collectible-name theme state set-state]}]
|
||||
(let [loader-opacity (reanimated/use-shared-value 1)
|
||||
avatar-opacity (reanimated/use-shared-value 0)
|
||||
[load-time set-load-time] (rn/use-state (datetime/now))]
|
||||
[load-time set-load-time] (rn/use-state (datetime/now))
|
||||
set-avatar-loaded (fn []
|
||||
(on-load-avatar {:set-state set-state
|
||||
:load-time load-time
|
||||
:loader-opacity loader-opacity
|
||||
:avatar-opacity avatar-opacity}))
|
||||
empty-name? (string/blank? collectible-name)]
|
||||
(rn/use-mount (fn []
|
||||
(when (string/blank? avatar-image-src)
|
||||
(set-avatar-loaded))))
|
||||
[rn/view {:style style/card-details-container}
|
||||
[reanimated/view {:style (style/avatar-container avatar-opacity)}
|
||||
(if community?
|
||||
[preview-list/view
|
||||
{:type :communities
|
||||
:size :size-20}
|
||||
(cond
|
||||
(string/blank? avatar-image-src)
|
||||
[loading-square theme]
|
||||
|
||||
community?
|
||||
[preview-list/view {:type :communities :size :size-20}
|
||||
[avatar-image-src]]
|
||||
|
||||
:else
|
||||
[collection-avatar/view
|
||||
{:size :size-20
|
||||
:on-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
|
||||
:on-load-end #(on-load-avatar {:set-state set-state
|
||||
:load-time load-time
|
||||
:loader-opacity loader-opacity
|
||||
:avatar-opacity avatar-opacity})
|
||||
:on-load-end set-avatar-loaded
|
||||
:image avatar-image-src}])
|
||||
[rn/view {:style {:width 8}}]
|
||||
[text/text
|
||||
{:size :paragraph-1
|
||||
:weight :semi-bold
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:style style/card-detail-text}
|
||||
collectible-name]]
|
||||
(when (not (:avatar-loaded? state))
|
||||
:style (style/card-detail-text empty-name? theme)}
|
||||
(if empty-name?
|
||||
(i18n/label :t/unknown)
|
||||
collectible-name)]]
|
||||
|
||||
(when-not (:avatar-loaded? state)
|
||||
[reanimated/view {:style (style/card-loader loader-opacity)}
|
||||
[loading-square theme]
|
||||
[loading-message theme]])]))
|
||||
@@ -128,40 +141,44 @@
|
||||
(let [theme (quo.theme/use-theme)
|
||||
loader-opacity (reanimated/use-shared-value (if supported-file? 1 0))
|
||||
image-opacity (reanimated/use-shared-value (if supported-file? 0 1))
|
||||
[load-time set-load-time] (rn/use-state (datetime/now))]
|
||||
[load-time set-load-time] (rn/use-state (datetime/now))
|
||||
set-image-loaded (fn []
|
||||
(animate-loading-image {:load-time load-time
|
||||
:set-state set-state
|
||||
:loader-opacity loader-opacity
|
||||
:image-opacity image-opacity}))]
|
||||
[rn/view {:style (style/card-view-container theme)}
|
||||
[rn/view {:style {:aspect-ratio 1}}
|
||||
(cond
|
||||
(:image-error? state)
|
||||
[fallback-view
|
||||
{:image-opacity image-opacity
|
||||
:theme theme
|
||||
:label (i18n/label :t/cant-fetch-info)}]
|
||||
(:image-error? state) [fallback-view
|
||||
{:image-opacity image-opacity
|
||||
:on-load-end set-image-loaded
|
||||
:theme theme
|
||||
:label (i18n/label :t/cant-fetch-info)}]
|
||||
(not supported-file?) [fallback-view
|
||||
{:image-opacity image-opacity
|
||||
:on-load-end set-image-loaded
|
||||
:theme theme
|
||||
:label (i18n/label :t/unsupported-file)}]
|
||||
(not (:image-loaded? state)) [loading-image
|
||||
{:loader-opacity loader-opacity
|
||||
:theme theme
|
||||
:gradient-color-index gradient-color-index}])
|
||||
|
||||
(not supported-file?)
|
||||
[fallback-view
|
||||
{:image-opacity image-opacity
|
||||
:theme theme
|
||||
:label (i18n/label :t/unsupported-file)}]
|
||||
|
||||
(not (:image-loaded? state))
|
||||
[loading-image
|
||||
{:loader-opacity loader-opacity
|
||||
:theme theme
|
||||
:gradient-color-index gradient-color-index}])
|
||||
(when supported-file?
|
||||
[reanimated/view {:style (style/supported-file image-opacity)}
|
||||
[rn/image
|
||||
{:style style/image
|
||||
:on-load #(on-load % set-state)
|
||||
:on-load-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
|
||||
:on-load-end #(on-load-end {:load-time load-time
|
||||
:set-state set-state
|
||||
:loader-opacity loader-opacity
|
||||
:image-opacity image-opacity})
|
||||
:on-load-end set-image-loaded
|
||||
:on-error #(on-load-error set-state)
|
||||
:source image-src}]])]
|
||||
(when (and (:image-loaded? state) (not (:image-error? state)) counter)
|
||||
|
||||
(when (and (or (:image-loaded? state)
|
||||
(not supported-file?))
|
||||
(not (:image-error? state))
|
||||
counter)
|
||||
[collectible-counter/view
|
||||
{:container-style style/collectible-counter
|
||||
:size :size-24
|
||||
@@ -206,10 +223,10 @@
|
||||
{:style style/image
|
||||
:on-load #(on-load % set-state)
|
||||
:on-load-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
|
||||
:on-load-end #(on-load-end {:load-time load-time
|
||||
:set-state set-state
|
||||
:loader-opacity loader-opacity
|
||||
:image-opacity image-opacity})
|
||||
:on-load-end #(animate-loading-image {:load-time load-time
|
||||
:set-state set-state
|
||||
:loader-opacity loader-opacity
|
||||
:image-opacity image-opacity})
|
||||
:on-error #(on-load-error set-state)
|
||||
:source image-src}]])
|
||||
(when (and (:image-loaded? state) (not (:image-error? state)) counter)
|
||||
|
||||
@@ -11,38 +11,24 @@
|
||||
[react-native.core :as rn]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[schema.core :as schema]
|
||||
[utils.datetime :as datetime]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(def timing-options-out 650)
|
||||
(def timing-options-in 1000)
|
||||
(def first-load-time 500)
|
||||
(def cached-load-time 200)
|
||||
(def loader-out 650)
|
||||
(def image-in 1000)
|
||||
(def error-wait-time 800)
|
||||
|
||||
(defn on-load-end
|
||||
[{:keys [load-time set-state loader-opacity image-opacity]}]
|
||||
(reanimated/animate loader-opacity 0 timing-options-out)
|
||||
(reanimated/animate image-opacity 1 timing-options-in)
|
||||
(if (> load-time cached-load-time)
|
||||
(js/setTimeout
|
||||
(fn []
|
||||
(set-state (fn [prev-state]
|
||||
(assoc prev-state :image-loaded? true))))
|
||||
first-load-time)
|
||||
(set-state (fn [prev-state]
|
||||
(assoc prev-state :image-loaded? true)))))
|
||||
[{:keys [loader-opacity image-opacity]}]
|
||||
(reanimated/animate loader-opacity 0 loader-out)
|
||||
(reanimated/animate image-opacity 1 image-in))
|
||||
|
||||
(defn on-load-error
|
||||
[set-state]
|
||||
(js/setTimeout (fn []
|
||||
(set-state (fn [prev-state] (assoc prev-state :image-error? true))))
|
||||
error-wait-time))
|
||||
[set-error]
|
||||
(js/setTimeout set-error error-wait-time))
|
||||
|
||||
(defn- loading-image
|
||||
[{:keys [theme gradient-color-index loader-opacity aspect-ratio]}]
|
||||
[reanimated/view
|
||||
{:style (style/loading-image-with-opacity loader-opacity)}
|
||||
[reanimated/view {:style (style/loading-image-with-opacity loader-opacity)}
|
||||
[gradients/view
|
||||
{:theme theme
|
||||
:container-style (style/gradient-view aspect-ratio)
|
||||
@@ -67,62 +53,64 @@
|
||||
:style {:color (colors/theme-colors colors/neutral-40 colors/neutral-50 theme)}}
|
||||
label]])
|
||||
|
||||
(defn- collectible-image
|
||||
[{:keys [aspect-ratio theme gradient-color-index supported-file? set-error native-ID
|
||||
square? image-src on-collectible-load counter]}]
|
||||
(let [loader-opacity (reanimated/use-shared-value (if supported-file? 1 0))
|
||||
image-opacity (reanimated/use-shared-value (if supported-file? 0 1))]
|
||||
[:<>
|
||||
[loading-image
|
||||
{:aspect-ratio aspect-ratio
|
||||
:loader-opacity loader-opacity
|
||||
:theme theme
|
||||
:gradient-color-index gradient-color-index}]
|
||||
|
||||
[reanimated/view {:style (style/supported-file image-opacity)}
|
||||
[rn/image
|
||||
{:style (style/image square? aspect-ratio theme)
|
||||
:source image-src
|
||||
:native-ID native-ID
|
||||
:on-load-end (fn []
|
||||
(on-load-end {:loader-opacity loader-opacity
|
||||
:image-opacity image-opacity}))
|
||||
:on-error #(on-load-error set-error)
|
||||
:on-load on-collectible-load}]
|
||||
(when counter
|
||||
[counter-view counter])
|
||||
[rn/view {:style (style/collectible-border theme)}]]]))
|
||||
|
||||
(defn view-internal
|
||||
[{:keys [container-style square? on-press counter image-src native-ID supported-file?
|
||||
on-collectible-load aspect-ratio]}]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
loader-opacity (reanimated/use-shared-value
|
||||
(if supported-file? 1 0))
|
||||
image-opacity (reanimated/use-shared-value
|
||||
(if supported-file? 0 1))
|
||||
[load-time set-load-time] (rn/use-state (datetime/now))
|
||||
[state set-state] (rn/use-state {:image-loaded? false
|
||||
:image-error? (or (nil? image-src)
|
||||
(string/blank?
|
||||
image-src))})]
|
||||
on-collectible-load aspect-ratio gradient-color-index]
|
||||
:or {gradient-color-index :gradient-1
|
||||
on-collectible-load (fn [])}}]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
[error? set-error] (rn/use-state (or (nil? image-src)
|
||||
(string/blank? image-src)))]
|
||||
[rn/pressable
|
||||
{:on-press (when (and (not (:image-error? state)) supported-file?) on-press)
|
||||
{:style (merge container-style (style/container aspect-ratio))
|
||||
:accessibility-label :expanded-collectible
|
||||
:style (merge container-style
|
||||
(style/container aspect-ratio))}
|
||||
(cond
|
||||
(not supported-file?)
|
||||
:on-press (when (and (not error?) supported-file?)
|
||||
on-press)}
|
||||
(if (or (not supported-file?) error?)
|
||||
[fallback-view
|
||||
{:aspect-ratio aspect-ratio
|
||||
:label (i18n/label :t/unsupported-file)
|
||||
:counter counter
|
||||
:theme theme
|
||||
:on-mount on-collectible-load}]
|
||||
|
||||
(:image-error? state)
|
||||
[fallback-view
|
||||
{:label (i18n/label :t/cant-fetch-info)
|
||||
{:label (i18n/label (if-not supported-file?
|
||||
:t/unsupported-file
|
||||
:t/cant-fetch-info))
|
||||
:counter counter
|
||||
:theme theme
|
||||
:on-mount on-collectible-load}]
|
||||
|
||||
(not (:image-loaded? state))
|
||||
[loading-image
|
||||
[collectible-image
|
||||
{:aspect-ratio aspect-ratio
|
||||
:loader-opacity loader-opacity
|
||||
:theme theme
|
||||
:gradient-color-index :gradient-5}])
|
||||
(when supported-file?
|
||||
[reanimated/view {:style (style/supported-file image-opacity)}
|
||||
[rn/image
|
||||
{:style (style/image square? aspect-ratio theme)
|
||||
:source image-src
|
||||
:native-ID native-ID
|
||||
:on-load-start #(set-load-time (fn [start-time] (- (datetime/now) start-time)))
|
||||
:on-load-end #(on-load-end {:load-time load-time
|
||||
:set-state set-state
|
||||
:loader-opacity loader-opacity
|
||||
:image-opacity image-opacity})
|
||||
:on-error #(on-load-error set-state)
|
||||
:on-load on-collectible-load}]
|
||||
(when counter
|
||||
[counter-view counter])
|
||||
[rn/view {:style (style/collectible-border theme)}]])]))
|
||||
:supported-file? supported-file?
|
||||
:set-error set-error
|
||||
:native-ID native-ID
|
||||
:square? square?
|
||||
:image-src image-src
|
||||
:on-collectible-load on-collectible-load
|
||||
:counter counter
|
||||
:gradient-color-index gradient-color-index}])]))
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
@@ -137,7 +125,8 @@
|
||||
[:square? {:optional true} [:maybe boolean?]]
|
||||
[:counter {:optional true} [:maybe string?]]
|
||||
[:on-press {:optional true} [:maybe fn?]]
|
||||
[:on-collectible-load {:optional true} [:maybe fn?]]]]]
|
||||
[:on-collectible-load {:optional true} [:maybe fn?]]
|
||||
[:gradient-color-index {:optional true} [:maybe keyword?]]]]]
|
||||
:any])
|
||||
|
||||
(def view (schema/instrument #'view-internal ?schema))
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
(defn color
|
||||
[blur? theme]
|
||||
{:color (if blur?
|
||||
colors/white-opa-70
|
||||
colors/white-opa-40
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme))})
|
||||
|
||||
(defn label-dot
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[:type {:optional true}
|
||||
[:maybe
|
||||
[:enum :default :multiuser :group :channel :community :token :network :multinetwork :account
|
||||
:collectible :address :icon :audio :wallet-user]]]
|
||||
:collectible :address :icon :audio :wallet-user :dapp]]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||
[:container-style {:optional true} [:maybe :map]]
|
||||
[:blur? {:optional true} [:maybe :boolean]]
|
||||
|
||||
@@ -17,16 +17,18 @@
|
||||
[schema.core :as schema]))
|
||||
|
||||
(defn- tag-skeleton
|
||||
[{:keys [size text] :or {size 24}} logo-component]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[rn/view {:style (style/tag-container size)}
|
||||
logo-component
|
||||
[rn/view {:style (style/tag-spacing size)}
|
||||
[text/text
|
||||
{:style (style/text theme)
|
||||
:weight :medium
|
||||
:size (if (= size 24) :paragraph-2 :paragraph-1)}
|
||||
text]]]))
|
||||
[{:keys [size text theme]
|
||||
:or {size 24
|
||||
theme (quo.theme/use-theme)}}
|
||||
logo-component]
|
||||
[rn/view {:style (style/tag-container size)}
|
||||
logo-component
|
||||
[rn/view {:style (style/tag-spacing size)}
|
||||
[text/text
|
||||
{:style (style/text theme)
|
||||
:weight :medium
|
||||
:size (if (= size 24) :paragraph-2 :paragraph-1)}
|
||||
text]]])
|
||||
|
||||
(defn- communities-tag
|
||||
[{:keys [size community-logo community-name blur? channel? channel-name]}]
|
||||
@@ -81,95 +83,100 @@
|
||||
context]]]))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [type size state blur? customization-color profile-picture full-name users
|
||||
[{:keys [type theme size state blur? customization-color profile-picture full-name users
|
||||
group-name amount token network-logo network-name networks
|
||||
account-name emoji collectible collectible-name collectible-number duration container-style]
|
||||
account-name emoji collectible collectible-name collectible-number
|
||||
dapp-name dapp-logo duration container-style]
|
||||
:or {customization-color :blue
|
||||
type :default
|
||||
state :default}
|
||||
state :default
|
||||
theme (quo.theme/use-theme)}
|
||||
:as props}]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[rn/view {:style (merge {:align-items :flex-start} container-style)}
|
||||
[rn/view
|
||||
{:style (style/container {:theme theme
|
||||
:type type
|
||||
:size size
|
||||
:state state
|
||||
:blur? blur?
|
||||
:customization-color customization-color})
|
||||
:accessibility-label :context-tag}
|
||||
(case type
|
||||
:default
|
||||
[tag-skeleton {:theme theme :size size :text full-name}
|
||||
[user-avatar/user-avatar
|
||||
{:full-name full-name
|
||||
:profile-picture profile-picture
|
||||
:size (if (= size 24) :xxs 28)
|
||||
:status-indicator? false
|
||||
:ring? false
|
||||
:customization-color customization-color}]]
|
||||
[rn/view {:style (merge {:align-items :flex-start} container-style)}
|
||||
[rn/view
|
||||
{:style (style/container {:theme theme
|
||||
:type type
|
||||
:size size
|
||||
:state state
|
||||
:blur? blur?
|
||||
:customization-color customization-color})
|
||||
:accessibility-label :context-tag}
|
||||
(case type
|
||||
:default
|
||||
[tag-skeleton {:theme theme :size size :text full-name}
|
||||
[user-avatar/user-avatar
|
||||
{:full-name full-name
|
||||
:profile-picture profile-picture
|
||||
:size (if (= size 24) :xxs 28)
|
||||
:status-indicator? false
|
||||
:ring? false
|
||||
:customization-color customization-color}]]
|
||||
|
||||
:multiuser
|
||||
[preview-list/view {:type :user :size :size-20}
|
||||
users]
|
||||
:multiuser
|
||||
[preview-list/view {:type :user :size :size-20}
|
||||
users]
|
||||
|
||||
:multinetwork
|
||||
[preview-list/view {:type :network :size :size-20}
|
||||
networks]
|
||||
:multinetwork
|
||||
[preview-list/view {:type :network :size :size-20}
|
||||
networks]
|
||||
|
||||
:audio
|
||||
[tag-skeleton {:theme theme :text (str duration)}
|
||||
[rn/view {:style (style/audio-tag-icon-container customization-color theme)}
|
||||
[icons/icon :i/play {:color style/audio-tag-icon-color :size 12}]]]
|
||||
:audio
|
||||
[tag-skeleton {:theme theme :text (str duration)}
|
||||
[rn/view {:style (style/audio-tag-icon-container customization-color theme)}
|
||||
[icons/icon :i/play {:color style/audio-tag-icon-color :size 12}]]]
|
||||
|
||||
:group
|
||||
[tag-skeleton {:theme theme :size size :text group-name}
|
||||
[group-avatar/view
|
||||
{:icon-name :i/members
|
||||
:size (if (= size 24) :size-20 :size-28)
|
||||
:customization-color (colors/custom-color customization-color 50)}]]
|
||||
:group
|
||||
[tag-skeleton {:theme theme :size size :text group-name}
|
||||
[group-avatar/view
|
||||
{:icon-name :i/members
|
||||
:size (if (= size 24) :size-20 :size-28)
|
||||
:customization-color (colors/custom-color customization-color 50)}]]
|
||||
|
||||
(:channel :community)
|
||||
[communities-tag (assoc props :channel? (= type :channel))]
|
||||
(:channel :community)
|
||||
[communities-tag (assoc props :channel? (= type :channel))]
|
||||
|
||||
:token
|
||||
[tag-skeleton {:theme theme :size size :text (str amount " " token)}
|
||||
[token/view
|
||||
{:style (style/token-logo size)
|
||||
:token token
|
||||
:size (if (= size 24) :size-20 :size-28)}]]
|
||||
:token
|
||||
[tag-skeleton {:theme theme :size size :text (str amount " " token)}
|
||||
[token/view
|
||||
{:style (style/token-logo size)
|
||||
:token token
|
||||
:size (if (= size 24) :size-20 :size-28)}]]
|
||||
|
||||
:network
|
||||
[tag-skeleton {:theme theme :size size :text network-name}
|
||||
[rn/image {:style (style/circle-logo size) :source network-logo}]]
|
||||
:network
|
||||
[tag-skeleton {:theme theme :size size :text network-name}
|
||||
[rn/image {:style (style/circle-logo size) :source network-logo}]]
|
||||
|
||||
:collectible
|
||||
[tag-skeleton
|
||||
{:theme theme
|
||||
:size size
|
||||
:text (str collectible-name " #" collectible-number)}
|
||||
[rn/image {:style (style/rounded-logo size) :source collectible}]]
|
||||
:collectible
|
||||
[tag-skeleton
|
||||
{:theme theme
|
||||
:size size
|
||||
:text (str collectible-name " #" collectible-number)}
|
||||
[rn/image {:style (style/rounded-logo size) :source collectible}]]
|
||||
|
||||
:account
|
||||
[tag-skeleton {:theme theme :size size :text account-name}
|
||||
[account-avatar/view
|
||||
{:customization-color customization-color
|
||||
:emoji emoji
|
||||
:size (if (= size 24) 20 28)}]]
|
||||
:account
|
||||
[tag-skeleton {:theme theme :size size :text account-name}
|
||||
[account-avatar/view
|
||||
{:customization-color customization-color
|
||||
:emoji emoji
|
||||
:size (if (= size 24) 20 28)}]]
|
||||
|
||||
:address
|
||||
[address-tag props]
|
||||
:address
|
||||
[address-tag props]
|
||||
|
||||
:icon
|
||||
[icon-tag props]
|
||||
:icon
|
||||
[icon-tag props]
|
||||
|
||||
:wallet-user
|
||||
[tag-skeleton {:theme theme :size size :text full-name}
|
||||
[wallet-user-avatar/wallet-user-avatar
|
||||
{:full-name full-name
|
||||
:size (if (= size 24) :size-20 :size-24)
|
||||
:customization-color customization-color}]]
|
||||
:wallet-user
|
||||
[tag-skeleton {:theme theme :size size :text full-name}
|
||||
[wallet-user-avatar/wallet-user-avatar
|
||||
{:full-name full-name
|
||||
:size (if (= size 24) :size-20 :size-24)
|
||||
:customization-color customization-color}]]
|
||||
|
||||
nil)]]))
|
||||
:dapp
|
||||
[tag-skeleton {:theme theme :size size :text dapp-name}
|
||||
[rn/image {:style (style/circle-logo size) :source dapp-logo}]]
|
||||
|
||||
nil)]])
|
||||
|
||||
(def view (schema/instrument #'view-internal component-schema/?schema))
|
||||
|
||||
@@ -24,12 +24,13 @@
|
||||
(get ui k))
|
||||
|
||||
(def dapps
|
||||
{:coingecko (js/require "../resources/images/dapps/CoinGecko.png")
|
||||
:1inch (js/require "../resources/images/dapps/1inch.png")
|
||||
:aave (js/require "../resources/images/dapps/Aave.png")
|
||||
:uniswap (js/require "../resources/images/dapps/Uniswap.png")
|
||||
:zapper (js/require "../resources/images/dapps/Zapper.png")
|
||||
:zerion (js/require "../resources/images/dapps/Zerion.png")})
|
||||
{:coingecko (js/require "../resources/images/dapps/CoinGecko.png")
|
||||
:1inch (js/require "../resources/images/dapps/1inch.png")
|
||||
:aave (js/require "../resources/images/dapps/Aave.png")
|
||||
:uniswap (js/require "../resources/images/dapps/Uniswap.png")
|
||||
:zapper (js/require "../resources/images/dapps/Zapper.png")
|
||||
:zerion (js/require "../resources/images/dapps/Zerion.png")
|
||||
:wallet-connect (js/require "../resources/images/dapps/WalletConnect.png")})
|
||||
|
||||
(defn get-dapp
|
||||
[k]
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
(clj->js {:proposal proposal
|
||||
:supportedNamespaces supported-namespaces})))
|
||||
|
||||
;; Get an error from this list:
|
||||
;; https://github.com/WalletConnect/walletconnect-monorepo/blob/c6e9529418a0c81d4efcc6ac4e61f242a50b56c5/packages/utils/src/errors.ts
|
||||
(defn get-sdk-error
|
||||
[error-key]
|
||||
(getSdkError error-key))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
(ns status-im.common.floating-button-page.floating-container.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im.common.floating-button-page.floating-container.style :as style]))
|
||||
@@ -9,9 +10,10 @@
|
||||
[child]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[quo/blur
|
||||
{:blur-amount 12
|
||||
:blur-radius 12
|
||||
:blur-type theme}
|
||||
{:blur-amount 52
|
||||
:blur-radius 20
|
||||
:blur-type :transparent
|
||||
:blur-overlay-color (colors/theme-colors colors/white-70-blur colors/neutral-95-opa-70-blur theme)}
|
||||
[rn/view {:style style/blur-inner-container}
|
||||
child]]))
|
||||
|
||||
|
||||
@@ -35,7 +35,9 @@
|
||||
user-in-syncing-devices-screen? (or (= (:view-id db) :screen/onboarding.syncing-progress)
|
||||
(= (:view-id db) :screen/profile.profiles)
|
||||
(= (:view-id db) :screen/onboarding.syncing-progress-intro))
|
||||
user-in-sign-in-intro-screen? (= (:view-id db) :screen/onboarding.sign-in-intro)]
|
||||
user-in-sign-in-intro-screen? (= (:view-id db) :screen/onboarding.sign-in-intro)
|
||||
keystore-files-transfer-action? (= action
|
||||
constants/local-pairing-action-keystore-files-transfer)]
|
||||
(merge {:db (cond-> db
|
||||
connection-success?
|
||||
(assoc-in [:syncing :pairing-status] :connected)
|
||||
@@ -61,7 +63,7 @@
|
||||
(and completed-pairing? receiver?)
|
||||
{:dispatch [:profile.login/local-paired-user]}
|
||||
|
||||
(and error-on-pairing? (some? error))
|
||||
(and error-on-pairing? (some? error) (not keystore-files-transfer-action?))
|
||||
{:dispatch [:toasts/upsert
|
||||
{:type :negative
|
||||
:text error}]}))))
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
(goog-define ALCHEMY_OPTIMISM_GOERLI_TOKEN "")
|
||||
(goog-define ALCHEMY_OPTIMISM_SEPOLIA_TOKEN "")
|
||||
(goog-define WALLET_CONNECT_PROJECT_ID "87815d72a81d739d2a7ce15c2cfdefb3")
|
||||
(goog-define MIXPANEL_APP_ID "3350627")
|
||||
(goog-define MIXPANEL_TOKEN "5c73bda2d36a9f688a5ee45641fb6775")
|
||||
|
||||
(def mainnet-rpc-url (str "https://eth-archival.rpc.grove.city/v1/" POKT_TOKEN))
|
||||
(def goerli-rpc-url (str "https://goerli-archival.gateway.pokt.network/v1/lb/" POKT_TOKEN))
|
||||
@@ -39,6 +41,9 @@
|
||||
(def opensea-link "https://opensea.io")
|
||||
(def opensea-tesnet-link "https://testnets.opensea.io")
|
||||
|
||||
(def mixpanel-app-id MIXPANEL_APP_ID)
|
||||
(def mixpanel-token MIXPANEL_TOKEN)
|
||||
|
||||
(def opensea-api-key OPENSEA_API_KEY)
|
||||
(def bootnodes-settings-enabled? (enabled? (get-config :BOOTNODES_SETTINGS_ENABLED "1")))
|
||||
(def mailserver-confirmations-enabled? (enabled? (get-config :MAILSERVER_CONFIRMATIONS_ENABLED)))
|
||||
@@ -58,7 +63,6 @@
|
||||
(def quo-preview-enabled? (enabled? (get-config :ENABLE_QUO_PREVIEW "0")))
|
||||
(def database-management-enabled? (enabled? (get-config :DATABASE_MANAGEMENT_ENABLED "0")))
|
||||
(def debug-webview? (enabled? (get-config :DEBUG_WEBVIEW "0")))
|
||||
(def collectibles-enabled? (enabled? (get-config :COLLECTIBLES_ENABLED "1")))
|
||||
(def test-stateofus? (enabled? (get-config :TEST_STATEOFUS "0")))
|
||||
(def two-minutes-syncing? (enabled? (get-config :TWO_MINUTES_SYNCING "0")))
|
||||
(def swap-enabled? (enabled? (get-config :SWAP_ENABLED "0")))
|
||||
|
||||
@@ -281,6 +281,7 @@
|
||||
(def ^:const wallet-connect-supported-events #{"accountsChanged" "chainChanged"})
|
||||
(def ^:const wallet-connect-session-proposal-event "session_proposal")
|
||||
(def ^:const wallet-connect-session-request-event "session_request")
|
||||
(def ^:const wallet-connect-user-rejected-error-key "USER_REJECTED")
|
||||
|
||||
(def ^:const transaction-pending-type-wallet-connect-transfer "WalletConnectTransfer")
|
||||
|
||||
@@ -369,16 +370,18 @@
|
||||
(def ^:const local-pairing-role-receiver "receiver")
|
||||
|
||||
;; sender and receiver events
|
||||
(def ^:const local-pairing-event-peer-discovered "peer-discovered")
|
||||
(def ^:const local-pairing-event-connection-success "connection-success")
|
||||
(def ^:const local-pairing-event-connection-error "connection-error")
|
||||
(def ^:const local-pairing-event-transfer-success "transfer-success")
|
||||
(def ^:const local-pairing-event-transfer-error "transfer-error")
|
||||
(def ^:const local-pairing-event-received-installation "received-installation")
|
||||
|
||||
;; receiver events
|
||||
(def ^:const local-pairing-event-received-account "received-account")
|
||||
(def ^:const local-pairing-event-process-success "process-success")
|
||||
(def ^:const local-pairing-event-process-error "process-error")
|
||||
(def ^:const local-pairing-event-received-installation "received-installation")
|
||||
(def ^:const local-pairing-event-received-keystore-files "received-keystore-files")
|
||||
|
||||
(def ^:const local-pairing-event-errors
|
||||
#{local-pairing-event-connection-error
|
||||
@@ -389,6 +392,8 @@
|
||||
(def ^:const local-pairing-action-pairing-account 2)
|
||||
(def ^:const local-pairing-action-sync-device 3)
|
||||
(def ^:const local-pairing-action-pairing-installation 4)
|
||||
(def ^:const local-pairing-action-peer-discovery 5)
|
||||
(def ^:const local-pairing-action-keystore-files-transfer 6)
|
||||
|
||||
(def ^:const serialization-key
|
||||
"We pass this serialization key as a parameter to MultiformatSerializePublicKey
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
(ns status-im.contexts.centralized-metrics.effects
|
||||
(:require
|
||||
[native-module.core :as native-module]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/reg-fx :effects.centralized-metrics/toggle-metrics
|
||||
(fn [enabled?]
|
||||
(native-module/toggle-centralized-metrics enabled? #(log/debug "toggled-metrics" % enabled?))))
|
||||
@@ -0,0 +1,33 @@
|
||||
(ns status-im.contexts.centralized-metrics.events
|
||||
(:require
|
||||
[native-module.core :as native-module]
|
||||
[re-frame.interceptor :as interceptor]
|
||||
status-im.contexts.centralized-metrics.effects
|
||||
[status-im.contexts.centralized-metrics.tracking :as tracking]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn push-event?
|
||||
[db]
|
||||
(or (not (:centralized-metrics/user-confirmed? db))
|
||||
(:centralized-metrics/enabled? db)))
|
||||
|
||||
(defn centralized-metrics-interceptor
|
||||
[context]
|
||||
(when-let [event (tracking/tracked-event (interceptor/get-coeffect context :event))]
|
||||
(log/debug "tracking event" event)
|
||||
(when (push-event? (interceptor/get-coeffect context :db))
|
||||
(native-module/add-centralized-metric event)))
|
||||
context)
|
||||
|
||||
(def interceptor
|
||||
(interceptor/->interceptor
|
||||
:id :centralized-metrics
|
||||
:after centralized-metrics-interceptor))
|
||||
|
||||
(rf/reg-event-fx :centralized-metrics/toggle-centralized-metrics
|
||||
(fn [{:keys [db]} [enabled?]]
|
||||
{:fx [[:effects.centralized-metrics/toggle-metrics enabled?]]
|
||||
:db (assoc db
|
||||
:centralized-metrics/user-confirmed? true
|
||||
:centralized-metrics/enabled? enabled?)}))
|
||||
@@ -0,0 +1,37 @@
|
||||
(ns status-im.contexts.centralized-metrics.events-test
|
||||
(:require
|
||||
[cljs.test :refer-macros [deftest is testing]]
|
||||
matcher-combinators.test
|
||||
[status-im.contexts.centralized-metrics.events :as events]
|
||||
[status-im.contexts.centralized-metrics.tracking :as tracking]
|
||||
[test-helpers.unit :as h]))
|
||||
|
||||
(deftest push-event-test
|
||||
(testing "returns correct boolean value"
|
||||
(is (true? (events/push-event? {:centralized-metrics/user-confirmed? false})))
|
||||
(is (true? (events/push-event? {:centralized-metrics/enabled? true})))
|
||||
(is (false? (events/push-event? {:centralized-metrics/user-confirmed? true
|
||||
:centralized-metrics/enabled? false})))))
|
||||
|
||||
(deftest centralized-metrics-interceptor-test
|
||||
(testing "processes context correctly"
|
||||
(with-redefs [tracking/tracked-event (fn [_] {:metric "mocked-event"})
|
||||
events/push-event? (fn [_] true)]
|
||||
(let [context {:coeffects {:event [:some-event]
|
||||
:db {:centralized-metrics/enabled? true}}}]
|
||||
(is (= context (events/centralized-metrics-interceptor context)))))))
|
||||
|
||||
(h/deftest-event :centralized-metrics/toggle-centralized-metrics
|
||||
[event-id dispatch]
|
||||
(testing "toggling value to true"
|
||||
(let [enabled? true
|
||||
expected-fxs {:db {:centralized-metrics/user-confirmed? true
|
||||
:centralized-metrics/enabled? enabled?}
|
||||
:fx [[:effects.centralized-metrics/toggle-metrics enabled?]]}]
|
||||
(is (match? expected-fxs (dispatch [event-id enabled?])))))
|
||||
(testing "toggling value to false"
|
||||
(let [enabled? false
|
||||
expected-fxs {:db {:centralized-metrics/user-confirmed? true
|
||||
:centralized-metrics/enabled? enabled?}
|
||||
:fx [[:effects.centralized-metrics/toggle-metrics enabled?]]}]
|
||||
(is (match? expected-fxs (dispatch [event-id enabled?]))))))
|
||||
@@ -0,0 +1,40 @@
|
||||
(ns status-im.contexts.centralized-metrics.tracking
|
||||
(:require
|
||||
[legacy.status-im.utils.build :as build]
|
||||
[react-native.platform :as platform]))
|
||||
|
||||
(defn user-journey-event
|
||||
[action]
|
||||
{:metric
|
||||
{:eventName "user-journey"
|
||||
:platform platform/os
|
||||
:appVersion build/app-short-version
|
||||
:eventValue {:action action}}})
|
||||
|
||||
(def ^:const app-started-event "app-started")
|
||||
(def ^:const navigate-to-create-profile-event "navigate-to-create-profile")
|
||||
(def ^:const communities-tab-clicked "communities-tab-clicked")
|
||||
(def ^:const wallet-tab-clicked "wallet-tab-clicked")
|
||||
(def ^:const chats-tab-clicked "chats-tab-clicked")
|
||||
|
||||
(defn track-view-id-event
|
||||
[view-id]
|
||||
(case view-id
|
||||
:communities-stack (user-journey-event communities-tab-clicked)
|
||||
:chats-stack (user-journey-event chats-tab-clicked)
|
||||
:wallet-stack (user-journey-event wallet-tab-clicked)
|
||||
nil))
|
||||
|
||||
(defn tracked-event
|
||||
[[event-name second-parameter]]
|
||||
(case event-name
|
||||
:onboarding/navigate-to-create-profile
|
||||
(user-journey-event navigate-to-create-profile-event)
|
||||
|
||||
:profile/get-profiles-overview-success
|
||||
(user-journey-event app-started-event)
|
||||
|
||||
:set-view-id
|
||||
(track-view-id-event second-parameter)
|
||||
|
||||
nil))
|
||||
@@ -0,0 +1,35 @@
|
||||
(ns status-im.contexts.centralized-metrics.tracking-test
|
||||
(:require
|
||||
[cljs.test :refer-macros [deftest is testing]]
|
||||
[legacy.status-im.utils.build :as build]
|
||||
[react-native.platform :as platform]
|
||||
[status-im.contexts.centralized-metrics.tracking :as tracking]))
|
||||
|
||||
(deftest user-journey-event-test
|
||||
(testing "creates correct metric event"
|
||||
(let [action "some-action"
|
||||
expected {:metric {:eventName "user-journey"
|
||||
:platform platform/os
|
||||
:appVersion build/app-short-version
|
||||
:eventValue {:action action}}}]
|
||||
(is (= expected (tracking/user-journey-event action))))))
|
||||
|
||||
(deftest track-view-id-event-test
|
||||
(testing "returns correct event for view-id"
|
||||
(is (= (tracking/user-journey-event tracking/communities-tab-clicked)
|
||||
(tracking/track-view-id-event :communities-stack)))
|
||||
(is (= (tracking/user-journey-event tracking/chats-tab-clicked)
|
||||
(tracking/track-view-id-event :chats-stack)))
|
||||
(is (= (tracking/user-journey-event tracking/wallet-tab-clicked)
|
||||
(tracking/track-view-id-event :wallet-stack)))
|
||||
(is (nil? (tracking/track-view-id-event :unknown-stack)))))
|
||||
|
||||
(deftest tracked-event-test
|
||||
(testing "returns correct event for given inputs"
|
||||
(is (= (tracking/user-journey-event tracking/navigate-to-create-profile-event)
|
||||
(tracking/tracked-event [:onboarding/navigate-to-create-profile])))
|
||||
(is (= (tracking/user-journey-event tracking/app-started-event)
|
||||
(tracking/tracked-event [:profile/get-profiles-overview-success])))
|
||||
(is (= (tracking/track-view-id-event :wallet-stack)
|
||||
(tracking/tracked-event [:set-view-id :wallet-stack])))
|
||||
(is (nil? (tracking/tracked-event [:unknown-event])))))
|
||||
@@ -139,6 +139,7 @@
|
||||
[id token-gated? intro-message]
|
||||
[[(when-not token-gated? (view-members id))
|
||||
(when-not token-gated? (view-rules id intro-message))
|
||||
(mark-as-read id)
|
||||
(invite-contacts id)
|
||||
(when token-gated? (view-token-gating id))
|
||||
(show-qr id)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.common.scroll-page.view :as scroll-page]
|
||||
[status-im.config :as config]
|
||||
[status-im.contexts.communities.actions.community-options.view :as options]
|
||||
[status-im.contexts.communities.discover.style :as style]
|
||||
[status-im.feature-flags :as ff]
|
||||
@@ -76,12 +77,14 @@
|
||||
:data [{:id :all
|
||||
:label (i18n/label :t/all)
|
||||
:accessibility-label :all-communities-tab}
|
||||
{:id :open
|
||||
:label (i18n/label :t/open)
|
||||
:accessibility-label :open-communities-tab}
|
||||
{:id :gated
|
||||
:label (i18n/label :t/gated)
|
||||
:accessibility-label :gated-communities-tab}]}]])
|
||||
(when config/show-not-implemented-features?
|
||||
{:id :open
|
||||
:label (i18n/label :t/open)
|
||||
:accessibility-label :open-communities-tab})
|
||||
(when config/show-not-implemented-features?
|
||||
{:id :gated
|
||||
:label (i18n/label :t/gated)
|
||||
:accessibility-label :gated-communities-tab})]}]])
|
||||
|
||||
(defn loading-community-item
|
||||
[_ _ _ {:keys [width]}]
|
||||
|
||||
@@ -343,7 +343,7 @@
|
||||
(when (get-in db [:communities community-id :joined])
|
||||
[:dispatch
|
||||
[:activity-center.notifications/dismiss-community-overview community-id]])]}
|
||||
(when-not (or (= current-view-id :shell) (= current-view-id :communities-stack))
|
||||
(when-not (#{:shell :communities-stack :discover-communities} current-view-id)
|
||||
(navigation/pop-to-root :shell-stack))))))
|
||||
|
||||
(rf/reg-event-fx :communities/navigate-to-community-overview navigate-to-community-overview)
|
||||
|
||||
@@ -72,10 +72,7 @@
|
||||
(let [insets (safe-area/get-insets)]
|
||||
[rn/view {:style (style/page-container insets)}
|
||||
[rn/view {:style style/page-heading}
|
||||
[quo/page-nav
|
||||
{:background :blur
|
||||
:icon-name :i/arrow-left
|
||||
:on-press #(rf/dispatch [:navigate-back])}]
|
||||
[quo/page-nav {:type :no-title :background :blur}]
|
||||
[page-title]]
|
||||
[enable-notifications-simple]
|
||||
[enable-notification-buttons {:insets insets}]]))
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
:onboarding/navigated-to-enter-seed-phrase-from-screen
|
||||
:screen/onboarding.new-to-status)]]
|
||||
:dispatch-later [{:ms constants/onboarding-generating-keys-animation-duration-ms
|
||||
:dispatch [:onboarding/navigate-to-identifiers]}]
|
||||
:dispatch [:init-root :screen/onboarding.enable-notifications]}]
|
||||
:db (-> db
|
||||
(dissoc :profile/login)
|
||||
(dissoc :auth-method)
|
||||
|
||||
@@ -28,21 +28,20 @@
|
||||
(defn create
|
||||
[]
|
||||
(let [log-enabled? (boolean (not-empty config/log-level))]
|
||||
(merge (login)
|
||||
{:deviceName (native-module/get-installation-name)
|
||||
:rootDataDir (native-module/backup-disabled-data-dir)
|
||||
:rootKeystoreDir (native-module/keystore-dir)
|
||||
|
||||
:logLevel (when log-enabled? config/log-level)
|
||||
:logEnabled log-enabled?
|
||||
:logFilePath (native-module/log-file-directory)
|
||||
:verifyTransactionURL config/verify-transaction-url
|
||||
:verifyENSURL config/verify-ens-url
|
||||
:verifyENSContractAddress config/verify-ens-contract-address
|
||||
:verifyTransactionChainID config/verify-transaction-chain-id
|
||||
:wakuV2LightClient false
|
||||
:previewPrivacy config/blank-preview?
|
||||
:testNetworksEnabled config/test-networks-enabled?})))
|
||||
(assoc (login)
|
||||
:deviceName (native-module/get-installation-name)
|
||||
:rootDataDir (native-module/backup-disabled-data-dir)
|
||||
:rootKeystoreDir (native-module/keystore-dir)
|
||||
:logLevel (when log-enabled? config/log-level)
|
||||
:logEnabled log-enabled?
|
||||
:logFilePath (native-module/log-file-directory)
|
||||
:verifyTransactionURL config/verify-transaction-url
|
||||
:verifyENSURL config/verify-ens-url
|
||||
:verifyENSContractAddress config/verify-ens-contract-address
|
||||
:verifyTransactionChainID config/verify-transaction-chain-id
|
||||
:wakuV2LightClient true
|
||||
:previewPrivacy config/blank-preview?
|
||||
:testNetworksEnabled config/test-networks-enabled?)))
|
||||
|
||||
(defn strip-file-prefix
|
||||
[path]
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
(ns status-im.contexts.profile.events
|
||||
(:require
|
||||
[legacy.status-im.data-store.settings :as data-store.settings]
|
||||
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[native-module.core :as native-module]
|
||||
[status-im.config :as config]
|
||||
[status-im.contexts.profile.edit.accent-colour.events]
|
||||
[status-im.contexts.profile.edit.bio.events]
|
||||
[status-im.contexts.profile.edit.header.events]
|
||||
@@ -27,7 +29,10 @@
|
||||
(rf/reg-fx
|
||||
:profile/get-profiles-overview
|
||||
(fn [callback]
|
||||
(native-module/open-accounts callback)))
|
||||
(native-module/initialize-application {:dataDir (native-module/backup-disabled-data-dir)
|
||||
:mixpanelAppId config/mixpanel-app-id
|
||||
:mixpanelToken config/mixpanel-token}
|
||||
callback)))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:profile/profile-selected
|
||||
@@ -36,23 +41,27 @@
|
||||
|
||||
(rf/reg-event-fx
|
||||
:profile/get-profiles-overview-success
|
||||
(fn [{:keys [db]} [profiles-overview]]
|
||||
(if (seq profiles-overview)
|
||||
(let [profiles (reduce-profiles profiles-overview)
|
||||
{:keys [key-uid]} (first (sort-by :timestamp > (vals profiles)))]
|
||||
{:db (if key-uid
|
||||
(-> db
|
||||
(assoc :profile/profiles-overview profiles)
|
||||
(update :profile/login #(select-profile % key-uid)))
|
||||
db)
|
||||
:fx [[:dispatch [:init-root :screen/profile.profiles]]
|
||||
(when key-uid
|
||||
[:effects.biometric/check-if-available
|
||||
{:key-uid key-uid
|
||||
:on-success (fn [auth-method]
|
||||
(rf/dispatch [:profile.login/check-biometric-success key-uid
|
||||
auth-method]))}])]})
|
||||
{:fx [[:dispatch [:init-root :screen/onboarding.intro]]]})))
|
||||
(fn [{:keys [db]} [{:keys [accounts] {:keys [userConfirmed enabled]} :centralizedMetricsInfo}]]
|
||||
(let [db-with-settings (assoc db
|
||||
:centralized-metrics/user-confirmed? userConfirmed
|
||||
:centralized-metrics/enabled? enabled)]
|
||||
(if (seq accounts)
|
||||
(let [profiles (reduce-profiles accounts)
|
||||
{:keys [key-uid]} (first (sort-by :timestamp > (vals profiles)))]
|
||||
{:db (if key-uid
|
||||
(-> db-with-settings
|
||||
(assoc :profile/profiles-overview profiles)
|
||||
(update :profile/login #(select-profile % key-uid)))
|
||||
db-with-settings)
|
||||
:fx [[:dispatch [:init-root :screen/profile.profiles]]
|
||||
(when key-uid
|
||||
[:effects.biometric/check-if-available
|
||||
{:key-uid key-uid
|
||||
:on-success (fn [auth-method]
|
||||
(rf/dispatch [:profile.login/check-biometric-success key-uid
|
||||
auth-method]))}])]})
|
||||
{:db db-with-settings
|
||||
:fx [[:dispatch [:init-root :screen/onboarding.intro]]]}))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:profile/update-setting-from-backup
|
||||
@@ -65,3 +74,11 @@
|
||||
:profile/update-profile-from-backup
|
||||
(fn [_ [{{:keys [ensUsernameDetails]} :backedUpProfile}]]
|
||||
{:fx [[:dispatch [:ens/update-usernames ensUsernameDetails]]]}))
|
||||
|
||||
(rf/reg-event-fx :profile/update-messages-from-contacts-only
|
||||
(fn [{:keys [db] :as cofx}]
|
||||
(multiaccounts.update/multiaccount-update
|
||||
cofx
|
||||
:messages-from-contacts-only
|
||||
(not (get-in db [:profile/profile :messages-from-contacts-only]))
|
||||
{})))
|
||||
|
||||
@@ -83,8 +83,7 @@
|
||||
[[:profile.settings/switch-theme-fx
|
||||
[(or (:appearance settings)
|
||||
constants/theme-type-dark)
|
||||
:shell-stack
|
||||
false]]
|
||||
:shell-stack]]
|
||||
[:dispatch [:init-root :shell-stack]]
|
||||
[:dispatch [:profile/show-testnet-mode-banner-if-enabled]]]))})))
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
[react-native.platform :as platform]
|
||||
[status-im.common.theme.core :as theme]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.setup.hot-reload :as hot-reload]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(re-frame/reg-fx
|
||||
@@ -20,7 +19,7 @@
|
||||
|
||||
(re-frame/reg-fx
|
||||
:profile.settings/switch-theme-fx
|
||||
(fn [[theme-type view-id reload-ui?]]
|
||||
(fn [[theme-type view-id]]
|
||||
(let [theme (if (or (= theme-type constants/theme-type-dark)
|
||||
(and (= theme-type constants/theme-type-system)
|
||||
(theme/device-theme-dark?)))
|
||||
@@ -28,8 +27,4 @@
|
||||
:light)]
|
||||
(theme/set-legacy-theme theme)
|
||||
(rf/dispatch [:theme/switch theme])
|
||||
(rf/dispatch [:reload-status-nav-color view-id])
|
||||
(when reload-ui?
|
||||
(re-frame/dispatch [:dismiss-all-overlays])
|
||||
(when js/goog.DEBUG
|
||||
(hot-reload/reload))))))
|
||||
(rf/dispatch [:reload-status-nav-color view-id]))))
|
||||
|
||||
@@ -95,14 +95,14 @@
|
||||
(rf/reg-event-fx :profile.settings/change-appearance
|
||||
(fn [_ [theme]]
|
||||
{:fx [[:dispatch [:profile.settings/profile-update :appearance theme]]
|
||||
[:profile.settings/switch-theme-fx [theme :appearance true]]]}))
|
||||
[:profile.settings/switch-theme-fx [theme :appearance]]]}))
|
||||
|
||||
(rf/reg-event-fx :profile.settings/switch-theme
|
||||
(fn [{:keys [db]} [theme view-id]]
|
||||
(let [theme (or theme
|
||||
(get-in db [:profile/profile :appearance])
|
||||
constants/theme-type-dark)]
|
||||
{:fx [[:profile.settings/switch-theme-fx [theme view-id false]]]})))
|
||||
{:fx [[:profile.settings/switch-theme-fx [theme view-id]]]})))
|
||||
|
||||
(rf/reg-fx :profile.settings/get-profile-picture
|
||||
(fn [key-uid]
|
||||
|
||||
@@ -61,13 +61,12 @@
|
||||
:image :icon
|
||||
:blur? true
|
||||
:action :arrow})]
|
||||
[(when config/show-not-implemented-features?
|
||||
{:title (i18n/label :t/privacy-and-security)
|
||||
:on-press #(rf/dispatch [:open-modal :screen/settings-privacy-and-security])
|
||||
:image-props :i/privacy
|
||||
:image :icon
|
||||
:blur? true
|
||||
:action :arrow})
|
||||
[{:title (i18n/label :t/privacy-and-security)
|
||||
:on-press #(rf/dispatch [:open-modal :screen/settings-privacy-and-security])
|
||||
:image-props :i/privacy
|
||||
:image :icon
|
||||
:blur? true
|
||||
:action :arrow}
|
||||
{:title (i18n/label :t/syncing)
|
||||
:on-press #(rf/dispatch [:open-modal :settings-syncing])
|
||||
:image-props :i/syncing
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
(ns status-im.contexts.profile.settings.screens.messages.view
|
||||
(:require [quo.core :as quo]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- navigate-back
|
||||
[]
|
||||
(rf/dispatch [:navigate-back]))
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.navigation :as navigation]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- open-blocked-users
|
||||
[]
|
||||
@@ -13,17 +12,27 @@
|
||||
|
||||
(defn view
|
||||
[]
|
||||
[quo/overlay {:type :shell :top-inset? true}
|
||||
[quo/page-nav
|
||||
{:background :blur
|
||||
:icon-name :i/arrow-left
|
||||
:on-press navigate-back}]
|
||||
[quo/page-top {:title (i18n/label :t/messages)}]
|
||||
[quo/category
|
||||
{:label (i18n/label :t/contacts)
|
||||
:data [{:title (i18n/label :t/blocked-users)
|
||||
:on-press open-blocked-users
|
||||
:blur? true
|
||||
:action :arrow}]
|
||||
:blur? true
|
||||
:list-type :settings}]])
|
||||
(let [allow-new-contact-requests? (rf/sub [:profile/allow-new-contact-requests?])
|
||||
toggle-allow-new-contact-requests (rn/use-callback
|
||||
(fn []
|
||||
(rf/dispatch [:profile/update-messages-from-contacts-only]))
|
||||
[allow-new-contact-requests?])]
|
||||
[quo/overlay {:type :shell :top-inset? true}
|
||||
[quo/page-nav
|
||||
{:background :blur
|
||||
:icon-name :i/arrow-left
|
||||
:on-press navigation/navigate-back}]
|
||||
[quo/page-top {:title (i18n/label :t/messages)}]
|
||||
[quo/category
|
||||
{:label (i18n/label :t/contacts)
|
||||
:data [{:title (i18n/label :t/allow-new-contact-requests)
|
||||
:blur? true
|
||||
:action :selector
|
||||
:action-props {:on-change toggle-allow-new-contact-requests
|
||||
:checked? allow-new-contact-requests?}}
|
||||
{:title (i18n/label :t/blocked-users)
|
||||
:on-press open-blocked-users
|
||||
:blur? true
|
||||
:action :arrow}]
|
||||
:blur? true
|
||||
:list-type :settings}]]))
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
profile)}}])}]}]]
|
||||
[rn/flat-list
|
||||
{:header [settings.header/view {:scroll-y scroll-y}]
|
||||
:data (settings.items/items (boolean (:mnemonic profile)))
|
||||
:data (settings.items/items (boolean (seq (:mnemonic profile))))
|
||||
:shows-vertical-scroll-indicator false
|
||||
:render-fn settings-category-view
|
||||
:get-item-layout get-item-layout
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
(ns status-im.contexts.settings.privacy-and-security.profile-picture.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.theme]
|
||||
[status-im.constants :as constants]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def pictures-visibility->label
|
||||
{constants/profile-pictures-visibility-everyone (i18n/label :t/everyone)
|
||||
constants/profile-pictures-visibility-contacts-only (i18n/label :t/contacts)
|
||||
constants/profile-pictures-visibility-none (i18n/label :t/no-one)})
|
||||
|
||||
(def pictures-show-to->label
|
||||
{constants/profile-pictures-show-to-everyone (i18n/label :t/everyone)
|
||||
constants/profile-pictures-show-to-contacts-only (i18n/label :t/contacts)
|
||||
constants/profile-pictures-show-to-none (i18n/label :t/no-one)})
|
||||
|
||||
(defn- update-profile
|
||||
[k v]
|
||||
(rf/dispatch [:profile.settings/profile-update k v])
|
||||
(rf/dispatch [:hide-bottom-sheet]))
|
||||
|
||||
(defn- update-pictures-visibility-everyone
|
||||
[]
|
||||
(update-profile :profile-pictures-visibility constants/profile-pictures-visibility-everyone))
|
||||
|
||||
(defn- update-pictures-visibility-contacts-only
|
||||
[]
|
||||
(update-profile :profile-pictures-visibility constants/profile-pictures-visibility-contacts-only))
|
||||
|
||||
(defn- update-pictures-visibility-nobody
|
||||
[]
|
||||
(update-profile :profile-pictures-visibility constants/profile-pictures-visibility-none))
|
||||
|
||||
(defn- update-pictures-show-to-everyone
|
||||
[]
|
||||
(update-profile :profile-pictures-show-to constants/profile-pictures-show-to-everyone))
|
||||
|
||||
(defn- update-pictures-show-to-contacts-only
|
||||
[]
|
||||
(update-profile :profile-pictures-show-to constants/profile-pictures-show-to-contacts-only))
|
||||
|
||||
(defn- update-pictures-show-to-nobody
|
||||
[]
|
||||
(update-profile :profile-pictures-show-to constants/profile-pictures-show-to-none))
|
||||
|
||||
(defn options-for-profile-pictures-visibility
|
||||
[setting]
|
||||
(let [customization-color (rf/sub [:profile/customization-color])]
|
||||
[:<>
|
||||
[quo/drawer-top {:title (i18n/label :t/show-profile-pictures)}]
|
||||
[quo/action-drawer
|
||||
[[{:icon :i/globe
|
||||
:accessibility-label :see-profile-pictures-from-everyone
|
||||
:label (i18n/label :t/everyone)
|
||||
:on-press update-pictures-visibility-everyone
|
||||
:state (when (= constants/profile-pictures-visibility-everyone setting)
|
||||
:selected)}
|
||||
{:icon :i/contact
|
||||
:icon-color customization-color
|
||||
:accessibility-label :see-profile-pictures-from-contacts
|
||||
:label (i18n/label :t/contacts)
|
||||
:on-press update-pictures-visibility-contacts-only
|
||||
:state (when (= constants/profile-pictures-visibility-contacts-only setting)
|
||||
:selected)}
|
||||
{:icon :i/hide
|
||||
:accessibility-label :see-profile-pictures-from-nobody
|
||||
:label (i18n/label :t/no-one)
|
||||
:add-divider? true
|
||||
:on-press update-pictures-visibility-nobody
|
||||
:state (when (= constants/profile-pictures-visibility-none setting)
|
||||
:selected)}]]]]))
|
||||
|
||||
(defn options-for-profile-pictures-show-to
|
||||
[setting]
|
||||
(let [customization-color (rf/sub [:profile/customization-color])]
|
||||
[:<>
|
||||
[quo/drawer-top {:title (i18n/label :t/show-profile-pictures-to)}]
|
||||
[quo/action-drawer
|
||||
[[{:icon :i/globe
|
||||
:accessibility-label :show-profile-pictures-to-everyone
|
||||
:label (i18n/label :t/everyone)
|
||||
:on-press update-pictures-show-to-everyone
|
||||
:state (when (= constants/profile-pictures-show-to-everyone setting)
|
||||
:selected)}
|
||||
{:icon :i/contact
|
||||
:icon-color customization-color
|
||||
:accessibility-label :show-profile-pictures-to-contacts
|
||||
:label (i18n/label :t/contacts)
|
||||
:on-press update-pictures-show-to-contacts-only
|
||||
:state (when (= constants/profile-pictures-show-to-contacts-only setting)
|
||||
:selected)}
|
||||
{:icon :i/hide
|
||||
:accessibility-label :show-profile-pictures-to-nobody
|
||||
:label (i18n/label :t/no-one)
|
||||
:on-press update-pictures-show-to-nobody
|
||||
:state (when (= constants/profile-pictures-show-to-none setting)
|
||||
:selected)
|
||||
:add-divider? true}]]]]))
|
||||
|
||||
(defn setting-profile-pictures-visibility
|
||||
[pictures-visibility on-press]
|
||||
{:title (i18n/label :t/show-profile-pictures)
|
||||
:description :text
|
||||
:description-props {:text (pictures-visibility->label pictures-visibility)}
|
||||
:blur? true
|
||||
:action :arrow
|
||||
:on-press on-press})
|
||||
|
||||
(defn setting-profile-pictures-show-to
|
||||
[pictures-show-to on-press]
|
||||
{:title (i18n/label :t/show-profile-pictures-to)
|
||||
:description :text
|
||||
:description-props {:text (pictures-show-to->label pictures-show-to)}
|
||||
:blur? true
|
||||
:action :arrow
|
||||
:on-press on-press})
|
||||
@@ -2,19 +2,65 @@
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im.contexts.settings.privacy-and-security.profile-picture.view :as profile-picture.view]
|
||||
[status-im.contexts.settings.privacy-and-security.style :as style]
|
||||
[status-im.feature-flags :as ff]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.navigation :as navigation]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn navigate-back
|
||||
[]
|
||||
(rf/dispatch [:navigate-back]))
|
||||
(defn- setting-preview-privacy
|
||||
[preview-privacy? customization-color on-change]
|
||||
{:title (i18n/label (if platform/android?
|
||||
:t/hide-content-when-switching-apps
|
||||
:t/hide-content-when-switching-apps-ios))
|
||||
:blur? true
|
||||
:action :selector
|
||||
:action-props {:on-change on-change
|
||||
:checked? preview-privacy?
|
||||
:id :preview-privacy
|
||||
:customization-color customization-color}})
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [insets (safe-area/get-insets)
|
||||
customization-color (rf/sub [:profile/customization-color])]
|
||||
(let [insets (safe-area/get-insets)
|
||||
centralized-metrics-enabled? (rf/sub [:centralized-metrics/enabled?])
|
||||
customization-color (rf/sub [:profile/customization-color])
|
||||
|
||||
preview-privacy? (rf/sub [:profile/preview-privacy?])
|
||||
see-profile-pictures-from (rf/sub [:profile/pictures-visibility])
|
||||
show-profile-pictures-to (rf/sub [:multiaccount/profile-pictures-show-to])
|
||||
|
||||
toggle-preview-privacy
|
||||
(rn/use-callback (fn []
|
||||
(rf/dispatch [:profile.settings/change-preview-privacy
|
||||
(not preview-privacy?)]))
|
||||
[preview-privacy?])
|
||||
|
||||
open-see-profile-pictures-from-options
|
||||
(rn/use-callback (fn []
|
||||
(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:theme :dark
|
||||
:blur? true
|
||||
:content (fn []
|
||||
[profile-picture.view/options-for-profile-pictures-visibility
|
||||
see-profile-pictures-from])}]))
|
||||
[see-profile-pictures-from])
|
||||
|
||||
open-show-profile-pictures-to-options
|
||||
(rn/use-callback (fn []
|
||||
(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:theme :dark
|
||||
:blur? true
|
||||
:content (fn []
|
||||
[profile-picture.view/options-for-profile-pictures-show-to
|
||||
show-profile-pictures-to])}]))
|
||||
[show-profile-pictures-to])]
|
||||
[quo/overlay
|
||||
{:type :shell
|
||||
:container-style (style/page-wrapper (:top insets))}
|
||||
@@ -22,7 +68,7 @@
|
||||
{:key :header
|
||||
:background :blur
|
||||
:icon-name :i/arrow-left
|
||||
:on-press navigate-back}]
|
||||
:on-press navigation/navigate-back}]
|
||||
[quo/standard-title
|
||||
{:title (i18n/label :t/privacy-and-security)
|
||||
:container-style style/title-container
|
||||
@@ -30,13 +76,22 @@
|
||||
:customization-color customization-color}]
|
||||
[quo/category
|
||||
{:key :category
|
||||
:data [{:title "Dummy"
|
||||
:image-props :i/placeholder
|
||||
:image :icon
|
||||
:data [(when (ff/enabled? ::ff/profile-pictures-visibility)
|
||||
(profile-picture.view/setting-profile-pictures-visibility
|
||||
see-profile-pictures-from
|
||||
open-see-profile-pictures-from-options))
|
||||
(when (ff/enabled? ::ff/profile-pictures-visibility)
|
||||
(profile-picture.view/setting-profile-pictures-show-to
|
||||
show-profile-pictures-to
|
||||
open-show-profile-pictures-to-options))
|
||||
(setting-preview-privacy preview-privacy? customization-color toggle-preview-privacy)
|
||||
{:title (i18n/label :t/share-usage-data)
|
||||
:blur? true
|
||||
:action :selector
|
||||
:action-props {:on-change identity
|
||||
:checked? false}
|
||||
:on-press identity}]
|
||||
:action-props {:on-change #(rf/dispatch
|
||||
[:centralized-metrics/toggle-centralized-metrics
|
||||
(not centralized-metrics-enabled?)])
|
||||
:customization-color customization-color
|
||||
:checked? centralized-metrics-enabled?}}]
|
||||
:blur? true
|
||||
:list-type :settings}]]))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns status-im.contexts.settings.wallet.events
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[native-module.core :as native-module]
|
||||
[status-im.contexts.settings.wallet.data-store :as data-store]
|
||||
[taoensso.timbre :as log]
|
||||
@@ -91,7 +92,37 @@
|
||||
|
||||
(rf/reg-event-fx :wallet/make-keypairs-accounts-fully-operable make-keypairs-accounts-fully-operable)
|
||||
|
||||
(defn connection-string-for-import-keypair
|
||||
|
||||
(rf/reg-event-fx :wallet/connection-string-for-import-keypairs-failed
|
||||
(fn [{:keys [db]} [keypairs-key-uids error]]
|
||||
(let [error-message (-> error ex-data :error)
|
||||
incorrect-keypair? (string/includes?
|
||||
error-message
|
||||
"one or more expected keystore files are not found among the sent files")
|
||||
single-keypair-to-update? (= (count keypairs-key-uids) 1)
|
||||
keypair-name (when single-keypair-to-update?
|
||||
(let [key-uid (first keypairs-key-uids)]
|
||||
(get-in db [:wallet :keypairs key-uid :name])))
|
||||
toast-message (cond
|
||||
(and single-keypair-to-update? incorrect-keypair?)
|
||||
(i18n/label
|
||||
:t/this-qr-does-not-contain-key-pair
|
||||
{:name keypair-name})
|
||||
|
||||
(and (not single-keypair-to-update?) incorrect-keypair?)
|
||||
(i18n/label
|
||||
:t/this-qr-does-not-contain-any-missing-key-pair)
|
||||
|
||||
:else
|
||||
error-message)]
|
||||
(log/error "failed to import missing key pairs with connection string"
|
||||
{:error error-message})
|
||||
(rf/dispatch [:toasts/upsert
|
||||
{:type :negative
|
||||
:theme :dark
|
||||
:text toast-message}]))))
|
||||
|
||||
(defn connection-string-for-import-keypairs
|
||||
[{:keys [db]} [{:keys [sha3-pwd keypairs-key-uids connection-string]}]]
|
||||
(let [key-uid (get-in db [:profile/profile :key-uid])]
|
||||
{:fx [[:effects.syncing/import-keypairs-keystores
|
||||
@@ -102,14 +133,11 @@
|
||||
:on-success (fn [key-uids]
|
||||
(rf/dispatch [:wallet/make-keypairs-accounts-fully-operable key-uids]))
|
||||
:on-fail (fn [error]
|
||||
(log/error "failed to import missing key pairs with connection string"
|
||||
{:error error})
|
||||
(rf/dispatch [:toasts/upsert
|
||||
{:type :negative
|
||||
:theme :dark
|
||||
:text (i18n/label :t/incorrect-qr-code)}]))}]]}))
|
||||
(rf/dispatch [:wallet/connection-string-for-import-keypairs-failed
|
||||
keypairs-key-uids
|
||||
error]))}]]}))
|
||||
|
||||
(rf/reg-event-fx :wallet/connection-string-for-import-keypair connection-string-for-import-keypair)
|
||||
(rf/reg-event-fx :wallet/connection-string-for-import-keypairs connection-string-for-import-keypairs)
|
||||
|
||||
(defn success-keypair-qr-scan
|
||||
[_ [connection-string keypairs-key-uids]]
|
||||
@@ -121,7 +149,7 @@
|
||||
:on-auth-success (fn [password]
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch
|
||||
[:wallet/connection-string-for-import-keypair
|
||||
[:wallet/connection-string-for-import-keypairs
|
||||
{:connection-string connection-string
|
||||
:keypairs-key-uids keypairs-key-uids
|
||||
:sha3-pwd password}]))}]]]})
|
||||
|
||||
@@ -83,11 +83,11 @@
|
||||
:on-success fn?
|
||||
:on-fail fn?}]]}]
|
||||
(is (match? expected
|
||||
(sut/connection-string-for-import-keypair cofx
|
||||
[{:sha3-pwd sha3-pwd
|
||||
:keypairs-key-uids [test-keypair-key-uid]
|
||||
:connection-string
|
||||
connection-string}])))))
|
||||
(sut/connection-string-for-import-keypairs cofx
|
||||
[{:sha3-pwd sha3-pwd
|
||||
:keypairs-key-uids [test-keypair-key-uid]
|
||||
:connection-string
|
||||
connection-string}])))))
|
||||
|
||||
(deftest success-keypair-qr-scan-test
|
||||
(let [connection-string "valid-connection-string"
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
[{:blur? true
|
||||
:icon :i/qr-code
|
||||
:accessibility-label :show-key-pr-qr
|
||||
:label (i18n/label :t/show-encrypted-qr-of-key-pairs)
|
||||
:label (i18n/label :t/show-encrypted-qr-of-key-pair)
|
||||
:on-press on-show-qr}]
|
||||
[{:blur? true
|
||||
:icon :i/scan
|
||||
|
||||
+6
-3
@@ -36,8 +36,10 @@
|
||||
(defn- address-input
|
||||
[{:keys [input-value on-change-text paste-into-input clear-input]}]
|
||||
(let [empty-input? (string/blank? input-value)
|
||||
on-scan-address (rn/use-callback #(rf/dispatch [:open-modal :screen/wallet.scan-address
|
||||
{:on-result on-change-text}]))]
|
||||
on-scan-address (rn/use-callback (fn []
|
||||
(rf/dispatch [:wallet/clean-scanned-address])
|
||||
(rf/dispatch [:open-modal :screen/wallet.scan-address
|
||||
{:on-result on-change-text}])))]
|
||||
[rn/view {:style style/input-container}
|
||||
[quo/input
|
||||
{:accessibility-label :add-address-to-save
|
||||
@@ -161,7 +163,8 @@
|
||||
(rf/dispatch
|
||||
[:open-modal :screen/settings.save-address]))
|
||||
[address ens-name? address-or-ens])]
|
||||
(rn/use-unmount #(rf/dispatch [:wallet/clear-address-to-save]))
|
||||
(rn/use-unmount #(rf/dispatch [:wallet/clean-scanned-address]))
|
||||
(rn/use-mount #(rf/dispatch [:wallet/clear-address-to-save]))
|
||||
[quo/overlay {:type :shell}
|
||||
[floating-button-page/view
|
||||
{:footer-container-padding 0
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
(ns status-im.contexts.syncing.utils
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[status-im.constants :as constants]
|
||||
[native-module.core :as native-module]
|
||||
[utils.transforms :as transforms]))
|
||||
|
||||
(defn validate-connection-string
|
||||
[connection-string]
|
||||
(native-module/validate-connection-string
|
||||
connection-string))
|
||||
|
||||
(defn valid-connection-string?
|
||||
[connection-string]
|
||||
(when connection-string
|
||||
(string/starts-with?
|
||||
connection-string
|
||||
constants/local-pairing-connection-string-identifier)))
|
||||
(some-> connection-string
|
||||
validate-connection-string
|
||||
string/blank?))
|
||||
|
||||
(defn extract-error
|
||||
[json-str]
|
||||
|
||||
@@ -11,9 +11,7 @@
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- on-collectible-press
|
||||
[{:keys [id]} aspect-ratio]
|
||||
(rf/dispatch [:wallet/get-collectible-details id aspect-ratio]))
|
||||
(def on-collectible-press #(rf/dispatch [:wallet/navigate-to-collectible-details %]))
|
||||
|
||||
(defn- on-collectible-long-press
|
||||
[{:keys [preview-url collectible-details id]}]
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
|
||||
(rf/reg-event-fx :wallet/seed-phrase-entered seed-phrase-entered)
|
||||
|
||||
(defn store-account-generated
|
||||
(defn store-account-generated-with-mnemonic
|
||||
[{:keys [db]} [{:keys [new-account-data keypair-name]}]]
|
||||
(let [new-account (update new-account-data :mnemonic security/mask-data)]
|
||||
{:db (-> db
|
||||
@@ -85,20 +85,21 @@
|
||||
:random-phrase))
|
||||
:fx [[:dispatch [:navigate-back-to :screen/wallet.create-account]]]}))
|
||||
|
||||
(rf/reg-event-fx :wallet/store-account-generated store-account-generated)
|
||||
(rf/reg-event-fx :wallet/store-account-generated-with-mnemonic store-account-generated-with-mnemonic)
|
||||
|
||||
(defn generate-account-for-keypair
|
||||
(defn generate-account-for-keypair-with-mnemonic
|
||||
[{:keys [db]} [{:keys [keypair-name]}]]
|
||||
(let [seed-phrase (-> db :wallet :ui :create-account :new-keypair :seed-phrase)]
|
||||
{:fx [[:effects.wallet/create-account-from-mnemonic
|
||||
{:mnemonic-phrase (security/safe-unmask-data seed-phrase)
|
||||
:paths [constants/path-default-wallet]
|
||||
:on-success (fn [new-account-data]
|
||||
(rf/dispatch [:wallet/store-account-generated
|
||||
(rf/dispatch [:wallet/store-account-generated-with-mnemonic
|
||||
{:new-account-data new-account-data
|
||||
:keypair-name keypair-name}]))}]]}))
|
||||
|
||||
(rf/reg-event-fx :wallet/generate-account-for-keypair generate-account-for-keypair)
|
||||
(rf/reg-event-fx :wallet/generate-account-for-keypair-with-mnemonic
|
||||
generate-account-for-keypair-with-mnemonic)
|
||||
|
||||
(defn clear-create-account-data
|
||||
[{:keys [db]}]
|
||||
@@ -159,14 +160,19 @@
|
||||
(rf/reg-event-fx
|
||||
:wallet/create-keypair-with-account
|
||||
(fn [{db :db} [password account-preferences]]
|
||||
(let [{:keys [keypair-name
|
||||
(let [{:keys [workflow
|
||||
keypair-name
|
||||
new-account-data]} (-> db :wallet :ui :create-account :new-keypair)
|
||||
keypair-type (if (= workflow :workflow/new-keypair.import-private-key)
|
||||
:key
|
||||
:seed)
|
||||
keypair-with-account (create-account.utils/prepare-new-account
|
||||
{:keypair-name keypair-name
|
||||
:keypair-type keypair-type
|
||||
:account-data new-account-data
|
||||
:account-preferences account-preferences})
|
||||
new-address (some-> new-account-data
|
||||
(create-account.utils/first-derived-account)
|
||||
(create-account.utils/first-derived-account keypair-type)
|
||||
(:address)
|
||||
(string/lower-case))
|
||||
unmasked-password (security/safe-unmask-data password)]
|
||||
@@ -176,7 +182,7 @@
|
||||
:on-success [:wallet/add-account-success new-address]
|
||||
:on-error #(log/error "Failed to add Keypair and create account" %)}]]]})))
|
||||
|
||||
(defn import-and-create-keypair-with-account
|
||||
(defn import-mnemonic-and-create-keypair-with-account
|
||||
[{db :db} [{:keys [password account-preferences]}]]
|
||||
(let [account-data (-> db :wallet :ui :create-account :new-keypair :new-account-data)
|
||||
unmasked-mnemonic (security/safe-unmask-data (:mnemonic account-data))
|
||||
@@ -187,7 +193,8 @@
|
||||
:on-success #(rf/dispatch
|
||||
[:wallet/create-keypair-with-account password account-preferences])}]]]}))
|
||||
|
||||
(rf/reg-event-fx :wallet/import-and-create-keypair-with-account import-and-create-keypair-with-account)
|
||||
(rf/reg-event-fx :wallet/import-mnemonic-and-create-keypair-with-account
|
||||
import-mnemonic-and-create-keypair-with-account)
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/derive-address-and-add-account
|
||||
@@ -206,3 +213,49 @@
|
||||
:on-error [:wallet/log-rpc-error
|
||||
{:event :wallet/derive-address-and-add-account
|
||||
:params [derived-from-address [derivation-path]]}]}]]]}))
|
||||
|
||||
(defn import-private-key-and-create-keypair-with-account
|
||||
[{:keys [db]} [{:keys [password account-preferences]}]]
|
||||
(let [private-key (get-in db
|
||||
[:wallet :ui :create-account :new-keypair
|
||||
:new-account-data :private-key])
|
||||
unmasked-private-key (security/safe-unmask-data private-key)
|
||||
unmasked-password (security/safe-unmask-data password)]
|
||||
{:json-rpc/call
|
||||
[{:method "accounts_importPrivateKey"
|
||||
:params [unmasked-private-key unmasked-password]
|
||||
:on-success [:wallet/create-keypair-with-account password account-preferences]
|
||||
:on-error #(log/error "Failed to import private key" %)}]}))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/import-private-key-and-create-keypair-with-account
|
||||
import-private-key-and-create-keypair-with-account)
|
||||
|
||||
(defn store-account-generated-with-private-key
|
||||
[{:keys [db]} [{:keys [new-account-data keypair-name]}]]
|
||||
{:db (-> db
|
||||
(update-in [:wallet :ui :create-account :new-keypair]
|
||||
assoc
|
||||
:new-account-data new-account-data
|
||||
:keypair-name keypair-name)
|
||||
(update-in [:wallet :ui :create-account :new-keypair]
|
||||
dissoc
|
||||
:private-key))
|
||||
:fx [[:dispatch [:navigate-back-to :screen/wallet.create-account]]]})
|
||||
|
||||
(rf/reg-event-fx :wallet/store-account-generated-with-private-key
|
||||
store-account-generated-with-private-key)
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/import-private-key-and-generate-account-for-keypair
|
||||
(fn [{:keys [db]} [{:keys [keypair-name]}]]
|
||||
(let [private-key (get-in db [:wallet :ui :create-account :private-key])]
|
||||
{:db (assoc-in db
|
||||
[:wallet :ui :create-account :new-keypair :workflow]
|
||||
:workflow/new-keypair.import-private-key)
|
||||
:fx [[:effects.wallet/create-account-from-private-key
|
||||
{:private-key private-key
|
||||
:on-success (fn [new-account-data]
|
||||
(rf/dispatch [:wallet/store-account-generated-with-private-key
|
||||
{:keypair-name keypair-name
|
||||
:new-account-data new-account-data}]))}]]})))
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
{:new-account-data {"test" "data"
|
||||
:mnemonic masked-mnemonic}
|
||||
:keypair-name "new-keypair-name"}}}}}
|
||||
effects (events/store-account-generated {:db db} props)
|
||||
effects (events/store-account-generated-with-mnemonic {:db db} props)
|
||||
result-db (:db effects)
|
||||
remove-mnemonic #(update-in %
|
||||
[:wallet :ui :create-account :new-keypair :new-account-data]
|
||||
@@ -61,7 +61,7 @@
|
||||
expected-effects [[:effects.wallet/create-account-from-mnemonic
|
||||
{:mnemonic-phrase "test-secret"
|
||||
:paths [constants/path-default-wallet]}]]
|
||||
effects (events/generate-account-for-keypair {:db db} props)]
|
||||
effects (events/generate-account-for-keypair-with-mnemonic {:db db} props)]
|
||||
(is (match?
|
||||
(update-in effects [:fx 0 1] dissoc :on-success)
|
||||
{:fx expected-effects}))
|
||||
|
||||
+7
-7
@@ -63,31 +63,31 @@
|
||||
(let [{:keys [message] :as props}
|
||||
(case state
|
||||
:scanning
|
||||
{:type :info
|
||||
{:status :default
|
||||
:icon :i/scanning
|
||||
:message :t/scanning-for-activity}
|
||||
|
||||
:inactive-address
|
||||
{:type :warning
|
||||
{:status :warning
|
||||
:icon :i/info
|
||||
:message :t/this-account-has-no-activity}
|
||||
|
||||
:active-address
|
||||
{:type :success
|
||||
{:status :success
|
||||
:icon :i/done
|
||||
:message :t/this-address-has-activity}
|
||||
|
||||
:invalid-private-key
|
||||
{:type :error
|
||||
{:status :error
|
||||
:icon :i/info
|
||||
:message :t/invalid-private-key}
|
||||
|
||||
nil)]
|
||||
(when props
|
||||
[quo/info-message
|
||||
(assoc props
|
||||
:size :default
|
||||
:style style/indicator)
|
||||
(-> props
|
||||
(assoc :size :default :container-style style/indicator)
|
||||
(dissoc :message))
|
||||
(i18n/label message)])))
|
||||
|
||||
(defn on-unmount
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[status-im.common.floating-button-page.view :as floating-button-page]
|
||||
[status-im.common.not-implemented :as not-implemented]
|
||||
[status-im.common.validation.general :as validators]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.add-account.create-account.key-pair-name.style :as style]
|
||||
@@ -25,12 +24,12 @@
|
||||
(defn- next-workflow-step
|
||||
[workflow key-pair-name]
|
||||
(case workflow
|
||||
;; TODO issue #19759. Implement creation account from private key
|
||||
:import-private-key
|
||||
(not-implemented/alert)
|
||||
(rf/dispatch [:wallet/import-private-key-and-generate-account-for-keypair
|
||||
{:keypair-name key-pair-name}])
|
||||
|
||||
(:new-keypair :recovery-phrase)
|
||||
(rf/dispatch [:wallet/generate-account-for-keypair
|
||||
(rf/dispatch [:wallet/generate-account-for-keypair-with-mnemonic
|
||||
{:keypair-name key-pair-name}])
|
||||
|
||||
(do
|
||||
|
||||
@@ -2,28 +2,57 @@
|
||||
(:require [status-im.constants :as constants]))
|
||||
|
||||
(defn first-derived-account
|
||||
[account-data]
|
||||
(-> account-data :derived first val))
|
||||
[account-data keypair-type]
|
||||
(if (= keypair-type :seed)
|
||||
(some-> account-data
|
||||
:derived
|
||||
first
|
||||
val)
|
||||
account-data))
|
||||
|
||||
(defn get-account-details
|
||||
[keypair-type account account-to-create]
|
||||
(if (= keypair-type :key)
|
||||
{:key-uid (:key-uid account)
|
||||
:public-key (:public-key account)
|
||||
:account-address (:address account)}
|
||||
{:key-uid (:keyUid account)
|
||||
:public-key (:publicKey account-to-create)
|
||||
:account-address (:address account-to-create)}))
|
||||
|
||||
(defn get-account-config
|
||||
[{:keys [account-address key-uid keypair-type public-key account-name emoji color]}]
|
||||
{:address account-address
|
||||
:key-uid key-uid
|
||||
:wallet false
|
||||
:chat false
|
||||
:type keypair-type
|
||||
:path constants/path-default-wallet
|
||||
:public-key public-key
|
||||
:name account-name
|
||||
:emoji emoji
|
||||
:colorID color
|
||||
:hidden false})
|
||||
|
||||
(defn prepare-new-account
|
||||
[{keypair-name :keypair-name
|
||||
{:keys [keyUid address] :as account} :account-data
|
||||
{:keys [account-name color emoji]} :account-preferences}]
|
||||
(let [account-to-create (first-derived-account account)
|
||||
account-config {:address (:address account-to-create)
|
||||
:key-uid keyUid
|
||||
:wallet false
|
||||
:chat false
|
||||
:type :seed
|
||||
:path constants/path-default-wallet
|
||||
:public-key (:publicKey account-to-create)
|
||||
:name account-name
|
||||
:emoji emoji
|
||||
:colorID color
|
||||
:hidden false}]
|
||||
{:key-uid keyUid
|
||||
[{:keys [keypair-name keypair-type]
|
||||
{:keys [address] :as account} :account-data
|
||||
{:keys [account-name color emoji]} :account-preferences}]
|
||||
(let [account-to-create (first-derived-account account keypair-type)
|
||||
{:keys [key-uid public-key account-address]} (get-account-details keypair-type
|
||||
account
|
||||
account-to-create)
|
||||
account-config (get-account-config {:account-address
|
||||
account-address
|
||||
:key-uid key-uid
|
||||
:keypair-type keypair-type
|
||||
:public-key public-key
|
||||
:account-name account-name
|
||||
:emoji emoji
|
||||
:color color})]
|
||||
{:key-uid key-uid
|
||||
:name keypair-name
|
||||
:type :seed
|
||||
:type keypair-type
|
||||
:derived-from address
|
||||
:last-used-derivation-index 0
|
||||
:accounts [account-config]}))
|
||||
|
||||
@@ -22,37 +22,38 @@
|
||||
|
||||
(defn- get-keypair-data
|
||||
[{:keys [title primary-keypair? new-keypair? derivation-path customization-color]}]
|
||||
(let [formatted-path (string/replace derivation-path #"/" " / ")
|
||||
on-auth-success (fn [password]
|
||||
(rf/dispatch [:navigate-to
|
||||
:screen/wallet.edit-derivation-path
|
||||
{:password password
|
||||
:current-derivation-path formatted-path}]))]
|
||||
[{:title title
|
||||
:image (if primary-keypair? :avatar :icon)
|
||||
:image-props (if primary-keypair?
|
||||
{:full-name (utils.string/get-initials title 1)
|
||||
:size :xxs
|
||||
:customization-color customization-color}
|
||||
:i/seed)
|
||||
:action (when-not new-keypair? :button)
|
||||
:action-props {:on-press #(rf/dispatch [:navigate-to :screen/wallet.select-keypair])
|
||||
:button-text (i18n/label :t/edit)
|
||||
:alignment :flex-start}
|
||||
:description :text
|
||||
:description-props {:text (i18n/label :t/on-device)}}
|
||||
{:title (i18n/label :t/derivation-path)
|
||||
:image :icon
|
||||
:image-props :i/derivated-path
|
||||
:action (if (ff/enabled? ::ff/wallet.edit-derivation-path) :button :none)
|
||||
:action-props {:on-press #(rf/dispatch [:standard-auth/authorize
|
||||
{:on-auth-success on-auth-success
|
||||
:auth-button-label (i18n/label :t/continue)}])
|
||||
:button-text (i18n/label :t/edit)
|
||||
:icon-left :i/face-id
|
||||
:alignment :flex-start}
|
||||
:description :text
|
||||
:description-props {:text formatted-path}}]))
|
||||
[{:title title
|
||||
:image (if primary-keypair? :avatar :icon)
|
||||
:image-props (if primary-keypair?
|
||||
{:full-name (utils.string/get-initials title 1)
|
||||
:size :xxs
|
||||
:customization-color customization-color}
|
||||
:i/seed)
|
||||
:action (when-not new-keypair? :button)
|
||||
:action-props {:on-press #(rf/dispatch [:navigate-to :screen/wallet.select-keypair])
|
||||
:button-text (i18n/label :t/edit)
|
||||
:alignment :flex-start}
|
||||
:description :text
|
||||
:description-props {:text (i18n/label :t/on-device)}}
|
||||
(when-not (string/blank? derivation-path)
|
||||
(let [formatted-path (string/replace derivation-path #"/" " / ")
|
||||
on-auth-success (fn [password]
|
||||
(rf/dispatch [:navigate-to
|
||||
:screen/wallet.edit-derivation-path
|
||||
{:password password
|
||||
:current-derivation-path formatted-path}]))]
|
||||
{:title (i18n/label :t/derivation-path)
|
||||
:image :icon
|
||||
:image-props :i/derivated-path
|
||||
:action (if (ff/enabled? ::ff/wallet.edit-derivation-path) :button :none)
|
||||
:action-props {:on-press #(rf/dispatch [:standard-auth/authorize
|
||||
{:on-auth-success on-auth-success
|
||||
:auth-button-label (i18n/label :t/continue)}])
|
||||
:button-text (i18n/label :t/edit)
|
||||
:icon-left :i/face-id
|
||||
:alignment :flex-start}
|
||||
:description :text
|
||||
:description-props {:text formatted-path}}))])
|
||||
|
||||
(defn- avatar
|
||||
[{:keys [account-color emoji on-select-emoji]}]
|
||||
@@ -167,38 +168,59 @@
|
||||
:container-style (style/slide-button-container bottom))]}]
|
||||
children))))
|
||||
|
||||
(defn- on-auth-success-mnemonic
|
||||
[password account-preferences]
|
||||
(rf/dispatch
|
||||
[:wallet/import-mnemonic-and-create-keypair-with-account
|
||||
{:password password
|
||||
:account-preferences account-preferences}]))
|
||||
|
||||
(defn- on-auth-success-import-private-key
|
||||
[password account-preferences]
|
||||
(rf/dispatch
|
||||
[:wallet/import-private-key-and-create-keypair-with-account
|
||||
{:password password
|
||||
:account-preferences account-preferences}]))
|
||||
|
||||
(defn add-new-keypair-variant
|
||||
[{{:keys [account-name account-color emoji]} :state}]
|
||||
(let [on-auth-success (fn [password]
|
||||
(rf/dispatch
|
||||
[:wallet/import-and-create-keypair-with-account
|
||||
{:password password
|
||||
:account-preferences {:account-name @account-name
|
||||
:color @account-color
|
||||
:emoji @emoji}}]))]
|
||||
(fn [{:keys [on-change-text set-account-color set-emoji customization-color keypair-name error]}]
|
||||
(let [{:keys [new-account-data]} (rf/sub [:wallet/create-account-new-keypair])]
|
||||
[floating-button
|
||||
{:account-color @account-color
|
||||
:slide-button-props {:on-auth-success on-auth-success
|
||||
:disabled? (empty? @account-name)
|
||||
:dependencies [new-account-data]}}
|
||||
[avatar
|
||||
{:account-color @account-color
|
||||
:emoji @emoji
|
||||
:on-select-emoji set-emoji}]
|
||||
[input
|
||||
{:account-color @account-color
|
||||
:account-name @account-name
|
||||
:on-change-text on-change-text
|
||||
:error error}]
|
||||
[color-picker
|
||||
{:account-color @account-color
|
||||
:set-account-color set-account-color}]
|
||||
[new-account-origin
|
||||
{:derivation-path constants/path-default-wallet
|
||||
:customization-color customization-color
|
||||
:keypair-title keypair-name}]]))))
|
||||
(fn [{:keys [on-change-text set-account-color set-emoji customization-color keypair-name error]}]
|
||||
(let [{:keys [new-account-data workflow]} (rf/sub [:wallet/create-account-new-keypair])
|
||||
derivation-path (when (not= workflow
|
||||
:workflow/new-keypair.import-private-key)
|
||||
constants/path-default-wallet)]
|
||||
[floating-button
|
||||
{:account-color @account-color
|
||||
:slide-button-props {:on-auth-success (fn on-auth-success [password]
|
||||
(let [account-preferences {:account-name @account-name
|
||||
:color @account-color
|
||||
:emoji @emoji}]
|
||||
(if (= workflow
|
||||
:workflow/new-keypair.import-private-key)
|
||||
(on-auth-success-import-private-key
|
||||
password
|
||||
account-preferences)
|
||||
(on-auth-success-mnemonic
|
||||
password
|
||||
account-preferences))))
|
||||
:disabled? (empty? @account-name)
|
||||
:dependencies [new-account-data]}}
|
||||
[avatar
|
||||
{:account-color @account-color
|
||||
:emoji @emoji
|
||||
:on-select-emoji set-emoji}]
|
||||
[input
|
||||
{:account-color @account-color
|
||||
:account-name @account-name
|
||||
:on-change-text on-change-text
|
||||
:error error}]
|
||||
[color-picker
|
||||
{:account-color @account-color
|
||||
:set-account-color set-account-color}]
|
||||
[new-account-origin
|
||||
{:derivation-path derivation-path
|
||||
:customization-color customization-color
|
||||
:keypair-title keypair-name}]])))
|
||||
|
||||
(defn derive-account-variant
|
||||
[{{:keys [account-name account-color emoji]} :state}]
|
||||
@@ -262,33 +284,33 @@
|
||||
:account-name-error account-name-error
|
||||
:emoji-and-color-error? emoji-and-color-error?}]
|
||||
(fn []
|
||||
(let [customization-color (rf/sub [:profile/customization-color])
|
||||
(let [customization-color (rf/sub [:profile/customization-color])
|
||||
;; Having a keypair means the user is importing it or creating it.
|
||||
{:keys [keypair-name]} (rf/sub [:wallet/create-account-new-keypair])
|
||||
accounts-names (rf/sub [:wallet/accounts-names])
|
||||
accounts-emojis-and-colors (rf/sub [:wallet/accounts-emojis-and-colors])
|
||||
on-change-text (rn/use-callback
|
||||
(fn [new-text]
|
||||
(reset! account-name new-text)
|
||||
(reset! account-name-error
|
||||
(common.utils/get-account-name-error new-text
|
||||
accounts-names)))
|
||||
[accounts-names accounts-emojis-and-colors])
|
||||
check-emoji-and-color-error (fn [emoji color]
|
||||
(let [repeated? (accounts-emojis-and-colors [emoji color])]
|
||||
(reset! emoji-and-color-error?
|
||||
(when repeated? :emoji-and-color))))
|
||||
set-account-color (rn/use-callback
|
||||
(fn [new-color]
|
||||
(reset! account-color new-color)
|
||||
(check-emoji-and-color-error @emoji new-color))
|
||||
[accounts-emojis-and-colors @emoji])
|
||||
set-emoji (rn/use-callback
|
||||
(fn [new-emoji]
|
||||
(reset! emoji new-emoji)
|
||||
(check-emoji-and-color-error new-emoji @account-color))
|
||||
[accounts-emojis-and-colors @account-color])
|
||||
error (or @account-name-error @emoji-and-color-error?)]
|
||||
{:keys [keypair-name workflow]} (rf/sub [:wallet/create-account-new-keypair])
|
||||
accounts-names (rf/sub [:wallet/accounts-names])
|
||||
accounts-emojis-and-colors (rf/sub [:wallet/accounts-emojis-and-colors])
|
||||
on-change-text (rn/use-callback
|
||||
(fn [new-text]
|
||||
(reset! account-name new-text)
|
||||
(reset! account-name-error
|
||||
(common.utils/get-account-name-error new-text
|
||||
accounts-names)))
|
||||
[accounts-names accounts-emojis-and-colors])
|
||||
check-emoji-and-color-error (fn [emoji color]
|
||||
(let [repeated? (accounts-emojis-and-colors [emoji color])]
|
||||
(reset! emoji-and-color-error?
|
||||
(when repeated? :emoji-and-color))))
|
||||
set-account-color (rn/use-callback
|
||||
(fn [new-color]
|
||||
(reset! account-color new-color)
|
||||
(check-emoji-and-color-error @emoji new-color))
|
||||
[accounts-emojis-and-colors @emoji])
|
||||
set-emoji (rn/use-callback
|
||||
(fn [new-emoji]
|
||||
(reset! emoji new-emoji)
|
||||
(check-emoji-and-color-error new-emoji @account-color))
|
||||
[accounts-emojis-and-colors @account-color])
|
||||
error (or @account-name-error @emoji-and-color-error?)]
|
||||
|
||||
(rn/use-mount #(check-emoji-and-color-error @emoji @account-color))
|
||||
(rn/use-unmount #(rf/dispatch [:wallet/clear-create-account]))
|
||||
@@ -300,8 +322,10 @@
|
||||
:on-change-text on-change-text
|
||||
:set-account-color set-account-color
|
||||
:set-emoji set-emoji
|
||||
|
||||
:keypair-name keypair-name
|
||||
:error error}]
|
||||
:error error
|
||||
:workflow workflow}]
|
||||
[derive-account-variant
|
||||
{:state state
|
||||
:customization-color customization-color
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns status-im.contexts.wallet.collectible.events
|
||||
(:require [camel-snake-kebab.extras :as cske]
|
||||
[clojure.string :as string]
|
||||
[react-native.platform :as platform]
|
||||
[status-im.contexts.wallet.collectible.utils :as collectible-utils]
|
||||
[taoensso.timbre :as log]
|
||||
@@ -44,13 +45,6 @@
|
||||
|
||||
(rf/reg-event-fx :wallet/clear-stored-collectibles clear-stored-collectibles)
|
||||
|
||||
(defn store-last-collectible-details
|
||||
[{:keys [db]} [collectible]]
|
||||
{:db (assoc-in db [:wallet :last-collectible-details] collectible)
|
||||
:dispatch [:navigate-to :screen/wallet.collectible]})
|
||||
|
||||
(rf/reg-event-fx :wallet/store-last-collectible-details store-last-collectible-details)
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/request-new-collectibles-for-account
|
||||
(fn [{:keys [db]} [{:keys [request-id account amount]}]]
|
||||
@@ -166,39 +160,58 @@
|
||||
[:dispatch [:wallet/flush-collectibles-fetched]])]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/get-collectible-details
|
||||
(fn [{:keys [db]} [collectible-id aspect-ratio]]
|
||||
:wallet/navigate-to-collectible-details
|
||||
(fn [{:keys [db]}
|
||||
[{{collectible-id :id :as collectible} :collectible
|
||||
aspect-ratio :aspect-ratio
|
||||
gradient-color :gradient-color}]]
|
||||
(let [request-id 0
|
||||
collectible-id-converted (cske/transform-keys transforms/->PascalCaseKeyword collectible-id)
|
||||
data-type (collectible-data-types :details)
|
||||
request-params [request-id [collectible-id-converted] data-type]]
|
||||
{:db (assoc-in db [:wallet :last-collectible-aspect-ratio] aspect-ratio)
|
||||
{:db (assoc-in db
|
||||
[:wallet :ui :collectible]
|
||||
{:details collectible
|
||||
:aspect-ratio aspect-ratio
|
||||
:gradient-color gradient-color})
|
||||
:fx [[:json-rpc/call
|
||||
[{:method "wallet_getCollectiblesByUniqueIDAsync"
|
||||
:params request-params
|
||||
:on-error (fn [error]
|
||||
(log/error "failed to request collectible"
|
||||
{:event :wallet/get-collectible-details
|
||||
{:event :wallet/navigate-to-collectible-details
|
||||
:error error
|
||||
:params request-params}))}]]]})))
|
||||
:params request-params}))}]]
|
||||
;; We delay the navigation because we need re-frame to update the DB on time.
|
||||
;; By doing it, we skip a blink while visiting the collectible detail page.
|
||||
[:dispatch-later
|
||||
{:ms 1
|
||||
:dispatch [:navigate-to :screen/wallet.collectible]}]]})))
|
||||
|
||||
(defn- keep-not-empty-value
|
||||
[old-value new-value]
|
||||
(if (or (string/blank? new-value) (nil? new-value))
|
||||
old-value
|
||||
new-value))
|
||||
|
||||
(def merge-skipping-empty-values (partial merge-with keep-not-empty-value))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/get-collectible-details-done
|
||||
(fn [_ [{:keys [message]}]]
|
||||
(let [response (cske/transform-keys transforms/->kebab-case-keyword
|
||||
(transforms/json->clj message))
|
||||
{:keys [collectibles]} response
|
||||
collectible (first collectibles)]
|
||||
(fn [{db :db} [{:keys [message]}]]
|
||||
(let [response (cske/transform-keys transforms/->kebab-case-keyword
|
||||
(transforms/json->clj message))
|
||||
{[collectible] :collectibles} response]
|
||||
(if collectible
|
||||
{:fx [[:dispatch [:wallet/store-last-collectible-details collectible]]]}
|
||||
{:db (update-in db [:wallet :ui :collectible :details] merge-skipping-empty-values collectible)}
|
||||
(log/error "failed to get collectible details"
|
||||
{:event :wallet/get-collectible-details-done
|
||||
:response response})))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/clear-last-collectible-details
|
||||
:wallet/clear-collectible-details
|
||||
(fn [{:keys [db]}]
|
||||
{:db (update-in db [:wallet] dissoc :last-collectible-details :last-collectible-aspect-ratio)}))
|
||||
{:db (update-in db [:wallet :ui] dissoc :collectible)}))
|
||||
|
||||
(rf/reg-event-fx :wallet/trigger-share-collectible
|
||||
(fn [_ [{:keys [title uri]}]]
|
||||
|
||||
@@ -43,18 +43,6 @@
|
||||
|
||||
(is (match? result-db expected-db))))))
|
||||
|
||||
(deftest store-last-collectible-details-test
|
||||
(testing "store-last-collectible-details"
|
||||
(let [db {:wallet {}}
|
||||
last-collectible {:description "Pandaria"
|
||||
:image-url "https://..."}
|
||||
expected-db {:wallet {:last-collectible-details {:description "Pandaria"
|
||||
:image-url "https://..."}}}
|
||||
effects (events/store-last-collectible-details {:db db}
|
||||
[last-collectible])
|
||||
result-db (:db effects)]
|
||||
(is (match? result-db expected-db)))))
|
||||
|
||||
(deftest request-new-collectibles-for-account-from-signal-test
|
||||
(testing "request new collectibles for account from signal"
|
||||
(let [db {:wallet {}}
|
||||
|
||||
@@ -8,12 +8,11 @@
|
||||
(def ^:private link-card-space 28)
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [window-width (rf/sub [:dimensions/window-width])
|
||||
item-width (- (/ window-width 2) link-card-space)
|
||||
{:keys [collectible-data]} (rf/sub [:wallet/last-collectible-details])
|
||||
link-card-container-style (style/link-card item-width)
|
||||
collectible-about {:cards []}]
|
||||
[{:keys [collectible-data]}]
|
||||
(let [window-width (rf/sub [:dimensions/window-width])
|
||||
item-width (- (/ window-width 2) link-card-space)
|
||||
link-card-container-style (style/link-card item-width)
|
||||
collectible-about {:cards []}]
|
||||
[:<>
|
||||
[rn/view {:style style/title}
|
||||
[quo/text
|
||||
|
||||
@@ -21,27 +21,25 @@
|
||||
:container-style style/traits-item}])
|
||||
|
||||
(defn- traits-section
|
||||
[]
|
||||
(let [traits (rf/sub [:wallet/last-collectible-details-traits])]
|
||||
(when (pos? (count traits))
|
||||
[rn/view
|
||||
[quo/section-label
|
||||
{:section (i18n/label :t/traits)
|
||||
:container-style style/traits-title-container}]
|
||||
[rn/flat-list
|
||||
{:render-fn trait-item
|
||||
:data traits
|
||||
:key :collectibles-list
|
||||
:key-fn :id
|
||||
:num-columns 2
|
||||
:content-container-style style/traits-container}]])))
|
||||
[traits]
|
||||
[rn/view
|
||||
[quo/section-label
|
||||
{:section (i18n/label :t/traits)
|
||||
:container-style style/traits-title-container}]
|
||||
[rn/flat-list
|
||||
{:render-fn trait-item
|
||||
:data traits
|
||||
:key :collectibles-list
|
||||
:key-fn :id
|
||||
:num-columns 2
|
||||
:content-container-style style/traits-container}]])
|
||||
|
||||
(defn- info
|
||||
[]
|
||||
(let [chain-id (rf/sub [:wallet/last-collectible-details-chain-id])
|
||||
{:keys [network-name]} (rf/sub [:wallet/network-details-by-chain-id chain-id])
|
||||
subtitle (string/capitalize (name (or network-name "")))
|
||||
{:keys [name emoji color]} (rf/sub [:wallet/last-collectible-details-owner])]
|
||||
[{:keys [chain-id account]}]
|
||||
(let [{:keys [network-name]} (rf/sub [:wallet/network-details-by-chain-id chain-id])
|
||||
subtitle (some-> network-name
|
||||
name
|
||||
string/capitalize)]
|
||||
[rn/view {:style style/info-container}
|
||||
[rn/view {:style style/account}
|
||||
[quo/data-item
|
||||
@@ -49,10 +47,10 @@
|
||||
:status :default
|
||||
:size :default
|
||||
:title (i18n/label :t/account-title)
|
||||
:subtitle name
|
||||
:emoji emoji
|
||||
:subtitle-type :account
|
||||
:customization-color color}]]
|
||||
:subtitle (:name account)
|
||||
:emoji (:emoji account)
|
||||
:customization-color (:color account)}]]
|
||||
[rn/view {:style style/network}
|
||||
[quo/data-item
|
||||
{:subtitle-type :network
|
||||
@@ -64,7 +62,12 @@
|
||||
:subtitle subtitle}]]]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
[:<>
|
||||
[info]
|
||||
[traits-section]])
|
||||
[collectible]
|
||||
(let [owner-account (rf/sub [:wallet/collectible-details-owner collectible])
|
||||
traits (-> collectible :collectible-data :traits)]
|
||||
[:<>
|
||||
[info
|
||||
{:chain-id (-> collectible :id :contract-id :chain-id)
|
||||
:account owner-account}]
|
||||
(when (pos? (count traits))
|
||||
[traits-section traits])]))
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
[status-im.contexts.wallet.collectible.tabs.overview.view :as overview]))
|
||||
|
||||
(defn view
|
||||
[{:keys [selected-tab]}]
|
||||
[{:keys [selected-tab collectible]}]
|
||||
(case selected-tab
|
||||
:overview [overview/view]
|
||||
:about [about/view]
|
||||
:overview [overview/view collectible]
|
||||
:about [about/view collectible]
|
||||
:activity [activity/view]
|
||||
nil))
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
:balance
|
||||
js/parseInt))
|
||||
|
||||
(def ^:const supported-collectible-types
|
||||
(def supported-collectible-types
|
||||
#{"image/jpeg"
|
||||
"image/gif"
|
||||
"image/bmp"
|
||||
|
||||
@@ -76,11 +76,10 @@
|
||||
(defn navigate-back-and-clear-collectible
|
||||
[]
|
||||
(rf/dispatch [:navigate-back])
|
||||
(js/setTimeout #(rf/dispatch [:wallet/clear-last-collectible-details]) 700))
|
||||
(rf/dispatch [:wallet/clear-collectible-details]))
|
||||
|
||||
(defn animated-header
|
||||
[{:keys [scroll-amount title-opacity page-nav-type picture title description theme
|
||||
id]}]
|
||||
[{:keys [scroll-amount title-opacity page-nav-type picture title description theme id]}]
|
||||
(let [blur-amount (header-animations/use-blur-amount scroll-amount)
|
||||
layer-opacity (header-animations/use-layer-opacity
|
||||
scroll-amount
|
||||
@@ -149,8 +148,9 @@
|
||||
(let [title-ref (rn/use-ref-atom nil)
|
||||
set-title-ref (rn/use-callback #(reset! title-ref %))
|
||||
animation-shared-element-id (rf/sub [:animation-shared-element-id])
|
||||
collectible-owner (rf/sub [:wallet/last-collectible-details-owner])
|
||||
aspect-ratio (rf/sub [:wallet/last-collectible-aspect-ratio])
|
||||
collectible-owner (rf/sub [:wallet/collectible-details-owner collectible])
|
||||
aspect-ratio (rf/sub [:wallet/collectible-aspect-ratio])
|
||||
gradient-color (rf/sub [:wallet/collectible-gradient-color])
|
||||
{:keys [id
|
||||
preview-url
|
||||
collection-data
|
||||
@@ -181,35 +181,36 @@
|
||||
[rn/view
|
||||
[gradient-layer preview-uri]
|
||||
[quo/expanded-collectible
|
||||
{:aspect-ratio aspect-ratio
|
||||
:image-src preview-uri
|
||||
:container-style (style/preview-container)
|
||||
:counter (utils/collectible-owned-counter total-owned)
|
||||
:native-ID (when (= animation-shared-element-id token-id) :shared-element)
|
||||
:supported-file? (utils/supported-file? (:animation-media-type collectible-data))
|
||||
:on-press (fn []
|
||||
(if svg?
|
||||
(js/alert "Can't visualize SVG images in lightbox")
|
||||
(rf/dispatch
|
||||
[:lightbox/navigate-to-lightbox
|
||||
token-id
|
||||
{:images [collectible-image]
|
||||
:index 0
|
||||
:on-options-press #(rf/dispatch [:show-bottom-sheet
|
||||
{:content
|
||||
(fn []
|
||||
[options-drawer/view
|
||||
{:name collectible-name
|
||||
:image
|
||||
preview-uri
|
||||
:id id}])}])}])))
|
||||
:on-collectible-load (fn []
|
||||
;; We need to delay the measurement because the
|
||||
;; navigation has an animation
|
||||
(js/setTimeout
|
||||
#(some-> @title-ref
|
||||
(oops/ocall "measureInWindow" set-title-bottom))
|
||||
300))}]]
|
||||
{:aspect-ratio aspect-ratio
|
||||
:image-src preview-uri
|
||||
:container-style (style/preview-container)
|
||||
:gradient-color-index gradient-color
|
||||
:counter (utils/collectible-owned-counter total-owned)
|
||||
:native-ID (when (= animation-shared-element-id token-id) :shared-element)
|
||||
:supported-file? (utils/supported-file? (:animation-media-type collectible-data))
|
||||
:on-press (fn []
|
||||
(if svg?
|
||||
(js/alert "Can't visualize SVG images in lightbox")
|
||||
(rf/dispatch
|
||||
[:lightbox/navigate-to-lightbox
|
||||
token-id
|
||||
{:images [collectible-image]
|
||||
:index 0
|
||||
:on-options-press #(rf/dispatch [:show-bottom-sheet
|
||||
{:content
|
||||
(fn []
|
||||
[options-drawer/view
|
||||
{:name collectible-name
|
||||
:image
|
||||
preview-uri
|
||||
:id id}])}])}])))
|
||||
:on-collectible-load (fn []
|
||||
;; We need to delay the measurement because the
|
||||
;; navigation has an animation
|
||||
(js/setTimeout
|
||||
#(some-> @title-ref
|
||||
(oops/ocall "measureInWindow" set-title-bottom))
|
||||
300))}]]
|
||||
[rn/view {:style (style/background-color theme)}
|
||||
[header collectible-name collection-name collection-image set-title-ref]
|
||||
[cta-buttons
|
||||
@@ -225,39 +226,43 @@
|
||||
:default-active @selected-tab
|
||||
:on-change on-tab-change
|
||||
:data tabs-data}]
|
||||
[tabs/view {:selected-tab @selected-tab}]]]))))
|
||||
[tabs/view
|
||||
{:selected-tab @selected-tab
|
||||
:collectible collectible}]]]))))
|
||||
|
||||
(defn- get-title-bottom-y-position
|
||||
[y-element-position element-height]
|
||||
(let [{:keys [top]} (safe-area/get-insets)
|
||||
title-height -56]
|
||||
(+ y-element-position
|
||||
element-height
|
||||
title-height
|
||||
(when platform/ios? (* top -2)))))
|
||||
|
||||
(defn view
|
||||
[_]
|
||||
(let [{:keys [top]} (safe-area/get-insets)
|
||||
theme (quo.theme/use-theme)
|
||||
title-bottom-coord (rn/use-ref-atom 0)
|
||||
set-title-bottom (rn/use-callback
|
||||
(fn [_ y _ height]
|
||||
(reset! title-bottom-coord
|
||||
(+ y
|
||||
height
|
||||
-56
|
||||
(when platform/ios?
|
||||
(* top -2))))))
|
||||
scroll-amount (reanimated/use-shared-value 0)
|
||||
title-opacity (reanimated/use-shared-value 0)
|
||||
collectible (rf/sub [:wallet/last-collectible-details])
|
||||
{:keys [preview-url
|
||||
collection-data
|
||||
collectible-data]} collectible
|
||||
{preview-uri :uri} preview-url
|
||||
{collectible-name :name} collectible-data
|
||||
{collection-name :name} collection-data]
|
||||
(let [{:keys [top]} (safe-area/get-insets)
|
||||
theme (quo.theme/use-theme)
|
||||
title-bottom-coord (rn/use-ref-atom 0)
|
||||
set-title-bottom (rn/use-callback
|
||||
(fn [_ y _ height]
|
||||
(reset! title-bottom-coord
|
||||
(get-title-bottom-y-position y height))))
|
||||
scroll-amount (reanimated/use-shared-value 0)
|
||||
title-opacity (reanimated/use-shared-value 0)
|
||||
{:keys [collection-data
|
||||
collectible-data
|
||||
preview-url]
|
||||
:as collectible} (rf/sub [:wallet/collectible-details])]
|
||||
[rn/view {:style (style/background-color theme)}
|
||||
[animated-header
|
||||
{:id (:id collectible)
|
||||
:scroll-amount scroll-amount
|
||||
:title-opacity title-opacity
|
||||
:page-nav-type :title-description
|
||||
:picture preview-uri
|
||||
:title collectible-name
|
||||
:description collection-name
|
||||
:picture (:uri preview-url)
|
||||
:title (:name collectible-data)
|
||||
:description (:name collection-data)
|
||||
:theme theme}]
|
||||
[reanimated/scroll-view
|
||||
{:style (style/scroll-view top)
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
:networks networks
|
||||
:align-center? true
|
||||
:networks-on-press #(rf/dispatch [:show-bottom-sheet {:content network-filter/view}])
|
||||
:right-side [(when (and (ff/enabled? ::wallet.wallet-connect)
|
||||
:right-side [(when (and (ff/enabled? ::ff/wallet.wallet-connect)
|
||||
(not watch-only?))
|
||||
{:icon-name :i/dapps
|
||||
:on-press #(rf/dispatch [:navigate-to :screen/wallet.connected-dapps])})
|
||||
|
||||
@@ -13,25 +13,34 @@
|
||||
[{:keys [preview-url collection-data collectible-data total-owned on-press on-long-press]
|
||||
:as collectible}
|
||||
index]
|
||||
(let [on-press-fn (rn/use-callback #(when on-press
|
||||
(on-press collectible %)))
|
||||
on-long-press-fn (rn/use-callback #(when on-long-press
|
||||
(on-long-press collectible)))]
|
||||
(let [gradient-color (keyword (str "gradient-" (inc (mod index 5))))
|
||||
on-press-fn (rn/use-callback
|
||||
(fn [aspect-ratio]
|
||||
(when (fn? on-press)
|
||||
(on-press {:collectible (dissoc collectible :on-press :on-long-press)
|
||||
:aspect-ratio aspect-ratio
|
||||
:gradient-color gradient-color}))))
|
||||
on-long-press-fn (rn/use-callback
|
||||
(fn [aspect-ratio]
|
||||
(when on-long-press
|
||||
(on-long-press
|
||||
(dissoc collectible :on-press :on-long-press)
|
||||
aspect-ratio))))]
|
||||
[quo/collectible-list-item
|
||||
{:type :card
|
||||
:image-src (:uri preview-url)
|
||||
:avatar-image-src (:image-url collection-data)
|
||||
:collectible-name (:name collection-data)
|
||||
:collectible-name (:name collectible-data)
|
||||
:supported-file? (utils/supported-file? (:animation-media-type collectible-data))
|
||||
:gradient-color-index (keyword (str "gradient-" (inc (mod index 5))))
|
||||
:gradient-color-index gradient-color
|
||||
:counter (utils/collectible-owned-counter total-owned)
|
||||
:container-style style/collectible-container
|
||||
:on-press on-press-fn
|
||||
:on-long-press on-long-press-fn}]))
|
||||
|
||||
(defn view
|
||||
[{:keys [collectibles filtered? on-end-reached
|
||||
on-collectible-press current-account-address on-collectible-long-press]}]
|
||||
[{:keys [collectibles filtered? on-end-reached on-collectible-press
|
||||
current-account-address on-collectible-long-press]}]
|
||||
(let [theme (quo.theme/use-theme)
|
||||
no-results-match-query? (and filtered? (empty? collectibles))]
|
||||
(cond
|
||||
|
||||
@@ -299,3 +299,18 @@
|
||||
(utils.string/contains-emoji? s) :emoji
|
||||
(existing-account-names s) :existing-name
|
||||
(utils.string/contains-special-character? s) :special-character))
|
||||
|
||||
(defn calculate-and-sort-tokens
|
||||
[{:keys [tokens color currency currency-symbol]}]
|
||||
(let [calculate-token (fn [token]
|
||||
(calculate-token-value {:token token
|
||||
:color color
|
||||
:currency currency
|
||||
:currency-symbol currency-symbol}))
|
||||
calculated-tokens (map calculate-token tokens)
|
||||
token-priority {"SNT" 1 "STT" 1 "ETH" 2 "DAI" 3}]
|
||||
(sort-by (fn [token]
|
||||
(let [fiat-value (get-in token [:values :fiat-unformatted-value])
|
||||
priority (get token-priority (:token token) 999)]
|
||||
[(- fiat-value) priority]))
|
||||
calculated-tokens)))
|
||||
|
||||
@@ -115,3 +115,39 @@
|
||||
(is (= (utils/prettify-percentage-change 1.113454) "1.11"))
|
||||
(is (= (utils/prettify-percentage-change -0.35) "0.35"))
|
||||
(is (= (utils/prettify-percentage-change -0.78234) "0.78"))))
|
||||
|
||||
(deftest calculate-and-sort-tokens-test
|
||||
(testing "calculate-and-sort-tokens function"
|
||||
(let [mock-color "blue"
|
||||
mock-currency "USD"
|
||||
mock-currency-symbol "$"]
|
||||
|
||||
(with-redefs [utils/calculate-token-value
|
||||
(fn [{:keys [token]}]
|
||||
(case (:symbol token)
|
||||
"ETH" {:token "ETH" :values {:fiat-unformatted-value 5}}
|
||||
"DAI" {:token "DAI" :values {:fiat-unformatted-value 10}}
|
||||
"SNT" {:token "SNT" :values {:fiat-unformatted-value 1}}))]
|
||||
(testing "Standard case with different fiat-unformatted-values"
|
||||
(let [mock-tokens [{:symbol "ETH"
|
||||
:name "Ethereum"
|
||||
:balances-per-chain {:mock-chain 5}
|
||||
:decimals 18}
|
||||
{:symbol "DAI"
|
||||
:name "Dai"
|
||||
:balances-per-chain {:mock-chain 10}
|
||||
:decimals 18}
|
||||
{:symbol "SNT"
|
||||
:name "Status Network Token"
|
||||
:balances-per-chain {:mock-chain 1}
|
||||
:decimals 18}]
|
||||
mock-input {:tokens mock-tokens
|
||||
:color mock-color
|
||||
:currency mock-currency
|
||||
:currency-symbol mock-currency-symbol}
|
||||
sorted-tokens (map :token (utils/calculate-and-sort-tokens mock-input))
|
||||
expected-order ["DAI" "ETH" "SNT"]]
|
||||
(is (= expected-order sorted-tokens))))))))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
(ns status-im.contexts.wallet.connected-dapps.scan-dapp.style
|
||||
(:require [quo.foundations.colors :as colors]))
|
||||
|
||||
(def subtitle-container
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:padding-horizontal 20
|
||||
:gap 4})
|
||||
|
||||
(def subtitle-text
|
||||
{:color colors/white})
|
||||
@@ -0,0 +1,44 @@
|
||||
(ns status-im.contexts.wallet.connected-dapps.scan-dapp.view
|
||||
(:require [quo.core :as quo]
|
||||
[quo.foundations.resources :as quo.resources]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.hooks :as hooks]
|
||||
[status-im.common.scan-qr-code.view :as scan-qr-code]
|
||||
[status-im.contexts.wallet.connected-dapps.scan-dapp.style :as style]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [{:keys [keyboard-shown]} (hooks/use-keyboard)
|
||||
{:keys [name emoji color]} (rf/sub [:wallet/current-viewing-account])]
|
||||
(rn/use-mount
|
||||
(fn []
|
||||
(when keyboard-shown
|
||||
(rn/dismiss-keyboard!))))
|
||||
[scan-qr-code/view
|
||||
{:title (i18n/label :t/scan-qr)
|
||||
:subtitle [rn/view style/subtitle-container
|
||||
[quo/context-tag
|
||||
{:theme :dark
|
||||
:type :account
|
||||
:size 24
|
||||
:account-name name
|
||||
:emoji emoji
|
||||
:customization-color color}]
|
||||
[quo/text
|
||||
{:style style/subtitle-text
|
||||
:size :paragraph-1}
|
||||
(i18n/label :t/wallet-connect-via)]
|
||||
[quo/context-tag
|
||||
{:theme :dark
|
||||
:type :dapp
|
||||
:size 24
|
||||
:dapp-name (i18n/label :t/wallet-connect-label)
|
||||
:dapp-logo (quo.resources/get-dapp :wallet-connect)}]]
|
||||
:on-success-scan (fn [scanned-text]
|
||||
(debounce/debounce-and-dispatch
|
||||
[:wallet-connect/on-scan-connection scanned-text]
|
||||
300))}]))
|
||||
@@ -90,7 +90,7 @@
|
||||
{:title (i18n/label :t/connected-dapps)
|
||||
:wallet-account wallet-account
|
||||
:on-close #(rf/dispatch [:navigate-back])
|
||||
:on-add #(js/alert "Feature not implemented")}]
|
||||
:on-add #(rf/dispatch [:navigate-to :screen/wallet.scan-dapp])}]
|
||||
(if (empty? pairings)
|
||||
[quo/empty-state
|
||||
{:title (i18n/label :t/no-dapps)
|
||||
|
||||
@@ -58,11 +58,11 @@
|
||||
:emoji-hash emojiHash
|
||||
:key-uid keyUid
|
||||
:public-key publicKey
|
||||
:private-key privateKey})))))
|
||||
:private-key (security/mask-data privateKey)})))))
|
||||
|
||||
(rf/reg-fx
|
||||
:effects.wallet/create-account-from-private-key
|
||||
(fn [[private-key on-success on-error]]
|
||||
(fn [{:keys [private-key on-success on-error]}]
|
||||
(-> (create-account-from-private-key private-key)
|
||||
(promesa/then (partial rf/call-continuation on-success))
|
||||
(promesa/catch (partial rf/call-continuation on-error)))))
|
||||
|
||||
@@ -362,15 +362,19 @@
|
||||
|
||||
(rf/reg-event-fx :wallet/address-validation-success
|
||||
(fn [{:keys [db]}]
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :ui :search-address :valid-ens-or-address?] true)
|
||||
(assoc-in [:wallet :ui :search-address :loading?] false))}))
|
||||
{:db (update-in db
|
||||
[:wallet :ui :search-address]
|
||||
assoc
|
||||
:valid-ens-or-address? true
|
||||
:loading? false)}))
|
||||
|
||||
(rf/reg-event-fx :wallet/address-validation-failed
|
||||
(fn [{:keys [db]}]
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :ui :search-address :valid-ens-or-address?] false)
|
||||
(assoc-in [:wallet :ui :search-address :loading?] false))}))
|
||||
{:db (update-in db
|
||||
[:wallet :ui :search-address]
|
||||
assoc
|
||||
:valid-ens-or-address? false
|
||||
:loading? false)}))
|
||||
|
||||
(rf/reg-event-fx :wallet/clean-local-suggestions
|
||||
(fn [{:keys [db]}]
|
||||
|
||||
@@ -17,9 +17,7 @@
|
||||
:name (:name collectible-data)
|
||||
:image (:uri preview-url)}])}]))
|
||||
|
||||
(defn- on-collectible-press
|
||||
[{:keys [id]} aspect-ratio]
|
||||
(rf/dispatch [:wallet/get-collectible-details id aspect-ratio]))
|
||||
(def on-collectible-press #(rf/dispatch [:wallet/navigate-to-collectible-details %]))
|
||||
|
||||
(defn view
|
||||
[{:keys [selected-tab]}]
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
{:collectibles collectibles
|
||||
:filtered? search-performed?
|
||||
:on-end-reached #(rf/dispatch [:wallet/request-collectibles-for-current-viewing-account])
|
||||
:on-collectible-press (fn [collectible]
|
||||
:on-collectible-press (fn [{:keys [collectible]}]
|
||||
(rf/dispatch [:wallet/set-collectible-to-send
|
||||
{:collectible collectible
|
||||
:current-screen :screen/wallet.select-asset}]))}]))
|
||||
|
||||
@@ -118,12 +118,27 @@
|
||||
|
||||
(rf/reg-fx
|
||||
:effects.wallet-connect/respond-session-request
|
||||
(fn [{:keys [web3-wallet topic id result on-success on-error]}]
|
||||
(fn [{:keys [web3-wallet topic id result error on-success on-error]}]
|
||||
(->
|
||||
(.respondSessionRequest web3-wallet
|
||||
(clj->js {:topic topic
|
||||
:response {:id id
|
||||
:jsonrpc "2.0"
|
||||
:result result}}))
|
||||
:response (merge {:id id
|
||||
:jsonrpc "2.0"}
|
||||
(when result
|
||||
{:result result})
|
||||
(when error
|
||||
{:error error}))}))
|
||||
(promesa/then on-success)
|
||||
(promesa/catch on-error))))
|
||||
|
||||
(rf/reg-fx
|
||||
:effects.wallet-connect/reject-session-proposal
|
||||
(fn [{:keys [web3-wallet proposal on-success on-error]}]
|
||||
(let [{:keys [id]} proposal
|
||||
reason (wallet-connect/get-sdk-error
|
||||
constants/wallet-connect-user-rejected-error-key)]
|
||||
(-> (.rejectSession web3-wallet
|
||||
(clj->js {:id id
|
||||
:reason reason}))
|
||||
(promesa/then on-success)
|
||||
(promesa/catch on-error)))))
|
||||
|
||||
@@ -67,8 +67,7 @@
|
||||
:session-networks session-networks
|
||||
:address (-> without-watched
|
||||
first
|
||||
:address)
|
||||
)
|
||||
:address))
|
||||
:fx [[:dispatch
|
||||
[:open-modal :screen/wallet.wallet-connect-session-proposal]]]}
|
||||
{:fx [[:dispatch
|
||||
@@ -167,16 +166,10 @@
|
||||
{:web3-wallet web3-wallet
|
||||
:proposal current-proposal
|
||||
:supported-namespaces supported-namespaces
|
||||
:on-success (fn []
|
||||
:on-success (fn [approved-session]
|
||||
(log/info "Wallet Connect session approved")
|
||||
(let [metadata (wallet-connect-core/get-session-dapp-metadata
|
||||
current-proposal)]
|
||||
(rf/dispatch [:wallet-connect/reset-current-session-proposal])
|
||||
(rf/dispatch [:wallet-connect/persist-session
|
||||
{:id (:id current-proposal)
|
||||
:dapp-name (:name metadata)
|
||||
:dapp-url (:url metadata)
|
||||
:session-info current-proposal}])))
|
||||
(rf/dispatch [:wallet-connect/reset-current-session-proposal])
|
||||
(rf/dispatch [:wallet-connect/persist-session approved-session]))
|
||||
:on-fail (fn [error]
|
||||
(log/error "Wallet Connect session approval failed"
|
||||
{:error error
|
||||
@@ -190,43 +183,27 @@
|
||||
(fn [_ [scanned-text]]
|
||||
(let [parsed-uri (wallet-connect/parse-uri scanned-text)
|
||||
version (:version parsed-uri)
|
||||
valid-wc-uri? (wc-utils/valid-uri? parsed-uri)
|
||||
expired? (-> parsed-uri
|
||||
:expiryTimestamp
|
||||
wc-utils/timestamp-expired?)
|
||||
version-supported? (wc-utils/version-supported? version)]
|
||||
(cond
|
||||
expired?
|
||||
(if (or (not valid-wc-uri?) expired? (not version-supported?))
|
||||
{:fx [[:dispatch
|
||||
[:toasts/upsert
|
||||
{:type :negative
|
||||
:theme :dark
|
||||
:text (i18n/label :t/wallet-connect-qr-expired)}]]]}
|
||||
:text (cond (not valid-wc-uri?)
|
||||
(i18n/label :t/wallet-connect-wrong-qr)
|
||||
|
||||
(not version-supported?)
|
||||
{:fx [[:dispatch
|
||||
[:toasts/upsert
|
||||
{:type :negative
|
||||
:theme :dark
|
||||
:text (i18n/label :t/wallet-connect-version-not-supported
|
||||
{:version version})}]]]}
|
||||
expired?
|
||||
(i18n/label :t/wallet-connect-qr-expired)
|
||||
|
||||
:else
|
||||
(not version-supported?)
|
||||
(i18n/label :t/wallet-connect-version-not-supported
|
||||
{:version version}))}]]]}
|
||||
{:fx [[:dispatch [:wallet-connect/pair scanned-text]]]}))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/persist-session
|
||||
(fn [_ [{:keys [id dapp-name dapp-url session-info]}]]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wakuext_addWalletConnectSession"
|
||||
:params [{:id (str id)
|
||||
:dappName dapp-name
|
||||
:dappUrl dapp-url
|
||||
:info (-> session-info
|
||||
clj->js
|
||||
js/JSON.stringify)}]
|
||||
:on-success #(log/info "Wallet Connect session persisted")
|
||||
:on-error #(log/info "Wallet Connect session persistence failed" %)}]]]}))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/fetch-persisted-sessions-success
|
||||
(fn [{:keys [db]} [sessions]]
|
||||
@@ -236,6 +213,18 @@
|
||||
:wallet-connect/fetch-persisted-sessions
|
||||
(fn [_ _]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wakuext_getWalletConnectSession"
|
||||
[{:method "wallet_getWalletConnectActiveSessions"
|
||||
;; This is the activeSince timestamp to avoid expired sessions
|
||||
;; 0 means, return everything
|
||||
:params [0]
|
||||
:on-success [:wallet-connect/fetch-persisted-sessions-success]
|
||||
:on-error #(log/info "Wallet Connect fetch persisted sessions failed")}]]]}))
|
||||
:on-error #(log/info "Wallet Connect fetch persisted sessions failed" %)}]]]}))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/persist-session
|
||||
(fn [_ [session-info]]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wallet_addWalletConnectSession"
|
||||
:params [(js/JSON.stringify session-info)]
|
||||
:on-success #(log/info "Wallet Connect session persisted")
|
||||
:on-error #(log/info "Wallet Connect session persistence failed" %)}]]]}))
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
(ns status-im.contexts.wallet.wallet-connect.modals.common.page-nav.view
|
||||
(:require [quo.core :as quo]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn view
|
||||
[{:keys [accessibility-label]}]
|
||||
[quo/page-nav
|
||||
{:icon-name :i/close
|
||||
:background :blur
|
||||
:on-press #(do (rf/dispatch [:navigate-back])
|
||||
(rf/dispatch [:wallet-connect/reject-session-request]))
|
||||
:accessibility-label accessibility-label}])
|
||||
@@ -5,6 +5,7 @@
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.data-block.view :as data-block]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.footer.view :as footer]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.header.view :as header]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.page-nav.view :as page-nav]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
@@ -20,11 +21,8 @@
|
||||
error-state]} (rf/sub [:wallet-connect/current-request-transaction-information])]
|
||||
[rn/view {:style (style/container bottom)}
|
||||
[quo/gradient-cover {:customization-color customization-color}]
|
||||
[quo/page-nav
|
||||
{:icon-name :i/close
|
||||
:background :blur
|
||||
:on-press #(rf/dispatch [:navigate-back])
|
||||
:accessibility-label :wallet-connect-sign-message-close}]
|
||||
[page-nav/view
|
||||
{:accessibility-label :wallet-connect-sign-message-close}]
|
||||
[rn/view {:flex 1}
|
||||
[rn/view {:style style/data-content-container}
|
||||
[header/view
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.data-block.view :as data-block]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.footer.view :as footer]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.header.view :as header]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.page-nav.view :as page-nav]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
@@ -17,11 +18,8 @@
|
||||
dapp (rf/sub [:wallet-connect/current-request-dapp])]
|
||||
[rn/view {:style (style/container bottom)}
|
||||
[quo/gradient-cover {:customization-color customization-color}]
|
||||
[quo/page-nav
|
||||
{:icon-name :i/close
|
||||
:background :blur
|
||||
:on-press #(rf/dispatch [:navigate-back])
|
||||
:accessibility-label :wallet-connect-sign-message-close}]
|
||||
[page-nav/view
|
||||
{:accessibility-label :wallet-connect-sign-message-close}]
|
||||
[rn/view {:flex 1}
|
||||
[rn/view {:style style/sign-message-content-container}
|
||||
[header/view
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.data-block.view :as data-block]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.footer.view :as footer]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.header.view :as header]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.page-nav.view :as page-nav]
|
||||
[status-im.contexts.wallet.wallet-connect.modals.common.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
@@ -20,11 +21,8 @@
|
||||
error-state]} (rf/sub [:wallet-connect/current-request-transaction-information])]
|
||||
[rn/view {:style (style/container bottom)}
|
||||
[quo/gradient-cover {:customization-color customization-color}]
|
||||
[quo/page-nav
|
||||
{:icon-name :i/close
|
||||
:background :blur
|
||||
:on-press #(rf/dispatch [:navigate-back])
|
||||
:accessibility-label :wallet-connect-sign-message-close}]
|
||||
[page-nav/view
|
||||
{:accessibility-label :wallet-connect-sign-message-close}]
|
||||
[rn/view {:flex 1}
|
||||
[rn/view {:style style/data-content-container}
|
||||
[header/view
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns status-im.contexts.wallet.wallet-connect.responding-events
|
||||
(:require [re-frame.core :as rf]
|
||||
[react-native.wallet-connect :as wallet-connect]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core]
|
||||
[taoensso.timbre :as log]))
|
||||
@@ -37,8 +38,7 @@
|
||||
:address address
|
||||
:data raw-data
|
||||
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
|
||||
:on-success #(rf/dispatch [:wallet-connect/send-response %])}]]})))
|
||||
|
||||
:on-success #(rf/dispatch [:wallet-connect/send-response {:result %}])}]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/respond-personal-sign
|
||||
@@ -49,7 +49,7 @@
|
||||
:address address
|
||||
:data raw-data
|
||||
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
|
||||
:on-success #(rf/dispatch [:wallet-connect/send-response %])}]]})))
|
||||
:on-success #(rf/dispatch [:wallet-connect/send-response {:result %}])}]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/respond-sign-typed-data
|
||||
@@ -61,7 +61,7 @@
|
||||
:data raw-data
|
||||
:version typed-data-version
|
||||
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
|
||||
:on-success #(rf/dispatch [:wallet-connect/send-response %])}]]})))
|
||||
:on-success #(rf/dispatch [:wallet-connect/send-response {:result %}])}]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/respond-send-transaction-data
|
||||
@@ -73,7 +73,7 @@
|
||||
:chain-id chain-id
|
||||
:tx raw-data
|
||||
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
|
||||
:on-success #(rf/dispatch [:wallet-connect/send-response %])}]]})))
|
||||
:on-success #(rf/dispatch [:wallet-connect/send-response {:result %}])}]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/respond-sign-transaction-data
|
||||
@@ -85,7 +85,7 @@
|
||||
:chain-id chain-id
|
||||
:tx raw-data
|
||||
:on-error #(rf/dispatch [:wallet-connect/on-sign-error %])
|
||||
:on-success #(rf/dispatch [:wallet-connect/send-response %])}]]})))
|
||||
:on-success #(rf/dispatch [:wallet-connect/send-response {:result %}])}]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/on-sign-error
|
||||
@@ -104,10 +104,9 @@
|
||||
{:fx [[:dispatch [:dismiss-modal screen]]
|
||||
[:dispatch [:wallet-connect/reset-current-request]]]})))
|
||||
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/send-response
|
||||
(fn [{:keys [db]} [result]]
|
||||
(fn [{:keys [db]} [{:keys [result error]}]]
|
||||
(let [{:keys [id topic] :as event} (get-in db [:wallet-connect/current-request :event])
|
||||
method (wallet-connect-core/get-request-method event)
|
||||
screen (wallet-connect-core/method-to-screen method)
|
||||
@@ -117,6 +116,7 @@
|
||||
:topic topic
|
||||
:id id
|
||||
:result result
|
||||
:error error
|
||||
:on-error (fn [error]
|
||||
(log/error "Failed to send Wallet Connect response"
|
||||
{:error error
|
||||
@@ -129,3 +129,28 @@
|
||||
(log/info "Successfully sent Wallet Connect response to dApp")
|
||||
(rf/dispatch [:dismiss-modal screen])
|
||||
(rf/dispatch [:wallet-connect/reset-current-request]))}]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/reject-session-proposal
|
||||
(fn [{:keys [db]} _]
|
||||
(let [web3-wallet (get db :wallet-connect/web3-wallet)
|
||||
current-proposal (get-in db [:wallet-connect/current-proposal :request])]
|
||||
{:fx [[:effects.wallet-connect/reject-session-proposal
|
||||
{:web3-wallet web3-wallet
|
||||
:proposal current-proposal
|
||||
:on-success #(log/info "Wallet Connect session proposal rejected")
|
||||
:on-error #(log/error "Wallet Connect unable to reject session proposal")}]
|
||||
[:dispatch [:wallet-connect/reset-current-session]]]})))
|
||||
|
||||
;; NOTE: Currently we only reject a session if the user rejected it
|
||||
;; But this needs to be solidified to ensure other cases:
|
||||
;; - Unsupported WC version
|
||||
;; - Invalid params from dapps
|
||||
;; - Unsupported method
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/reject-session-request
|
||||
(fn [_ _]
|
||||
{:fx [[:dispatch
|
||||
[:wallet-connect/send-response
|
||||
{:error (wallet-connect/get-sdk-error
|
||||
constants/wallet-connect-user-rejected-error-key)}]]]}))
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
:accessibility-label :wc-deny-connection
|
||||
:on-press #(do (rf/dispatch [:navigate-back])
|
||||
(rf/dispatch
|
||||
[:wallet-connect/reset-current-session]))}
|
||||
[:wallet-connect/reject-session-proposal]))}
|
||||
:button-one-label (i18n/label :t/connect)
|
||||
:button-one-props {:customization-color customization-color
|
||||
:type :primary
|
||||
|
||||
@@ -11,6 +11,12 @@
|
||||
|
||||
(def ^:private initial-flags
|
||||
{::community.edit-account-selection (enabled-in-env? :FLAG_EDIT_ACCOUNT_SELECTION_ENABLED)
|
||||
|
||||
;; Feature toggled (off by default) because the desktop app disabled this
|
||||
;; feature and we want both clients in sync. We keep the code because it
|
||||
;; works and we may re-enable it by default.
|
||||
::profile-pictures-visibility (enabled-in-env? :FLAG_PROFILE_PICTURES_VISIBILITY_ENABLED)
|
||||
|
||||
::settings.import-all-keypairs (enabled-in-env?
|
||||
:FLAG_WALLET_SETTINGS_IMPORT_ALL_KEYPAIRS)
|
||||
::shell.jump-to (enabled-in-env? :ENABLE_JUMP_TO)
|
||||
|
||||
@@ -123,16 +123,6 @@
|
||||
(hide-bottom-sheet new-cofx)
|
||||
{:show-bottom-sheet {:theme theme}}))))))
|
||||
|
||||
(rf/defn dismiss-all-overlays
|
||||
{:events [:dismiss-all-overlays]}
|
||||
[_]
|
||||
{:dispatch-n [[:hide-popover]
|
||||
[:hide-visibility-status-popover]
|
||||
[:hide-bottom-sheet]
|
||||
[:bottom-sheet-hidden]
|
||||
[:bottom-sheet/hide-old-navigation-overlay]
|
||||
[:toasts/close-all-toasts]]})
|
||||
|
||||
(rf/defn set-view-id
|
||||
{:events [:set-view-id]}
|
||||
[{:keys [db]} view-id]
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user