Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47cc8a5757 |
@@ -273,9 +273,6 @@ run-re-frisk: ##@run Start re-frisk server
|
||||
|
||||
# TODO: Migrate this to a Nix recipe, much the same way as nix/mobile/android/targets/release-android.nix
|
||||
run-android: export TARGET := android
|
||||
# Disabled for debug builds to avoid 'maximum call stack exceeded' errors.
|
||||
# https://github.com/status-im/status-mobile/issues/18493
|
||||
run-android: export ORG_GRADLE_PROJECT_hermesEnabled := false
|
||||
# INFO: If it's empty (no devices attached, parsing issues, script error) - for Nix it's the same as not set.
|
||||
run-android: export ANDROID_ABI_INCLUDE ?= $(shell ./scripts/adb_devices_abis.sh)
|
||||
run-android: ##@run Build Android APK and start it on the device
|
||||
|
||||
@@ -57,6 +57,4 @@ newArchEnabled=false
|
||||
|
||||
# Use this property to enable or disable the Hermes JS engine.
|
||||
# If set to false, you will be using JSC instead.
|
||||
# Disabled for debug builds to avoid 'maximum call stack exceeded' errors.
|
||||
# https://github.com/status-im/status-mobile/issues/18493
|
||||
hermesEnabled=false
|
||||
hermesEnabled=true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.8.5'
|
||||
library 'status-jenkins-lib@v1.8.4'
|
||||
|
||||
/* Options section can't access functions in objects. */
|
||||
def isPRBuild = utils.isPRBuild()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.8.5'
|
||||
library 'status-jenkins-lib@v1.8.4'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.8.5'
|
||||
library 'status-jenkins-lib@v1.8.4'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.8.5'
|
||||
library 'status-jenkins-lib@v1.8.4'
|
||||
|
||||
/* Options section can't access functions in objects. */
|
||||
def isPRBuild = utils.isPRBuild()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.8.5'
|
||||
library 'status-jenkins-lib@v1.8.4'
|
||||
|
||||
/* Options section can't access functions in objects. */
|
||||
def isPRBuild = utils.isPRBuild()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.8.5'
|
||||
library 'status-jenkins-lib@v1.7.15'
|
||||
|
||||
pipeline {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.8.5'
|
||||
library 'status-jenkins-lib@v1.7.15'
|
||||
|
||||
pipeline {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.8.5'
|
||||
library 'status-jenkins-lib@v1.7.15'
|
||||
|
||||
pipeline {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.8.5'
|
||||
library 'status-jenkins-lib@v1.7.15'
|
||||
|
||||
pipeline {
|
||||
agent { label 'macos' }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.8.5'
|
||||
library 'status-jenkins-lib@v1.7.15'
|
||||
|
||||
pipeline {
|
||||
agent { label params.AGENT_LABEL }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.8.5'
|
||||
library 'status-jenkins-lib@v1.7.15'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env groovy
|
||||
library 'status-jenkins-lib@v1.8.5'
|
||||
library 'status-jenkins-lib@v1.7.15'
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
|
||||
@@ -79,9 +79,6 @@ in stdenv.mkDerivation rec {
|
||||
STATUS_GO_SRC_OVERRIDE = statusGoSrcOverride;
|
||||
ANDROID_ABI_SPLIT = androidAbiSplit;
|
||||
ANDROID_ABI_INCLUDE = androidAbiInclude;
|
||||
# Disabled for debug builds to avoid 'maximum call stack exceeded' errors.
|
||||
# https://github.com/status-im/status-mobile/issues/18493
|
||||
ORG_GRADLE_PROJECT_hermesEnabled = true;
|
||||
|
||||
# Fix for ERR_OSSL_EVP_UNSUPPORTED error.
|
||||
NODE_OPTIONS = "--openssl-legacy-provider";
|
||||
|
||||
@@ -33,17 +33,10 @@ trap "rm -vf ${SECRETS_FILE_PATH}" EXIT ERR INT QUIT
|
||||
|
||||
# Names of variables containing secrets to save in env file.
|
||||
SECRETS_ENV_VARS=(
|
||||
'ALCHEMY_ETHEREUM_MAINNET_TOKEN'
|
||||
'ALCHEMY_ETHEREUM_GOERLI_TOKEN'
|
||||
'ALCHEMY_ETHEREUM_SEPOLIA_TOKEN'
|
||||
'ALCHEMY_ARBITRUM_GOERLI_TOKEN'
|
||||
'ALCHEMY_ARBITRUM_MAINNET_TOKEN'
|
||||
'ALCHEMY_ARBITRUM_SEPOLIA_TOKEN'
|
||||
'ALCHEMY_OPTIMISM_GOERLI_TOKEN'
|
||||
'ALCHEMY_OPTIMISM_MAINNET_TOKEN'
|
||||
'ALCHEMY_OPTIMISM_SEPOLIA_TOKEN'
|
||||
'RARIBLE_MAINNET_API_KEY'
|
||||
'RARIBLE_TESTNET_API_KEY'
|
||||
'INFURA_TOKEN'
|
||||
'INFURA_TOKEN_SECRET'
|
||||
'OPENSEA_API_KEY'
|
||||
|
||||
+6
-27
@@ -63,17 +63,10 @@
|
||||
{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/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"
|
||||
status-im.config/ALCHEMY_ETHEREUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ETHEREUM_GOERLI_TOKEN"
|
||||
status-im.config/ALCHEMY_ETHEREUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ETHEREUM_SEPOLIA_TOKEN"
|
||||
status-im.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"
|
||||
status-im.config/ALCHEMY_ARBITRUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ARBITRUM_GOERLI_TOKEN"
|
||||
status-im.config/ALCHEMY_ARBITRUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ARBITRUM_SEPOLIA_TOKEN"
|
||||
status-im.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
|
||||
status-im.config/ALCHEMY_OPTIMISM_GOERLI_TOKEN #shadow/env "ALCHEMY_OPTIMISM_GOERLI_TOKEN"
|
||||
status-im.config/ALCHEMY_OPTIMISM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_OPTIMISM_SEPOLIA_TOKEN"}
|
||||
status-im.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
|
||||
status-im.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"}
|
||||
:compiler-options {:output-feature-set :es5
|
||||
;; We disable `:fn-deprecated` warnings because we
|
||||
;; are managing deprecation via clj-kondo and we
|
||||
@@ -97,17 +90,10 @@
|
||||
{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/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"
|
||||
status-im.config/ALCHEMY_ETHEREUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ETHEREUM_GOERLI_TOKEN"
|
||||
status-im.config/ALCHEMY_ETHEREUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ETHEREUM_SEPOLIA_TOKEN"
|
||||
status-im.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"
|
||||
status-im.config/ALCHEMY_ARBITRUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ARBITRUM_GOERLI_TOKEN"
|
||||
status-im.config/ALCHEMY_ARBITRUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ARBITRUM_SEPOLIA_TOKEN"
|
||||
status-im.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
|
||||
status-im.config/ALCHEMY_OPTIMISM_GOERLI_TOKEN #shadow/env "ALCHEMY_OPTIMISM_GOERLI_TOKEN"
|
||||
status-im.config/ALCHEMY_OPTIMISM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_OPTIMISM_SEPOLIA_TOKEN"}
|
||||
status-im.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
|
||||
status-im.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"}
|
||||
:compiler-options {:output-feature-set :es6
|
||||
;;disable for android build as there
|
||||
;;is an intermittent warning with deftype
|
||||
@@ -137,17 +123,10 @@
|
||||
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/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"
|
||||
status-im.config/ALCHEMY_ETHEREUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ETHEREUM_GOERLI_TOKEN"
|
||||
status-im.config/ALCHEMY_ETHEREUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ETHEREUM_SEPOLIA_TOKEN"
|
||||
status-im.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"
|
||||
status-im.config/ALCHEMY_ARBITRUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ARBITRUM_GOERLI_TOKEN"
|
||||
status-im.config/ALCHEMY_ARBITRUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ARBITRUM_SEPOLIA_TOKEN"
|
||||
status-im.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
|
||||
status-im.config/ALCHEMY_OPTIMISM_GOERLI_TOKEN #shadow/env "ALCHEMY_OPTIMISM_GOERLI_TOKEN"
|
||||
status-im.config/ALCHEMY_OPTIMISM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_OPTIMISM_SEPOLIA_TOKEN"}
|
||||
status-im.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
|
||||
status-im.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"}
|
||||
:compiler-options
|
||||
{;; needed because we override require and it
|
||||
;; messes with source-map which reports callstack
|
||||
|
||||
@@ -44,37 +44,22 @@
|
||||
[categ]
|
||||
(reduce-kv #(assoc %1 (name %2) %3) {} categ))
|
||||
|
||||
(defn role-permission?
|
||||
[token-permission]
|
||||
(contains? constants/community-role-permissions (:type token-permission)))
|
||||
|
||||
(defn membership-permission?
|
||||
[token-permission]
|
||||
(= (:type token-permission) constants/community-token-permission-become-member))
|
||||
|
||||
(defn <-rpc
|
||||
[c]
|
||||
(-> c
|
||||
(set/rename-keys
|
||||
{:canRequestAccess :can-request-access?
|
||||
:canManageUsers :can-manage-users?
|
||||
:canDeleteMessageForEveryone :can-delete-message-for-everyone?
|
||||
;; This flag is misleading based on its name alone
|
||||
;; because it should not be used to decide if the user
|
||||
;; is *allowed* to join. Allowance is based on token
|
||||
;; permissions. Still, the flag can be used to know
|
||||
;; whether or not the user will have to wait until an
|
||||
;; admin approves a join request.
|
||||
:canJoin :can-join?
|
||||
:requestedToJoinAt :requested-to-join-at
|
||||
:isMember :is-member?
|
||||
:adminSettings :admin-settings
|
||||
:tokenPermissions :token-permissions
|
||||
:communityTokensMetadata :tokens-metadata
|
||||
:introMessage :intro-message
|
||||
:muteTill :muted-till
|
||||
:lastOpenedAt :last-opened-at
|
||||
:joinedAt :joined-at})
|
||||
(set/rename-keys {:canRequestAccess :can-request-access?
|
||||
:canManageUsers :can-manage-users?
|
||||
:canDeleteMessageForEveryone :can-delete-message-for-everyone?
|
||||
:canJoin :can-join?
|
||||
:requestedToJoinAt :requested-to-join-at
|
||||
:isMember :is-member?
|
||||
:adminSettings :admin-settings
|
||||
:tokenPermissions :token-permissions
|
||||
:communityTokensMetadata :tokens-metadata
|
||||
:introMessage :intro-message
|
||||
:muteTill :muted-till
|
||||
:lastOpenedAt :last-opened-at
|
||||
:joinedAt :joined-at})
|
||||
(update :admin-settings
|
||||
set/rename-keys
|
||||
{:pinMessageAllMembersEnabled :pin-message-all-members-enabled?})
|
||||
@@ -82,16 +67,9 @@
|
||||
(update :chats <-chats-rpc)
|
||||
(update :token-permissions seq)
|
||||
(update :categories <-categories-rpc)
|
||||
(assoc :role-permissions?
|
||||
(->> c
|
||||
:tokenPermissions
|
||||
vals
|
||||
(some role-permission?)))
|
||||
(assoc :membership-permissions?
|
||||
(->> c
|
||||
:tokenPermissions
|
||||
vals
|
||||
(some membership-permission?)))
|
||||
(some #(= (:type %) constants/community-token-permission-become-member)
|
||||
(vals (:tokenPermissions c))))
|
||||
(assoc :token-images
|
||||
(reduce (fn [acc {sym :symbol image :image}]
|
||||
(assoc acc sym image))
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
transactions-management-enabled?
|
||||
current-fleet
|
||||
webview-debug
|
||||
test-networks-enabled?
|
||||
is-sepolia-enabled?]}]
|
||||
test-networks-enabled?]}]
|
||||
(keep
|
||||
identity
|
||||
[{:size :small
|
||||
@@ -111,14 +110,6 @@
|
||||
#(re-frame/dispatch [:profile.settings/toggle-test-networks])
|
||||
:accessory :switch
|
||||
:active test-networks-enabled?}
|
||||
{:size :small
|
||||
:title "Enable Sepolia as test network"
|
||||
:accessibility-label :enable-sepolia-as-test-network
|
||||
:container-margin-bottom 8
|
||||
:on-press
|
||||
#(re-frame/dispatch [:profile.settings/toggle-sepolia-test-network])
|
||||
:accessory :switch
|
||||
:active is-sepolia-enabled?}
|
||||
{:size :small
|
||||
:title (i18n/label :t/set-currency)
|
||||
:accessibility-label :wallet-change-currency
|
||||
@@ -139,7 +130,6 @@
|
||||
(views/defview advanced-settings
|
||||
[]
|
||||
(views/letsubs [test-networks-enabled? [:profile/test-networks-enabled?]
|
||||
is-sepolia-enabled? [:profile/is-sepolia-enabled?]
|
||||
light-client-enabled? [:profile/light-client-enabled?]
|
||||
webview-debug [:profile/webview-debug]
|
||||
network-name [:network-name]
|
||||
@@ -155,7 +145,6 @@
|
||||
:current-fleet current-fleet
|
||||
:dev-mode? false
|
||||
:webview-debug webview-debug
|
||||
:test-networks-enabled? test-networks-enabled?
|
||||
:is-sepolia-enabled? is-sepolia-enabled?})
|
||||
:test-networks-enabled? test-networks-enabled?})
|
||||
:key-fn (fn [_ i] (str i))
|
||||
:render-fn render-item}]))
|
||||
|
||||
@@ -3,11 +3,9 @@
|
||||
[quo.foundations.colors :as colors]))
|
||||
|
||||
(defn divider
|
||||
[theme blur?]
|
||||
[theme]
|
||||
{:border-top-width 1
|
||||
:border-top-color (if blur?
|
||||
colors/white-opa-5
|
||||
(colors/theme-colors colors/neutral-10 colors/neutral-90 theme))
|
||||
:border-top-color (colors/theme-colors colors/neutral-10 colors/neutral-90 theme)
|
||||
:margin-top 8
|
||||
:margin-bottom 7
|
||||
:align-items :center
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
|
||||
|
||||
(defn- divider
|
||||
[theme blur?]
|
||||
[theme]
|
||||
[rn/view
|
||||
{:style (style/divider theme blur?)
|
||||
{:style (style/divider theme)
|
||||
:accessible true
|
||||
:accessibility-label :divider}])
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
blur?]}]
|
||||
[:<>
|
||||
(when add-divider?
|
||||
[divider theme blur?])
|
||||
[divider theme])
|
||||
[maybe-pressable disabled?
|
||||
{:accessibility-label accessibility-label
|
||||
:style (style/container {:sub-label sub-label
|
||||
|
||||
@@ -182,7 +182,7 @@
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [title title-icon type theme description blur? community-name community-logo button-icon
|
||||
account-name emoji context-tag-type
|
||||
account-name emoji
|
||||
on-button-press
|
||||
on-button-long-press
|
||||
button-disabled? account-avatar-emoji account-avatar-type customization-color icon-avatar
|
||||
@@ -214,7 +214,6 @@
|
||||
:description description
|
||||
:community-name community-name
|
||||
:community-logo community-logo
|
||||
:context-tag-type context-tag-type
|
||||
:customization-color customization-color
|
||||
:account-name account-name
|
||||
:emoji emoji}]]
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
[:cat
|
||||
[:map {:closed true}
|
||||
[:size {:optional true :default 32} [:or keyword? pos-int?]]
|
||||
[:token {:optional true} [:maybe [:or keyword? string?]]]
|
||||
[:token {:optional true} [:or keyword? string?]]
|
||||
[:style {:optional true} map?]
|
||||
;; Ignores `token` and uses this as parameter to `rn/image`'s source.
|
||||
[:image-source {:optional true} [:maybe [:or :schema.common/image-source :string]]]]]
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
(ns quo.components.wallet.token-input.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[oops.core :as oops]
|
||||
[quo.components.buttons.button.view :as button]
|
||||
[quo.components.dividers.divider-line.view :as divider-line]
|
||||
[quo.components.markdown.text :as text]
|
||||
@@ -73,25 +72,18 @@
|
||||
[token-name-text theme text]])
|
||||
|
||||
(defn input-section
|
||||
[{:keys [on-change-text value value-atom on-selection-change]}]
|
||||
(let [input-ref (atom nil)
|
||||
set-ref #(reset! input-ref %)
|
||||
focus-input #(when-let [ref ^js @input-ref]
|
||||
(.focus ref))
|
||||
controlled-input? (some? value)
|
||||
handle-on-change-text (fn [v]
|
||||
(when-not controlled-input?
|
||||
(reset! value-atom v))
|
||||
(when on-change-text
|
||||
(on-change-text v)))
|
||||
handle-selection-change (fn [^js e]
|
||||
(when on-selection-change
|
||||
(-> e
|
||||
(oops/oget "nativeEvent.selection")
|
||||
(js->clj :keywordize-keys true)
|
||||
(on-selection-change))))]
|
||||
(fn [{:keys [theme token customization-color show-keyboard? crypto? currency value error?
|
||||
selection]
|
||||
[{:keys [on-change-text value value-atom]}]
|
||||
(let [input-ref (atom nil)
|
||||
set-ref #(reset! input-ref %)
|
||||
focus-input #(when-let [ref ^js @input-ref]
|
||||
(.focus ref))
|
||||
controlled-input? (some? value)
|
||||
handle-on-change-text (fn [v]
|
||||
(when-not controlled-input?
|
||||
(reset! value-atom v))
|
||||
(when on-change-text
|
||||
(on-change-text v)))]
|
||||
(fn [{:keys [theme token customization-color show-keyboard? crypto? currency value error?]
|
||||
:or {show-keyboard? true}}]
|
||||
[rn/pressable
|
||||
{:on-press focus-input
|
||||
@@ -110,9 +102,7 @@
|
||||
:max-length 12
|
||||
:on-change-text handle-on-change-text
|
||||
:selection-color customization-color
|
||||
:show-soft-input-on-focus show-keyboard?
|
||||
:on-selection-change handle-selection-change
|
||||
:selection (clj->js selection)}
|
||||
:show-soft-input-on-focus show-keyboard?}
|
||||
controlled-input? (assoc :value value)
|
||||
(not controlled-input?) (assoc :default-value @value-atom))]]
|
||||
[token-label
|
||||
@@ -121,32 +111,33 @@
|
||||
:value (if controlled-input? value @value-atom)}]])))
|
||||
|
||||
(defn- view-internal
|
||||
[]
|
||||
(let [width (:width (rn/get-window))
|
||||
value-atom (reagent/atom nil)
|
||||
crypto? (reagent/atom true)]
|
||||
(fn [{:keys [theme container-style value on-swap] :as props}]
|
||||
(let [handle-on-swap (fn []
|
||||
(swap! crypto? not)
|
||||
(when on-swap (on-swap @crypto?)))]
|
||||
[rn/view {:style (merge (style/main-container width) container-style)}
|
||||
[rn/view {:style style/amount-container}
|
||||
[input-section
|
||||
(assoc props
|
||||
:value-atom value-atom
|
||||
:crypto? @crypto?)]
|
||||
[button/button
|
||||
{:icon true
|
||||
:icon-only? true
|
||||
:size 32
|
||||
:on-press handle-on-swap
|
||||
:type :outline
|
||||
:accessibility-label :reorder}
|
||||
:i/reorder]]
|
||||
[divider-line/view {:container-style (style/divider theme)}]
|
||||
[data-info
|
||||
(assoc props
|
||||
:crypto? @crypto?
|
||||
:amount (or value @value-atom))]]))))
|
||||
[{:keys [on-swap]}]
|
||||
(let [width (:width (rn/get-window))
|
||||
value-atom (reagent/atom nil)
|
||||
crypto? (reagent/atom true)
|
||||
handle-on-swap (fn []
|
||||
(swap! crypto? not)
|
||||
(when on-swap
|
||||
(on-swap @crypto?)))]
|
||||
(fn [{:keys [theme container-style value] :as props}]
|
||||
[rn/view {:style (merge (style/main-container width) container-style)}
|
||||
[rn/view {:style style/amount-container}
|
||||
[input-section
|
||||
(assoc props
|
||||
:value-atom value-atom
|
||||
:crypto? @crypto?)]
|
||||
[button/button
|
||||
{:icon true
|
||||
:icon-only? true
|
||||
:size 32
|
||||
:on-press handle-on-swap
|
||||
:type :outline
|
||||
:accessibility-label :reorder}
|
||||
:i/reorder]]
|
||||
[divider-line/view {:container-style (style/divider theme)}]
|
||||
[data-info
|
||||
(assoc props
|
||||
:crypto? @crypto?
|
||||
:amount (or value @value-atom))]])))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -3,69 +3,62 @@
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.platform :as platform]
|
||||
[utils.number]))
|
||||
|
||||
;; Set radius coefficient based on Android Version.
|
||||
;; A good way to know is to check if shadow color is supported i.e API level 28 (Android 9) above
|
||||
(def ^:private shadow-radius-coefficient (if platform/is-shadow-color-supported? 0.8 0.1))
|
||||
|
||||
(defn- get-shadow-color
|
||||
"Calculates the shadow color based on a given color and opacity, with an optional coefficient.
|
||||
- Arity [color opacity]: Uses a default coefficient value of 5 (empirically determined) to compute the shadow color.
|
||||
- Arity [color opacity coefficient]: Uses the specified coefficient to compute the shadow color.
|
||||
On Android platforms, the shadow color's alpha is adjusted based on the product of opacity and
|
||||
coefficient, constrained between 0 and 1. Returns a map with :shadow-color and :shadow-opacity keys."
|
||||
([color opacity]
|
||||
(get-shadow-color color opacity 5))
|
||||
([color opacity coefficient]
|
||||
{:shadow-color (if platform/android?
|
||||
(colors/alpha color (utils.number/value-in-range (* opacity coefficient) 0 1))
|
||||
color)
|
||||
:shadow-opacity opacity}))
|
||||
|
||||
(defn- get-shadow-radius
|
||||
"Computes shadow radius and elevation properties based on a given radius, with an optional coefficient.
|
||||
- Arity [radius]: Uses a default coefficient of 0.8 for API level 28 and above and 0.1 otherwise (empirically determined) to compute the elevation.
|
||||
- Arity [radius coefficient]: Uses the specified coefficient to compute the elevation.
|
||||
Returns a map with :elevation, computed as the product of radius and coefficient, and :shadow-radius keys."
|
||||
([radius]
|
||||
(get-shadow-radius radius shadow-radius-coefficient))
|
||||
([radius coefficient]
|
||||
{:elevation (* radius coefficient)
|
||||
:shadow-radius radius}))
|
||||
[react-native.platform :as platform]))
|
||||
|
||||
(def ^:private shadows
|
||||
(let [dark-normal {1 (merge {:shadow-offset {:width 0 :height 4}}
|
||||
(get-shadow-color colors/neutral-100 0.5)
|
||||
(get-shadow-radius 20))
|
||||
2 (merge {:shadow-offset {:width 0 :height 4}}
|
||||
(get-shadow-color colors/neutral-100 0.64)
|
||||
(get-shadow-radius 20))
|
||||
3 (merge {:shadow-offset {:width 0 :height 12}}
|
||||
(get-shadow-color colors/neutral-100 0.64)
|
||||
(get-shadow-radius 20))
|
||||
4 (merge {:shadow-offset {:width 0 :height 16}}
|
||||
(get-shadow-color colors/neutral-100 0.72)
|
||||
(get-shadow-radius 20))}
|
||||
(let [dark-normal {1 {:shadow-color (when platform/ios?
|
||||
(colors/alpha colors/neutral-100 0.5))
|
||||
:shadow-offset {:width 0 :height 4}
|
||||
:elevation 3
|
||||
:shadow-opacity 1
|
||||
:shadow-radius 20}
|
||||
2 {:shadow-color (when platform/ios?
|
||||
(colors/alpha colors/neutral-100 0.64))
|
||||
:shadow-offset {:width 0 :height 4}
|
||||
:elevation 4
|
||||
:shadow-opacity 1
|
||||
:shadow-radius 20}
|
||||
3 {:shadow-color (when platform/ios?
|
||||
(colors/alpha colors/neutral-100 0.64))
|
||||
:shadow-offset {:width 0 :height 12}
|
||||
:elevation 8
|
||||
:shadow-opacity 1
|
||||
:shadow-radius 20}
|
||||
4 {:shadow-color (when platform/ios?
|
||||
(colors/alpha colors/neutral-100 0.72))
|
||||
:shadow-offset {:width 0 :height 16}
|
||||
:shadow-opacity 1
|
||||
:shadow-radius 20
|
||||
:elevation 15}}
|
||||
dark-normal-inverted (-> dark-normal
|
||||
(update-in [:soft :shadow-offset :height] -)
|
||||
(update-in [:medium :shadow-offset :height] -)
|
||||
(update-in [:intense :shadow-offset :height] -)
|
||||
(update-in [:strong :shadow-offset :height] -))
|
||||
light-normal {1 (merge {:shadow-offset {:width 0 :height 4}}
|
||||
(get-shadow-color colors/neutral-100 0.04)
|
||||
(get-shadow-radius 16))
|
||||
|
||||
2 (merge {:shadow-offset {:width 0 :height 4}}
|
||||
(get-shadow-color colors/neutral-100 0.08)
|
||||
(get-shadow-radius 16))
|
||||
3 (merge {:shadow-offset {:width 0 :height 12}}
|
||||
(get-shadow-color colors/neutral-100 0.12)
|
||||
(get-shadow-radius 16))
|
||||
4 (merge {:shadow-offset {:width 0 :height 16}}
|
||||
(get-shadow-color colors/neutral-100 0.16)
|
||||
(get-shadow-radius 16))}
|
||||
light-normal {1 {:shadow-color (when platform/ios?
|
||||
(colors/alpha colors/neutral-100 0.04))
|
||||
:shadow-offset {:width 0 :height 4}
|
||||
:elevation 1
|
||||
:shadow-opacity 1
|
||||
:shadow-radius 16}
|
||||
2 {:shadow-color (when platform/ios?
|
||||
(colors/alpha colors/neutral-100 0.08))
|
||||
:shadow-offset {:width 0 :height 4}
|
||||
:elevation 6
|
||||
:shadow-opacity 1
|
||||
:shadow-radius 16}
|
||||
3 {:shadow-color (when platform/ios?
|
||||
(colors/alpha colors/neutral-100 0.12))
|
||||
:shadow-offset {:width 0 :height 12}
|
||||
:elevation 8
|
||||
:shadow-opacity 1
|
||||
:shadow-radius 16}
|
||||
4 {:shadow-color (when platform/ios?
|
||||
(colors/alpha colors/neutral-100 0.16))
|
||||
:shadow-offset {:width 0 :height 16}
|
||||
:shadow-opacity 1
|
||||
:shadow-radius 16
|
||||
:elevation 13}}
|
||||
light-normal-inverted (-> light-normal
|
||||
(update-in [:soft :shadow-offset :height] -)
|
||||
(update-in [:medium :shadow-offset :height] -)
|
||||
|
||||
@@ -14,5 +14,3 @@
|
||||
(def low-device? (and android? (< version 29)))
|
||||
|
||||
(def is-below-android-13? (and android? (< version 33)))
|
||||
|
||||
(def is-shadow-color-supported? (and android? (> version 27)))
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
[status-im.common.lightbox.animations :as anim]
|
||||
[status-im.common.lightbox.constants :as constants]
|
||||
[status-im.common.lightbox.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.url :as url]))
|
||||
|
||||
@@ -39,6 +40,25 @@
|
||||
(anim/animate top-view-width screen-width)
|
||||
(anim/animate top-view-bg colors/neutral-100-opa-0)))))
|
||||
|
||||
(defn drawer
|
||||
[images index]
|
||||
(let [{:keys [image]} (nth images index)
|
||||
uri (url/replace-port image (rf/sub [:mediaserver/port]))]
|
||||
[quo/action-drawer
|
||||
[[{:icon :i/save
|
||||
:accessibility-label :save-image
|
||||
:label (i18n/label :t/save-image-library)
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch
|
||||
[:lightbox/save-image-to-gallery
|
||||
uri
|
||||
#(rf/dispatch [:toasts/upsert
|
||||
{:id :random-id
|
||||
:type :positive
|
||||
:container-style {:bottom (when platform/android? 20)}
|
||||
:text (i18n/label :t/photo-saved)}])]))}]]]))
|
||||
|
||||
(defn share-image
|
||||
[images index]
|
||||
(let [{:keys [image]} (nth images index)
|
||||
@@ -46,7 +66,7 @@
|
||||
(rf/dispatch [:lightbox/share-image uri])))
|
||||
|
||||
(defn top-view
|
||||
[images insets index animations derived landscape? screen-width on-options-press]
|
||||
[images insets index animations derived landscape? screen-width]
|
||||
(let [{:keys [description header]} (nth images @index)
|
||||
bg-color (if landscape?
|
||||
colors/neutral-100-opa-70
|
||||
@@ -93,6 +113,7 @@
|
||||
[rn/touchable-opacity
|
||||
{:active-opacity 1
|
||||
:accessibility-label :image-options
|
||||
:on-press #(on-options-press images @index)
|
||||
:on-press #(rf/dispatch [:show-bottom-sheet
|
||||
{:content (fn [] [drawer images @index])}])
|
||||
:style style/close-container}
|
||||
[quo/icon :options {:size 20 :color colors/white}]]]]))
|
||||
|
||||
@@ -44,8 +44,7 @@
|
||||
[rn/view {:style {:width constants/separator-width}}]])
|
||||
|
||||
(defn lightbox-content
|
||||
[{:keys [props state animations derived images index handle-items-changed bottom-text-component
|
||||
on-options-press]}]
|
||||
[{:keys [props state animations derived images index handle-items-changed bottom-text-component]}]
|
||||
(let [{:keys [data transparent? scroll-index
|
||||
set-full-height?]} state
|
||||
insets (safe-area/get-insets)
|
||||
@@ -70,7 +69,7 @@
|
||||
{:height screen-height})}
|
||||
(when-not @transparent?
|
||||
[:f> top-view/top-view images insets scroll-index animations derived landscape?
|
||||
screen-width on-options-press])
|
||||
screen-width])
|
||||
[gesture/gesture-detector
|
||||
{:gesture (utils/drag-gesture animations (and landscape? platform/ios?) set-full-height?)}
|
||||
[reanimated/view
|
||||
@@ -137,8 +136,7 @@
|
||||
|
||||
(defn- f-lightbox
|
||||
[]
|
||||
(let [{:keys [images index bottom-text-component on-options-press]}
|
||||
(rf/sub [:get-screen-params])
|
||||
(let [{:keys [images index bottom-text-component]} (rf/sub [:get-screen-params])
|
||||
props
|
||||
(utils/init-props)
|
||||
state
|
||||
@@ -162,8 +160,7 @@
|
||||
:images images
|
||||
:index index
|
||||
:handle-items-changed handle-items-changed
|
||||
:bottom-text-component bottom-text-component
|
||||
:on-options-press on-options-press}]))))
|
||||
:bottom-text-component bottom-text-component}]))))
|
||||
|
||||
(defn lightbox
|
||||
[]
|
||||
|
||||
@@ -26,8 +26,7 @@
|
||||
:discover (js/require "../resources/images/ui2/discover.png")
|
||||
:invite-friends (js/require "../resources/images/ui2/invite-friends.png")
|
||||
:transaction-progress (js/require "../resources/images/ui2/transaction-progress.png")
|
||||
:welcome-illustration (js/require "../resources/images/ui2/welcome_illustration.png")
|
||||
:notifications (js/require "../resources/images/ui2/notifications.png")})
|
||||
:welcome-illustration (js/require "../resources/images/ui2/welcome_illustration.png")})
|
||||
|
||||
(def ui-themed
|
||||
{:angry-man
|
||||
|
||||
@@ -11,18 +11,11 @@
|
||||
|
||||
(goog-define INFURA_TOKEN "")
|
||||
(goog-define POKT_TOKEN "3ef2018191814b7e1009b8d9")
|
||||
(goog-define OPENSEA_API_KEY "")
|
||||
(goog-define RARIBLE_MAINNET_API_KEY "")
|
||||
(goog-define RARIBLE_TESTNET_API_KEY "")
|
||||
(goog-define ALCHEMY_ETHEREUM_MAINNET_TOKEN "")
|
||||
(goog-define ALCHEMY_ETHEREUM_GOERLI_TOKEN "")
|
||||
(goog-define ALCHEMY_ETHEREUM_SEPOLIA_TOKEN "")
|
||||
(goog-define ALCHEMY_ARBITRUM_MAINNET_TOKEN "")
|
||||
(goog-define ALCHEMY_ARBITRUM_GOERLI_TOKEN "")
|
||||
(goog-define ALCHEMY_ARBITRUM_SEPOLIA_TOKEN "")
|
||||
(goog-define ALCHEMY_OPTIMISM_MAINNET_TOKEN "")
|
||||
(goog-define ALCHEMY_OPTIMISM_GOERLI_TOKEN "")
|
||||
(goog-define ALCHEMY_OPTIMISM_SEPOLIA_TOKEN "")
|
||||
(goog-define ALCHEMY_OPTIMISM_MAINNET_TOKEN "")
|
||||
(goog-define ALCHEMY_ARBITRUM_MAINNET_TOKEN "")
|
||||
(goog-define OPENSEA_API_KEY "")
|
||||
|
||||
(def mainnet-rpc-url (str "https://eth-archival.gateway.pokt.network/v1/lb/" POKT_TOKEN))
|
||||
(def goerli-rpc-url (str "https://goerli-archival.gateway.pokt.network/v1/lb/" POKT_TOKEN))
|
||||
@@ -167,7 +160,7 @@
|
||||
|
||||
(def default-kdf-iterations 3200)
|
||||
|
||||
(def community-accounts-selection-enabled? (enabled? (get-config :ACCOUNT_SELECTION_ENABLED "0")))
|
||||
(def community-accounts-selection-enabled? false)
|
||||
(def fetch-messages-enabled? (enabled? (get-config :FETCH_MESSAGES_ENABLED "1")))
|
||||
|
||||
(def wallet-feature-flags
|
||||
|
||||
@@ -153,11 +153,6 @@
|
||||
(def ^:const community-token-permission-can-view-and-post-channel 4)
|
||||
(def ^:const community-token-permission-become-token-master 5)
|
||||
(def ^:const community-token-permission-become-token-owner 6)
|
||||
(def ^:const community-role-permissions
|
||||
#{community-token-permission-become-admin
|
||||
community-token-permission-become-member
|
||||
community-token-permission-become-token-master
|
||||
community-token-permission-become-token-owner})
|
||||
|
||||
;; Community rules for joining
|
||||
(def ^:const community-rule-ens-only "ens-only")
|
||||
@@ -410,15 +405,12 @@
|
||||
(def ^:const ens-action-type-set-pub-key 2)
|
||||
|
||||
;; wallet
|
||||
(def ^:const ethereum-mainnet-chain-id 1)
|
||||
(def ^:const ethereum-goerli-chain-id 5)
|
||||
(def ^:const ethereum-sepolia-chain-id 11155111)
|
||||
(def ^:const arbitrum-mainnet-chain-id 42161)
|
||||
(def ^:const arbitrum-goerli-chain-id 421613)
|
||||
(def ^:const arbitrum-sepolia-chain-id 421614)
|
||||
(def ^:const optimism-mainnet-chain-id 10)
|
||||
(def ^:const optimism-goerli-chain-id 420)
|
||||
(def ^:const optimism-sepolia-chain-id 11155420)
|
||||
(def ^:const mainnet-chain-id 1)
|
||||
(def ^:const optimism-chain-id 10)
|
||||
(def ^:const optimism-test-chain-id 420)
|
||||
(def ^:const arbitrum-chain-id 42161)
|
||||
(def ^:const arbitrum-test-chain-id 421613)
|
||||
(def ^:const goerli-chain-id 5)
|
||||
|
||||
(def ^:const mainnet-short-name "eth")
|
||||
(def ^:const optimism-short-name "opt")
|
||||
|
||||
@@ -66,12 +66,7 @@
|
||||
album-messages))
|
||||
:bottom-text-component
|
||||
[lightbox/bottom-text-for-lightbox
|
||||
first-image]
|
||||
:on-options-press (fn [images index]
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:content (fn [] [lightbox/drawer
|
||||
images
|
||||
index])}]))}])}
|
||||
first-image]}])}
|
||||
[fast-image/fast-image
|
||||
{:style (style/image dimensions index portrait? images-count)
|
||||
:source {:uri (url/replace-port (:image (:content item)) media-server-port)}
|
||||
|
||||
@@ -57,13 +57,7 @@
|
||||
:index 0
|
||||
:insets insets
|
||||
:bottom-text-component
|
||||
[lightbox/bottom-text-for-lightbox message]
|
||||
:on-options-press (fn [images index]
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:content (fn []
|
||||
[lightbox/drawer
|
||||
images
|
||||
index])}]))}])}
|
||||
[lightbox/bottom-text-for-lightbox message]}])}
|
||||
[fast-image/fast-image
|
||||
{:source {:uri image-local-url}
|
||||
:style (merge dimensions {:border-radius 12})
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
(ns status-im.contexts.chat.messenger.messages.content.lightbox.view
|
||||
(:require
|
||||
[oops.core :as oops]
|
||||
[quo.core :as quo]
|
||||
[react-native.platform :as platform]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.common.lightbox.constants :as constants]
|
||||
[status-im.contexts.chat.messenger.messages.content.lightbox.style :as style]
|
||||
[status-im.contexts.chat.messenger.messages.content.text.view :as message-view]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.url :as url]))
|
||||
[status-im.contexts.chat.messenger.messages.content.text.view :as message-view]))
|
||||
|
||||
(defn bottom-text-for-lightbox
|
||||
[_]
|
||||
@@ -21,22 +16,3 @@
|
||||
:chat-id chat-id
|
||||
:style-override (style/bottom-text expandable-text?)
|
||||
:on-layout #(reset! text-height (oops/oget % "nativeEvent.layout.height"))}]))))
|
||||
|
||||
(defn drawer
|
||||
[images index]
|
||||
(let [{:keys [image]} (nth images index)
|
||||
uri (url/replace-port image (rf/sub [:mediaserver/port]))]
|
||||
[quo/action-drawer
|
||||
[[{:icon :i/save
|
||||
:accessibility-label :save-image
|
||||
:label (i18n/label :t/save-image-library)
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch
|
||||
[:lightbox/save-image-to-gallery
|
||||
uri
|
||||
#(rf/dispatch [:toasts/upsert
|
||||
{:id :random-id
|
||||
:type :positive
|
||||
:container-style {:bottom (when platform/android? 20)}
|
||||
:text (i18n/label :t/photo-saved)}])]))}]]]))
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
[quo/drawer-top
|
||||
{:type :context-tag
|
||||
:title (i18n/label :t/addresses-for-permissions)
|
||||
:context-tag-type :community
|
||||
:community-name name
|
||||
:button-icon :i/info
|
||||
:on-button-press not-implemented/alert
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
[:<>
|
||||
[quo/drawer-top
|
||||
{:type :context-tag
|
||||
:context-tag-type :community
|
||||
:title (i18n/label :t/airdrop-addresses)
|
||||
:community-name name
|
||||
:button-icon :i/info
|
||||
|
||||
@@ -23,8 +23,10 @@
|
||||
(defn- view-internal
|
||||
[{:keys [theme]}]
|
||||
(fn []
|
||||
(let [{:keys [id]} (rf/sub [:get-screen-params])
|
||||
{:keys [color name images]} (rf/sub [:communities/community id])]
|
||||
(let [{:keys [name
|
||||
id
|
||||
images]} (rf/sub [:get-screen-params])
|
||||
{:keys [color]} (rf/sub [:communities/community id])]
|
||||
[rn/safe-area-view {:flex 1}
|
||||
[gesture/scroll-view {:style style/container}
|
||||
[rn/view style/page-container
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.common.home.actions.view :as actions]
|
||||
[status-im.common.password-authentication.view :as password-authentication]
|
||||
[status-im.common.scroll-page.style :as scroll-page.style]
|
||||
[status-im.common.scroll-page.view :as scroll-page]
|
||||
[status-im.config :as config]
|
||||
@@ -14,20 +15,38 @@
|
||||
[status-im.contexts.communities.actions.chat.view :as chat-actions]
|
||||
[status-im.contexts.communities.actions.community-options.view :as options]
|
||||
[status-im.contexts.communities.overview.style :as style]
|
||||
[status-im.contexts.communities.overview.utils :as utils]
|
||||
[status-im.contexts.communities.utils :as communities.utils]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- add-category-height
|
||||
[categories-heights category height]
|
||||
(swap! categories-heights assoc category height))
|
||||
(defn preview-user-list
|
||||
[user-list]
|
||||
(when (seq user-list)
|
||||
[rn/view style/preview-user
|
||||
[quo/preview-list
|
||||
{:type :user
|
||||
:number (count user-list)
|
||||
:size :size-24}
|
||||
user-list]
|
||||
[quo/text
|
||||
{:accessibility-label :communities-screen-title
|
||||
:style {:margin-left 8}
|
||||
:size :label}
|
||||
(utils/join-existing-users-string user-list)]]))
|
||||
|
||||
(defn- collapse-category
|
||||
(defn add-category-height
|
||||
[categories-heights category height]
|
||||
(swap! categories-heights
|
||||
(fn [heights]
|
||||
(assoc heights category height))))
|
||||
|
||||
(defn collapse-category
|
||||
[community-id category-id collapsed?]
|
||||
(rf/dispatch [:communities/toggle-collapsed-category community-id category-id (not collapsed?)]))
|
||||
|
||||
(defn- layout-y
|
||||
(defn layout-y
|
||||
[event]
|
||||
(oops/oget event "nativeEvent.layout.y"))
|
||||
|
||||
@@ -58,7 +77,7 @@
|
||||
{:on-press on-press
|
||||
:on-long-press #(rf/dispatch [:show-bottom-sheet channel-sheet-data])})]]))
|
||||
|
||||
(defn- channel-list-component
|
||||
(defn channel-list-component
|
||||
[{:keys [on-category-layout community-id community-color on-first-channel-height-changed]}
|
||||
channels-list]
|
||||
[rn/view
|
||||
@@ -85,7 +104,7 @@
|
||||
^{:key (:id chat)}
|
||||
[channel-chat-item community-id community-color chat])])])])
|
||||
|
||||
(defn- get-access-type
|
||||
(defn get-access-type
|
||||
[access]
|
||||
(condp = access
|
||||
constants/community-no-membership-access :open
|
||||
@@ -93,9 +112,17 @@
|
||||
constants/community-on-request-access :request-access
|
||||
:unknown-access))
|
||||
|
||||
(defn- info-button
|
||||
(defn join-gated-community
|
||||
[id]
|
||||
(rf/dispatch [:password-authentication/show
|
||||
{:content (fn [] [password-authentication/view])}
|
||||
{:label (i18n/label :t/join-open-community)
|
||||
:on-press #(rf/dispatch [:communities/request-to-join
|
||||
{:community-id id :password %}])}]))
|
||||
|
||||
(defn info-button
|
||||
[]
|
||||
[rn/pressable
|
||||
[rn/touchable-without-feedback
|
||||
{:on-press
|
||||
#(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
@@ -110,116 +137,119 @@
|
||||
[rn/view
|
||||
[quo/icon :i/info {:no-color true}]]])
|
||||
|
||||
(defn- token-requirements
|
||||
[{:keys [id color]}]
|
||||
(let [{:keys [can-request-access?
|
||||
number-of-hold-tokens tokens
|
||||
highest-permission-role]} (rf/sub [:community/token-gated-overview id])
|
||||
highest-role-text
|
||||
(i18n/label
|
||||
(communities.utils/role->translation-key highest-permission-role :t/member))]
|
||||
[rn/view {:style (style/token-gated-container)}
|
||||
[rn/view
|
||||
{:style {:padding-horizontal 12
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :space-between
|
||||
:flex 1}}
|
||||
[quo/text {:weight :medium}
|
||||
(if can-request-access?
|
||||
(i18n/label :t/you-eligible-to-join-as {:role highest-role-text})
|
||||
(i18n/label :t/you-not-eligible-to-join))]
|
||||
[info-button]]
|
||||
(when (pos? number-of-hold-tokens)
|
||||
[quo/text {:style {:padding-horizontal 12 :padding-bottom 18} :size :paragraph-2}
|
||||
(if can-request-access?
|
||||
(i18n/label :t/you-hold-number-of-hold-tokens-of-these
|
||||
{:number-of-hold-tokens number-of-hold-tokens})
|
||||
(i18n/label :t/you-must-hold))])
|
||||
[quo/token-requirement-list
|
||||
{:tokens tokens
|
||||
:padding? true}]
|
||||
[quo/button
|
||||
{:on-press (if config/community-accounts-selection-enabled?
|
||||
#(rf/dispatch [:open-modal :community-account-selection
|
||||
{:community-id id}])
|
||||
#(rf/dispatch [:open-modal :community-requests-to-join {:id id}]))
|
||||
:accessibility-label :join-community-button
|
||||
:customization-color color
|
||||
:container-style {:margin-horizontal 12 :margin-top 12 :margin-bottom 12}
|
||||
:disabled? (not can-request-access?)
|
||||
:icon-left (if can-request-access? :i/unlocked :i/locked)}
|
||||
(i18n/label :t/join-open-community)]]))
|
||||
(defn token-gates
|
||||
[]
|
||||
(fn [{:keys [id color]}]
|
||||
(let [{:keys [can-request-access?
|
||||
number-of-hold-tokens tokens
|
||||
highest-permission-role]} (rf/sub [:community/token-gated-overview id])
|
||||
highest-role-text
|
||||
(i18n/label
|
||||
(communities.utils/role->translation-key highest-permission-role :t/member))]
|
||||
[rn/view {:style (style/token-gated-container)}
|
||||
[rn/view
|
||||
{:style {:padding-horizontal 12
|
||||
:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :space-between
|
||||
:flex 1}}
|
||||
[quo/text {:weight :medium}
|
||||
(if can-request-access?
|
||||
(i18n/label :t/you-eligible-to-join-as {:role highest-role-text})
|
||||
(i18n/label :t/you-not-eligible-to-join))]
|
||||
[info-button]]
|
||||
(when (pos? number-of-hold-tokens)
|
||||
[quo/text {:style {:padding-horizontal 12 :padding-bottom 18} :size :paragraph-2}
|
||||
(if can-request-access?
|
||||
(i18n/label :t/you-hold-number-of-hold-tokens-of-these
|
||||
{:number-of-hold-tokens number-of-hold-tokens})
|
||||
(i18n/label :t/you-must-hold))])
|
||||
[quo/token-requirement-list
|
||||
{:tokens tokens
|
||||
:padding? true}]
|
||||
[quo/button
|
||||
{:on-press
|
||||
(if config/community-accounts-selection-enabled?
|
||||
#(rf/dispatch [:open-modal :community-account-selection {:community-id id}])
|
||||
#(join-gated-community id))
|
||||
:accessibility-label :join-community-button
|
||||
:customization-color color
|
||||
:container-style {:margin-horizontal 12 :margin-top 12 :margin-bottom 12}
|
||||
:disabled? (not can-request-access?)
|
||||
:icon-left (if can-request-access? :i/unlocked :i/locked)}
|
||||
(i18n/label :t/join-open-community)]])))
|
||||
|
||||
(defn- join-community
|
||||
[{:keys [id color joined permissions role-permissions? can-join?] :as community}]
|
||||
(let [pending? (rf/sub [:communities/my-pending-request-to-join id])
|
||||
access-type (get-access-type (:access permissions))
|
||||
(defn join-community
|
||||
[{:keys [joined color permissions token-permissions membership-permissions? id] :as community}
|
||||
pending?]
|
||||
(let [access-type (get-access-type (:access permissions))
|
||||
unknown-access? (= access-type :unknown-access)
|
||||
invite-only? (= access-type :invite-only)]
|
||||
[:<>
|
||||
(when-not (or joined pending? invite-only? unknown-access?)
|
||||
(if role-permissions?
|
||||
[token-requirements community]
|
||||
(if membership-permissions?
|
||||
[token-gates community]
|
||||
[quo/button
|
||||
{:on-press (if config/community-accounts-selection-enabled?
|
||||
#(rf/dispatch [:open-modal :community-account-selection
|
||||
{:community-id id}])
|
||||
#(rf/dispatch [:open-modal :community-requests-to-join {:id id}]))
|
||||
{:on-press
|
||||
(if config/community-accounts-selection-enabled?
|
||||
#(rf/dispatch [:open-modal :community-account-selection {:community-id id}])
|
||||
#(rf/dispatch [:open-modal :community-requests-to-join community]))
|
||||
|
||||
:accessibility-label :show-request-to-join-screen-button
|
||||
:customization-color color
|
||||
:icon-left :i/communities}
|
||||
:icon-left :i/communities}
|
||||
(i18n/label :t/request-to-join)]))
|
||||
(when (not (or pending? role-permissions? can-join?))
|
||||
|
||||
(when (not (or joined pending? token-permissions))
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :regular
|
||||
:style style/review-notice}
|
||||
(i18n/label :t/community-admins-will-review-your-request)])]))
|
||||
|
||||
(defn- status-tag
|
||||
[community-id joined]
|
||||
(let [pending? (rf/sub [:communities/my-pending-request-to-join community-id])]
|
||||
(when (or pending? joined)
|
||||
[rn/view {:style {:position :absolute :top 12 :right 12}}
|
||||
[quo/status-tag
|
||||
{:status {:type (if joined :positive :pending)}
|
||||
:label (if joined
|
||||
(i18n/label :t/joined)
|
||||
(i18n/label :t/pending))}]])))
|
||||
(defn status-tag
|
||||
[pending? joined]
|
||||
(when (or pending? joined)
|
||||
[rn/view {:style {:position :absolute :top 12 :right 12}}
|
||||
[quo/status-tag
|
||||
{:status {:type (if joined :positive :pending)}
|
||||
:label (if joined
|
||||
(i18n/label :t/joined)
|
||||
(i18n/label :t/pending))}]]))
|
||||
|
||||
(defn- add-handlers
|
||||
(defn add-handlers
|
||||
[community-id
|
||||
joined-or-spectated
|
||||
{:keys [id locked?]
|
||||
:or {locked? false}
|
||||
:as chat}]
|
||||
(cond-> chat
|
||||
(and (not locked?) id)
|
||||
(assoc :on-press (when joined-or-spectated
|
||||
(fn []
|
||||
(rf/dispatch [:dismiss-keyboard])
|
||||
(debounce/dispatch-and-chill
|
||||
[:communities/navigate-to-community-chat (str community-id id)]
|
||||
1000)))
|
||||
:on-long-press #(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content (fn []
|
||||
[chat-actions/actions chat false])}])
|
||||
:community-id community-id)))
|
||||
(merge
|
||||
chat
|
||||
(when (and (not locked?) id)
|
||||
{:on-press (when joined-or-spectated
|
||||
(fn []
|
||||
(rf/dispatch [:dismiss-keyboard])
|
||||
(debounce/dispatch-and-chill
|
||||
[:communities/navigate-to-community-chat (str community-id id)]
|
||||
1000)))
|
||||
:on-long-press #(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content (fn []
|
||||
[chat-actions/actions chat false])}])
|
||||
:community-id community-id})))
|
||||
|
||||
(defn- add-handlers-to-chats
|
||||
(defn add-handlers-to-chats
|
||||
[community-id joined-or-spectated chats]
|
||||
(mapv (partial add-handlers community-id joined-or-spectated) chats))
|
||||
|
||||
(defn- add-handlers-to-categorized-chats
|
||||
(defn add-handlers-to-categorized-chats
|
||||
[community-id categorized-chats joined-or-spectated]
|
||||
(let [add-on-press (partial add-handlers-to-chats community-id joined-or-spectated)]
|
||||
(map (fn [[category v]]
|
||||
[category (update v :chats add-on-press)])
|
||||
categorized-chats)))
|
||||
|
||||
(defn- community-header
|
||||
(defn community-header
|
||||
[title logo description]
|
||||
[quo/text-combinations
|
||||
{:container-style
|
||||
@@ -236,11 +266,11 @@
|
||||
:title-accessibility-label :community-title
|
||||
:description-accessibility-label :community-description}])
|
||||
|
||||
(defn- community-content
|
||||
[{:keys [id]}]
|
||||
(rf/dispatch [:communities/check-all-community-channels-permissions id])
|
||||
(fn [{:keys [name description joined spectated images tags color id membership-permissions?]
|
||||
:as community}
|
||||
(defn community-content
|
||||
[community]
|
||||
(rf/dispatch [:communities/check-all-community-channels-permissions (:id community)])
|
||||
(fn [{:keys [name description joined spectated images tags color id token-permissions] :as community}
|
||||
pending?
|
||||
{:keys [on-category-layout
|
||||
collapsed?
|
||||
on-first-channel-height-changed]}]
|
||||
@@ -249,7 +279,7 @@
|
||||
[:<>
|
||||
[rn/view {:style style/community-content-container}
|
||||
(when-not collapsed?
|
||||
[status-tag id joined])
|
||||
[status-tag pending? joined])
|
||||
[community-header name (when collapsed? (get-in images [:thumbnail :uri]))
|
||||
(when-not collapsed? description)]
|
||||
(when (and (seq tags) (not collapsed?))
|
||||
@@ -257,8 +287,9 @@
|
||||
{:tags tags
|
||||
:last-item-style style/last-community-tag
|
||||
:container-style style/community-tag-container}])
|
||||
[join-community community]]
|
||||
(when (or joined (not membership-permissions?))
|
||||
[join-community community pending?]]
|
||||
(when (or (and (seq token-permissions) joined)
|
||||
(empty? token-permissions))
|
||||
[channel-list-component
|
||||
{:on-category-layout on-category-layout
|
||||
:community-id id
|
||||
@@ -266,7 +297,7 @@
|
||||
:on-first-channel-height-changed on-first-channel-height-changed}
|
||||
(add-handlers-to-categorized-chats id chats-by-category joined-or-spectated)])])))
|
||||
|
||||
(defn- sticky-category-header
|
||||
(defn sticky-category-header
|
||||
[_]
|
||||
(fn [{:keys [enabled label]}]
|
||||
(when enabled
|
||||
@@ -279,7 +310,7 @@
|
||||
{:chevron :left}
|
||||
label]])))
|
||||
|
||||
(defn- page-nav-right-section-buttons
|
||||
(defn page-nav-right-section-buttons
|
||||
[id]
|
||||
[{:icon-name :i/options
|
||||
:accessibility-label :community-options-for-community
|
||||
@@ -287,7 +318,7 @@
|
||||
[:show-bottom-sheet
|
||||
{:content (fn [] [options/community-options-bottom-sheet id])}])}])
|
||||
|
||||
(defn- pick-first-category-by-height
|
||||
(defn pick-first-category-by-height
|
||||
[scroll-height first-channel-height categories-heights]
|
||||
(->> categories-heights
|
||||
(sort-by (comp - second))
|
||||
@@ -295,7 +326,7 @@
|
||||
(and (>= scroll-height (+ height first-channel-height))
|
||||
category)))))
|
||||
|
||||
(defn- community-scroll-page
|
||||
(defn community-scroll-page
|
||||
[{:keys [joined]}]
|
||||
(let [scroll-height (reagent/atom 0)
|
||||
categories-heights (reagent/atom {})
|
||||
@@ -305,7 +336,7 @@
|
||||
;; from not collapsed to collapsed if the
|
||||
;; user is on this page
|
||||
initial-joined? joined]
|
||||
(fn [{:keys [id name images] :as community}]
|
||||
(fn [{:keys [id name images] :as community} pending?]
|
||||
(let [cover {:uri (get-in images [:banner :uri])}
|
||||
logo {:uri (get-in images [:thumbnail :uri])}
|
||||
collapsed? (and initial-joined? (:joined community))
|
||||
@@ -332,6 +363,7 @@
|
||||
@categories-heights)}]}
|
||||
[community-content
|
||||
community
|
||||
pending?
|
||||
{:on-category-layout (partial add-category-height categories-heights)
|
||||
:collapsed? collapsed?
|
||||
:on-first-channel-height-changed
|
||||
@@ -341,16 +373,17 @@
|
||||
(swap! categories-heights select-keys categories)
|
||||
(reset! first-channel-height height))}]]))))
|
||||
|
||||
(defn- community-card-page-view
|
||||
(defn community-card-page-view
|
||||
[id]
|
||||
(let [{:keys [id joined]
|
||||
:as community} (rf/sub [:communities/community id])]
|
||||
:as community} (rf/sub [:communities/community id])
|
||||
pending? (rf/sub [:communities/my-pending-request-to-join id])]
|
||||
(when community
|
||||
(when joined
|
||||
(rf/dispatch [:activity-center.notifications/dismiss-community-overview id]))
|
||||
[community-scroll-page community])))
|
||||
[community-scroll-page community pending?])))
|
||||
|
||||
(defn view
|
||||
(defn overview
|
||||
[id]
|
||||
(let [id (or id (rf/sub [:get-screen-params :community-overview]))
|
||||
customization-color (rf/sub [:profile/customization-color])]
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
[react-native.platform :as platform]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.common.profile-picture-picker.view :as profile-picture-picker]
|
||||
[status-im.common.validation.profile :as profile-validator]
|
||||
[status-im.constants :as c]
|
||||
[status-im.contexts.onboarding.create-profile.style :as style]
|
||||
[status-im.contexts.onboarding.select-photo.method-menu.view :as method-menu]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.responsiveness :as responsiveness]))
|
||||
@@ -144,9 +144,7 @@
|
||||
(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content (fn []
|
||||
[profile-picture-picker/view
|
||||
{:update-profile-pic-callback on-change-profile-pic
|
||||
:has-picture? false}])
|
||||
[method-menu/view on-change-profile-pic])
|
||||
:shell? true}]))
|
||||
:image-picker-props {:profile-picture @profile-pic
|
||||
:full-name (if (seq @full-name)
|
||||
|
||||
+3
-13
@@ -1,4 +1,4 @@
|
||||
(ns status-im.common.profile-picture-picker.view
|
||||
(ns status-im.contexts.onboarding.select-photo.method-menu.view
|
||||
(:require
|
||||
["react-native-image-crop-picker" :default image-picker]
|
||||
[quo.core :as quo]
|
||||
@@ -59,7 +59,7 @@
|
||||
crop-opts))
|
||||
|
||||
(defn view
|
||||
[{:keys [update-profile-pic-callback has-picture?]}]
|
||||
[update-profile-pic-callback]
|
||||
[quo/action-drawer
|
||||
[[{:icon :i/camera
|
||||
:accessibility-label :take-photo-button
|
||||
@@ -86,15 +86,5 @@
|
||||
:on-allowed (fn [] (pick-pic update-profile-pic-callback))
|
||||
:on-denied (fn []
|
||||
(log/info
|
||||
"user has denied permissions to select picture"))}))}
|
||||
(when has-picture?
|
||||
{:accessibility-label :remove-profile-picture
|
||||
:add-divider? true
|
||||
:danger? true
|
||||
:blur? true
|
||||
:icon :i/delete
|
||||
:label (i18n/label :t/profile-pic-remove)
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(update-profile-pic-callback nil))})]]])
|
||||
"user has denied permissions to select picture"))}))}]]])
|
||||
|
||||
@@ -13,17 +13,10 @@
|
||||
:openseaAPIKey config/opensea-api-key
|
||||
:poktToken config/POKT_TOKEN
|
||||
:infuraToken config/INFURA_TOKEN
|
||||
:raribleMainnetAPIKey config/RARIBLE_MAINNET_API_KEY
|
||||
:raribleTestnetAPIKey config/RARIBLE_TESTNET_API_KEY
|
||||
:alchemyEthereumMainnetToken config/ALCHEMY_ETHEREUM_MAINNET_TOKEN
|
||||
:alchemyEthereumGoerliToken config/ALCHEMY_ETHEREUM_GOERLI_TOKEN
|
||||
:alchemyEthereumSepoliaToken config/ALCHEMY_ETHEREUM_SEPOLIA_TOKEN
|
||||
:alchemyOptimismMainnetToken config/ALCHEMY_OPTIMISM_MAINNET_TOKEN
|
||||
:alchemyOptimismGoerliToken config/ALCHEMY_OPTIMISM_GOERLI_TOKEN
|
||||
:alchemyOptimismSepoliaToken config/ALCHEMY_OPTIMISM_SEPOLIA_TOKEN
|
||||
:alchemyArbitrumMainnetToken config/ALCHEMY_ARBITRUM_MAINNET_TOKEN
|
||||
:alchemyArbitrumGoerliToken config/ALCHEMY_ARBITRUM_GOERLI_TOKEN
|
||||
:alchemyArbitrumSepoliaToken config/ALCHEMY_ARBITRUM_SEPOLIA_TOKEN})
|
||||
:alchemyArbitrumGoerliToken config/ALCHEMY_ARBITRUM_GOERLI_TOKEN})
|
||||
|
||||
(defn create
|
||||
[]
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
(ns status-im.contexts.profile.edit.header.events
|
||||
(:require [clojure.string :as string]
|
||||
[status-im.common.profile-picture-picker.view :as profile-picture-picker]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/reg-event-fx :profile/update-local-picture
|
||||
(fn [{:keys [db]} [images]]
|
||||
{:db (if images
|
||||
(assoc-in db [:profile/profile :images] images)
|
||||
(update db :profile/profile dissoc :images))}))
|
||||
|
||||
(rf/reg-event-fx :profile/edit-profile-picture-success
|
||||
(fn [_ [images]]
|
||||
{:fx [[:dispatch [:profile/update-local-picture (reverse images)]]
|
||||
[:dispatch
|
||||
[:toasts/upsert
|
||||
{:type :positive
|
||||
:theme :dark
|
||||
:text (i18n/label :t/profile-picture-added)}]]]}))
|
||||
|
||||
(defn edit-profile-picture
|
||||
[{:keys [db]} [picture crop-width crop-height]]
|
||||
(let [key-uid (get-in db [:profile/profile :key-uid])
|
||||
crop-width (or crop-width profile-picture-picker/crop-size)
|
||||
crop-height (or crop-height profile-picture-picker/crop-size)
|
||||
path (string/replace-first picture #"file://" "")]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "multiaccounts_storeIdentityImage"
|
||||
:params [key-uid path 0 0 crop-width crop-height]
|
||||
:on-success [:profile/edit-profile-picture-success]}]]]}))
|
||||
|
||||
(rf/reg-event-fx :profile/edit-picture edit-profile-picture)
|
||||
|
||||
(rf/reg-event-fx :profile/delete-profile-picture-success
|
||||
(fn [_]
|
||||
{:fx [[:dispatch [:profile/update-local-picture nil]]
|
||||
[:dispatch
|
||||
[:toasts/upsert
|
||||
{:type :positive
|
||||
:theme :dark
|
||||
:text (i18n/label :t/profile-picture-removed)}]]]}))
|
||||
|
||||
(defn delete-profile-picture
|
||||
[{:keys [db]}]
|
||||
(let [key-uid (get-in db [:profile/profile :key-uid])]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "multiaccounts_deleteIdentityImage"
|
||||
:params [key-uid]
|
||||
:on-success [:profile/delete-profile-picture-success]}]]]}))
|
||||
|
||||
(rf/reg-event-fx :profile/delete-picture delete-profile-picture)
|
||||
@@ -1,27 +0,0 @@
|
||||
(ns status-im.contexts.profile.edit.header.events-test
|
||||
(:require [cljs.test :refer [deftest is]]
|
||||
matcher-combinators.test
|
||||
[status-im.common.profile-picture-picker.view :as profile-picture-picker]
|
||||
[status-im.contexts.profile.edit.header.events :as sut]))
|
||||
|
||||
(deftest edit-picture-test
|
||||
(let [picture "new-picture"
|
||||
key-uid "key-uid"
|
||||
cofx {:db {:profile/profile {:key-uid key-uid}}}
|
||||
expected {:fx [[:json-rpc/call
|
||||
[{:method "multiaccounts_storeIdentityImage"
|
||||
:params [key-uid picture 0 0 profile-picture-picker/crop-size
|
||||
profile-picture-picker/crop-size]
|
||||
:on-success [:profile/edit-profile-picture-success]}]]]}]
|
||||
(is (match? expected
|
||||
(sut/edit-profile-picture cofx [picture])))))
|
||||
|
||||
(deftest delete-picture-test
|
||||
(let [key-uid "key-uid"
|
||||
cofx {:db {:profile/profile {:key-uid key-uid}}}
|
||||
expected {:fx [[:json-rpc/call
|
||||
[{:method "multiaccounts_deleteIdentityImage"
|
||||
:params [key-uid]
|
||||
:on-success [:profile/delete-profile-picture-success]}]]]}]
|
||||
(is (match? expected
|
||||
(sut/delete-profile-picture cofx)))))
|
||||
@@ -1,7 +1,7 @@
|
||||
(ns status-im.contexts.profile.edit.header.view
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[status-im.common.profile-picture-picker.view :as profile-picture-picker]
|
||||
[status-im.common.not-implemented :as not-implemented]
|
||||
[status-im.contexts.profile.edit.style :as style]
|
||||
[status-im.contexts.profile.utils :as profile.utils]
|
||||
[utils.i18n :as i18n]
|
||||
@@ -9,37 +9,22 @@
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [profile (rf/sub [:profile/profile-with-image])
|
||||
customization-color (rf/sub [:profile/customization-color])
|
||||
full-name (profile.utils/displayed-name profile)
|
||||
profile-picture (profile.utils/photo profile)
|
||||
has-picture? (rf/sub [:profile/has-picture])
|
||||
on-change-profile-pic (fn [picture]
|
||||
(if picture
|
||||
(rf/dispatch [:profile/edit-picture picture])
|
||||
(rf/dispatch [:profile/delete-picture])))]
|
||||
(let [profile (rf/sub [:profile/profile-with-image])
|
||||
full-name (profile.utils/displayed-name profile)
|
||||
profile-picture (profile.utils/photo profile)]
|
||||
[rn/view
|
||||
{:key :edit-profile
|
||||
:style style/screen-container}
|
||||
[quo/text-combinations {:title (i18n/label :t/edit-profile)}]
|
||||
[rn/view style/avatar-wrapper
|
||||
[quo/user-avatar
|
||||
{:full-name full-name
|
||||
:profile-picture profile-picture
|
||||
:customization-color customization-color
|
||||
:status-indicator? false
|
||||
:ring? true
|
||||
:size :big}]
|
||||
{:full-name full-name
|
||||
:profile-picture profile-picture
|
||||
:status-indicator? false
|
||||
:ring? true
|
||||
:size :big}]
|
||||
[quo/button
|
||||
{:on-press (fn []
|
||||
(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content (fn []
|
||||
[profile-picture-picker/view
|
||||
{:update-profile-pic-callback on-change-profile-pic
|
||||
:has-picture? has-picture?}])
|
||||
:theme :dark
|
||||
:shell? true}]))
|
||||
{:on-press not-implemented/alert
|
||||
:container-style style/camera-button
|
||||
:icon-only? true
|
||||
:type :grey
|
||||
|
||||
@@ -2,21 +2,17 @@
|
||||
(:require [utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/reg-event-fx :profile/edit-profile-name-success
|
||||
(fn [_]
|
||||
{:fx [[:dispatch [:navigate-back]]
|
||||
[:dispatch
|
||||
[:toasts/upsert
|
||||
{:type :positive
|
||||
:theme :dark
|
||||
:text (i18n/label :t/name-updated)}]]]}))
|
||||
|
||||
(defn edit-profile-name
|
||||
[{:keys [db]} [name]]
|
||||
{:db (assoc-in db [:profile/profile :display-name] name)
|
||||
:fx [[:json-rpc/call
|
||||
[{:method "wakuext_setDisplayName"
|
||||
:params [name]
|
||||
:on-success [:profile/edit-profile-name-success]}]]]})
|
||||
:on-success (fn []
|
||||
(rf/dispatch [:navigate-back])
|
||||
(rf/dispatch [:toasts/upsert
|
||||
{:type :positive
|
||||
:theme :dark
|
||||
:text (i18n/label :t/name-updated)}]))}]]]})
|
||||
|
||||
(rf/reg-event-fx :profile/edit-name edit-profile-name)
|
||||
|
||||
@@ -10,6 +10,6 @@
|
||||
:fx [[:json-rpc/call
|
||||
[{:method "wakuext_setDisplayName"
|
||||
:params [name]
|
||||
:on-success [:profile/edit-profile-name-success]}]]]}]
|
||||
:on-success fn?}]]]}]
|
||||
(is (match? expected
|
||||
(sut/edit-profile-name cofx [new-name])))))
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
[legacy.status-im.data-store.settings :as data-store.settings]
|
||||
[native-module.core :as native-module]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.contexts.profile.edit.header.events]
|
||||
[status-im.contexts.profile.edit.name.events]
|
||||
[status-im.contexts.profile.login.events :as profile.login]
|
||||
[status-im.contexts.profile.rpc :as profile.rpc]
|
||||
|
||||
@@ -70,15 +70,6 @@
|
||||
{:on-success on-success}])
|
||||
:on-cancel nil}]]})))
|
||||
|
||||
(rf/reg-event-fx :profile.settings/toggle-sepolia-test-network
|
||||
(fn [{:keys [db]}]
|
||||
(let [value (get-in db [:profile/profile :is-sepolia-enabled?])
|
||||
on-success #(rf/dispatch [:wallet/initialize])]
|
||||
{:fx [[:dispatch
|
||||
[:profile.settings/profile-update :is-sepolia-enabled?
|
||||
(not value)
|
||||
{:on-success on-success}]]]})))
|
||||
|
||||
(rf/defn change-preview-privacy-flag
|
||||
{:events [:profile.settings/change-preview-privacy]}
|
||||
[{:keys [db] :as cofx} private?]
|
||||
@@ -89,6 +80,7 @@
|
||||
(boolean private?)
|
||||
{})))
|
||||
|
||||
|
||||
(rf/defn change-profile-pictures-show-to
|
||||
{:events [:profile.settings/change-profile-pictures-show-to]}
|
||||
[cofx id]
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
(def screens-map
|
||||
{shell.constants/chat-screen chat/chat
|
||||
shell.constants/community-screen communities.overview/view
|
||||
shell.constants/community-screen communities.overview/overview
|
||||
shell.constants/discover-communities-screen communities.discover/view})
|
||||
|
||||
(defn f-screen
|
||||
|
||||
@@ -3,15 +3,13 @@
|
||||
[quo.core :as quo]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.svg :as svg]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.common.scroll-page.view :as scroll-page]
|
||||
[status-im.contexts.wallet.collectible.style :as style]
|
||||
[status-im.contexts.wallet.collectible.tabs.view :as tabs]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.url :as url]))
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn header
|
||||
[collectible-name collection-name collection-image-url]
|
||||
@@ -73,32 +71,6 @@
|
||||
:accessibility-label :share-details
|
||||
:label (i18n/label :t/share-details)}]]])
|
||||
|
||||
(defn options-drawer
|
||||
[images index]
|
||||
(let [{:keys [image]} (nth images index)
|
||||
uri (url/replace-port image (rf/sub [:mediaserver/port]))]
|
||||
[quo/action-drawer
|
||||
[[{:icon :i/link
|
||||
:accessibility-label :view-on-etherscan
|
||||
:label (i18n/label :t/view-on-eth)}]
|
||||
[{:icon :i/save
|
||||
:accessibility-label :save-image
|
||||
:label (i18n/label :t/save-image-to-photos)
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch
|
||||
[:lightbox/save-image-to-gallery
|
||||
uri
|
||||
#(rf/dispatch [:toasts/upsert
|
||||
{:id :random-id
|
||||
:type :positive
|
||||
:container-style {:bottom (when platform/android? 20)}
|
||||
:text (i18n/label :t/photo-saved)}])]))}]
|
||||
[{:icon :i/share
|
||||
:accessibility-label :share-collectible
|
||||
:label (i18n/label :t/share-collectible)
|
||||
:right-icon :i/external}]]]))
|
||||
|
||||
(defn view-internal
|
||||
[{:keys [theme] :as _props}]
|
||||
(let [selected-tab (reagent/atom :overview)
|
||||
@@ -135,27 +107,20 @@
|
||||
:on-press (fn []
|
||||
(if svg?
|
||||
(js/alert "Can't visualize SVG images in lightbox")
|
||||
(rf/dispatch
|
||||
[:lightbox/navigate-to-lightbox
|
||||
token-id
|
||||
{:images [{:image preview-uri
|
||||
:image-width 300 ; collectibles don't have
|
||||
; width/height but we need
|
||||
; to pass something
|
||||
:image-height 300 ; without it animation
|
||||
; doesn't work smoothly
|
||||
; and :border-radius not
|
||||
; applied
|
||||
:id token-id
|
||||
:header collectible-name
|
||||
:description collection-name}]
|
||||
:index 0
|
||||
:on-options-press (fn [images index]
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:content (fn []
|
||||
[options-drawer
|
||||
images
|
||||
index])}]))}])))}
|
||||
(rf/dispatch [:lightbox/navigate-to-lightbox
|
||||
token-id
|
||||
{:images [{:image preview-uri
|
||||
:image-width 300 ; collectibles don't have
|
||||
; width/height but we need
|
||||
; to pass something
|
||||
:image-height 300 ; without it animation
|
||||
; doesn't work smoothly and
|
||||
; :border-radius not
|
||||
; applied
|
||||
:id token-id
|
||||
:header collectible-name
|
||||
:description collection-name}]
|
||||
:index 0}])))}
|
||||
(if svg?
|
||||
[rn/view
|
||||
{:style (assoc style/preview :overflow :hidden)
|
||||
|
||||
@@ -74,13 +74,11 @@
|
||||
(defn get-standard-crypto-format
|
||||
"For full details: https://github.com/status-im/status-mobile/issues/18225"
|
||||
[{:keys [market-values-per-currency]} token-units]
|
||||
(if (or (nil? token-units)
|
||||
(nil? market-values-per-currency)
|
||||
(money/equal-to token-units 0))
|
||||
"0"
|
||||
(let [price (-> market-values-per-currency :usd :price)
|
||||
one-cent-value (if (pos? price) (/ 0.01 price) 0)
|
||||
decimals-count (calc-max-crypto-decimals one-cent-value)]
|
||||
(let [price (get-in market-values-per-currency [:usd :price])
|
||||
one-cent-value (if (pos? price) (/ 0.01 price) 0)
|
||||
decimals-count (calc-max-crypto-decimals one-cent-value)]
|
||||
(if (money/equal-to token-units 0)
|
||||
"0"
|
||||
(if (< token-units one-cent-value)
|
||||
(str "<" (remove-trailing-zeroes (.toFixed one-cent-value decimals-count)))
|
||||
(remove-trailing-zeroes (.toFixed token-units decimals-count))))))
|
||||
@@ -190,20 +188,17 @@
|
||||
address))
|
||||
|
||||
(def id->network
|
||||
{constants/ethereum-mainnet-chain-id :ethereum
|
||||
constants/ethereum-goerli-chain-id :ethereum
|
||||
constants/ethereum-sepolia-chain-id :ethereum
|
||||
constants/optimism-mainnet-chain-id :optimism
|
||||
constants/optimism-goerli-chain-id :optimism
|
||||
constants/optimism-sepolia-chain-id :optimism
|
||||
constants/arbitrum-mainnet-chain-id :arbitrum
|
||||
constants/arbitrum-goerli-chain-id :arbitrum
|
||||
constants/arbitrum-sepolia-chain-id :arbitrum})
|
||||
{constants/mainnet-chain-id :ethereum
|
||||
constants/goerli-chain-id :ethereum
|
||||
constants/optimism-chain-id :optimism
|
||||
constants/optimism-test-chain-id :optimism
|
||||
constants/arbitrum-chain-id :arbitrum
|
||||
constants/arbitrum-test-chain-id :arbitrum})
|
||||
|
||||
(def short-name->id
|
||||
{:eth constants/ethereum-mainnet-chain-id
|
||||
:opt constants/optimism-mainnet-chain-id
|
||||
:arb1 constants/arbitrum-mainnet-chain-id})
|
||||
{:eth constants/mainnet-chain-id
|
||||
:opt constants/optimism-chain-id
|
||||
:arb1 constants/arbitrum-chain-id})
|
||||
|
||||
(defn get-standard-fiat-format
|
||||
[crypto-value currency-symbol fiat-value]
|
||||
|
||||
@@ -3,12 +3,10 @@
|
||||
[camel-snake-kebab.core :as csk]
|
||||
[camel-snake-kebab.extras :as cske]
|
||||
[clojure.string :as string]
|
||||
[native-module.core :as native-module]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.send.utils :as send-utils]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.address :as address]
|
||||
[utils.money :as money]
|
||||
[utils.number]
|
||||
[utils.re-frame :as rf]))
|
||||
@@ -58,14 +56,11 @@
|
||||
(fn [{:keys [db]}]
|
||||
{:db (update-in db [:wallet :ui :send] dissoc :recipient :to-address)}))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/select-send-address
|
||||
(rf/reg-event-fx :wallet/select-send-address
|
||||
(fn [{:keys [db]} [{:keys [address token recipient stack-id]}]]
|
||||
(let [[prefix to-address] (utils/split-prefix-and-address address)
|
||||
prefix-seq (string/split prefix #":")
|
||||
selected-networks (->> prefix-seq
|
||||
(remove string/blank?)
|
||||
(mapv #(utils/short-name->id (keyword %))))]
|
||||
selected-networks (mapv #(utils/short-name->id (keyword %)) prefix-seq)]
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :ui :send :recipient] (or recipient address))
|
||||
(assoc-in [:wallet :ui :send :to-address] to-address)
|
||||
@@ -76,20 +71,18 @@
|
||||
[:wallet-send-input-amount stack-id]
|
||||
[:wallet-select-asset stack-id])]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/update-receiver-networks
|
||||
(rf/reg-event-fx :wallet/update-receiver-networks
|
||||
(fn [{:keys [db]} [selected-networks]]
|
||||
{:db (assoc-in db [:wallet :ui :send :selected-networks] selected-networks)}))
|
||||
|
||||
(rf/reg-event-fx :wallet/send-select-token
|
||||
(fn [{:keys [db]} [{:keys [token stack-id]}]]
|
||||
{:db (-> db
|
||||
(update-in [:wallet :ui :send] dissoc :collectible)
|
||||
(assoc-in [:wallet :ui :send :token] token))
|
||||
:fx [[:navigate-to-within-stack [:wallet-send-input-amount stack-id]]]}))
|
||||
{:db (assoc-in db [:wallet :ui :send :token] token)
|
||||
:fx [[:dispatch-later
|
||||
{:ms 1
|
||||
:dispatch [:navigate-to-within-stack [:wallet-send-input-amount stack-id]]}]]}))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/send-select-token-drawer
|
||||
(rf/reg-event-fx :wallet/send-select-token-drawer
|
||||
(fn [{:keys [db]} [{:keys [token]}]]
|
||||
{:db (assoc-in db [:wallet :ui :send :token] token)}))
|
||||
|
||||
@@ -97,15 +90,6 @@
|
||||
(fn [{:keys [db]}]
|
||||
{:db (assoc-in db [:wallet :ui :send :token] nil)}))
|
||||
|
||||
(rf/reg-event-fx :wallet/send-select-collectible
|
||||
(fn [{:keys [db]} [{:keys [collectible stack-id]}]]
|
||||
{:db (-> db
|
||||
(update-in [:wallet :ui :send] dissoc :token)
|
||||
(assoc-in [:wallet :ui :send :collectible] collectible)
|
||||
(assoc-in [:wallet :ui :send :amount] 1))
|
||||
:fx [[:dispatch [:wallet/get-suggested-routes 1]]
|
||||
[:navigate-to-within-stack [:wallet-transaction-confirmation stack-id]]]}))
|
||||
|
||||
(rf/reg-event-fx :wallet/send-select-amount
|
||||
(fn [{:keys [db]} [{:keys [amount stack-id]}]]
|
||||
{:db (assoc-in db [:wallet :ui :send :amount] amount)
|
||||
@@ -115,25 +99,19 @@
|
||||
(fn [{:keys [db now]} [amount]]
|
||||
(let [wallet-address (get-in db [:wallet :current-viewing-account-address])
|
||||
token (get-in db [:wallet :ui :send :token])
|
||||
collectible (get-in db [:wallet :ui :send :collectible])
|
||||
to-address (get-in db [:wallet :ui :send :to-address])
|
||||
token-decimal (when token (:decimals token))
|
||||
token-id (if token
|
||||
(:symbol token)
|
||||
(str (get-in collectible [:id :contract-id :address])
|
||||
":"
|
||||
(get-in collectible [:id :token-id])))
|
||||
network-preferences (if token [] [(get-in collectible [:id :contract-id :chain-id])])
|
||||
account-address (get-in db [:wallet :ui :send :send-account-address])
|
||||
selected-networks (get-in db [:wallet :ui :send :selected-networks])
|
||||
to-address (or account-address (get-in db [:wallet :ui :send :to-address]))
|
||||
token-decimal (:decimals token)
|
||||
token-id (:symbol token)
|
||||
network-preferences selected-networks
|
||||
gas-rates constants/gas-rate-medium
|
||||
amount-in (send-utils/amount-in-hex amount (if token token-decimal 0))
|
||||
amount-in (send-utils/amount-in-hex amount token-decimal)
|
||||
from-address wallet-address
|
||||
disabled-from-chain-ids []
|
||||
disabled-to-chain-ids []
|
||||
from-locked-amount {}
|
||||
transaction-type (if token
|
||||
constants/send-type-transfer
|
||||
constants/send-type-erc-721-transfer)
|
||||
request-params [transaction-type
|
||||
request-params [constants/send-type-transfer
|
||||
from-address
|
||||
to-address
|
||||
amount-in
|
||||
@@ -177,46 +155,21 @@
|
||||
{:fx [[:dispatch [:dismiss-modal :wallet-transaction-progress]]]}))
|
||||
|
||||
(defn- transaction-bridge
|
||||
[{:keys [from-address from-chain-id to-address token-id token-address route data eth-transfer?]}]
|
||||
(let [{:keys [bridge-name amount-out gas-amount
|
||||
gas-fees]} route
|
||||
eip-1559-enabled? (:eip-1559-enabled gas-fees)
|
||||
{:keys [gas-price max-fee-per-gas-medium
|
||||
max-priority-fee-per-gas]} gas-fees
|
||||
transfer-tx (cond-> {:From from-address
|
||||
:To (or token-address to-address)
|
||||
:Gas (money/to-hex gas-amount)
|
||||
:Value (when eth-transfer? amount-out)
|
||||
:Nonce nil
|
||||
:Input ""
|
||||
:Data (or data "0x")}
|
||||
eip-1559-enabled? (assoc :TxType "0x02"
|
||||
:MaxFeePerGas
|
||||
(money/to-hex
|
||||
(money/->wei
|
||||
:gwei
|
||||
max-fee-per-gas-medium))
|
||||
:MaxPriorityFeePerGas
|
||||
(money/to-hex
|
||||
(money/->wei
|
||||
:gwei
|
||||
max-priority-fee-per-gas)))
|
||||
(not eip-1559-enabled?) (assoc :TxType "0x00"
|
||||
:GasPrice (money/to-hex
|
||||
(money/->wei
|
||||
:gwei
|
||||
gas-price))))]
|
||||
[(cond-> {:BridgeName bridge-name
|
||||
:ChainID from-chain-id}
|
||||
|
||||
(= bridge-name constants/bridge-name-erc-721-transfer)
|
||||
(assoc :ERC721TransferTx
|
||||
(assoc transfer-tx
|
||||
:Recipient to-address
|
||||
:TokenID token-id))
|
||||
|
||||
(= bridge-name constants/bridge-name-transfer)
|
||||
(assoc :TransferTx transfer-tx))]))
|
||||
[{:keys [from-address to-address route]}]
|
||||
(let [{:keys [from bridge-name amount-out gas-amount gas-fees]} route
|
||||
{:keys [gas-price max-fee-per-gas-medium max-priority-fee-per-gas]} gas-fees]
|
||||
[{:BridgeName bridge-name
|
||||
:ChainID (:chain-id from)
|
||||
:TransferTx {:From from-address
|
||||
:To to-address
|
||||
:Gas (money/to-hex gas-amount)
|
||||
:GasPrice (money/to-hex (money/->wei :gwei gas-price))
|
||||
:Value amount-out
|
||||
:Nonce nil
|
||||
:MaxFeePerGas (money/to-hex (money/->wei :gwei max-fee-per-gas-medium))
|
||||
:MaxPriorityFeePerGas (money/to-hex (money/->wei :gwei max-priority-fee-per-gas))
|
||||
:Input ""
|
||||
:Data "0x"}}]))
|
||||
|
||||
(defn- multi-transaction-command
|
||||
[{:keys [from-address to-address from-asset to-asset amount-out transfer-type]
|
||||
@@ -230,50 +183,25 @@
|
||||
|
||||
(rf/reg-event-fx :wallet/send-transaction
|
||||
(fn [{:keys [db]} [sha3-pwd]]
|
||||
(let [route (get-in db [:wallet :ui :send :route])
|
||||
from-address (get-in db [:wallet :current-viewing-account-address])
|
||||
token (get-in db [:wallet :ui :send :token])
|
||||
collectible (get-in db [:wallet :ui :send :collectible])
|
||||
from-chain-id (get-in route [:from :chain-id])
|
||||
token-id (if token
|
||||
(:symbol token)
|
||||
(get-in collectible [:id :token-id]))
|
||||
erc20-transfer? (and token (not= token-id "ETH"))
|
||||
eth-transfer? (and token (not erc20-transfer?))
|
||||
token-address (cond collectible
|
||||
(get-in collectible
|
||||
[:id :contract-id :address])
|
||||
erc20-transfer?
|
||||
(get-in token [:balances-per-chain from-chain-id :address]))
|
||||
to-address (get-in db [:wallet :ui :send :to-address])
|
||||
data (when erc20-transfer?
|
||||
(native-module/encode-transfer (address/normalized-hex to-address)
|
||||
(:amount-out route)))
|
||||
request-params [(multi-transaction-command
|
||||
{:from-address from-address
|
||||
:to-address to-address
|
||||
:from-asset token-id
|
||||
:to-asset token-id
|
||||
:amount-out (if eth-transfer? (:amount-out route) "0x0")})
|
||||
(transaction-bridge {:to-address to-address
|
||||
:from-address from-address
|
||||
:route route
|
||||
:from-chain-id from-chain-id
|
||||
:token-address token-address
|
||||
:token-id (when collectible
|
||||
(money/to-hex (js/parseInt token-id)))
|
||||
:data data
|
||||
:eth-transfer? eth-transfer?})
|
||||
sha3-pwd]]
|
||||
(let [route (get-in db [:wallet :ui :send :route])
|
||||
from-address (get-in db [:wallet :current-viewing-account-address])
|
||||
to-address (get-in db [:wallet :ui :send :to-address])
|
||||
token (get-in db [:wallet :ui :send :token])
|
||||
token-id (:symbol token)
|
||||
request-params [(multi-transaction-command {:from-address from-address
|
||||
:to-address to-address
|
||||
:from-asset token-id
|
||||
:to-asset token-id
|
||||
:amount-out (:amount-out route)})
|
||||
(transaction-bridge {:to-address to-address
|
||||
:from-address from-address
|
||||
:route route})
|
||||
sha3-pwd]]
|
||||
{:json-rpc/call [{:method "wallet_createMultiTransaction"
|
||||
:params request-params
|
||||
:on-success (fn [result]
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch [:wallet/add-authorized-transaction result])
|
||||
(rf/dispatch [:wallet/clean-scanned-address])
|
||||
(rf/dispatch [:wallet/clean-local-suggestions])
|
||||
(rf/dispatch [:wallet/clean-send-address])
|
||||
(rf/dispatch [:wallet/select-address-tab nil]))
|
||||
(rf/dispatch [:wallet/add-authorized-transaction result]))
|
||||
:on-error (fn [error]
|
||||
(log/error "failed to send transaction"
|
||||
{:event :wallet/send-transaction
|
||||
|
||||
@@ -53,9 +53,8 @@
|
||||
(h/test "Default render"
|
||||
(h/setup-subs sub-mocks)
|
||||
(h/render [input-amount/view
|
||||
{:crypto-decimals 2
|
||||
:limit-crypto 250
|
||||
:initial-crypto-currency? false}])
|
||||
{:crypto-decimals 2
|
||||
:limit-crypto 250}])
|
||||
(h/is-truthy (h/get-by-text "0"))
|
||||
(h/is-truthy (h/get-by-text "ETH"))
|
||||
(h/is-truthy (h/get-by-text "$0.00"))
|
||||
@@ -66,10 +65,9 @@
|
||||
(h/setup-subs sub-mocks)
|
||||
(let [on-confirm (h/mock-fn)]
|
||||
(h/render [input-amount/view
|
||||
{:on-confirm on-confirm
|
||||
:crypto-decimals 10
|
||||
:limit-crypto 1000
|
||||
:initial-crypto-currency? false}])
|
||||
{:on-confirm on-confirm
|
||||
:crypto-decimals 10
|
||||
:limit-crypto 1000}])
|
||||
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-1))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-2))
|
||||
@@ -90,10 +88,9 @@
|
||||
|
||||
(let [on-confirm (h/mock-fn)]
|
||||
(h/render [input-amount/view
|
||||
{:crypto-decimals 10
|
||||
:limit-crypto 1000
|
||||
:on-confirm on-confirm
|
||||
:initial-crypto-currency? false}])
|
||||
{:crypto-decimals 10
|
||||
:limit-crypto 1000
|
||||
:on-confirm on-confirm}])
|
||||
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-1))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-2))
|
||||
|
||||
@@ -30,54 +30,28 @@
|
||||
(defn valid-input?
|
||||
[current v]
|
||||
(let [max-length 12
|
||||
length-overflow? (>= (count current) max-length)
|
||||
length-owerflow? (>= (count current) max-length)
|
||||
extra-dot? (and (= v dot) (string/includes? current dot))
|
||||
extra-leading-zero? (and (= current "0") (= "0" (str v)))
|
||||
non-numeric? (re-find not-digits-or-dot-pattern (str v))]
|
||||
(not (or non-numeric? extra-dot? extra-leading-zero? length-overflow?))))
|
||||
|
||||
(defn- add-char-to-string
|
||||
[s c idx]
|
||||
(let [size (count s)]
|
||||
(if (= size idx)
|
||||
(str s c)
|
||||
(str (subs s 0 idx)
|
||||
c
|
||||
(subs s idx size)))))
|
||||
|
||||
(defn- move-input-cursor
|
||||
([input-selection-atom new-idx]
|
||||
(move-input-cursor input-selection-atom new-idx new-idx))
|
||||
([input-selection-atom new-start-idx new-end-idx]
|
||||
(let [start-idx (if (< new-start-idx 0) 0 new-start-idx)
|
||||
end-idx (if (< new-end-idx 0) 0 new-start-idx)]
|
||||
(swap! input-selection-atom assoc :start start-idx :end end-idx))))
|
||||
(not (or non-numeric? extra-dot? extra-leading-zero? length-owerflow?))))
|
||||
|
||||
(defn- normalize-input
|
||||
[current v input-selection-atom]
|
||||
(let [{:keys [start end]} @input-selection-atom]
|
||||
(if (= start end)
|
||||
(cond
|
||||
(and (string/blank? current) (= v dot))
|
||||
(do
|
||||
(move-input-cursor input-selection-atom 2)
|
||||
(str "0" v))
|
||||
[current v]
|
||||
(cond
|
||||
(and (string/blank? current) (= v dot))
|
||||
(str "0" v)
|
||||
|
||||
(and (= current "0") (not= v dot))
|
||||
(do
|
||||
(move-input-cursor input-selection-atom 1)
|
||||
(str v))
|
||||
(and (= current "0") (not= v dot))
|
||||
(str v)
|
||||
|
||||
:else
|
||||
(do
|
||||
(move-input-cursor input-selection-atom (inc start))
|
||||
(add-char-to-string current v start)))
|
||||
current)))
|
||||
:else
|
||||
(str current v)))
|
||||
|
||||
(defn- make-new-input
|
||||
[current v input-selection-atom]
|
||||
[current v]
|
||||
(if (valid-input? current v)
|
||||
(normalize-input current v input-selection-atom)
|
||||
(normalize-input current v)
|
||||
current))
|
||||
|
||||
(defn- reset-input-error
|
||||
@@ -85,154 +59,124 @@
|
||||
(reset! input-error
|
||||
(> new-value prev-value)))
|
||||
|
||||
(defn delete-from-string
|
||||
[s idx]
|
||||
(let [size (count s)]
|
||||
(str (subs s 0 (dec idx)) (subs s idx size))))
|
||||
|
||||
(defn- f-view-internal
|
||||
;; crypto-decimals, limit-crypto and initial-crypto-currency? args are needed
|
||||
;; for component tests only
|
||||
[{default-on-confirm :on-confirm
|
||||
default-limit-crypto :limit-crypto
|
||||
default-crypto-decimals :crypto-decimals
|
||||
initial-crypto-currency? :initial-crypto-currency?
|
||||
:or {initial-crypto-currency? true}}]
|
||||
(let [_ (rn/dismiss-keyboard!)
|
||||
bottom (safe-area/get-bottom)
|
||||
input-value (reagent/atom "")
|
||||
input-error (reagent/atom false)
|
||||
crypto-currency? (reagent/atom initial-crypto-currency?)
|
||||
input-selection (reagent/atom {:start 0 :end 0})
|
||||
handle-swap (fn [{:keys [crypto? limit-fiat limit-crypto]}]
|
||||
(let [num-value (parse-double @input-value)
|
||||
current-limit (if crypto? limit-crypto limit-fiat)]
|
||||
(reset! crypto-currency? crypto?)
|
||||
(reset-input-error num-value current-limit input-error)))
|
||||
handle-keyboard-press (fn [v loading-routes? current-limit-amount]
|
||||
(when-not loading-routes?
|
||||
(let [current-value @input-value
|
||||
new-value (make-new-input current-value v input-selection)
|
||||
num-value (or (parse-double new-value) 0)]
|
||||
(reset! input-value new-value)
|
||||
(reset-input-error num-value current-limit-amount input-error)
|
||||
(reagent/flush))))
|
||||
handle-delete (fn [loading-routes? current-limit-amount]
|
||||
(when-not loading-routes?
|
||||
(let [{:keys [start end]} @input-selection]
|
||||
(reset-input-error @input-value current-limit-amount input-error)
|
||||
(when (= start end)
|
||||
(swap! input-value delete-from-string start)
|
||||
(move-input-cursor input-selection (dec start)))
|
||||
(reagent/flush))))
|
||||
handle-on-change (fn [v current-limit-amount]
|
||||
(when (valid-input? @input-value v)
|
||||
(let [num-value (or (parse-double v) 0)]
|
||||
(reset! input-value v)
|
||||
(reset-input-error num-value current-limit-amount input-error)
|
||||
(reagent/flush))))
|
||||
on-navigate-back (fn []
|
||||
(rf/dispatch [:wallet/clean-selected-token])
|
||||
(rf/dispatch [:navigate-back-within-stack :wallet-send-input-amount]))
|
||||
fetch-routes (fn [input-num-value current-limit-amount]
|
||||
;; crypto-decimals and limit-crypto args are needed for component tests only
|
||||
[{:keys [crypto-decimals limit-crypto]}]
|
||||
(let [bottom (safe-area/get-bottom)
|
||||
{:keys [currency]} (rf/sub [:profile/profile])
|
||||
token (rf/sub [:wallet/wallet-send-token])
|
||||
loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
|
||||
token-symbol (:symbol token)
|
||||
limit-crypto (or limit-crypto
|
||||
(utils/get-standard-crypto-format token (:total-balance token)))
|
||||
conversion-rate (get-in token [:market-values-per-currency :usd :price])
|
||||
limit-fiat (.toFixed (* (:total-balance token) conversion-rate) 2)
|
||||
crypto-decimals (or crypto-decimals (utils/get-crypto-decimals-count token))
|
||||
input-value (reagent/atom "")
|
||||
input-error (reagent/atom false)
|
||||
current-limit (reagent/atom {:amount limit-crypto
|
||||
:currency token-symbol})
|
||||
handle-swap (fn [crypto?]
|
||||
(let [num-value (parse-double @input-value)]
|
||||
(reset! current-limit (if crypto?
|
||||
{:amount limit-crypto
|
||||
:currency token-symbol}
|
||||
{:amount limit-fiat
|
||||
:currency currency}))
|
||||
(reset-input-error num-value
|
||||
(:amount @current-limit)
|
||||
input-error)))
|
||||
handle-keyboard-press (fn [v]
|
||||
(let [current-value @input-value
|
||||
new-value (make-new-input current-value v)
|
||||
num-value (or (parse-double new-value) 0)
|
||||
current-limit-amount (:amount @current-limit)]
|
||||
(when (not loading-suggested-routes?)
|
||||
(reset! input-value new-value)
|
||||
(reset-input-error num-value current-limit-amount input-error)
|
||||
(reagent/flush))))
|
||||
handle-delete (fn [_]
|
||||
(when-not loading-suggested-routes?
|
||||
(let [current-limit-amount (:amount @current-limit)]
|
||||
(swap! input-value #(subs % 0 (dec (count %))))
|
||||
(reset-input-error @input-value current-limit-amount input-error)
|
||||
(reagent/flush))))
|
||||
handle-on-change (fn [v]
|
||||
(when (valid-input? @input-value v)
|
||||
(let [num-value (or (parse-double v) 0)
|
||||
current-limit-amount (:amount @current-limit)]
|
||||
(reset! input-value v)
|
||||
(reset-input-error num-value current-limit-amount input-error)
|
||||
(reagent/flush))))]
|
||||
(fn [{:keys [on-confirm]
|
||||
:or {on-confirm #(rf/dispatch [:wallet/send-select-amount
|
||||
{:amount @input-value
|
||||
:stack-id :wallet-send-input-amount}])}}]
|
||||
(let [limit-label (make-limit-label @current-limit)
|
||||
input-num-value (parse-double @input-value)
|
||||
suggested-routes (rf/sub [:wallet/wallet-send-suggested-routes])
|
||||
route (rf/sub [:wallet/wallet-send-route])
|
||||
confirm-disabled? (or
|
||||
(nil? route)
|
||||
(empty? @input-value)
|
||||
(<= input-num-value 0)
|
||||
(> input-num-value (:amount @current-limit)))
|
||||
amount (str @input-value " " token-symbol)
|
||||
{:keys [color]} (rf/sub [:wallet/current-viewing-account])
|
||||
fetch-routes (fn []
|
||||
(rf/dispatch [:wallet/clean-suggested-routes])
|
||||
(when-not (or (empty? @input-value)
|
||||
(<= input-num-value 0)
|
||||
(> input-num-value current-limit-amount))
|
||||
(debounce/debounce-and-dispatch
|
||||
[:wallet/get-suggested-routes @input-value]
|
||||
100)))
|
||||
handle-on-confirm (fn []
|
||||
(rf/dispatch [:wallet/send-select-amount
|
||||
{:amount @input-value
|
||||
:stack-id :wallet-send-input-amount}]))
|
||||
selection-change (fn [selection]
|
||||
;; `reagent/flush` is needed to properly propagate the
|
||||
;; input cursor state. Since this is a controlled
|
||||
;; component the cursor will become static if
|
||||
;; `reagent/flush` is removed.
|
||||
(reset! input-selection selection)
|
||||
(reagent/flush))]
|
||||
(fn []
|
||||
(let [{fiat-currency :currency} (rf/sub [:profile/profile])
|
||||
{:keys [color]} (rf/sub [:wallet/current-viewing-account])
|
||||
{token-balance :total-balance
|
||||
token-symbol :symbol
|
||||
token-networks :networks
|
||||
:as token} (rf/sub [:wallet/wallet-send-token])
|
||||
conversion-rate (-> token :market-values-per-currency :usd :price)
|
||||
loading-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
|
||||
suggested-routes (rf/sub [:wallet/wallet-send-suggested-routes])
|
||||
route (rf/sub [:wallet/wallet-send-route])
|
||||
on-confirm (or default-on-confirm handle-on-confirm)
|
||||
crypto-decimals (or default-crypto-decimals
|
||||
(utils/get-crypto-decimals-count token))
|
||||
crypto-limit (or default-limit-crypto
|
||||
(utils/get-standard-crypto-format token token-balance))
|
||||
fiat-limit (.toFixed (* token-balance conversion-rate) 2)
|
||||
current-limit (if @crypto-currency? crypto-limit fiat-limit)
|
||||
current-currency (if @crypto-currency? token-symbol fiat-currency)
|
||||
limit-label (make-limit-label {:amount current-limit
|
||||
:currency current-currency})
|
||||
input-num-value (parse-double @input-value)
|
||||
confirm-disabled? (or (nil? route)
|
||||
(empty? @input-value)
|
||||
(<= input-num-value 0)
|
||||
(> input-num-value current-limit))
|
||||
amount-text (str @input-value " " token-symbol)]
|
||||
(when-not (or
|
||||
(empty? @input-value)
|
||||
(<= input-num-value 0)
|
||||
(> input-num-value (:amount @current-limit)))
|
||||
(debounce/debounce-and-dispatch [:wallet/get-suggested-routes
|
||||
@input-value]
|
||||
100)))]
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(let [dismiss-keyboard-fn #(when (= % "active") (rn/dismiss-keyboard!))
|
||||
app-keyboard-listener (.addEventListener rn/app-state "change" dismiss-keyboard-fn)]
|
||||
#(.remove app-keyboard-listener))))
|
||||
(rn/use-effect
|
||||
#(fetch-routes input-num-value current-limit)
|
||||
[@input-value])
|
||||
(rn/use-effect #(fetch-routes) [@input-value])
|
||||
[rn/view
|
||||
{:style style/screen
|
||||
:accessibility-label (str "container" (when @input-error "-error"))}
|
||||
[account-switcher/view
|
||||
{:icon-name :i/arrow-left
|
||||
:on-press on-navigate-back
|
||||
:on-press #(rf/dispatch [:navigate-back-within-stack :wallet-send-input-amount])
|
||||
:switcher-type :select-account}]
|
||||
[quo/token-input
|
||||
{:container-style style/input-container
|
||||
:token token-symbol
|
||||
:currency current-currency
|
||||
:crypto-decimals crypto-decimals
|
||||
:error? @input-error
|
||||
:networks token-networks
|
||||
:title (i18n/label :t/send-limit {:limit limit-label})
|
||||
:conversion conversion-rate
|
||||
:show-keyboard? false
|
||||
:value @input-value
|
||||
:selection @input-selection
|
||||
:on-change-text #(handle-on-change % current-limit)
|
||||
:on-selection-change selection-change
|
||||
:on-swap #(handle-swap
|
||||
{:crypto? %
|
||||
:currency current-currency
|
||||
:token-symbol token-symbol
|
||||
:limit-fiat fiat-limit
|
||||
:limit-crypto crypto-limit})}]
|
||||
{:container-style style/input-container
|
||||
:token token-symbol
|
||||
:currency currency
|
||||
:crypto-decimals crypto-decimals
|
||||
:error? @input-error
|
||||
:networks (:networks token)
|
||||
:title (i18n/label :t/send-limit {:limit limit-label})
|
||||
:conversion conversion-rate
|
||||
:show-keyboard? false
|
||||
:value @input-value
|
||||
:on-swap handle-swap
|
||||
:on-change-text (fn [text]
|
||||
(handle-on-change text))}]
|
||||
[routes/view
|
||||
{:amount amount-text
|
||||
{:amount amount
|
||||
:routes suggested-routes
|
||||
:token token
|
||||
:input-value @input-value
|
||||
:fetch-routes #(fetch-routes % current-limit)}]
|
||||
:fetch-routes fetch-routes}]
|
||||
[quo/bottom-actions
|
||||
{:actions :1-action
|
||||
:customization-color color
|
||||
:button-one-label (i18n/label :t/confirm)
|
||||
:button-one-props {:disabled? confirm-disabled?
|
||||
:on-press on-confirm}}]
|
||||
:on-press on-confirm}
|
||||
:customization-color color}]
|
||||
[quo/numbered-keyboard
|
||||
{:container-style (style/keyboard-container bottom)
|
||||
:left-action :dot
|
||||
:delete-key? true
|
||||
:on-press #(handle-keyboard-press % loading-routes? current-limit)
|
||||
:on-delete #(handle-delete loading-routes? current-limit)}]]))))
|
||||
:on-press handle-keyboard-press
|
||||
:on-delete handle-delete}]]))))
|
||||
|
||||
(defn- view-internal
|
||||
[props]
|
||||
|
||||
@@ -17,21 +17,22 @@
|
||||
{:id :tab/collectibles :label (i18n/label :t/collectibles) :accessibility-label :collectibles-tab}])
|
||||
|
||||
(defn- asset-component
|
||||
[token _ _ {:keys [currency currency-symbol]}]
|
||||
(let [on-press #(rf/dispatch [:wallet/send-select-token
|
||||
{:token token
|
||||
:stack-id :wallet-select-asset}])
|
||||
token-units (utils/total-token-units-in-all-chains token)
|
||||
crypto-formatted (utils/get-standard-crypto-format token token-units)
|
||||
fiat-value (utils/total-token-fiat-value currency token)
|
||||
fiat-formatted (utils/get-standard-fiat-format crypto-formatted currency-symbol fiat-value)]
|
||||
[quo/token-network
|
||||
{:token (:symbol token)
|
||||
:label (:name token)
|
||||
:token-value (str crypto-formatted " " (:symbol token))
|
||||
:fiat-value fiat-formatted
|
||||
:networks (:networks token)
|
||||
:on-press on-press}]))
|
||||
[]
|
||||
(fn [token _ _ {:keys [currency currency-symbol]}]
|
||||
(let [on-press #(rf/dispatch [:wallet/send-select-token
|
||||
{:token token
|
||||
:stack-id :wallet-select-asset}])
|
||||
token-units (utils/total-token-units-in-all-chains token)
|
||||
crypto-formatted (utils/get-standard-crypto-format token token-units)
|
||||
fiat-value (utils/total-token-fiat-value currency token)
|
||||
fiat-formatted (utils/get-standard-fiat-format crypto-formatted currency-symbol fiat-value)]
|
||||
[quo/token-network
|
||||
{:token (:symbol token)
|
||||
:label (:name token)
|
||||
:token-value (str crypto-formatted " " (:symbol token))
|
||||
:fiat-value fiat-formatted
|
||||
:networks (:networks token)
|
||||
:on-press on-press}])))
|
||||
|
||||
(defn- asset-list
|
||||
[search-text]
|
||||
|
||||
@@ -14,18 +14,16 @@
|
||||
{:margin-right 4})
|
||||
|
||||
(defn details-container
|
||||
[{:keys [loading-suggested-routes? route-loaded? theme]}]
|
||||
[route? theme]
|
||||
{:flex-direction :row
|
||||
:justify-content (if route-loaded? :space-between :center)
|
||||
:height (when (or loading-suggested-routes? route-loaded?) 52)
|
||||
:justify-content (if route? :space-between :center)
|
||||
:height 52
|
||||
:padding-horizontal 12
|
||||
:padding-top 7
|
||||
:padding-bottom 8
|
||||
:border-radius 16
|
||||
:border-width 1
|
||||
:border-color (if (or loading-suggested-routes? route-loaded?)
|
||||
(colors/theme-colors colors/neutral-10 colors/neutral-90 theme)
|
||||
:transparent)})
|
||||
:border-color (colors/theme-colors colors/neutral-10 colors/neutral-90 theme)})
|
||||
|
||||
(def details-title-container
|
||||
{:padding-horizontal 20
|
||||
|
||||
@@ -74,10 +74,9 @@
|
||||
:account-props account-props}]])
|
||||
|
||||
(defn- transaction-details
|
||||
[{:keys [estimated-time-min max-fees token-symbol amount to-address route theme]}]
|
||||
(let [currency-symbol (rf/sub [:profile/currency-symbol])
|
||||
route-loaded? (some? route)
|
||||
loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])]
|
||||
[{:keys [estimated-time-min max-fees token amount to-address route theme]}]
|
||||
(let [currency-symbol (rf/sub [:profile/currency-symbol])
|
||||
route-loaded? (some? route)]
|
||||
[rn/view
|
||||
{:style style/details-title-container}
|
||||
[quo/text
|
||||
@@ -87,14 +86,8 @@
|
||||
:accessibility-label :summary-from-label}
|
||||
(i18n/label :t/details)]
|
||||
[rn/view
|
||||
{:style (style/details-container
|
||||
{:loading-suggested-routes? loading-suggested-routes?
|
||||
:route-loaded? route-loaded?
|
||||
:theme theme})}
|
||||
(cond
|
||||
loading-suggested-routes?
|
||||
[rn/activity-indicator {:style {:align-self :center}}]
|
||||
route-loaded?
|
||||
{:style (style/details-container route-loaded? theme)}
|
||||
(if route-loaded?
|
||||
[:<>
|
||||
[quo/data-item
|
||||
{:container-style style/detail-item
|
||||
@@ -130,10 +123,8 @@
|
||||
:status :default
|
||||
:size :small
|
||||
:title (i18n/label :t/user-gets {:name (utils/get-shortened-address to-address)})
|
||||
:subtitle (str amount " " token-symbol)}]]
|
||||
:else
|
||||
[quo/text {:style {:align-self :center}}
|
||||
(i18n/label :t/no-routes-found-confirmation)])]]))
|
||||
:subtitle (str amount " " (:symbol token))}]]
|
||||
[rn/activity-indicator {:style {:align-self :center}}])]]))
|
||||
|
||||
(defn- view-internal
|
||||
[_]
|
||||
@@ -149,10 +140,9 @@
|
||||
collectible-data (:collectible-data collectible)
|
||||
collectible-id (get-in collectible [:id :token-id])
|
||||
token-symbol (if collectible
|
||||
(first (remove
|
||||
string/blank?
|
||||
[(:name collectible-data)
|
||||
(str (:name collection-data) " #" collectible-id)]))
|
||||
(first (remove string/blank?
|
||||
[(:name collectible-data)
|
||||
(str (:name collection-data) " #" collectible-id)]))
|
||||
(:symbol token))
|
||||
image-url (when collectible (:image-url collectible-data))
|
||||
amount (:amount send-transaction-data)
|
||||
@@ -167,8 +157,7 @@
|
||||
:emoji (:emoji account)
|
||||
:type :default
|
||||
:name (:name account)
|
||||
:address (utils/get-shortened-address (:address
|
||||
account))}
|
||||
:address (utils/get-shortened-address (:address account))}
|
||||
user-props {:full-name to-address
|
||||
:address (utils/get-shortened-address to-address)}]
|
||||
[rn/view {:style {:flex 1}}
|
||||
@@ -184,17 +173,17 @@
|
||||
:on-press #(js/alert
|
||||
"to be implemented")
|
||||
:accessibility-label :advanced-options}]}]
|
||||
:footer (when route
|
||||
:footer (if route
|
||||
[standard-auth/slide-button
|
||||
{:size :size-48
|
||||
:track-text (i18n/label :t/slide-to-send)
|
||||
:container-style {:z-index 2}
|
||||
:customization-color account-color
|
||||
:on-auth-success #(rf/dispatch
|
||||
[:wallet/send-transaction
|
||||
(security/safe-unmask-data
|
||||
%)])
|
||||
:auth-button-label (i18n/label :t/confirm)}])
|
||||
:on-auth-success #(rf/dispatch [:wallet/send-transaction
|
||||
(security/safe-unmask-data
|
||||
%)])
|
||||
:auth-button-label (i18n/label :t/confirm)}]
|
||||
[rn/activity-indicator])
|
||||
:gradient-cover? true
|
||||
:customization-color (:color account)}
|
||||
[rn/view
|
||||
@@ -224,7 +213,7 @@
|
||||
[transaction-details
|
||||
{:estimated-time-min estimated-time-min
|
||||
:max-fees max-fees
|
||||
:token-symbol token-symbol
|
||||
:token token
|
||||
:amount amount
|
||||
:to-address to-address
|
||||
:theme theme
|
||||
|
||||
@@ -13,8 +13,7 @@
|
||||
[react-native.platform :as platform]
|
||||
[react-native.shake :as react-native-shake]
|
||||
[reagent.impl.batching :as batching]
|
||||
[status-im.common.log :as logging]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.common.log :as log]
|
||||
[status-im.common.universal-links :as universal-links]
|
||||
[status-im.config :as config]
|
||||
[status-im.contexts.profile.push-notifications.events :as notifications]
|
||||
@@ -35,17 +34,12 @@
|
||||
|
||||
(def adjust-resize 16)
|
||||
|
||||
(defn is-hermes
|
||||
[]
|
||||
(boolean (.-HermesInternal js/global)))
|
||||
|
||||
(defn init
|
||||
[]
|
||||
|
||||
(native-module/init #(re-frame/dispatch [:signals/signal-received %]))
|
||||
(when platform/android?
|
||||
(native-module/set-soft-input-mode adjust-resize))
|
||||
(logging/setup config/log-level)
|
||||
(log/setup config/log-level)
|
||||
(global-error/register-handler)
|
||||
(notifications/listen-notifications)
|
||||
(.addEventListener rn/app-state "change" #(re-frame/dispatch [:app-state-change %]))
|
||||
@@ -60,6 +54,5 @@
|
||||
(async-storage/get-item :screen-height #(reset! shell.state/screen-height %))
|
||||
|
||||
(dev/setup)
|
||||
(log/info "hermesEnabled ->" (is-hermes))
|
||||
|
||||
(re-frame/dispatch-sync [:app-started]))
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
(:require
|
||||
[cljs.test :refer [deftest is]]
|
||||
[day8.re-frame.test :as rf-test]
|
||||
[legacy.status-im.multiaccounts.logout.core :as logout]
|
||||
[legacy.status-im.utils.test :as utils.test]
|
||||
[status-im.contexts.profile.utils :as profile.utils]
|
||||
[test-helpers.integration :as h]
|
||||
[utils.re-frame :as rf]))
|
||||
@@ -21,38 +19,4 @@
|
||||
[:toasts/upsert]
|
||||
(let [profile (rf/sub [:profile/profile])
|
||||
display-name (profile.utils/displayed-name profile)]
|
||||
(is (= new-name display-name)))
|
||||
(h/logout)
|
||||
(rf-test/wait-for [::logout/logout-method]))))))))
|
||||
|
||||
(deftest edit-profile-picture-test
|
||||
(h/log-headline :edit-profile-picture-test)
|
||||
(let [mock-image "resources/images/mock2/monkey.png"
|
||||
absolute-path (.resolve utils.test/path mock-image)]
|
||||
(rf-test/run-test-async
|
||||
(h/with-app-initialized
|
||||
(h/with-account
|
||||
(rf/dispatch [:profile/edit-picture absolute-path 80 80])
|
||||
(rf-test/wait-for
|
||||
[:profile/update-local-picture]
|
||||
(rf-test/wait-for
|
||||
[:toasts/upsert]
|
||||
(let [profile (rf/sub [:profile/profile])]
|
||||
(is (not (nil? (:images profile)))))
|
||||
(h/logout)
|
||||
(rf-test/wait-for [::logout/logout-method]))))))))
|
||||
|
||||
(deftest delete-profile-picture-test
|
||||
(h/log-headline :delete-profile-picture-test)
|
||||
(rf-test/run-test-async
|
||||
(h/with-app-initialized
|
||||
(h/with-account
|
||||
(rf/dispatch [:profile/delete-picture])
|
||||
(rf-test/wait-for
|
||||
[:profile/update-local-picture]
|
||||
(rf-test/wait-for
|
||||
[:toasts/upsert]
|
||||
(let [profile (rf/sub [:profile/profile])]
|
||||
(is (nil? (:image profile))))
|
||||
(h/logout)
|
||||
(rf-test/wait-for [::logout/logout-method])))))))
|
||||
(is (= new-name display-name))))))))))
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
:component communities.discover/view}
|
||||
|
||||
{:name :community-overview
|
||||
:component communities.overview/view}
|
||||
:component communities.overview/overview}
|
||||
|
||||
{:name :settings
|
||||
:options options/transparent-screen-options
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
(ns status-im.subs.communities
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.data-store.communities :as data-store]
|
||||
[legacy.status-im.ui.screens.profile.visibility-status.utils :as visibility-status-utils]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
@@ -308,6 +307,10 @@
|
||||
[(re-frame/subscribe [:communities/community community-id])])
|
||||
(fn [[{:keys [token-permissions-check token-permissions checking-permissions? token-images]}] _]
|
||||
(let [can-request-access? (:satisfied token-permissions-check)
|
||||
role-permissions #{constants/community-token-permission-become-admin
|
||||
constants/community-token-permission-become-member
|
||||
constants/community-token-permission-become-token-master
|
||||
constants/community-token-permission-become-token-owner}
|
||||
highest-permission-role
|
||||
(when can-request-access?
|
||||
(->> token-permissions-check
|
||||
@@ -318,7 +321,7 @@
|
||||
(and (first criteria)
|
||||
(some #{(:type (permission-id->permission-value token-permissions
|
||||
permission-id))}
|
||||
constants/community-role-permissions))]
|
||||
role-permissions))]
|
||||
(if highest-permission-role
|
||||
(min highest-permission-role permission-type)
|
||||
permission-type)
|
||||
@@ -336,8 +339,8 @@
|
||||
(:permissions token-permissions-check))
|
||||
:tokens (->>
|
||||
token-permissions
|
||||
(filter (fn [[_ permission]]
|
||||
(data-store/role-permission? permission)))
|
||||
(filter (fn [[_ {:keys [type]}]]
|
||||
(= type constants/community-token-permission-become-member)))
|
||||
(map (fn [[perm-key {:keys [token_criteria]}]]
|
||||
(let [check-criteria (get-in token-permissions-check
|
||||
[:permissions perm-key :criteria])]
|
||||
|
||||
@@ -455,11 +455,7 @@
|
||||
(swap! rf-db/app-db assoc-in [:communities community-id] community)
|
||||
(is (match? {:can-request-access? true
|
||||
:number-of-hold-tokens 2
|
||||
:tokens [[{:symbol "DAI"
|
||||
:amount "5.0"
|
||||
:sufficient? nil
|
||||
:loading? checking-permissions?}]
|
||||
[{:symbol "ETH"
|
||||
:tokens [[{:symbol "ETH"
|
||||
:amount "0.001"
|
||||
:sufficient? nil
|
||||
:loading? checking-permissions?
|
||||
|
||||
@@ -106,12 +106,6 @@
|
||||
(fn [profile]
|
||||
(:test-networks-enabled? profile)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:profile/is-sepolia-enabled?
|
||||
:<- [:profile/profile]
|
||||
(fn [profile]
|
||||
(:is-sepolia-enabled? profile)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:multiaccount/contact
|
||||
:<- [:profile/profile]
|
||||
|
||||
@@ -30,22 +30,11 @@
|
||||
:short-name constants/optimism-short-name
|
||||
:network-name constants/optimism-network-name})
|
||||
|
||||
(defn get-network-details
|
||||
[chain-id]
|
||||
(case chain-id
|
||||
(constants/ethereum-mainnet-chain-id constants/ethereum-goerli-chain-id
|
||||
constants/ethereum-sepolia-chain-id)
|
||||
mainnet-network-details
|
||||
|
||||
(constants/arbitrum-mainnet-chain-id constants/arbitrum-goerli-chain-id
|
||||
constants/arbitrum-sepolia-chain-id)
|
||||
arbitrum-network-details
|
||||
|
||||
(constants/optimism-mainnet-chain-id constants/optimism-goerli-chain-id
|
||||
constants/optimism-sepolia-chain-id)
|
||||
optimism-network-details
|
||||
|
||||
nil))
|
||||
(def network-list
|
||||
{constants/mainnet-chain-id mainnet-network-details
|
||||
constants/goerli-chain-id mainnet-network-details
|
||||
constants/arbitrum-chain-id arbitrum-network-details
|
||||
constants/optimism-chain-id optimism-network-details})
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet/network-details
|
||||
@@ -54,7 +43,7 @@
|
||||
(->> networks
|
||||
(keep
|
||||
(fn [{:keys [chain-id related-chain-id layer test?]}]
|
||||
(let [network-details (get-network-details (if test? related-chain-id chain-id))]
|
||||
(let [network-details (get network-list (if test? related-chain-id chain-id))]
|
||||
(assoc network-details
|
||||
:chain-id chain-id
|
||||
:related-chain-id related-chain-id
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
||||
"owner": "status-im",
|
||||
"repo": "status-go",
|
||||
"version": "e9b10c4beb2ddd16e9ddff089831392a951b5851",
|
||||
"commit-sha1": "e9b10c4beb2ddd16e9ddff089831392a951b5851",
|
||||
"src-sha256": "04f40067rh0s667yx4p94irl2h84ipi8ig0m023ifqik068fjdjv"
|
||||
"version": "1256d8121e6fae4fc4517736a271624e473d5417",
|
||||
"commit-sha1": "1256d8121e6fae4fc4517736a271624e473d5417",
|
||||
"src-sha256": "0v9pbb79r8avvlx6ss7czj2j3s8csb2j2gkwavjbya6bys80hqmf"
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ from selenium.common.exceptions import TimeoutException, NoSuchElementException
|
||||
|
||||
from tests import marks, run_in_parallel, transl
|
||||
from tests.base_test_case import MultipleSharedDeviceTestCase, create_shared_drivers
|
||||
from views.base_element import Button
|
||||
from views.sign_in_view import SignInView
|
||||
|
||||
|
||||
@@ -162,15 +161,13 @@ class TestOneToOneChatMultipleSharedDevicesNewUi(MultipleSharedDeviceTestCase):
|
||||
|
||||
self.home_2.just_fyi("Check 'Open in Status' option")
|
||||
# url_to_open = 'http://status.app'
|
||||
url_to_open = 'https://github.com/status-im/status-mobile'
|
||||
url_to_open = 'https://www.ethereum.org/en/run-a-node/'
|
||||
self.chat_1.send_message(url_to_open)
|
||||
chat_element = self.chat_2.chat_element_by_text(url_to_open)
|
||||
if chat_element.is_element_displayed(120):
|
||||
chat_element.click_on_link_inside_message_body()
|
||||
web_view = self.chat_2.open_in_status_button.click()
|
||||
text_element = web_view.element_by_text("a free (libre) open source, mobile OS for Ethereum")
|
||||
sign_in_button = Button(self.chat_2.driver, xpath="//android.view.View[@content-desc='Sign in']")
|
||||
if not text_element.is_element_displayed(30) or not sign_in_button.is_element_displayed(30):
|
||||
if not web_view.element_by_text("Take full control. Run your own node.").is_element_displayed(60):
|
||||
self.errors.append('URL was not opened from 1-1 chat')
|
||||
else:
|
||||
self.errors.append("Message with URL was not received")
|
||||
|
||||
@@ -1090,6 +1090,8 @@ class TestCommunityMultipleDeviceMergedTwo(MultipleSharedDeviceTestCase):
|
||||
self.errors.verify_no_errors()
|
||||
|
||||
@marks.testrail_id(703629)
|
||||
@marks.xfail(
|
||||
reason="Can't join a community if admin goes offline, https://github.com/status-im/status-mobile/issues/17678")
|
||||
def test_community_join_when_node_owner_offline(self):
|
||||
for home in self.homes:
|
||||
home.navigate_back_to_home_view()
|
||||
@@ -1141,8 +1143,7 @@ class TestCommunityMultipleDeviceMergedTwo(MultipleSharedDeviceTestCase):
|
||||
else:
|
||||
self.errors.append("Community channel is not displayed for user before join")
|
||||
self.community_2.toast_content_element.wait_for_invisibility_of_element(30)
|
||||
self.community_2.close_community_view_button.click_until_absense_of_element(
|
||||
self.community_2.close_community_view_button)
|
||||
self.community_2.close_community_view_button.click()
|
||||
self.home_2.pending_communities_tab.click()
|
||||
if self.home_2.get_chat(community_name, community=True).is_element_displayed():
|
||||
self.home_2.get_chat(community_name, community=True).click()
|
||||
@@ -1165,8 +1166,7 @@ class TestCommunityMultipleDeviceMergedTwo(MultipleSharedDeviceTestCase):
|
||||
# ToDo: add verification when toast is fixed
|
||||
if not self.community_2.community_status_joined.is_element_displayed():
|
||||
self.errors.append("Joined status is not displayed")
|
||||
self.community_2.close_community_view_button.click_until_absense_of_element(
|
||||
self.community_2.close_community_view_button)
|
||||
self.community_2.close_community_view_button.click()
|
||||
self.home_2.joined_communities_tab.click()
|
||||
chat_element = self.home_2.get_chat(community_name, community=True)
|
||||
if chat_element.is_element_displayed(30):
|
||||
|
||||
@@ -1183,8 +1183,6 @@
|
||||
"profile-details": "Profile details",
|
||||
"profile-name": "Profile name",
|
||||
"profile-name-is-too-long": "Profile name is too long",
|
||||
"profile-picture-added": "Profile picture added",
|
||||
"profile-picture-removed": "Profile picture removed",
|
||||
"public-chat": "Public chat",
|
||||
"public-chats": "Public chats",
|
||||
"public-group-status": "Public",
|
||||
@@ -1285,7 +1283,6 @@
|
||||
"share-channel": "Share channel",
|
||||
"share-address": "Share address",
|
||||
"share-chat": "Share chat",
|
||||
"share-collectible": "Share collectible",
|
||||
"share-contact-code": "Share my chat key",
|
||||
"share-community": "Share community",
|
||||
"share-dapp-text": "Check out this DApp I'm using on Status: {{link}}",
|
||||
@@ -2482,6 +2479,5 @@
|
||||
"preferred-by-receiver": "Preferred by receiver",
|
||||
"not-preferred-by-receiver": "Not preferred by receiver",
|
||||
"apply-changes": "Apply changes",
|
||||
"receiver-networks-warning": "Changing these settings may result in sending tokens to networks the recipient doesn't use",
|
||||
"no-routes-found-confirmation": "No routes found. Token type may not be supported or you may don't have enough ETH to cover gas."
|
||||
"receiver-networks-warning": "Changing these settings may result in sending tokens to networks the recipient doesn't use"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user