Compare commits
22
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50759346c4 | ||
|
|
98811e3511 | ||
|
|
818b9e2bdf | ||
|
|
a79c3ad0bf | ||
|
|
ed7463132a | ||
|
|
d20f10cf8b | ||
|
|
ebbae051bd | ||
|
|
521f39b6fb | ||
|
|
ee1f93defb | ||
|
|
3665fe26da | ||
|
|
3ec7209fcc | ||
|
|
195826a7f4 | ||
|
|
5bb4f3632a | ||
|
|
4fe62553ca | ||
|
|
cb586c8676 | ||
|
|
fd50e4281c | ||
|
|
dcbb080217 | ||
|
|
97d1b3faa1 | ||
|
|
9c322397a2 | ||
|
|
ca2b1d5c8e | ||
|
|
9a4bc7e250 | ||
|
|
c6dbfb6244 |
@@ -282,11 +282,12 @@ SIMULATOR=iPhone 13
|
||||
# TODO: fix IOS_STATUS_GO_TARGETS to be either amd64 or arm64 when RN is upgraded
|
||||
run-ios: export TARGET := ios
|
||||
run-ios: export IOS_STATUS_GO_TARGETS := ios/arm64;iossimulator/amd64
|
||||
run-ios: export XCBeautify=$(shell which xcbeautify) # for react-native-cli to pick this up and to auto format output
|
||||
run-ios: ##@run Build iOS app and start it in a simulator/device
|
||||
ifneq ("$(SIMULATOR)", "")
|
||||
npx react-native run-ios --simulator="$(SIMULATOR)" | xcbeautify
|
||||
npx react-native run-ios --simulator="$(SIMULATOR)"
|
||||
else
|
||||
npx react-native run-ios | xcbeautify
|
||||
npx react-native run-ios
|
||||
endif
|
||||
|
||||
show-ios-devices: ##@other shows connected ios device and its name
|
||||
|
||||
@@ -46,61 +46,6 @@ subprojects {
|
||||
}
|
||||
}
|
||||
|
||||
task printUniquePluginsAndDependencies {
|
||||
doLast {
|
||||
def allItems = []
|
||||
// Kotlin plugin version check
|
||||
if (project.hasProperty('kotlinPluginVersion')) {
|
||||
def kotlinVersion = project.kotlinPluginVersion
|
||||
// since we are not using the plugins DSL we have to manually add this here
|
||||
allItems.add("org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:$kotlinVersion")
|
||||
}
|
||||
|
||||
allprojects { project ->
|
||||
// Collect plugins
|
||||
project.plugins.each { plugin ->
|
||||
allItems.add(plugin.getClass().getName())
|
||||
}
|
||||
|
||||
// Collect artifacts from the buildscript classpath
|
||||
project.buildscript.configurations.classpath.resolvedConfiguration.resolvedArtifacts.each { artifact ->
|
||||
allItems.add("${artifact.moduleVersion.id.group}:${artifact.name}:${artifact.moduleVersion.id.version}")
|
||||
}
|
||||
|
||||
// Collect dependencies from all configurations, excluding 'test' configurations
|
||||
project.configurations.each { config ->
|
||||
if (!config.name.toLowerCase().startsWith('test')) {
|
||||
try {
|
||||
config.resolvedConfiguration.resolvedArtifacts.each { artifact ->
|
||||
allItems.add("${artifact.moduleVersion.id.group}:${artifact.name}:${artifact.moduleVersion.id.version}")
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Handle the case where a configuration is not resolvable
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Filter out specific dependencies and invalid entries
|
||||
def filteredItems = allItems.findAll { item ->
|
||||
!item.startsWith("StatusIm:") && // to strip out status-im:status-go:ea3e59f
|
||||
!item.startsWith("status-im:") && // to strip out StatusIm:react-native-touch-id:unspecified
|
||||
!item.contains("null") && // to strip out com.facebook.react:react-android:null
|
||||
!item.contains("unspecified") && // to strip out com.facebook.react:react-native-gradle-plugin:unspecified
|
||||
!item.endsWith("Inject") && // to strip out org.gradle.api.plugins.BasePlugin$Inject
|
||||
!item.endsWith("ReactPlugin") && // to strip out com.facebook.react.ReactPlugin
|
||||
!item.endsWith("DownloadTaskPlugin") && // to strip out de.undercouch.gradle.tasks.download.DownloadTaskPlugin
|
||||
!item.endsWith("KotlinAndroidPluginWrapper") && // to strip out org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper
|
||||
!item.contains("com.android.build.gradle.") // to strip out com.android.build.gradle.AppPlugin
|
||||
}
|
||||
|
||||
// Remove duplicates & sort
|
||||
filteredItems.unique().sort().each {
|
||||
println it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
beforeEvaluate {
|
||||
if (System.env.STATUS_GO_ANDROID_LIBDIR == null || System.env.STATUS_GO_ANDROID_LIBDIR == "") {
|
||||
@@ -118,12 +63,3 @@ allprojects {
|
||||
maven { url 'https://mvnrepository.com/artifact/com.github.gundy/semver4j'}
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
apply plugin: 'project-report'
|
||||
|
||||
task('allDependencies', type: org.gradle.api.tasks.diagnostics.DependencyReportTask) {
|
||||
// Depend on the evaluation of child projects to ensure all configurations are available
|
||||
evaluationDependsOnChildren()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,23 @@ function gen_deps_list() {
|
||||
echo -e "${CLR}Found ${GRN}$(wc -l < "${DEPS_LIST}")${RST} direct dependencies..."
|
||||
}
|
||||
|
||||
# FIXME: Temporary fix for missing packages.
|
||||
# https://github.com/status-im/status-mobile/issues/15447
|
||||
function add_deps_hack() {
|
||||
echo -n \
|
||||
'com.android.tools.build:gradle:1.3.1
|
||||
com.squareup.okio:okio:1.13.0
|
||||
com.squareup.okio:okio:1.15.0
|
||||
com.squareup.okhttp3:okhttp:3.12.1
|
||||
org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.7.22
|
||||
com.android.tools.lint:lint-gradle:30.4.2
|
||||
com.android.tools.build:gradle:7.4.2
|
||||
com.android.tools.build:aapt2:7.4.2-8841542
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2
|
||||
org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.9.0' \
|
||||
>> "${DEPS_LIST}"
|
||||
}
|
||||
|
||||
# Find download URLs for each dependency.
|
||||
function gen_deps_urls() {
|
||||
go-maven-resolver < "${DEPS_LIST}" | sort -uV -o "${DEPS_URLS}"
|
||||
@@ -82,6 +99,7 @@ fi
|
||||
# Run each stage in order
|
||||
gen_proj_list
|
||||
gen_deps_list
|
||||
add_deps_hack
|
||||
gen_deps_urls
|
||||
gen_deps_json
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ stdenv.mkDerivation {
|
||||
"patchKeyChainPhase"
|
||||
"patchGlogPhase"
|
||||
"patchBoostPodSpec"
|
||||
"patchRNGradlePluginPhase"
|
||||
"installPhase"
|
||||
];
|
||||
|
||||
@@ -87,11 +86,6 @@ stdenv.mkDerivation {
|
||||
'https://sourceforge.net/projects/boost/files/boost/1.76.0/boost_1_76_0.tar.bz2' \
|
||||
'';
|
||||
|
||||
patchRNGradlePluginPhase = ''
|
||||
substituteInPlace ./node_modules/@react-native/gradle-plugin/build.gradle.kts \
|
||||
--replace '1.7.22' '1.9.0'
|
||||
'';
|
||||
|
||||
# The ELF types are incompatible with the host platform, so let's not even try
|
||||
# TODO: Use Android NDK to strip binaries manually
|
||||
dontPatchELF = true;
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
[db]
|
||||
(into #{}
|
||||
(remove #(= (:type %) :watch)
|
||||
(map #(eip55/address->checksum (:address %)) (get db :profile/wallet-accounts)))))
|
||||
(map #(eip55/address->checksum (:address %)) (vals (get-in db [:wallet :accounts]))))))
|
||||
|
||||
;;NOTE we want to handle only last resolve
|
||||
(def resolve-last-id (atom nil))
|
||||
|
||||
@@ -79,10 +79,15 @@
|
||||
"recent-history-ready" (recent-history-fetching-ended cofx event)
|
||||
"fetching-history-error" (fetching-error cofx event)
|
||||
"non-archival-node-detected" (non-archival-node-detected cofx event)
|
||||
"pending-transaction-status-changed" {:fx
|
||||
[[:dispatch
|
||||
[:wallet/pending-transaction-status-changed-received
|
||||
event]]]}
|
||||
"wallet-owned-collectibles-filtering-done" {:fx [[:dispatch
|
||||
[:wallet/owned-collectibles-filtering-done
|
||||
event]]]}
|
||||
"wallet-get-collectibles-details-done" {:fx [[:dispatch
|
||||
[:wallet/get-collectible-details-done
|
||||
event]]]}
|
||||
"wallet-tick-reload" {:fx [[:dispatch [:wallet/reload]]]}
|
||||
(log/debug ::unknown-wallet-event :type type :event event)))
|
||||
|
||||
@@ -76,15 +76,19 @@
|
||||
(str description " · " (i18n/label :t/on-device))])
|
||||
|
||||
(defn- context-tag-subtitle
|
||||
[{:keys [community-logo community-name]}]
|
||||
[rn/view
|
||||
{:accessibility-label :context-tag-wrapper
|
||||
:style {:flex-wrap :wrap}}
|
||||
[context-tag/view
|
||||
{:type :community
|
||||
:community-name community-name
|
||||
:community-logo community-logo
|
||||
:size 24}]])
|
||||
[{:keys [context-tag-type community-logo community-name account-name emoji customization-color]}]
|
||||
(let [tag-type (or context-tag-type :account)]
|
||||
[rn/view
|
||||
{:accessibility-label :context-tag-wrapper
|
||||
:style {:flex-wrap :wrap}}
|
||||
[context-tag/view
|
||||
{:type tag-type
|
||||
:account-name account-name
|
||||
:emoji emoji
|
||||
:community-name community-name
|
||||
:community-logo community-logo
|
||||
:size 24
|
||||
:customization-color customization-color}]]))
|
||||
|
||||
(defn- description-subtitle
|
||||
[{:keys [theme blur? description]}]
|
||||
@@ -95,7 +99,8 @@
|
||||
description])
|
||||
|
||||
(defn- subtitle
|
||||
[{:keys [type theme blur? keycard? networks description community-name community-logo]}]
|
||||
[{:keys [type theme blur? keycard? networks description community-name community-logo
|
||||
context-tag-type account-name emoji customization-color]}]
|
||||
(cond
|
||||
(= :keypair type)
|
||||
[keypair-subtitle
|
||||
@@ -118,8 +123,12 @@
|
||||
|
||||
(= :context-tag type)
|
||||
[context-tag-subtitle
|
||||
{:community-logo community-logo
|
||||
:community-name community-name}]
|
||||
{:context-tag-type context-tag-type
|
||||
:community-logo community-logo
|
||||
:community-name community-name
|
||||
:account-name account-name
|
||||
:emoji emoji
|
||||
:customization-color customization-color}]
|
||||
|
||||
(and (not= :label type) description)
|
||||
[description-subtitle
|
||||
@@ -173,6 +182,7 @@
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [title title-icon type theme description blur? community-name community-logo button-icon
|
||||
account-name emoji
|
||||
on-button-press
|
||||
on-button-long-press
|
||||
button-disabled? account-avatar-emoji account-avatar-type customization-color icon-avatar
|
||||
@@ -196,14 +206,17 @@
|
||||
:theme theme
|
||||
:blur? blur?}]
|
||||
[subtitle
|
||||
{:type type
|
||||
:theme theme
|
||||
:blur? blur?
|
||||
:keycard? keycard?
|
||||
:networks networks
|
||||
:description description
|
||||
:community-name community-name
|
||||
:community-logo community-logo}]]
|
||||
{:type type
|
||||
:theme theme
|
||||
:blur? blur?
|
||||
:keycard? keycard?
|
||||
:networks networks
|
||||
:description description
|
||||
:community-name community-name
|
||||
:community-logo community-logo
|
||||
:customization-color customization-color
|
||||
:account-name account-name
|
||||
:emoji emoji}]]
|
||||
[right-icon
|
||||
{:theme theme
|
||||
:type type
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
(ns quo.components.gradient.gradient-cover.style)
|
||||
|
||||
(defn root-container
|
||||
[opacity]
|
||||
{:height 252
|
||||
[opacity height]
|
||||
{:height (or height 252)
|
||||
:opacity opacity})
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[react-native.linear-gradient :as linear-gradient]))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [customization-color opacity container-style] :or {customization-color :blue}}]
|
||||
[{:keys [customization-color opacity container-style height] :or {customization-color :blue}}]
|
||||
(let [color-top (colors/custom-color customization-color 50 20)
|
||||
color-bottom (colors/custom-color customization-color 50 0)]
|
||||
[linear-gradient/linear-gradient
|
||||
@@ -14,6 +14,6 @@
|
||||
:colors [color-top color-bottom]
|
||||
:start {:x 0 :y 0}
|
||||
:end {:x 0 :y 1}
|
||||
:style (merge (style/root-container opacity) container-style)}]))
|
||||
:style (merge (style/root-container opacity height) container-style)}]))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
(ns quo.components.list-items.network-list.component-spec
|
||||
(:require [quo.components.list-items.network-list.view :as network-list]
|
||||
[quo.foundations.colors :as colors]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(defn- render
|
||||
[component]
|
||||
(h/render-with-theme-provider component :light))
|
||||
|
||||
(def props
|
||||
{:theme :light
|
||||
:state :default
|
||||
:label "Mainnet"
|
||||
:network-image 873
|
||||
:customization-color :blue
|
||||
:token-value "100.00 ETH"
|
||||
:fiat-value "€100.00"})
|
||||
|
||||
|
||||
(h/describe "List items: Network List"
|
||||
(h/test "default state explicit"
|
||||
(render [network-list/view props])
|
||||
(h/is-truthy (h/get-by-text "Mainnet")))
|
||||
|
||||
(h/test "Pressed state"
|
||||
(render [network-list/view props])
|
||||
(h/fire-event :on-press-in (h/get-by-label-text ::network-list))
|
||||
(h/wait-for #(h/has-style (h/query-by-label-text ::network-list)
|
||||
{:backgroundColor (colors/resolve-color :blue :light 5)})))
|
||||
|
||||
(h/test "Active state"
|
||||
(render [network-list/view (assoc props :state :active)])
|
||||
(h/has-style (h/query-by-label-text ::network-list)
|
||||
{:backgroundColor (colors/resolve-color :blue :light 10)}))
|
||||
|
||||
(h/test "Call on-press"
|
||||
(let [on-press (h/mock-fn)]
|
||||
(render [network-list/view (assoc props :on-press on-press)])
|
||||
(h/fire-event :on-press (h/get-by-label-text ::network-list))
|
||||
(h/was-called on-press))))
|
||||
@@ -0,0 +1,41 @@
|
||||
(ns quo.components.list-items.network-list.style
|
||||
(:require [quo.foundations.colors :as colors]))
|
||||
|
||||
(defn- background-color
|
||||
[state customization-color theme]
|
||||
(case state
|
||||
:pressed (colors/resolve-color customization-color theme 5)
|
||||
:active (colors/resolve-color customization-color theme 10)
|
||||
:transparent))
|
||||
|
||||
(defn container
|
||||
[state customization-color theme]
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center
|
||||
:padding-horizontal 12
|
||||
:padding-vertical 8
|
||||
:border-radius 12
|
||||
:height 56
|
||||
:background-color (background-color state customization-color theme)})
|
||||
|
||||
(def info
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:gap 2})
|
||||
|
||||
(def network-image
|
||||
{:border-width 1
|
||||
:border-radius 16
|
||||
:border-color colors/neutral-80-opa-5
|
||||
:margin-right 8
|
||||
:background-color colors/neutral-80-opa-5
|
||||
:height 32
|
||||
:width 32})
|
||||
|
||||
(def values-container
|
||||
{:align-items :flex-end})
|
||||
|
||||
(defn fiat-value
|
||||
[theme]
|
||||
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
|
||||
@@ -0,0 +1,76 @@
|
||||
(ns quo.components.list-items.network-list.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[quo.components.list-items.network-list.style :as style]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[schema.core :as schema]))
|
||||
|
||||
(defn- info
|
||||
[{:keys [network-image label]}]
|
||||
[rn/view {:style style/info}
|
||||
[rn/image
|
||||
{:source network-image
|
||||
:style style/network-image}]
|
||||
[rn/view
|
||||
[text/text
|
||||
{:weight :semi-bold
|
||||
:style {:text-transform :capitalize}
|
||||
:number-of-lines 1}
|
||||
(if (string/blank? label) "-" label)]]])
|
||||
|
||||
(defn- values
|
||||
[{:keys [token-value fiat-value theme]}]
|
||||
[rn/view {:style style/values-container}
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:size :paragraph-2
|
||||
:number-of-lines 1}
|
||||
token-value]
|
||||
[text/text
|
||||
{:style (style/fiat-value theme)
|
||||
:size :paragraph-2
|
||||
:number-of-lines 1}
|
||||
fiat-value]])
|
||||
|
||||
(def ?schema
|
||||
[:=>
|
||||
[:catn
|
||||
[:props
|
||||
[:map {:closed true}
|
||||
[:network-image :int]
|
||||
[:label :string]
|
||||
[:fiat-value :string]
|
||||
[:token-value :string]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||
[:state [:enum :pressed :active :default]]
|
||||
[:on-press {:optional true} [:maybe fn?]]
|
||||
[:theme :schema.common/theme]]]]
|
||||
:any])
|
||||
|
||||
(defn- view-internal
|
||||
[]
|
||||
(let [pressed? (reagent/atom false)
|
||||
on-press-in #(reset! pressed? true)
|
||||
on-press-out #(reset! pressed? false)]
|
||||
(fn [{:keys [on-press state customization-color theme]
|
||||
:as props
|
||||
:or {customization-color :blue}}]
|
||||
(let [internal-state (if @pressed?
|
||||
:pressed
|
||||
state)]
|
||||
|
||||
[rn/pressable
|
||||
{:style (style/container internal-state customization-color theme)
|
||||
:on-press-in on-press-in
|
||||
:on-press-out on-press-out
|
||||
:on-press on-press
|
||||
:accessibility-label :network-list}
|
||||
[info props]
|
||||
[values props]]))))
|
||||
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal ?schema)))
|
||||
@@ -34,10 +34,9 @@
|
||||
(= :pinned use-case)
|
||||
theme)
|
||||
container-style)}
|
||||
[rn/image
|
||||
{:style {:width 15 :height 15}
|
||||
:accessibility-label :emoji
|
||||
:source (reaction.resource/get-reaction emoji)}]
|
||||
[rn/text
|
||||
{:accessibility-label :emoji}
|
||||
(reaction.resource/system-emojis emoji)]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :semi-bold
|
||||
|
||||
@@ -4,6 +4,14 @@
|
||||
(def ^:private reactions
|
||||
(resolve-all-reactions))
|
||||
|
||||
(def system-emojis
|
||||
{:reaction/thumbs-up "👍"
|
||||
:reaction/thumbs-down "👎"
|
||||
:reaction/love "❤"
|
||||
:reaction/laugh "😂"
|
||||
:reaction/sad "😢"
|
||||
:reaction/angry "😡"})
|
||||
|
||||
(defn get-reaction
|
||||
[reaction]
|
||||
(assert (keyword? reaction) "Reaction should be a keyword")
|
||||
|
||||
@@ -19,6 +19,5 @@
|
||||
(swap! pressed? not)
|
||||
(when on-press
|
||||
(on-press e)))}
|
||||
[rn/image
|
||||
{:source (reactions.resource/get-reaction emoji)
|
||||
:style {:width 20 :height 20}}]])))
|
||||
[rn/text
|
||||
(reactions.resource/system-emojis emoji)]])))
|
||||
|
||||
@@ -8,19 +8,20 @@
|
||||
|
||||
(defn- category-internal
|
||||
[{:keys [label data container-style] :as props}]
|
||||
[rn/view {:style (merge (style/container label) container-style)}
|
||||
(when label
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:size :paragraph-2
|
||||
:style (style/label props)}
|
||||
label])
|
||||
[rn/view {:style (style/settings-items props)}
|
||||
(for [item data]
|
||||
^{:key item}
|
||||
[:<>
|
||||
[settings-item/view item]
|
||||
(when-not (= item (last data))
|
||||
[rn/view {:style (style/settings-separator props)}])])]])
|
||||
(let [settings-item (filter identity data)]
|
||||
[rn/view {:style (merge (style/container label) container-style)}
|
||||
(when label
|
||||
[text/text
|
||||
{:weight :medium
|
||||
:size :paragraph-2
|
||||
:style (style/label props)}
|
||||
label])
|
||||
[rn/view {:style (style/settings-items props)}
|
||||
(for [item settings-item]
|
||||
^{:key item}
|
||||
[:<>
|
||||
[settings-item/view item]
|
||||
(when-not (= item (last settings-item))
|
||||
[rn/view {:style (style/settings-separator props)}])])]]))
|
||||
|
||||
(def settings-category (quo.theme/with-theme category-internal))
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
network-image]
|
||||
:or {subtitle-type :default}}]
|
||||
[rn/view {:style style/subtitle-container}
|
||||
(when (not= :small size)
|
||||
(when (and subtitle-type (not= :small size))
|
||||
[rn/view {:style (style/subtitle-icon-container subtitle-type)}
|
||||
(case subtitle-type
|
||||
:icon [icons/icon icon
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
:padding-top 12
|
||||
:padding-bottom 8})
|
||||
|
||||
(def gradient-bg
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:left 0
|
||||
:right 0})
|
||||
|
||||
;;; Header
|
||||
(def header-container
|
||||
{:flex-direction :row
|
||||
|
||||
@@ -4,14 +4,13 @@
|
||||
[oops.core :as oops]
|
||||
[quo.components.avatars.account-avatar.view :as account-avatar]
|
||||
[quo.components.buttons.button.view :as button]
|
||||
[quo.components.gradient.gradient-cover.view :as gradient-cover]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.share.qr-code.view :as qr-code]
|
||||
[quo.components.share.share-qr-code.style :as style]
|
||||
[quo.components.tabs.tab.view :as tab]
|
||||
[quo.theme]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[reagent.core :as reagent]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
@@ -126,41 +125,44 @@
|
||||
[{:keys [share-qr-type qr-image-uri component-width customization-color full-name
|
||||
profile-picture emoji on-share-press]
|
||||
:as props}]
|
||||
[rn/view {:style style/content-container}
|
||||
[rn/view
|
||||
{:style style/share-qr-container}
|
||||
[:<>
|
||||
[rn/view {:style style/gradient-bg}
|
||||
[gradient-cover/view {:customization-color customization-color :height 463}]]
|
||||
[rn/view {:style style/content-container}
|
||||
[rn/view
|
||||
{:style style/share-qr-inner-container}
|
||||
[account-avatar/view
|
||||
{:customization-color customization-color
|
||||
:emoji emoji
|
||||
:size 32}]
|
||||
[text/text
|
||||
{:size :heading-2
|
||||
:weight :semi-bold
|
||||
:style {:margin-left 8}} full-name]]
|
||||
[share-button {:on-press on-share-press}]]
|
||||
(when (#{:wallet-legacy :wallet-multichain} share-qr-type)
|
||||
[header props])
|
||||
[quo.theme/provider {:theme :light}
|
||||
[qr-code/view
|
||||
{:qr-image-uri qr-image-uri
|
||||
:size (style/qr-code-size component-width)
|
||||
:avatar (if (= share-qr-type :profile)
|
||||
:profile
|
||||
:wallet-account)
|
||||
:customization-color customization-color
|
||||
:full-name full-name
|
||||
:profile-picture profile-picture
|
||||
:emoji emoji}]]
|
||||
[rn/view {:style style/bottom-container}
|
||||
(case share-qr-type
|
||||
:profile [profile-bottom props]
|
||||
:wallet-legacy [wallet-legacy-bottom props]
|
||||
:wallet-multichain [wallet-multichain-bottom props]
|
||||
nil)]])
|
||||
{:style style/share-qr-container}
|
||||
[rn/view
|
||||
{:style style/share-qr-inner-container}
|
||||
[account-avatar/view
|
||||
{:customization-color customization-color
|
||||
:emoji emoji
|
||||
:size 32}]
|
||||
[text/text
|
||||
{:size :heading-2
|
||||
:weight :semi-bold
|
||||
:style {:margin-left 8}} full-name]]
|
||||
[share-button {:on-press on-share-press}]]
|
||||
(when (#{:wallet-legacy :wallet-multichain} share-qr-type)
|
||||
[header props])
|
||||
[quo.theme/provider {:theme :light}
|
||||
[qr-code/view
|
||||
{:qr-image-uri qr-image-uri
|
||||
:size (style/qr-code-size component-width)
|
||||
:avatar (if (= share-qr-type :profile)
|
||||
:profile
|
||||
:wallet-account)
|
||||
:customization-color customization-color
|
||||
:full-name full-name
|
||||
:profile-picture profile-picture
|
||||
:emoji emoji}]]
|
||||
[rn/view {:style style/bottom-container}
|
||||
(case share-qr-type
|
||||
:profile [profile-bottom props]
|
||||
:wallet-legacy [wallet-legacy-bottom props]
|
||||
:wallet-multichain [wallet-multichain-bottom props]
|
||||
nil)]]])
|
||||
|
||||
(defn view
|
||||
(defn- view-internal
|
||||
"Receives the following properties:
|
||||
- type: :profile | :wallet-legacy | :wallet-multichain
|
||||
- qr-image-uri: Image source value.
|
||||
@@ -190,16 +192,9 @@
|
||||
Sometimes while using a blur layer on top of another on Android, this component looks
|
||||
bad because of the `blur/view`, so we can set `unblur-on-android? true` to fix it.
|
||||
"
|
||||
[{:keys [unblur-on-android?] :as props}]
|
||||
[props]
|
||||
(reagent/with-let [component-width (reagent/atom nil)
|
||||
container-component (if (and platform/android? unblur-on-android?)
|
||||
[rn/view {:background-color style/overlay-color}]
|
||||
[blur/view
|
||||
{:blur-radius 20
|
||||
:blur-amount 20
|
||||
:blur-type :transparent
|
||||
:overlay-color style/overlay-color
|
||||
:background-color style/overlay-color}])]
|
||||
container-component [rn/view {:background-color style/overlay-color}]]
|
||||
[quo.theme/provider {:theme :dark}
|
||||
[rn/view
|
||||
{:accessibility-label :share-qr-code
|
||||
@@ -211,3 +206,6 @@
|
||||
(-> props
|
||||
(assoc :component-width @component-width)
|
||||
(clojure.set/rename-keys {:type :share-qr-type}))]))]]))
|
||||
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
(ns quo.components.wallet.token-input.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.foundations.typography :as typography]
|
||||
[react-native.platform :as platform]))
|
||||
[quo.foundations.typography :as typography]))
|
||||
|
||||
(defn main-container
|
||||
[width]
|
||||
@@ -16,23 +15,55 @@
|
||||
:flex-direction :row
|
||||
:justify-content :space-between})
|
||||
|
||||
(defn text-input
|
||||
(defn token-name
|
||||
[theme]
|
||||
(merge typography/heading-1
|
||||
{:font-weight "600"
|
||||
:margin-left 8
|
||||
:margin-right (if platform/ios? 6 4)
|
||||
:color (colors/theme-colors colors/neutral-100 colors/white theme)
|
||||
:padding 0
|
||||
:text-align :center
|
||||
:height "100%"}))
|
||||
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
|
||||
:margin-right 8
|
||||
:padding-bottom 2})
|
||||
|
||||
(def token-label-container
|
||||
{:position :absolute
|
||||
:left 40 ; token image size + margin
|
||||
:right 0
|
||||
:bottom 0
|
||||
:top 0
|
||||
:flex-direction :row
|
||||
:align-items :flex-end})
|
||||
|
||||
(def text-input-container
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
:left 40 ; token image size + margin
|
||||
:right 0})
|
||||
|
||||
(def text-input-dimensions
|
||||
(-> typography/heading-1
|
||||
(dissoc :letter-spacing)
|
||||
(assoc :font-weight "600"
|
||||
:margin-right 5
|
||||
:padding-left 0
|
||||
:padding-right 0
|
||||
:padding-top 0
|
||||
:padding-bottom 0
|
||||
:height "100%")))
|
||||
|
||||
(defn text-input
|
||||
[theme error?]
|
||||
(assoc text-input-dimensions
|
||||
:color
|
||||
(if error?
|
||||
(colors/resolve-color :danger theme)
|
||||
(colors/theme-colors colors/neutral-100 colors/white theme))))
|
||||
|
||||
(defn placeholder-text
|
||||
[theme]
|
||||
(colors/theme-colors colors/neutral-40 colors/neutral-50 theme))
|
||||
|
||||
(defn divider
|
||||
[width theme]
|
||||
{:height 1
|
||||
:width width
|
||||
:background-color (colors/theme-colors colors/neutral-10 colors/neutral-90 theme)
|
||||
:margin-vertical 8})
|
||||
[theme]
|
||||
{:margin-vertical 8
|
||||
:background-color (colors/theme-colors colors/neutral-10 colors/neutral-90 theme)})
|
||||
|
||||
(def data-container
|
||||
{:padding-top 4
|
||||
@@ -40,3 +71,7 @@
|
||||
:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center})
|
||||
|
||||
(defn fiat-amount
|
||||
[theme]
|
||||
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
[quo.components.tags.network-tags.view :as network-tag]
|
||||
[quo.components.utilities.token.view :as token]
|
||||
[quo.components.wallet.token-input.style :as style]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.foundations.common :as common]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
@@ -25,83 +24,120 @@
|
||||
|
||||
(defn calc-value
|
||||
[{:keys [crypto? currency token value conversion crypto-decimals]}]
|
||||
(let [num-value (if (string? value) (parse-double (or value "0")) value)]
|
||||
(let [num-value (if (string? value)
|
||||
(or (parse-double value) 0)
|
||||
value)]
|
||||
(if crypto?
|
||||
(fiat-format currency num-value conversion)
|
||||
(crypto-format num-value conversion crypto-decimals token))))
|
||||
|
||||
(defn- data-info
|
||||
[{:keys [theme token crypto-decimals conversion networks title crypto? currency amount error?]}]
|
||||
[rn/view {:style style/data-container}
|
||||
[network-tag/view
|
||||
{:networks networks
|
||||
:title title
|
||||
:status (when error? :error)}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (style/fiat-amount theme)}
|
||||
(calc-value {:crypto? crypto?
|
||||
:currency currency
|
||||
:token token
|
||||
:value amount
|
||||
:conversion conversion
|
||||
:crypto-decimals crypto-decimals})]])
|
||||
|
||||
(defn- token-name-text
|
||||
[theme text]
|
||||
[text/text
|
||||
{:style (style/token-name theme)
|
||||
:size :paragraph-2
|
||||
:weight :semi-bold}
|
||||
(string/upper-case (or (clj->js text) ""))])
|
||||
|
||||
(defn- token-label
|
||||
[{:keys [theme value text]}]
|
||||
[rn/view
|
||||
{:style style/token-label-container
|
||||
:pointer-events :none}
|
||||
[rn/text-input
|
||||
{:max-length 12
|
||||
:style style/text-input-dimensions
|
||||
:editable false
|
||||
:placeholder "0"
|
||||
:opacity 0
|
||||
:value value}]
|
||||
[token-name-text theme text]])
|
||||
|
||||
(defn input-section
|
||||
[{: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
|
||||
:style {:flex 1}}
|
||||
[token/view
|
||||
{:token token
|
||||
:size :size-32}]
|
||||
[rn/view {:style style/text-input-container}
|
||||
[rn/text-input
|
||||
(cond-> {:style (style/text-input theme error?)
|
||||
:placeholder-text-color (style/placeholder-text theme)
|
||||
:auto-focus true
|
||||
:ref set-ref
|
||||
:placeholder "0"
|
||||
:keyboard-type :numeric
|
||||
:max-length 12
|
||||
:on-change-text handle-on-change-text
|
||||
:selection-color customization-color
|
||||
:show-soft-input-on-focus show-keyboard?}
|
||||
controlled-input? (assoc :value value)
|
||||
(not controlled-input?) (assoc :default-value @value-atom))]]
|
||||
[token-label
|
||||
{:theme theme
|
||||
:text (if crypto? token currency)
|
||||
:value (if controlled-input? value @value-atom)}]])))
|
||||
|
||||
(defn- view-internal
|
||||
[{external-value :value}]
|
||||
(let [width (:width (rn/get-window))
|
||||
value (reagent/atom nil)
|
||||
crypto? (reagent/atom true)
|
||||
input-ref (atom nil)
|
||||
controlled-input? (some? external-value)]
|
||||
(fn [{:keys [theme token currency crypto-decimals conversion networks title
|
||||
customization-color
|
||||
on-change-text on-swap container-style show-keyboard?]
|
||||
:or {show-keyboard? true}
|
||||
external-value :value}]
|
||||
[rn/view
|
||||
{:style (merge
|
||||
(style/main-container width)
|
||||
container-style)}
|
||||
[{: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}
|
||||
[rn/pressable
|
||||
{:on-press #(when @input-ref (.focus ^js @input-ref))
|
||||
:style {:flex-direction :row
|
||||
:flex-grow 1
|
||||
:align-items :flex-end}}
|
||||
[token/view {:token token :size :size-32}]
|
||||
[rn/text-input
|
||||
(cond-> {:auto-focus true
|
||||
:ref #(reset! input-ref %)
|
||||
:placeholder "0"
|
||||
:placeholder-text-color (colors/theme-colors colors/neutral-40
|
||||
colors/neutral-50
|
||||
theme)
|
||||
:keyboard-type :numeric
|
||||
:max-length 12
|
||||
:on-change-text (fn [v]
|
||||
(when-not controlled-input?
|
||||
(reset! value v))
|
||||
(when on-change-text
|
||||
(on-change-text v)))
|
||||
:style (style/text-input theme)
|
||||
:selection-color customization-color
|
||||
:show-soft-input-on-focus show-keyboard?}
|
||||
controlled-input? (assoc :value external-value)
|
||||
(not controlled-input?) (assoc :default-value @value))]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :semi-bold
|
||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
|
||||
:margin-right 8
|
||||
:padding-bottom 2}}
|
||||
(string/upper-case (or (clj->js (if @crypto? token currency)) ""))]]
|
||||
[input-section
|
||||
(assoc props
|
||||
:value-atom value-atom
|
||||
:crypto? @crypto?)]
|
||||
[button/button
|
||||
{:icon true
|
||||
:icon-only? true
|
||||
:size 32
|
||||
:on-press (fn []
|
||||
(swap! crypto? not)
|
||||
(when on-swap
|
||||
(on-swap @crypto?)))
|
||||
:on-press handle-on-swap
|
||||
:type :outline
|
||||
:accessibility-label :reorder}
|
||||
:i/reorder]]
|
||||
[divider-line/view {:container-style {:margin-vertical 8}}]
|
||||
[rn/view {:style style/data-container}
|
||||
[network-tag/view {:networks networks :title title}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
|
||||
(calc-value {:crypto? @crypto?
|
||||
:currency currency
|
||||
:token token
|
||||
:value (or external-value @value)
|
||||
:conversion conversion
|
||||
:crypto-decimals crypto-decimals})]]])))
|
||||
[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))
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
quo.components.list-items.community.view
|
||||
quo.components.list-items.dapp.view
|
||||
quo.components.list-items.menu-item
|
||||
quo.components.list-items.network-list.view
|
||||
quo.components.list-items.preview-list.view
|
||||
quo.components.list-items.quiz-item.view
|
||||
quo.components.list-items.saved-address.view
|
||||
@@ -302,6 +303,7 @@
|
||||
(def community-list quo.components.list-items.community.view/view)
|
||||
(def dapp quo.components.list-items.dapp.view/view)
|
||||
(def menu-item quo.components.list-items.menu-item/menu-item)
|
||||
(def network-list quo.components.list-items.network-list.view/view)
|
||||
(def preview-list quo.components.list-items.preview-list.view/view)
|
||||
(def quiz-item quo.components.list-items.quiz-item.view/view)
|
||||
(def saved-address quo.components.list-items.saved-address.view/view)
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
quo.components.list-items.channel.component-spec
|
||||
quo.components.list-items.community.component-spec
|
||||
quo.components.list-items.dapp.component-spec
|
||||
quo.components.list-items.network-list.component-spec
|
||||
quo.components.list-items.quiz-item.component-spec
|
||||
quo.components.list-items.saved-address.component-spec
|
||||
quo.components.list-items.saved-contact-address.component-spec
|
||||
|
||||
@@ -52,7 +52,8 @@
|
||||
:remove-listeners remove-listeners}))
|
||||
|
||||
(defn view
|
||||
[{:keys [header footer customization-color gradient-cover?]} &
|
||||
[{:keys [header footer customization-color footer-container-padding gradient-cover?]
|
||||
:or {footer-container-padding (safe-area/get-top)}} &
|
||||
children]
|
||||
(reagent/with-let [window-height (:height (rn/get-window))
|
||||
footer-container-height (reagent/atom 0)
|
||||
@@ -94,7 +95,7 @@
|
||||
children)]
|
||||
[rn/keyboard-avoiding-view
|
||||
{:style style/keyboard-avoiding-view
|
||||
:keyboard-vertical-offset (if platform/ios? (safe-area/get-top) 0)
|
||||
:keyboard-vertical-offset (if platform/ios? footer-container-padding 0)
|
||||
:pointer-events :box-none}
|
||||
[floating-container/view
|
||||
{:on-layout set-footer-container-height
|
||||
|
||||
@@ -127,8 +127,9 @@
|
||||
(defn change-text
|
||||
"Update `text-value`, update cursor selection, find links, find mentions"
|
||||
[text
|
||||
{:keys [input-ref record-reset-fn]}
|
||||
{:keys [text-value cursor-position recording?]}]
|
||||
{:keys [input-ref record-reset-fn] :as props}
|
||||
{:keys [text-value cursor-position recording?]}
|
||||
scroll-to-end]
|
||||
(reset! text-value text)
|
||||
(reagent/next-tick #(when @input-ref
|
||||
(.setNativeProps ^js @input-ref
|
||||
@@ -140,6 +141,8 @@
|
||||
(rf/dispatch [:chat.ui/set-chat-input-text text])
|
||||
(debounce/debounce-and-dispatch [:link-preview/unfurl-urls text]
|
||||
constants/unfurl-debounce-ms)
|
||||
(when (string/ends-with? text (with-out-str (newline)))
|
||||
(scroll-to-end props))
|
||||
(if (string/ends-with? text "@")
|
||||
(rf/dispatch [:mention/on-change-text text])
|
||||
(debounce/debounce-and-dispatch [:mention/on-change-text text] 300)))
|
||||
|
||||
@@ -69,17 +69,11 @@
|
||||
:min-height constants/input-height})
|
||||
|
||||
(defn input-text
|
||||
[{:keys [saved-emoji-kb-extra-height]}
|
||||
{:keys [focused? maximized?]}
|
||||
{:keys [max-height theme]}]
|
||||
[{:keys [maximized?]}
|
||||
{:keys [theme]}]
|
||||
(assoc typography/paragraph-1
|
||||
:color (colors/theme-colors :black :white theme)
|
||||
:text-align-vertical :top
|
||||
:position (if @saved-emoji-kb-extra-height :relative :absolute)
|
||||
:top 0
|
||||
:left 0
|
||||
:right (when (or focused? platform/ios?) 0)
|
||||
:max-height max-height
|
||||
:padding-bottom (when @maximized? 0)))
|
||||
|
||||
(defn background
|
||||
|
||||
@@ -175,7 +175,8 @@
|
||||
:record-reset-fn (atom nil)
|
||||
:scroll-y (atom 0)
|
||||
:selection-event (atom nil)
|
||||
:selection-manager (rn/selectable-text-input-manager)})
|
||||
:selection-manager (rn/selectable-text-input-manager)
|
||||
:composer-scrollview-ref (atom nil)})
|
||||
|
||||
(defn init-reactive-state
|
||||
[]
|
||||
|
||||
@@ -68,7 +68,14 @@
|
||||
;; Cursor position, needed to determine where to display the mentions view
|
||||
cursor-pos (utils/cursor-y-position-relative-to-container
|
||||
props
|
||||
state)]
|
||||
state)
|
||||
scroll-to-end (fn []
|
||||
;; Needs to be queued, Otherwise might not be called on the right
|
||||
;; time.
|
||||
(js/setTimeout #(when @(:composer-scrollview-ref props)
|
||||
(.scrollToEnd @(:composer-scrollview-ref props)))
|
||||
50))
|
||||
chat-screen-loaded? (rf/sub [:shell/chat-screen-loaded?])]
|
||||
(effects/did-mount props)
|
||||
(effects/initialize props
|
||||
state
|
||||
@@ -90,8 +97,7 @@
|
||||
{:style style/composer-sheet-and-jump-to-container}
|
||||
[sub-view/shell-button state chat-list-scroll-y window-height]
|
||||
[gesture/gesture-detector
|
||||
{:gesture
|
||||
(drag-gesture/drag-gesture props state animations dimensions keyboard-shown)}
|
||||
{:gesture (drag-gesture/drag-gesture props state animations dimensions keyboard-shown)}
|
||||
[reanimated/view
|
||||
{:style (style/sheet-container insets state animations theme)
|
||||
:on-layout #(handler/layout % state blur-height)}
|
||||
@@ -112,36 +118,43 @@
|
||||
{:ref #(reset! (:selectable-input-ref props) %)
|
||||
:menu-items @(:menu-items state)
|
||||
:style (style/input-view state)}
|
||||
[rn/text-input
|
||||
{:ref #(reset! (:input-ref props) %)
|
||||
:default-value @(:text-value state)
|
||||
:on-focus #(handler/focus props state animations dimensions)
|
||||
:on-blur #(handler/blur state animations dimensions subscriptions)
|
||||
:on-content-size-change #(handler/content-size-change %
|
||||
state
|
||||
animations
|
||||
dimensions
|
||||
(or keyboard-shown
|
||||
(:edit subscriptions)))
|
||||
:on-scroll #(handler/scroll % props state animations dimensions)
|
||||
:on-change-text #(handler/change-text % props state)
|
||||
:on-selection-change #(handler/selection-change % props state)
|
||||
:on-selection #(selection/on-selection % props state)
|
||||
:keyboard-appearance (quo.theme/theme-value :light :dark)
|
||||
:max-font-size-multiplier 1
|
||||
:multiline true
|
||||
:placeholder (i18n/label :t/type-something)
|
||||
:placeholder-text-color (colors/theme-colors colors/neutral-40 colors/neutral-50)
|
||||
:style (style/input-text props
|
||||
state
|
||||
{:max-height max-height
|
||||
:theme theme})
|
||||
:max-length constants/max-text-size
|
||||
:accessibility-label :chat-message-input}]]]
|
||||
[:<>
|
||||
[gradients/view props state animations show-bottom-gradient?]
|
||||
[link-preview/view]
|
||||
[images/images-list]]
|
||||
;; https://github.com/facebook/react-native/issues/39660
|
||||
[rn/scroll-view
|
||||
{:on-scroll #(handler/scroll % props state animations dimensions)
|
||||
:keyboard-should-persist-taps :handled
|
||||
:scroll-event-throttle 64
|
||||
:ref #(reset! (:composer-scrollview-ref props) %)
|
||||
:shows-vertical-scroll-indicator false}
|
||||
[rn/text-input
|
||||
{:ref #(reset! (:input-ref props) %)
|
||||
:default-value @(:text-value state)
|
||||
:on-focus #(handler/focus props state animations dimensions)
|
||||
:on-blur #(handler/blur state animations dimensions subscriptions)
|
||||
:on-change-text #(handler/change-text % props state scroll-to-end)
|
||||
:on-selection-change #(handler/selection-change % props state)
|
||||
:on-content-size-change #(handler/content-size-change %1
|
||||
state
|
||||
animations
|
||||
dimensions
|
||||
(or keyboard-shown
|
||||
(:edit subscriptions)))
|
||||
:on-selection #(selection/on-selection % props state)
|
||||
:keyboard-appearance (quo.theme/theme-value :light :dark)
|
||||
:max-font-size-multiplier 1
|
||||
:multiline true
|
||||
:scroll-enabled false
|
||||
:placeholder (i18n/label :t/type-something)
|
||||
:placeholder-text-color (colors/theme-colors colors/neutral-40 colors/neutral-50)
|
||||
:style (style/input-text state
|
||||
{:max-height max-height
|
||||
:theme theme})
|
||||
:max-length constants/max-text-size
|
||||
:accessibility-label :chat-message-input}]]]]
|
||||
(when chat-screen-loaded?
|
||||
[:<>
|
||||
[gradients/view props state animations show-bottom-gradient?]
|
||||
[link-preview/view]
|
||||
[images/images-list]])
|
||||
[:f> actions/view props state animations window-height insets subscriptions]]]]]))
|
||||
|
||||
(defn f-composer
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
(get constants/reactions (:emoji-id reaction))))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [message-id chat-id pinned-by theme]} user-message-content]
|
||||
[{:keys [message-id chat-id pinned-by preview? theme]} user-message-content]
|
||||
(let [reactions (rf/sub [:chats/message-reactions message-id chat-id])]
|
||||
[:<>
|
||||
(when (seq reactions)
|
||||
@@ -60,7 +60,7 @@
|
||||
{:container-style {:margin-left 44
|
||||
:margin-top 8}
|
||||
:reactions (map add-emoji-key reactions)
|
||||
:add-reaction? true
|
||||
:add-reaction? (not preview?)
|
||||
:use-case (when pinned-by :pinned)
|
||||
:on-press #(on-press (assoc % :message-id message-id))
|
||||
:on-long-press #(on-long-press (assoc %
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]))
|
||||
|
||||
(def ^:private message-padding-scaling-ratio 4.5)
|
||||
|
||||
(defn message-container
|
||||
([]
|
||||
(message-container false nil nil false))
|
||||
@@ -16,10 +18,16 @@
|
||||
(assoc :margin-top 4))))
|
||||
|
||||
(defn user-message-content
|
||||
[{:keys [outgoing outgoing-status]}]
|
||||
[{:keys [outgoing outgoing-status six-reactions? window-scale small-screen?]}]
|
||||
{:border-radius 16
|
||||
:padding-horizontal 8
|
||||
:padding-vertical 4
|
||||
:padding-top 4
|
||||
:padding-bottom (if (or small-screen?
|
||||
(and
|
||||
(> 3 window-scale)
|
||||
six-reactions?))
|
||||
(* message-padding-scaling-ratio window-scale)
|
||||
4)
|
||||
:opacity (if (and outgoing (= outgoing-status :sending))
|
||||
0.5
|
||||
1)})
|
||||
|
||||
@@ -119,31 +119,38 @@
|
||||
[]
|
||||
(let [show-delivery-state? (reagent/atom false)]
|
||||
(fn [{:keys [message-data context keyboard-shown? show-reactions? in-reaction-and-action-menu?
|
||||
show-user-info? theme]}]
|
||||
show-user-info? preview? theme]}]
|
||||
(let [{:keys [content-type quoted-message content
|
||||
outgoing outgoing-status pinned-by]} message-data
|
||||
first-image (first (:album message-data))
|
||||
outgoing-status (if (= content-type
|
||||
constants/content-type-album)
|
||||
(:outgoing-status first-image)
|
||||
outgoing-status)
|
||||
outgoing (if (= content-type
|
||||
constants/content-type-album)
|
||||
(:outgoing first-image)
|
||||
outgoing)
|
||||
context (assoc context
|
||||
:on-long-press
|
||||
#(on-long-press message-data
|
||||
context
|
||||
keyboard-shown?))
|
||||
response-to (:response-to content)
|
||||
height (rf/sub [:dimensions/window-height])
|
||||
{window-width :width} (rn/get-window)
|
||||
message-container-data {:window-width window-width
|
||||
:padding-right 20
|
||||
:padding-left 20
|
||||
:avatar-container-width 32
|
||||
:message-margin-left 8}]
|
||||
outgoing outgoing-status pinned-by
|
||||
message-id chat-id]} message-data
|
||||
first-image (first (:album message-data))
|
||||
outgoing-status (if (= content-type
|
||||
constants/content-type-album)
|
||||
(:outgoing-status first-image)
|
||||
outgoing-status)
|
||||
outgoing (if (= content-type
|
||||
constants/content-type-album)
|
||||
(:outgoing first-image)
|
||||
outgoing)
|
||||
context (assoc context
|
||||
:on-long-press
|
||||
#(on-long-press message-data
|
||||
context
|
||||
keyboard-shown?))
|
||||
response-to (:response-to content)
|
||||
height (rf/sub [:dimensions/window-height])
|
||||
{window-width :width
|
||||
window-scale :scale} (rn/get-window)
|
||||
message-container-data {:window-width window-width
|
||||
:padding-right 20
|
||||
:padding-left 20
|
||||
:avatar-container-width 32
|
||||
:message-margin-left 8}
|
||||
reactions (rf/sub [:chats/message-reactions message-id
|
||||
chat-id])
|
||||
six-reactions? (-> reactions
|
||||
count
|
||||
(= 6))]
|
||||
[rn/touchable-highlight
|
||||
{:accessibility-label (if (and outgoing (= outgoing-status :sending))
|
||||
:message-sending
|
||||
@@ -152,7 +159,10 @@
|
||||
:style (style/user-message-content
|
||||
{:first-in-group? (:first-in-group? message-data)
|
||||
:outgoing outgoing
|
||||
:outgoing-status outgoing-status})
|
||||
:outgoing-status outgoing-status
|
||||
:small-screen? rn/small-screen?
|
||||
:window-scale window-scale
|
||||
:six-reactions? six-reactions?})
|
||||
:on-press (fn []
|
||||
(if (and platform/ios? keyboard-shown?)
|
||||
(do
|
||||
@@ -212,7 +222,7 @@
|
||||
(when @show-delivery-state?
|
||||
[status/status outgoing-status])])]
|
||||
(when show-reactions?
|
||||
[reactions/message-reactions-row message-data
|
||||
[reactions/message-reactions-row (assoc message-data :preview? preview?)
|
||||
[rn/view {:pointer-events :none}
|
||||
[user-message-content-internal
|
||||
{:theme theme
|
||||
@@ -226,22 +236,24 @@
|
||||
(defn on-long-press
|
||||
[{:keys [deleted? deleted-for-me?] :as message-data} context keyboard-shown?]
|
||||
(rf/dispatch [:dismiss-keyboard])
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:content (drawers/reactions-and-actions message-data context)
|
||||
:border-radius 16
|
||||
:selected-item
|
||||
(if (or deleted? deleted-for-me?)
|
||||
(fn [] [content.deleted/deleted-message message-data])
|
||||
(fn []
|
||||
[rn/view
|
||||
{:pointer-events :none
|
||||
:padding-top 4}
|
||||
[user-message-content
|
||||
{:message-data message-data
|
||||
:context context
|
||||
:keyboard-shown? keyboard-shown?
|
||||
:show-reactions? true
|
||||
:show-user-info? true}]]))}]))
|
||||
(rf/dispatch
|
||||
[:show-bottom-sheet
|
||||
{:content (drawers/reactions-and-actions message-data context)
|
||||
:border-radius 16
|
||||
:selected-item
|
||||
(if (or deleted? deleted-for-me?)
|
||||
(fn [] [content.deleted/deleted-message message-data])
|
||||
(fn []
|
||||
[rn/view
|
||||
{:pointer-events :none
|
||||
:padding-top 4}
|
||||
[user-message-content
|
||||
{:message-data message-data
|
||||
:context context
|
||||
:keyboard-shown? keyboard-shown?
|
||||
:show-reactions? true
|
||||
:show-user-info? true
|
||||
:preview? true}]]))}]))
|
||||
|
||||
(defn system-message?
|
||||
[content-type]
|
||||
|
||||
@@ -8,9 +8,7 @@
|
||||
:justify-content :center})
|
||||
|
||||
(def tab-icon
|
||||
{:margin-right 4
|
||||
:width 20
|
||||
:height 20})
|
||||
{:margin-right 4})
|
||||
|
||||
(defn tab-count
|
||||
[active? theme]
|
||||
|
||||
@@ -34,10 +34,10 @@
|
||||
{:id reaction-type-int
|
||||
:accessibility-label (keyword (str "authors-for-reaction-" reaction-type-int))
|
||||
:label [rn/view {:style style/tab}
|
||||
[rn/image
|
||||
{:source (reactions.resource/get-reaction
|
||||
(get constants/reactions reaction-type-int))
|
||||
:style style/tab-icon}]
|
||||
[rn/text
|
||||
{:style style/tab-icon}
|
||||
(reactions.resource/system-emojis
|
||||
(get constants/reactions reaction-type-int))]
|
||||
[quo/text
|
||||
{:weight :medium
|
||||
:size :paragraph-1
|
||||
|
||||
@@ -159,7 +159,7 @@
|
||||
unmute-chat-label
|
||||
mute-chat-label))
|
||||
:color cover-bg-color
|
||||
:icon (if muted? :i/muted :i/activity-center)
|
||||
:icon (if muted? :i/activity-center :i/muted)
|
||||
:on-press (fn []
|
||||
(if muted?
|
||||
(home.actions/unmute-chat-action chat-id)
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
:status-indicator? false
|
||||
:customization-color customization-color}]]
|
||||
[rn/view
|
||||
{:style style/card-view}
|
||||
{:pointer-events :none :style style/card-view}
|
||||
[reanimated/view
|
||||
{:style (style/card-container container-background)}
|
||||
[rn/view {:style style/card-header}
|
||||
|
||||
@@ -15,3 +15,8 @@
|
||||
{:justify-self :flex-end
|
||||
:margin-bottom 46
|
||||
:margin-horizontal 20})
|
||||
|
||||
(defn carousel-background
|
||||
[height width]
|
||||
{:height height
|
||||
:width width})
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
paused? (atom nil)
|
||||
is-dragging? (atom nil)
|
||||
drag-amount (atom nil)
|
||||
window-width (rf/sub [:dimensions/window-width])
|
||||
window-height (rf/sub [:dimensions/window-height])
|
||||
{:keys [emoji-hash display-name compressed-key
|
||||
public-key]} (rf/sub [:profile/profile])
|
||||
{:keys [color]} (rf/sub [:onboarding/profile])
|
||||
@@ -42,11 +44,16 @@
|
||||
{:animate? true
|
||||
:progress progress
|
||||
:paused? paused?
|
||||
:gesture :tappable
|
||||
:gesture :swipeable
|
||||
:is-dragging? is-dragging?
|
||||
:drag-amount drag-amount
|
||||
:header-text header-text}]
|
||||
[rn/view {:style style/content-container}
|
||||
:header-text header-text
|
||||
:background [rn/view
|
||||
{:style (style/carousel-background window-height
|
||||
(* (count header-text) window-width))}]}]
|
||||
[rn/view
|
||||
{:style style/content-container
|
||||
:pointer-events :box-none}
|
||||
[profile-card/profile-card
|
||||
{:profile-picture photo-path
|
||||
:name display-name
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
(ns status-im.contexts.preview.quo.list-items.network-list
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.resources :as quo.resources]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.contexts.preview.quo.preview :as preview]))
|
||||
|
||||
(def descriptor
|
||||
[{:key :state
|
||||
:type :select
|
||||
:options [{:key :default}
|
||||
{:key :active}
|
||||
{:key :pressed}]}
|
||||
{:key :network-image
|
||||
:type :select
|
||||
:options [{:key (quo.resources/get-network :ethereum)
|
||||
:value :ethereum}
|
||||
{:key (quo.resources/get-network :arbitrum)
|
||||
:value :arbitrum}
|
||||
{:key (quo.resources/get-network :optimism)
|
||||
:value :optimism}]}
|
||||
{:key :label
|
||||
:type :text}
|
||||
{:key :token-value
|
||||
:type :text}
|
||||
{:key :fiat-value
|
||||
:type :text}
|
||||
{:key :show-alert-on-press?
|
||||
:type :boolean}])
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [state (reagent/atom {:network-image (quo.resources/get-network :ethereum)
|
||||
:label "Mainnet"
|
||||
:token-value "0.00 ETH"
|
||||
:fiat-value "€0.00"
|
||||
:state :default
|
||||
:customization-color :blue})]
|
||||
(fn []
|
||||
[preview/preview-container
|
||||
{:state state
|
||||
:descriptor descriptor}
|
||||
[quo/network-list
|
||||
(merge @state
|
||||
(when (:show-alert-on-press? @state)
|
||||
{:on-press #(js/alert "Pressed!")}))]])))
|
||||
@@ -94,6 +94,7 @@
|
||||
[status-im.contexts.preview.quo.list-items.address :as address]
|
||||
[status-im.contexts.preview.quo.list-items.channel :as channel]
|
||||
[status-im.contexts.preview.quo.list-items.dapp :as dapp]
|
||||
[status-im.contexts.preview.quo.list-items.network-list :as network-list]
|
||||
[status-im.contexts.preview.quo.list-items.preview-lists :as preview-lists]
|
||||
[status-im.contexts.preview.quo.list-items.quiz-item :as quiz-item]
|
||||
[status-im.contexts.preview.quo.list-items.saved-address :as saved-address]
|
||||
@@ -351,6 +352,8 @@
|
||||
:component community-list-item/view}
|
||||
{:name :dapp
|
||||
:component dapp/preview}
|
||||
{:name :network-list
|
||||
:component network-list/view}
|
||||
{:name :preview-lists
|
||||
:component preview-lists/view}
|
||||
{:name :quiz-item
|
||||
|
||||
@@ -320,7 +320,7 @@
|
||||
(defn- f-preview-container
|
||||
[{:keys [title state descriptor blur? blur-dark-only?
|
||||
component-container-style
|
||||
blur-container-style blur-view-props blur-height show-blur-background?]
|
||||
blur-container-style blur-view-props blur-height show-blur-background? full-screen?]
|
||||
:or {blur-height 200}}
|
||||
& children]
|
||||
(let [theme (quo.theme/use-theme-value)
|
||||
@@ -337,8 +337,11 @@
|
||||
[common/navigation-bar {:title title}]
|
||||
[rn/scroll-view
|
||||
{:style (style/panel-basic)
|
||||
:shows-vertical-scroll-indicator false}
|
||||
[rn/pressable {:on-press rn/dismiss-keyboard!}
|
||||
:shows-vertical-scroll-indicator false
|
||||
:content-container-style (when full-screen? {:flex 1})}
|
||||
[rn/pressable
|
||||
{:style (when full-screen? {:flex 1})
|
||||
:on-press rn/dismiss-keyboard!}
|
||||
(when descriptor
|
||||
[rn/view {:style style/customizer-container}
|
||||
[customizer state descriptor]])
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.resources :as resources]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.contexts.preview.quo.preview :as preview]))
|
||||
|
||||
@@ -20,21 +21,35 @@
|
||||
{:key :currency
|
||||
:type :select
|
||||
:options [{:key :usd}
|
||||
{:key :eur}]}])
|
||||
{:key :eur}]}
|
||||
{:key :error?
|
||||
:type :boolean}])
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [state (reagent/atom {:token :eth
|
||||
:currency :usd
|
||||
:conversion 0.02
|
||||
:networks networks
|
||||
:title title
|
||||
:customization-color :blue})]
|
||||
(let [state (reagent/atom {:token :eth
|
||||
:currency :usd
|
||||
:conversion 0.02
|
||||
:networks networks
|
||||
:title title
|
||||
:customization-color :blue
|
||||
:show-keyboard? false})
|
||||
value (reagent/atom "")
|
||||
set-value (fn [v]
|
||||
(swap! value str v))
|
||||
delete (fn [_]
|
||||
(swap! value #(subs % 0 (dec (count %)))))]
|
||||
(fn []
|
||||
[preview/preview-container
|
||||
{:state state
|
||||
:descriptor descriptor
|
||||
:component-container-style {:padding-horizontal 20
|
||||
:margin-top 50
|
||||
:align-items :center}}
|
||||
[quo/token-input @state]])))
|
||||
:full-screen? true
|
||||
:component-container-style {:flex 1
|
||||
:justify-content :space-between}}
|
||||
[quo/token-input (assoc @state :value @value)]
|
||||
[quo/numbered-keyboard
|
||||
{:container-style {:padding-bottom (safe-area/get-top)}
|
||||
:left-action :dot
|
||||
:delete-key? true
|
||||
:on-press set-value
|
||||
:on-delete delete}]])))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns status-im.contexts.profile.settings.list-items
|
||||
(:require [status-im.common.not-implemented :as not-implemented]
|
||||
[status-im.config :as config]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
@@ -89,12 +90,13 @@
|
||||
:image :icon
|
||||
:blur? true
|
||||
:image-props :i/toggle}
|
||||
{:title "Quo preview"
|
||||
:on-press #(rf/dispatch [:navigate-to :quo-preview])
|
||||
:action :arrow
|
||||
:image :icon
|
||||
:blur? true
|
||||
:image-props :i/light}]
|
||||
(when config/quo-preview-enabled?
|
||||
{:title "Quo preview"
|
||||
:on-press #(rf/dispatch [:navigate-to :quo-preview])
|
||||
:action :arrow
|
||||
:image :icon
|
||||
:blur? true
|
||||
:image-props :i/light})]
|
||||
[{:title (i18n/label :t/about)
|
||||
:on-press not-implemented/alert
|
||||
:action :arrow}
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
abbreviated-url (address/get-abbreviated-profile-url
|
||||
universal-profile-url)
|
||||
emoji-hash-string (string/join emoji-hash)]
|
||||
[:<>
|
||||
[rn/scroll-view
|
||||
{:content-container-style {:padding-bottom 16}}
|
||||
[rn/view {:style style/qr-code-container}
|
||||
[qr-codes/share-qr-code
|
||||
{:type :profile
|
||||
:unblur-on-android? true
|
||||
:qr-data universal-profile-url
|
||||
:qr-data-label-shown abbreviated-url
|
||||
:on-share-press #(list-selection/open-share {:message universal-profile-url})
|
||||
|
||||
@@ -5,13 +5,6 @@
|
||||
|
||||
(def screen-padding 20)
|
||||
|
||||
(def blur
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 0
|
||||
:overlay-color colors/neutral-80-opa-80-blur})
|
||||
|
||||
(def header-row
|
||||
{:flex-direction :row
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
(ns status-im.contexts.shell.share.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.contexts.shell.share.profile.view :as profile-view]
|
||||
@@ -43,7 +41,7 @@
|
||||
[]
|
||||
(let [selected-tab (reagent/atom :profile)]
|
||||
(fn []
|
||||
[:<>
|
||||
[rn/view {:style {:padding-top (safe-area/get-top)}}
|
||||
[header]
|
||||
[rn/view {:style style/tabs-container}
|
||||
[quo/segmented-control
|
||||
@@ -61,9 +59,7 @@
|
||||
|
||||
(defn view
|
||||
[]
|
||||
[rn/view {:flex 1 :padding-top (safe-area/get-top)}
|
||||
[blur/view
|
||||
{:style style/blur
|
||||
:blur-amount 20
|
||||
:blur-radius (if platform/android? 25 10)}]
|
||||
[tab-content]])
|
||||
[quo/overlay {:type :shell}
|
||||
[rn/view
|
||||
{:key :share}
|
||||
[tab-content]]])
|
||||
|
||||
@@ -66,7 +66,6 @@
|
||||
:networks @selected-networks
|
||||
:on-share-press #(share-action qr-url share-title)
|
||||
:profile-picture nil
|
||||
:unblur-on-android? true
|
||||
:full-name (:name account)
|
||||
:customization-color (:color account)
|
||||
:emoji (:emoji account)
|
||||
|
||||
@@ -46,7 +46,9 @@
|
||||
[quo/wallet-graph {:time-frame :empty}]
|
||||
(when (not watch-only?)
|
||||
[quo/wallet-ctas
|
||||
{:send-action #(rf/dispatch [:open-modal :wallet-select-address])
|
||||
{:send-action (fn []
|
||||
(rf/dispatch [:wallet/clean-send-data])
|
||||
(rf/dispatch [:open-modal :wallet-select-address]))
|
||||
:receive-action #(rf/dispatch [:open-modal :wallet-share-address {:status :receive}])
|
||||
:buy-action #(rf/dispatch [:show-bottom-sheet
|
||||
{:content buy-drawer}])
|
||||
|
||||
@@ -122,17 +122,17 @@
|
||||
(rf/dispatch [:wallet/clean-scanned-address])
|
||||
(rf/dispatch [:wallet/clear-address-activity-check])
|
||||
(rf/dispatch [:navigate-back]))}]
|
||||
:footer
|
||||
[quo/button
|
||||
{:customization-color customization-color
|
||||
:disabled? (or (string/blank? @input-value) (some? (validate @input-value)))
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:navigate-to
|
||||
:confirm-address-to-watch
|
||||
{:address @input-value}])
|
||||
(clear-input))
|
||||
:container-style {:z-index 2}}
|
||||
(i18n/label :t/continue)]}
|
||||
:footer [quo/button
|
||||
{:customization-color customization-color
|
||||
:disabled? (or (string/blank? @input-value)
|
||||
(some? (validate @input-value)))
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:navigate-to
|
||||
:confirm-address-to-watch
|
||||
{:address @input-value}])
|
||||
(clear-input))
|
||||
:container-style {:z-index 2}}
|
||||
(i18n/label :t/continue)]}
|
||||
[quo/text-combinations
|
||||
{:container-style style/header-container
|
||||
:title (i18n/label :t/add-address)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
[react-native.platform :as platform]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.contexts.wallet.common.sheets.account-options.style :as style]
|
||||
[status-im.contexts.wallet.common.sheets.remove-account.view :as remove-account]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
@@ -95,7 +96,11 @@
|
||||
:icon :i/delete
|
||||
:accessibility-label :remove-account
|
||||
:label (i18n/label :t/remove-account)
|
||||
:danger? true}]]]
|
||||
:danger? true
|
||||
:on-press #(rf/dispatch [:show-bottom-sheet
|
||||
{:content
|
||||
(fn []
|
||||
[remove-account/view])}])}]]]
|
||||
(when show-account-selector?
|
||||
[:<>
|
||||
[quo/divider-line {:container-style style/divider-label}]
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
(ns status-im.contexts.wallet.common.sheets.remove-account.style)
|
||||
|
||||
(def desc-container
|
||||
{:padding-horizontal 20
|
||||
:padding-top 4
|
||||
:padding-bottom 12})
|
||||
|
||||
(def copy-container
|
||||
{:margin-horizontal 20
|
||||
:margin-top 4
|
||||
:margin-bottom 8})
|
||||
|
||||
(def checkbox-container
|
||||
{:flex-direction :row
|
||||
:padding-horizontal 20
|
||||
:padding-vertical 8
|
||||
:gap 10})
|
||||
@@ -0,0 +1,91 @@
|
||||
(ns status-im.contexts.wallet.common.sheets.remove-account.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.theme]
|
||||
[react-native.clipboard :as clipboard]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.contexts.wallet.common.sheets.remove-account.style :as style]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- footer
|
||||
[{:keys [submit-disabled?]}]
|
||||
[quo/bottom-actions
|
||||
{:actions :2-actions
|
||||
:customization-color :danger
|
||||
:button-one-label (i18n/label :t/remove)
|
||||
:button-one-props {:on-press #(js/alert "Will be implemented")
|
||||
:type :danger
|
||||
:disabled? submit-disabled?}
|
||||
:button-two-label (i18n/label :t/cancel)
|
||||
:button-two-props {:on-press #(rf/dispatch [:hide-bottom-sheet])
|
||||
:type :grey}}])
|
||||
|
||||
(defn- recovery-phase-flow
|
||||
[]
|
||||
(let [confirmed? (reagent/atom false)]
|
||||
(fn [{:keys [name emoji path color] :as _account}]
|
||||
(let [formatted-path (utils/format-derivation-path path)]
|
||||
[:<>
|
||||
[quo/drawer-top
|
||||
{:title (i18n/label :t/remove-account-title)
|
||||
:type :context-tag
|
||||
:context-tag-type :account
|
||||
:account-name name
|
||||
:emoji emoji
|
||||
:customization-color color}]
|
||||
[rn/view {:style style/desc-container}
|
||||
[quo/text {:weight :medium}
|
||||
(i18n/label :t/remove-account-desc)]]
|
||||
[quo/data-item
|
||||
{:size :default
|
||||
:status :default
|
||||
:card? true
|
||||
:title (i18n/label :t/derivation-path)
|
||||
:custom-subtitle (fn []
|
||||
[quo/text {:weight :medium}
|
||||
formatted-path])
|
||||
:icon-right? true
|
||||
:right-icon :i/copy
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:toasts/upsert
|
||||
{:type :positive
|
||||
:text (i18n/label :t/derivation-path-copied)}])
|
||||
(clipboard/set-string formatted-path))
|
||||
:container-style style/copy-container}]
|
||||
[rn/pressable
|
||||
{:style style/checkbox-container
|
||||
:on-press #(swap! confirmed? not)}
|
||||
[quo/selectors
|
||||
{:type :checkbox
|
||||
:customization-color color
|
||||
:checked? @confirmed?
|
||||
:on-change #(swap! confirmed? not)}]
|
||||
[quo/text (i18n/label :t/remove-account-confirmation)]]
|
||||
[footer {:submit-disabled? (not @confirmed?)}]]))))
|
||||
|
||||
(defn- watched-address-flow
|
||||
[{:keys [name emoji color] :as _account}]
|
||||
[:<>
|
||||
[quo/drawer-top
|
||||
{:title (i18n/label :t/remove-watched-address-title)
|
||||
:type :context-tag
|
||||
:context-tag-type :account
|
||||
:account-name name
|
||||
:emoji emoji
|
||||
:customization-color color}]
|
||||
[rn/view {:style style/desc-container}
|
||||
[quo/text {:weight :medium}
|
||||
(i18n/label :t/remove-watched-address-desc)]]
|
||||
[footer {:submit-disabled? false}]])
|
||||
|
||||
(defn- view-internal
|
||||
[]
|
||||
(let [{:keys [type] :as account} (rf/sub [:wallet/current-viewing-account])]
|
||||
(case type
|
||||
:generated [recovery-phase-flow account]
|
||||
:watch [watched-address-flow account])))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -18,6 +18,7 @@
|
||||
:label (i18n/label :t/send)
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch [:wallet/clean-send-data])
|
||||
(rf/dispatch [:wallet/send-select-token-drawer {:token token-data}])
|
||||
(rf/dispatch [:open-modal :wallet-select-address]))}
|
||||
{:icon :i/receive
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
:as create-or-edit-account]
|
||||
[status-im.contexts.wallet.common.sheets.network-preferences.view
|
||||
:as network-preferences]
|
||||
[status-im.contexts.wallet.common.sheets.remove-account.view :as remove-account]
|
||||
[status-im.contexts.wallet.edit-account.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
@@ -62,7 +63,12 @@
|
||||
(= name @edited-account-name))]
|
||||
[create-or-edit-account/view
|
||||
{:page-nav-right-side [{:icon-name :i/delete
|
||||
:on-press #(js/alert "Delete account: to be implemented")}]
|
||||
:on-press
|
||||
(fn []
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:content
|
||||
(fn []
|
||||
[remove-account/view])}]))}]
|
||||
:account-name account-name
|
||||
:account-emoji emoji
|
||||
:account-color color
|
||||
|
||||
@@ -327,9 +327,23 @@
|
||||
{:fx [[:dispatch [:hide-bottom-sheet]]
|
||||
[:dispatch [:browser.ui/open-url (str explorer-link "/" address)]]]}))
|
||||
|
||||
(rf/reg-event-fx :wallet/reload
|
||||
(fn [_]
|
||||
{:fx [[:dispatch-n [[:wallet/get-wallet-token]]]]}))
|
||||
|
||||
(rf/reg-event-fx :wallet/start-wallet
|
||||
(fn [_]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wallet_startWallet"
|
||||
:on-error #(log/info "failed to start wallet"
|
||||
{:error %
|
||||
:event :wallet/start-wallet})}]]]}))
|
||||
|
||||
(rf/reg-event-fx :wallet/initialize
|
||||
(fn []
|
||||
{:fx [[:dispatch-n [[:wallet/get-ethereum-chains] [:wallet/get-accounts]]]]}))
|
||||
{:fx [[:dispatch [:wallet/start-wallet]]
|
||||
[:dispatch [:wallet/get-ethereum-chains]]
|
||||
[:dispatch [:wallet/get-accounts]]]}))
|
||||
|
||||
(rf/reg-event-fx :wallet/share-account
|
||||
(fn [_ [{:keys [content title]}]]
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
(:require [camel-snake-kebab.core :as csk]
|
||||
[camel-snake-kebab.extras :as cske]
|
||||
[clojure.string :as string]
|
||||
[re-frame.core :as rf]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.ethereum.chain :as chain]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.transforms :as types]))
|
||||
|
||||
(def collectible-data-types
|
||||
@@ -66,8 +66,9 @@
|
||||
data-type (collectible-data-types :header)
|
||||
fetch-criteria {:fetch-type (fetch-type :fetch-if-not-cached)
|
||||
:max-cache-age-seconds max-cache-age-seconds}
|
||||
chain-ids (chain/chain-ids db)
|
||||
request-params [request-id
|
||||
[(chain/chain-id db)]
|
||||
chain-ids
|
||||
(keys (get-in db [:wallet :accounts]))
|
||||
collectibles-filter
|
||||
start-at-index
|
||||
|
||||
@@ -10,9 +10,12 @@
|
||||
[utils.number]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/reg-event-fx :wallet/clean-send-data
|
||||
(fn [{:keys [db]}]
|
||||
{:db (update-in db [:wallet :ui] dissoc :send)}))
|
||||
|
||||
(rf/reg-event-fx :wallet/select-address-tab
|
||||
(fn [{:keys [db]} [tab]]
|
||||
|
||||
{:db (assoc-in db [:wallet :ui :send :select-address-tab] tab)}))
|
||||
|
||||
(rf/reg-event-fx :wallet/suggested-routes-success
|
||||
@@ -126,14 +129,21 @@
|
||||
|
||||
(rf/reg-event-fx :wallet/add-authorized-transaction
|
||||
(fn [{:keys [db]} [transaction]]
|
||||
(let [transaction-hashes (:hashes transaction)
|
||||
chain-id (key (first transaction-hashes))
|
||||
tx-id (first (val (first transaction-hashes)))
|
||||
transaction-detes {:status :pending
|
||||
:id (:id transaction)
|
||||
:chain-id chain-id}]
|
||||
{:db (assoc-in db [:wallet :transactions tx-id] transaction-detes)
|
||||
:fx [[:dispatch [:navigate-to :wallet-transaction-progress]]]})))
|
||||
(let [transaction-batch-id (:id transaction)
|
||||
transaction-hashes (:hashes transaction)
|
||||
transaction-ids (flatten (vals transaction-hashes))
|
||||
transaction-details (send-utils/map-multitransaction-by-ids transaction-batch-id
|
||||
transaction-hashes)]
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet :transactions] transaction-details)
|
||||
(assoc-in [:wallet :ui :send :transaction-ids] transaction-ids))
|
||||
:fx [[:dispatch
|
||||
[:navigate-to-within-stack
|
||||
[:wallet-transaction-progress :wallet-transaction-confirmation]]]]})))
|
||||
|
||||
(rf/reg-event-fx :wallet/close-transaction-progress-page
|
||||
(fn [_]
|
||||
{:fx [[:dispatch [:dismiss-modal :wallet-transaction-progress]]]}))
|
||||
|
||||
(defn- transaction-bridge
|
||||
[{:keys [from-address to-address route]}]
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
(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"))
|
||||
(h/is-truthy (h/get-by-label-text :container))
|
||||
(h/is-disabled (h/get-by-label-text :button-one)))
|
||||
|
||||
(h/test "Fill token input and confirm"
|
||||
@@ -77,6 +78,7 @@
|
||||
(-> (h/wait-for #(h/get-by-text "$1234.50"))
|
||||
(.then (fn []
|
||||
(h/is-truthy (h/get-by-label-text :button-one))
|
||||
(h/is-truthy (h/get-by-label-text :container))
|
||||
(h/fire-event :press (h/get-by-label-text :button-one))
|
||||
(h/was-called on-confirm))))))
|
||||
|
||||
@@ -99,61 +101,33 @@
|
||||
(-> (h/wait-for #(h/get-by-text "$1234.50"))
|
||||
(.then (fn []
|
||||
(h/is-truthy (h/get-by-label-text :button-one))
|
||||
(h/is-truthy (h/get-by-label-text :container))
|
||||
(h/fire-event :press (h/get-by-label-text :button-one))
|
||||
(h/was-called on-confirm))))))
|
||||
|
||||
(h/test "Try to fill more than limit"
|
||||
(h/setup-subs sub-mocks)
|
||||
(h/render [input-amount/view
|
||||
{:crypto-decimals 10
|
||||
:limit-crypto 286}])
|
||||
{:crypto-decimals 1
|
||||
:limit-crypto 1}])
|
||||
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-2))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-9))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-5))
|
||||
|
||||
(-> (h/wait-for #(h/is-truthy (h/get-by-text "$290.00")))
|
||||
(.then (fn []
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-backspace))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-8))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-5))
|
||||
(h/wait-for #(h/get-by-text "$2850.00"))))))
|
||||
|
||||
(h/test "Try to fill more than limit"
|
||||
(h/setup-subs sub-mocks)
|
||||
(h/render [input-amount/view
|
||||
{:crypto-decimals 10
|
||||
:limit-crypto 286
|
||||
:on-confirm #()}])
|
||||
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-2))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-9))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-5))
|
||||
|
||||
(-> (h/wait-for #(h/get-by-text "$290.00"))
|
||||
(.then (fn []
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-backspace))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-8))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-5))
|
||||
(h/wait-for #(h/get-by-text "$2850.00"))))))
|
||||
(h/is-truthy (h/get-by-label-text :container-error)))
|
||||
|
||||
(h/test "Switch from crypto to fiat and check limit"
|
||||
(h/setup-subs sub-mocks)
|
||||
(h/render [input-amount/view
|
||||
{:crypto-decimals 2
|
||||
:limit-crypto 250
|
||||
{:crypto-decimals 1
|
||||
:limit-crypto 1
|
||||
:on-confirm #()}])
|
||||
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-2))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-0))
|
||||
(-> (h/wait-for #(h/get-by-text "$200.00"))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-9))
|
||||
(h/is-truthy (h/get-by-label-text :container-error))
|
||||
(h/fire-event :press (h/query-by-label-text :reorder))
|
||||
|
||||
(-> (h/wait-for #(h/get-by-text "Max: 1000.00 USD"))
|
||||
(.then (fn []
|
||||
(h/fire-event :press (h/query-by-label-text :reorder))
|
||||
(h/wait-for #(h/get-by-text "2.00 ETH"))))
|
||||
(.then (fn []
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-5))
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-5))
|
||||
(h/wait-for #(h/get-by-text "20.50 ETH"))))
|
||||
(.then (fn []
|
||||
(h/fire-event :press (h/query-by-label-text :keyboard-key-5))
|
||||
(h/wait-for #(h/get-by-text "20.50 ETH")))))))
|
||||
(h/wait-for #(h/is-truthy (h/get-by-label-text :container))))))))
|
||||
|
||||
@@ -61,6 +61,11 @@
|
||||
(>= (js/parseFloat balance) input-value)))
|
||||
(map first)))
|
||||
|
||||
(defn- reset-input-error
|
||||
[new-value prev-value input-error]
|
||||
(reset! input-error
|
||||
(> new-value prev-value)))
|
||||
|
||||
(defn- f-view-internal
|
||||
;; crypto-decimals and limit-crypto args are needed for component tests only
|
||||
[{:keys [crypto-decimals limit-crypto]}]
|
||||
@@ -75,6 +80,7 @@
|
||||
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?]
|
||||
@@ -84,27 +90,30 @@
|
||||
:currency token-symbol}
|
||||
{:amount limit-fiat
|
||||
:currency currency}))
|
||||
(when (> num-value (:amount @current-limit))
|
||||
(reset! input-value ""))))
|
||||
(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)]
|
||||
(when (and (not loading-suggested-routes?)
|
||||
(<= num-value (:amount @current-limit)))
|
||||
(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?
|
||||
(swap! input-value #(subs % 0 (dec (count %))))
|
||||
(reagent/flush)))
|
||||
(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)]
|
||||
(if (> num-value current-limit-amount)
|
||||
(reset! input-value (str current-limit-amount))
|
||||
(reset! input-value v))
|
||||
(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
|
||||
@@ -119,7 +128,8 @@
|
||||
(empty? @input-value)
|
||||
(<= input-num-value 0)
|
||||
(> input-num-value (:amount @current-limit)))
|
||||
amount (str @input-value " " token-symbol)]
|
||||
amount (str @input-value " " token-symbol)
|
||||
{:keys [color]} (rf/sub [:wallet/current-viewing-account])]
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(let [dismiss-keyboard-fn #(when (= % "active") (rn/dismiss-keyboard!))
|
||||
@@ -135,7 +145,8 @@
|
||||
100)))
|
||||
[@input-value])
|
||||
[rn/view
|
||||
{:style style/screen}
|
||||
{:style style/screen
|
||||
:accessibility-label (str "container" (when @input-error "-error"))}
|
||||
[account-switcher/view
|
||||
{:icon-name :i/arrow-left
|
||||
:on-press #(rf/dispatch [:navigate-back-within-stack :wallet-send-input-amount])
|
||||
@@ -145,6 +156,7 @@
|
||||
: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
|
||||
@@ -159,10 +171,11 @@
|
||||
:loading-networks (find-affordable-networks token @input-value)
|
||||
:networks (:networks token)}]
|
||||
[quo/bottom-actions
|
||||
{:actions :1-action
|
||||
:button-one-label (i18n/label :t/confirm)
|
||||
:button-one-props {:disabled? confirm-disabled?
|
||||
:on-press on-confirm}}]
|
||||
{:actions :1-action
|
||||
:button-one-label (i18n/label :t/confirm)
|
||||
:button-one-props {:disabled? confirm-disabled?
|
||||
:on-press on-confirm}
|
||||
:customization-color color}]
|
||||
[quo/numbered-keyboard
|
||||
{:container-style (style/keyboard-container bottom)
|
||||
:left-action :dot
|
||||
|
||||
@@ -128,26 +128,30 @@
|
||||
(fn []
|
||||
(let [selected-tab (or (rf/sub [:wallet/send-tab]) (:id (first tabs-data)))
|
||||
token (rf/sub [:wallet/wallet-send-token])
|
||||
valid-ens-or-address? (boolean (rf/sub [:wallet/valid-ens-or-address?]))]
|
||||
valid-ens-or-address? (boolean (rf/sub [:wallet/valid-ens-or-address?]))
|
||||
{:keys [color]} (rf/sub [:wallet/current-viewing-account])]
|
||||
(rn/use-effect (fn []
|
||||
(fn []
|
||||
(rf/dispatch [:wallet/clean-scanned-address])
|
||||
(rf/dispatch [:wallet/clean-local-suggestions]))))
|
||||
[floating-button-page/view
|
||||
{:header [account-switcher/view
|
||||
{:on-press on-close
|
||||
:margin-top (safe-area/get-top)
|
||||
:switcher-type :select-account}]
|
||||
:footer (when (> (count @input-value) 0)
|
||||
[quo/button
|
||||
{:accessibility-label :continue-button
|
||||
:type :primary
|
||||
:disabled? (not valid-ens-or-address?)
|
||||
:on-press #(rf/dispatch [:wallet/select-send-address
|
||||
{:address @input-value
|
||||
:token token
|
||||
:stack-id :wallet-select-address}])}
|
||||
(i18n/label :t/continue)])}
|
||||
{:footer-container-padding 0
|
||||
:header [account-switcher/view
|
||||
{:on-press on-close
|
||||
:margin-top (safe-area/get-top)
|
||||
:switcher-type :select-account}]
|
||||
:footer (when (> (count @input-value) 0)
|
||||
[quo/button
|
||||
{:accessibility-label :continue-button
|
||||
:type :primary
|
||||
:disabled? (not valid-ens-or-address?)
|
||||
:on-press #(rf/dispatch [:wallet/select-send-address
|
||||
{:address @input-value
|
||||
:token token
|
||||
:stack-id
|
||||
:wallet-select-address}])
|
||||
:customization-color color}
|
||||
(i18n/label :t/continue)])}
|
||||
[quo/text-combinations
|
||||
{:title (i18n/label :t/send-to)
|
||||
:container-style style/title-container
|
||||
|
||||
@@ -162,28 +162,30 @@
|
||||
:address (utils/get-shortened-address to-address)}]
|
||||
[rn/view {:style {:flex 1}}
|
||||
[floating-button-page/view
|
||||
{:header [quo/page-nav
|
||||
{:icon-name :i/arrow-left
|
||||
:on-press on-close
|
||||
:margin-top (safe-area/get-top)
|
||||
:background :blur
|
||||
:accessibility-label :top-bar
|
||||
:right-side [{:icon-name :i/advanced
|
||||
:on-press #(js/alert
|
||||
"to be implemented")
|
||||
:accessibility-label :advanced-options}]}]
|
||||
: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)}]
|
||||
[rn/activity-indicator])
|
||||
:gradient-cover? true
|
||||
:customization-color (:color account)}
|
||||
{:footer-container-padding 0
|
||||
:header [quo/page-nav
|
||||
{:icon-name :i/arrow-left
|
||||
:on-press on-close
|
||||
:margin-top (safe-area/get-top)
|
||||
:background :blur
|
||||
:accessibility-label :top-bar
|
||||
:right-side [{:icon-name :i/advanced
|
||||
:on-press #(js/alert
|
||||
"to be implemented")
|
||||
:accessibility-label :advanced-options}]}]
|
||||
: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)}]
|
||||
[rn/activity-indicator])
|
||||
:gradient-cover? true
|
||||
:customization-color (:color account)}
|
||||
[rn/view
|
||||
[transaction-title
|
||||
{:token-symbol token-symbol
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.common.floating-button-page.view :as floating-button-page]
|
||||
[status-im.common.resources :as resources]
|
||||
[status-im.contexts.wallet.send.transaction-progress.style :as style]
|
||||
@@ -13,39 +12,43 @@
|
||||
(defn titles
|
||||
[status]
|
||||
(case status
|
||||
:sending (i18n/label :t/sending-with-elipsis)
|
||||
:pending (i18n/label :t/sending-with-ellipsis)
|
||||
:confirmed (i18n/label :t/transaction-confirmed)
|
||||
:finalised (i18n/label :t/transacation-finalised)
|
||||
""))
|
||||
|
||||
(defn combined-status-overview
|
||||
[transaction-details]
|
||||
(cond
|
||||
(every? (fn [[_k v]] (= (:status v) :finalised)) transaction-details) :finalised
|
||||
(some (fn [[_k v]] (= (:status v) :pending)) transaction-details) :pending
|
||||
(some (fn [[_k v]] (= (:status v) :confirmed)) transaction-details) :confirmed
|
||||
:else nil))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [current-address (rf/sub [:wallet/current-viewing-account-address])
|
||||
leave-page (fn []
|
||||
(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 [:navigate-to :wallet-accounts current-address]))
|
||||
status (reagent/atom :sending)
|
||||
(let [leave-page #(rf/dispatch [:wallet/close-transaction-progress-page])
|
||||
{:keys [color]} (rf/sub [:wallet/current-viewing-account])]
|
||||
[floating-button-page/view
|
||||
{:header [quo/page-nav
|
||||
{:type :no-title
|
||||
:background :blur
|
||||
:icon-name :i/close
|
||||
:margin-top (safe-area/get-top)
|
||||
:on-press leave-page
|
||||
:accessibility-label :top-bar}]
|
||||
:footer [quo/button
|
||||
{:customization-color color
|
||||
:on-press leave-page}
|
||||
(i18n/label :t/done)]
|
||||
:customization-color color
|
||||
:gradient-cover? true}
|
||||
[rn/view {:style style/content-container}
|
||||
[rn/image
|
||||
{:source (resources/get-image :transaction-progress)
|
||||
:style {:margin-bottom 12}}]
|
||||
[quo/standard-title
|
||||
{:title (titles @status)}]]]))
|
||||
(fn []
|
||||
(let [transaction-details (rf/sub [:wallet/send-transaction-progress])]
|
||||
[floating-button-page/view
|
||||
{:footer-container-padding 0
|
||||
:header [quo/page-nav
|
||||
{:type :no-title
|
||||
:background :blur
|
||||
:icon-name :i/close
|
||||
:margin-top (safe-area/get-top)
|
||||
:on-press leave-page
|
||||
:accessibility-label :top-bar}]
|
||||
:footer [quo/button
|
||||
{:customization-color color
|
||||
:on-press leave-page}
|
||||
(i18n/label :t/done)]
|
||||
:customization-color color
|
||||
:gradient-cover? true}
|
||||
[rn/view {:style style/content-container}
|
||||
[rn/image
|
||||
{:source (resources/get-image :transaction-progress)
|
||||
:style {:margin-bottom 12}}]
|
||||
[quo/standard-title
|
||||
{:title (titles (combined-status-overview transaction-details))}]]]))))
|
||||
|
||||
@@ -4,3 +4,19 @@
|
||||
(defn amount-in-hex
|
||||
[amount token-decimal]
|
||||
(money/to-hex (money/mul (money/bignumber amount) (money/from-decimal token-decimal))))
|
||||
|
||||
(defn map-multitransaction-by-ids
|
||||
[transaction-batch-id transaction-hashes]
|
||||
(reduce-kv (fn [map1 chain-id value1]
|
||||
(merge map1
|
||||
(reduce
|
||||
(fn [map2 tx-id]
|
||||
(assoc map2
|
||||
tx-id
|
||||
{:status :pending
|
||||
:id transaction-batch-id
|
||||
:chain-id chain-id}))
|
||||
{}
|
||||
value1)))
|
||||
{}
|
||||
transaction-hashes))
|
||||
|
||||
@@ -8,3 +8,22 @@
|
||||
decimal 18]
|
||||
(is (= (utils/amount-in-hex amount decimal)
|
||||
"0xde0b6b3a7640000")))))
|
||||
|
||||
(def multichain-transacation
|
||||
{:id 61
|
||||
:hashes {:5 ["0x5"]
|
||||
:420 ["0x12" "0x11"]}})
|
||||
|
||||
(deftest test-map-multitransaction-by-ids
|
||||
(testing "test map-multitransaction-by-ids formats to right data structure"
|
||||
(let [{:keys [id hashes]} multichain-transacation]
|
||||
(is (= (utils/map-multitransaction-by-ids id hashes)
|
||||
{"0x5" {:status :pending
|
||||
:id 61
|
||||
:chain-id :5}
|
||||
"0x12" {:status :pending
|
||||
:id 61
|
||||
:chain-id :420}
|
||||
"0x11" {:status :pending
|
||||
:id 61
|
||||
:chain-id :420}})))))
|
||||
|
||||
@@ -73,7 +73,8 @@
|
||||
[quo/overlay {:type :shell}
|
||||
[rn/view
|
||||
{:flex 1
|
||||
:padding-top padding-top}
|
||||
:padding-top padding-top
|
||||
:key :share-adress}
|
||||
[quo/page-nav
|
||||
{:icon-name :i/close
|
||||
:on-press #(rf/dispatch [:navigate-back])
|
||||
@@ -92,7 +93,6 @@
|
||||
:networks @selected-networks
|
||||
:on-share-press #(share-action qr-url share-title)
|
||||
:profile-picture nil
|
||||
:unblur-on-android? true
|
||||
:full-name (:name account)
|
||||
:customization-color color
|
||||
:emoji emoji
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
(ns status-im.contexts.wallet.signals
|
||||
(:require [utils.re-frame :as rf]))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet/pending-transaction-status-changed-received
|
||||
(fn [{:keys [db]} [{:keys [message]}]]
|
||||
(let [details (js->clj (js/JSON.parse message) :keywordize-keys true)
|
||||
tx-hash (:hash details)]
|
||||
{:db (update-in db [:wallet :transactions tx-hash] assoc :status :confirmed :blocks 1)})))
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
[status-im.contexts.profile.push-notifications.events :as notifications]
|
||||
[status-im.contexts.shell.jump-to.state :as shell.state]
|
||||
[status-im.contexts.shell.jump-to.utils :as shell.utils]
|
||||
status-im.contexts.wallet.signals
|
||||
status-im.events
|
||||
status-im.navigation.core
|
||||
[status-im.setup.dev :as dev]
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
status-im.contexts.wallet.effects
|
||||
status-im.contexts.wallet.events
|
||||
status-im.contexts.wallet.send.events
|
||||
status-im.contexts.wallet.signals
|
||||
[status-im.db :as db]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
|
||||
@@ -366,7 +366,6 @@
|
||||
:component wallet-transaction-confirmation/view}
|
||||
|
||||
{:name :wallet-transaction-progress
|
||||
:options {:insets {:bottom? true}}
|
||||
:component wallet-transaction-progress/view}
|
||||
|
||||
{:name :scan-address
|
||||
|
||||
@@ -12,14 +12,17 @@
|
||||
:short-name "eth"
|
||||
:network-name :ethereum
|
||||
:related-chain-id 1
|
||||
:chain-id 3
|
||||
:layer 1}
|
||||
{:test? true
|
||||
:short-name "arb1"
|
||||
:related-chain-id 42161
|
||||
:chain-id 4
|
||||
:layer 2}
|
||||
{:test? true
|
||||
:short-name "opt"
|
||||
:related-chain-id 10
|
||||
:chain-id 5
|
||||
:layer 2}]
|
||||
:prod [{:test? false
|
||||
:short-name "eth"
|
||||
|
||||
@@ -18,3 +18,17 @@
|
||||
:wallet/wallet-send-recipient
|
||||
:<- [:wallet/wallet-send]
|
||||
:-> :recipient)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/send-transaction-ids
|
||||
:<- [:wallet/wallet-send]
|
||||
:-> :transaction-ids)
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/send-transaction-progress
|
||||
:<- [:wallet/send-transaction-ids]
|
||||
:<- [:wallet/transactions]
|
||||
(fn [[tx-ids transactions]]
|
||||
(let [send-tx-ids (set (keys transactions))]
|
||||
(select-keys transactions
|
||||
(filter send-tx-ids tx-ids)))))
|
||||
|
||||
@@ -12,3 +12,44 @@
|
||||
(testing "returns active tab for selecting address"
|
||||
(swap! rf-db/app-db assoc-in [:wallet :ui :send :select-address-tab] :tabs/recent)
|
||||
(is (= :tabs/recent (rf/sub [sub-name])))))
|
||||
|
||||
(h/deftest-sub :wallet/send-transaction-ids
|
||||
[sub-name]
|
||||
(testing "returns the transaction ids attached the last send flow"
|
||||
(swap! rf-db/app-db assoc-in [:wallet :ui :send :transaction-ids] ["0x123" "0x321"])
|
||||
(is (= ["0x123" "0x321"] (rf/sub [sub-name])))))
|
||||
|
||||
(h/deftest-sub :wallet/send-transaction-progress
|
||||
[sub-name]
|
||||
(testing "returns transaction data for a transaction with multiple transactions"
|
||||
(swap! rf-db/app-db assoc-in
|
||||
[:wallet :transactions]
|
||||
{"0x123" {:status :pending
|
||||
:id 240
|
||||
:chain-id 5}
|
||||
"0x321" {:status :pending
|
||||
:id 240
|
||||
:chain-id 1}})
|
||||
(swap! rf-db/app-db assoc-in [:wallet :ui :send :transaction-ids] ["0x123" "0x321"])
|
||||
(is (= {"0x123" {:status :pending
|
||||
:id 240
|
||||
:chain-id 5}
|
||||
"0x321" {:status :pending
|
||||
:id 240
|
||||
:chain-id 1}}
|
||||
(rf/sub [sub-name]))))
|
||||
|
||||
(testing "returns transaction data for a transaction with a single transaction"
|
||||
(swap! rf-db/app-db assoc-in
|
||||
[:wallet :transactions]
|
||||
{"0x123" {:status :pending
|
||||
:id 100
|
||||
:chain-id 5}
|
||||
"0x321" {:status :pending
|
||||
:id 240
|
||||
:chain-id 1}})
|
||||
(swap! rf-db/app-db assoc-in [:wallet :ui :send :transaction-ids] ["0x123"])
|
||||
(is (= {"0x123" {:status :pending
|
||||
:id 100
|
||||
:chain-id 5}}
|
||||
(rf/sub [sub-name])))))
|
||||
|
||||
@@ -219,3 +219,8 @@
|
||||
(map (fn [{:keys [color] :as account}]
|
||||
(assoc account :customization-color color))
|
||||
accounts)))
|
||||
|
||||
(rf/reg-sub
|
||||
:wallet/transactions
|
||||
:<- [:wallet]
|
||||
:-> :transactions)
|
||||
|
||||
@@ -84,3 +84,10 @@
|
||||
(defn chain-id
|
||||
[db]
|
||||
(network->chain-id (get-current-network db)))
|
||||
|
||||
(defn chain-ids
|
||||
[db]
|
||||
(let [test-networks-enabled? (get-in db [:profile/profile :test-networks-enabled?])
|
||||
networks (get-in db [:wallet :networks])
|
||||
env-networks (get networks (if test-networks-enabled? :test :prod))]
|
||||
(map :chain-id env-networks)))
|
||||
|
||||
@@ -3,7 +3,21 @@
|
||||
[cljs.test :refer-macros [deftest is]]
|
||||
[utils.ethereum.chain :as chain]))
|
||||
|
||||
(defn chain-ids-db
|
||||
[test-networks-enabled?]
|
||||
{:profile/profile {:test-networks-enabled? test-networks-enabled?}
|
||||
:wallet {:networks {:test [{:chain-id 3}
|
||||
{:chain-id 4}
|
||||
{:chain-id 5}]
|
||||
:prod [{:chain-id 1}
|
||||
{:chain-id 42161}
|
||||
{:chain-id 10}]}}})
|
||||
|
||||
(deftest chain-id->chain-keyword
|
||||
(is (= (chain/chain-id->chain-keyword 1) :mainnet))
|
||||
(is (= (chain/chain-id->chain-keyword 5) :goerli))
|
||||
(is (= (chain/chain-id->chain-keyword 5777) :custom)))
|
||||
|
||||
(deftest chain-ids
|
||||
(is (= (chain/chain-ids (chain-ids-db false)) [1 42161 10]))
|
||||
(is (= (chain/chain-ids (chain-ids-db true)) [3 4 5])))
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
||||
"owner": "status-im",
|
||||
"repo": "status-go",
|
||||
"version": "v0.172.5",
|
||||
"commit-sha1": "ea3e59ffeefa623373b4a39ecf7fa5558e384ad0",
|
||||
"src-sha256": "11rds4i2ylngaddiz5f4g0r0rzwplcbkg5c4wvwzzxl49gza50j3"
|
||||
"version": "v0.172.6",
|
||||
"commit-sha1": "6e30fbb211b0e0bb1e7966cce4e215c4080aac5c",
|
||||
"src-sha256": "1k3hg2m25qvgvqxmy8im3xhjwvdyvaq49yks92642h9rw494nb94"
|
||||
}
|
||||
|
||||
@@ -276,7 +276,7 @@ class ChatElementByText(Text):
|
||||
self.emoji = emoji
|
||||
self.emojis_id = 'emoji-reaction-%s' % str(emojis[self.emoji])
|
||||
super().__init__(driver, prefix=parent_locator,
|
||||
xpath="/../..//*[@content-desc='%s']/android.widget.TextView" % self.emojis_id)
|
||||
xpath="/../..//*[@content-desc='%s']/android.widget.TextView[2]" % self.emojis_id)
|
||||
|
||||
@property
|
||||
def text(self):
|
||||
|
||||
@@ -2454,7 +2454,7 @@
|
||||
"what-are-you-waiting-for": "What are you waiting for?",
|
||||
"no-relevant-tokens": "No relevant tokens",
|
||||
"on-the-web": "On the web",
|
||||
"sending-with-elipsis": "Sending...",
|
||||
"sending-with-ellipsis": "Sending...",
|
||||
"transaction-confirmed": "Transaction confirmed!",
|
||||
"transacation-finalised": "Transaction finalised!",
|
||||
"no-relevant-tokens": "No relevant tokens",
|
||||
@@ -2463,5 +2463,11 @@
|
||||
"oops-wrong-word": "Oops! Wrong word",
|
||||
"time-in-mins": "{{minutes}} min",
|
||||
"amount-with-currency-symbol": "{{symbol}} {{amount}}",
|
||||
"no-routes-found": "No routes found"
|
||||
"no-routes-found": "No routes found",
|
||||
"remove-watched-address-title": "Remove watched address",
|
||||
"remove-watched-address-desc": "The watched address will be removed from all of your synced devices.",
|
||||
"remove-account-title": "Remove account",
|
||||
"remove-account-desc": "The account will be removed from all of your synced devices. Make sure you have a backup of your keypair or recovery phrase and derivation path (if it’s not default).",
|
||||
"derivation-path-copied": "Derivation path copied",
|
||||
"remove-account-confirmation": "I have taken note of the derivation path"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user