Compare commits

..
Author SHA1 Message Date
Ulises M 4a5b947afd Transformed successfully 2024-01-18 01:32:46 -06:00
Ulises M f673e442f3 test 2024-01-17 20:54:10 -06:00
Ulises M 548f212c6f Fix token input flickering 2024-01-17 18:52:14 -06:00
Ulises M f033677be8 Add custom keyboard to token-input preview 2024-01-17 18:52:14 -06:00
86 changed files with 5357 additions and 1036 deletions
-64
View File
@@ -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()
}
}
+18
View File
@@ -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
-6
View File
@@ -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;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

+4288
View File
File diff suppressed because one or more lines are too long
@@ -51,9 +51,3 @@
(visibility-status-updates/<-rpc-settings)
(set/rename-keys {:compressedKey :compressed-key
:emojiHash :emoji-hash})))
(defn rpc->setting-value
[{:keys [name] :as setting}]
(condp = name
:currency (update setting :value keyword)
setting))
-1
View File
@@ -43,7 +43,6 @@
[react-native.permissions :as permissions]
[react-native.platform :as platform]
[status-im.common.biometric.events :as biometric]
status-im.common.serialization
status-im.common.standard-authentication.events
[status-im.common.theme.core :as theme]
[status-im.common.universal-links :as universal-links]
@@ -246,7 +246,7 @@
[rn/touchable-opacity
{:on-press #(do
(rf/dispatch [:pop-to-root :shell-stack])
(rf/dispatch [:communities/navigate-to-community-overview (:id community)])
(rf/dispatch [:navigate-to :community-overview (:id community)])
(rf/dispatch [:chat/close]))}
[rn/text
{:style {:text-align :center
+11 -11
View File
@@ -11,17 +11,17 @@
(defn token-requirement-list-row
[tokens padding?]
[rn/view {:style (style/token-row padding?)}
(map-indexed (fn [token-index {:keys [img-src amount sufficient? purchasable?] :as token}]
^{:key token-index}
[rn/view {:style style/token-tag-spacing}
[token-tag/view
{:token-symbol (:symbol token)
:token-img-src img-src
:token-value amount
:size :size-24
:options (cond
sufficient? :hold
purchasable? :add)}]])
(map-indexed (fn [token-index token]
(let [{:keys [amount sufficient? purchasable?]} token]
^{:key token-index}
[rn/view {:style style/token-tag-spacing}
[token-tag/view
{:token-symbol (:symbol token)
:token-value amount
:size :size-24
:options (cond
sufficient? :hold
purchasable? :add)}]]))
tokens)])
(defn- internal-view
@@ -1,4 +1,4 @@
(ns quo.components.list-items.user
(ns quo.components.list-items.user-list
(:require
[quo.components.avatars.user-avatar.view :as user-avatar]
[quo.components.icon :as icons]
@@ -18,14 +18,14 @@
:align-items :center})
(defn action-icon
[{:keys [type on-press on-check disabled? checked?]} theme]
[{:keys [type on-press on-check disabled? checked?]}]
[rn/touchable-opacity
{:on-press (when on-press on-press)}
(case type
:options
[icons/icon :i/options
{:size 20
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}]
:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]
:checkbox
[selectors/view
{:type :checkbox
@@ -37,33 +37,30 @@
[text/text "not implemented"]
[rn/view])])
(defn user
(defn user-list
[{:keys [short-chat-key primary-name secondary-name photo-path online? contact? verified?
untrustworthy? on-press on-long-press accessory customization-color theme]}]
[rn/touchable-highlight
untrustworthy? on-press on-long-press accessory]}]
[rn/touchable-opacity
{:style container-style
:underlay-color (colors/resolve-color customization-color theme 5)
:accessibility-label :user-list
:on-press (when on-press on-press)
:on-long-press (when on-long-press on-long-press)}
[:<>
[user-avatar/user-avatar
{:full-name primary-name
:profile-picture photo-path
:online? online?
:size :small}]
[rn/view {:style {:margin-horizontal 8 :flex 1}}
[author/view
{:primary-name primary-name
:secondary-name secondary-name
:contact? contact?
:verified? verified?
:untrustworthy? untrustworthy?
:size 15}]
(when short-chat-key
[text/text
{:size :paragraph-2
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
short-chat-key])]
(when accessory
[action-icon accessory theme])]])
[user-avatar/user-avatar
{:full-name primary-name
:profile-picture photo-path
:online? online?
:size :small}]
[rn/view {:style {:margin-horizontal 8 :flex 1}}
[author/view
{:primary-name primary-name
:secondary-name secondary-name
:contact? contact?
:verified? verified?
:untrustworthy? untrustworthy?}]
(when short-chat-key
[text/text
{:size :paragraph-1
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
short-chat-key])]
(when accessory
[action-icon accessory])])
@@ -38,7 +38,7 @@
(defn icon-container
[is-first?]
{:margin-left (if is-first? 4 2)
:margin-bottom 4})
:margin-bottom 2})
(defn time-text
[theme]
+2 -1
View File
@@ -51,7 +51,8 @@
[icons/icon :main-icons2/untrustworthy
{:size 12
:no-color true
:container-style (style/icon-container contact?)}])]
:container-style (style/icon-container contact?)}])
]
(when (and (not verified?) short-chat-key)
[text/text
{:weight :monospace
+6 -7
View File
@@ -20,7 +20,7 @@
- :token-symbol - string"
[]
(let [container-width (reagent/atom 0)]
(fn [{:keys [options size blur? theme token-value token-img-src token-symbol]
(fn [{:keys [options size blur? theme token-value token-symbol]
:or {size :size-24}}]
[rn/view
{:on-layout #(reset! container-width
@@ -42,12 +42,11 @@
[])}
[rn/view {:style (style/container size options blur? theme)}
[token/view
{:style (style/token-img size)
:token token-symbol
:size (case size
:size-24 :size-20
:size-32 :size-28)
:image-source token-img-src}]
{:style (style/token-img size)
:token token-symbol
:size (case size
:size-24 :size-20
:size-32 :size-28)}]
[text/text
{:size :paragraph-2
:weight :medium
+18 -20
View File
@@ -15,7 +15,9 @@
[:token {:optional true} [:or keyword? string?]]
[:style {:optional true} map?]
;; Ignores `token` and uses this as parameter to `rn/image`'s source.
[:image-source {:optional true} [:or :schema.common/image-source :string]]]]
[:image-source {:optional true} [:or :schema.common/image-source :string]]
;; If true, adds `data:image/png;base64,` as prefix to the string passed as `image-source`
[:add-b64-prefix? {:optional true} boolean?]]]
:any])
(defn- size->number
@@ -50,32 +52,28 @@
first
string/capitalize)]])
(defn- normalize-b64-string
[b64-image]
(if (string/starts-with? b64-image "data:image/")
b64-image
(str b64-png-image-prefix b64-image)))
(defn view-internal
"Render a token image.
Props:
- style: extra styles to apply to the `rn/image` component.
- size: `:size-nn` or just `nn`, being `nn` any number. Defaults to 32.
- token: string or keyword, it can contain upper case letters or not.
E.g. all of these are valid and resolve to the same:
:token/snt | :snt | :SNT | \"SNT\" | \"snt\".
- image-source: Ignores `token` and uses this as parameter to `rn/image`'s source, it
can be a b64 string representing an image.
- style: extra styles to apply to the `rn/image` component.
- size: `:size-nn` or just `nn`, being `nn` any number. Defaults to 32.
- token: string or keyword, it can contain upper case letters or not.
E.g. all of these are valid and resolve to the same:
:token/snt | :snt | :SNT | \"SNT\" | \"snt\".
- image-source: Ignores `token` and uses this as parameter to `rn/image`'s source.
- add-b64-prefix?: If true, adds `data:image/png;base64,` as prefix to the string
passed as `image-source`.
"
[{:keys [token size style image-source]
[{:keys [token size style image-source add-b64-prefix?]
:or {size 32}}]
(let [img-src (if (string? image-source)
(normalize-b64-string image-source)
image-source)]
(if-let [existing-source (or img-src (token-loader/get-token-image token))]
(let [b64-string (if (and image-source add-b64-prefix?)
(str b64-png-image-prefix image-source)
image-source)
source (or b64-string (token-loader/get-token-image token))]
(if source
[rn/image
{:style (token-style style size)
:source existing-source}]
:source source}]
[temp-empty-symbol token size style])))
(def view (schema/instrument #'view-internal ?schema))
@@ -16,23 +16,48 @@
:flex-direction :row
:justify-content :space-between})
(defn token-name
[theme]
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
:margin-right 8
:padding-bottom 2})
(def token-label-container
{:position :absolute
:left 32
:right 0
:bottom 0
:top 0
:flex-direction :row
:align-items :flex-end})
(def text-input-container
{:position :absolute
:top 0
:bottom 0
:left 32 ; token image size
:right 0})
(def text-input-dimensions
(assoc typography/heading-1
:font-weight "600"
:margin-left 8
:margin-right (if platform/ios? 6 4)
:padding 0
:height "100%"))
(defn text-input
[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%"}))
(assoc text-input-dimensions :color (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 +65,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)})
+99 -79
View File
@@ -7,101 +7,121 @@
[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]
[reagent.core :as reagent]))
(defn fiat-format
[currency num-value conversion]
(str (get common/currency-label currency) (.toFixed (* num-value conversion) 2)))
(defn crypto-format
[num-value conversion crypto-decimals token]
(str (.toFixed (/ num-value conversion) (or crypto-decimals 2))
" "
(string/upper-case (or (clj->js token) ""))))
(defn calc-value
[{:keys [crypto? currency token value conversion crypto-decimals]}]
(let [num-value (if (string? value) (parse-double (or value "0")) value)]
[crypto? currency token value conversion]
(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))))
(str (get common/currency-label currency) (.toFixed (* num-value conversion) 2))
(str (.toFixed (/ num-value conversion) 2)
" "
(string/upper-case (or (clj->js token) ""))))))
(defn- data-info
[{:keys [theme conversion networks title crypto? currency token amount]}]
[rn/view {:style style/data-container}
[network-tag/view {:networks networks :title title}]
[text/text
{:size :paragraph-2
:weight :medium
:style (style/fiat-amount theme)}
(calc-value crypto? currency token amount conversion)]])
(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
{:auto-focus true
:max-length 12
:style style/text-input-dimensions
:editable false
: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]
: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)
: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))
+3 -3
View File
@@ -86,7 +86,7 @@
quo.components.list-items.saved-contact-address.view
quo.components.list-items.token-network.view
quo.components.list-items.token-value.view
quo.components.list-items.user
quo.components.list-items.user-list
quo.components.loaders.skeleton-list.view
quo.components.markdown.list.view
quo.components.markdown.text
@@ -299,7 +299,7 @@
(def account-list-card quo.components.list-items.account-list-card.view/view)
(def address quo.components.list-items.address.view/view)
(def channel quo.components.list-items.channel.view/view)
(def community-list quo.components.list-items.community.view/view)
(def community-list-item 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 preview-list quo.components.list-items.preview-list.view/view)
@@ -308,7 +308,7 @@
(def saved-contact-address quo.components.list-items.saved-contact-address.view/view)
(def token-network quo.components.list-items.token-network.view/view)
(def token-value quo.components.list-items.token-value.view/view)
(def user quo.components.list-items.user/user)
(def user-list quo.components.list-items.user-list/user-list)
;;;; Loaders
(def skeleton-list quo.components.loaders.skeleton-list.view/view)
+11 -13
View File
@@ -17,19 +17,19 @@
(fn [^js data]
(let [^js section (.-section data)]
(reagent/as-element [f
{:index (.-index section)
:title (.-title section)
{:title (.-title section)
:data (.-data section)}]))))
(defn- wrap-per-section-render-fn
[index props]
(-> (if-let [f (:render-fn props)]
(assoc (dissoc props :render-fn :render-data)
:renderItem
(memo-wrap-render-fn f (:render-data props)))
props)
(update :data to-array)
(assoc :index index)))
[props]
(update
(if-let [f (:render-fn props)]
(assoc (dissoc props :render-fn :render-data)
:renderItem
(memo-wrap-render-fn f (:render-data props)))
props)
:data
to-array))
(defn section-list
"A wrapper for SectionList.
@@ -42,8 +42,6 @@
props
(when render-section-footer-fn
{:renderSectionFooter (wrap-render-section-header-fn render-section-footer-fn)})
{:sections (->> sections
(map-indexed wrap-per-section-render-fn)
(clj->js))
{:sections (clj->js (map wrap-per-section-render-fn sections))
:renderSectionHeader (wrap-render-section-header-fn render-section-header-fn)
:style style})])
@@ -1,5 +0,0 @@
(ns status-im.common.contact-list.style)
(defn contacts-section-header
[first-item?]
{:padding-top (if first-item? 0 8)})
+3 -6
View File
@@ -1,10 +1,7 @@
(ns status-im.common.contact-list.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.common.contact-list.style :as style]))
[quo.core :as quo]))
(defn contacts-section-header
[{:keys [title index]}]
[rn/view (style/contacts-section-header (= index 0))
[quo/divider-label title]])
[{:keys [title]}]
[quo/divider-label title])
@@ -6,21 +6,17 @@
(defn contact-list-item
[{:keys [on-press on-long-press accessory]}
{:keys [primary-name secondary-name public-key compressed-key ens-verified added?]}
theme]
(let [photo-path (rf/sub [:chats/photo-path public-key])
online? (rf/sub [:visibility-status-updates/online? public-key])
customization-color (rf/sub [:profile/customization-color])]
[quo/user
{:customization-color customization-color
:theme theme
:short-chat-key (address/get-shortened-compressed-key (or compressed-key public-key))
:primary-name primary-name
:secondary-name secondary-name
:photo-path photo-path
:online? online?
:verified? ens-verified
:contact? added?
:on-press on-press
:on-long-press on-long-press
:accessory accessory}]))
{:keys [primary-name secondary-name public-key compressed-key ens-verified added?]}]
(let [photo-path (rf/sub [:chats/photo-path public-key])
online? (rf/sub [:visibility-status-updates/online? public-key])]
[quo/user-list
{:short-chat-key (address/get-shortened-compressed-key (or compressed-key public-key))
:primary-name primary-name
:secondary-name secondary-name
:photo-path photo-path
:online? online?
:verified? ens-verified
:contact? added?
:on-press on-press
:on-long-press on-long-press
:accessory accessory}]))
-3
View File
@@ -38,9 +38,6 @@
:no-contacts
{:light (js/require "../resources/images/ui2/no-contacts-light.png")
:dark (js/require "../resources/images/ui2/no-contacts-dark.png")}
:no-contacts-to-chat
{:light (js/require "../resources/images/ui2/no-contacts-to-chat-light.png")
:dark (js/require "../resources/images/ui2/no-contacts-to-chat-dark.png")}
:keycard-chip
{:light (js/require "../resources/images/ui2/keycard-chip-light.png")
:dark (js/require "../resources/images/ui2/keycard-chip-dark.png")}
+8 -2
View File
@@ -259,6 +259,12 @@
{:type :wallet-account
:account (when account (string/lower-case account))})
(defn community-route-type
[route-params]
(if (string/starts-with? (:community-id route-params) "z")
:desktop-community
:community))
(defn handle-uri
[chain chats uri cb]
(let [{:keys [handler route-params query-params]} (match-uri uri)]
@@ -291,14 +297,14 @@
(cb {:type handler :community-id (:community-id route-params)})
(and (= handler :community) (:community-id route-params))
(cb {:type :community
(cb {:type (community-route-type route-params)
:community-id (:community-id route-params)})
(and (= handler :community-chat) (:community-channel-id route-params) (:community-id route-params))
(match-community-channel-async route-params cb)
(and (= handler :community-chat) (:community-id route-params))
(cb {:type :community
(cb {:type (community-route-type route-params)
:community-id (:community-id route-params)})
;; NOTE: removed in `match-uri`, might need this in the future
-27
View File
@@ -1,27 +0,0 @@
(ns status-im.common.serialization
(:require
[native-module.core :as native-module]
[status-im.constants :as constants]
[utils.re-frame :as rf]
[utils.transforms :as transforms]))
(rf/reg-fx :serialization/deserialize-and-compress-key
(fn [{:keys [serialized-key on-success on-error]}]
(native-module/deserialize-and-compress-key
serialized-key
(fn [resp]
(let [{:keys [error]} (transforms/json->clj resp)]
(if error
(on-error error)
(on-success resp)))))))
(rf/reg-fx :serialization/decompress-public-key
(fn [{:keys [compressed-key on-success on-error]}]
(native-module/compressed-key->public-key
compressed-key
constants/deserialization-key
(fn [resp]
(let [{:keys [error]} (transforms/json->clj resp)]
(if error
(on-error error)
(on-success (str "0x" (subs resp 5)))))))))
+31 -4
View File
@@ -2,12 +2,12 @@
(:require
[clojure.string :as string]
[goog.string :as gstring]
[native-module.core :as native-module]
[re-frame.core :as re-frame]
[react-native.async-storage :as async-storage]
[react-native.core :as rn]
[schema.core :as schema]
[status-im.constants :as constants]
[status-im.contexts.communities.events :as communities.events]
[status-im.navigation.events :as navigation]
[taoensso.timbre :as log]
[utils.ethereum.chain :as chain]
@@ -68,6 +68,32 @@
(log/info "universal-links: handling community request " community-id)
(navigation/navigate-to cofx :community-requests-to-join {:community-id community-id}))
(rf/defn handle-community
[cofx {:keys [community-id]}]
(log/info "universal-links: handling community" community-id)
(navigation/navigate-to cofx :community {:community-id community-id}))
(rf/defn handle-navigation-to-desktop-community-from-mobile
{:events [:handle-navigation-to-desktop-community-from-mobile]}
[cofx deserialized-key]
(rf/merge
cofx
{:dispatch [:navigate-to :community-overview deserialized-key]}
(navigation/pop-to-root :shell-stack)))
(rf/defn handle-desktop-community
[_ {:keys [community-id]}]
(native-module/deserialize-and-compress-key
community-id
(fn [deserialized-key]
(rf/dispatch [:chat.ui/fetch-community (str deserialized-key)])
(rf/dispatch [:handle-navigation-to-desktop-community-from-mobile (str deserialized-key)]))))
(rf/defn handle-community-chat
[cofx {:keys [chat-id]}]
(log/info "universal-links: handling community chat" chat-id)
{:dispatch [:chat/pop-to-root-and-navigate-to-chat chat-id]})
(rf/defn handle-view-profile
[{:keys [db] :as cofx} {:keys [public-key ens-name]}]
(log/info "universal-links: handling view profile" public-key)
@@ -117,13 +143,14 @@
(rf/defn on-handle
{:events [::match-value]}
[cofx url {:keys [type chat-id] :as data}]
[cofx url {:keys [type] :as data}]
(case type
:group-chat (handle-group-chat cofx data)
:private-chat (handle-private-chat cofx data)
:community-requests (handle-community-requests cofx data)
:community (communities.events/navigate-to-serialized-community cofx data)
:community-chat {:dispatch [:communities/navigate-to-community-chat chat-id :pop-to-root]}
:community (handle-community cofx data)
:desktop-community (handle-desktop-community cofx data)
:community-chat (handle-community-chat cofx data)
:contact (handle-view-profile cofx data)
:browser (handle-browse cofx data)
:eip681 (handle-eip681 cofx data)
-7
View File
@@ -338,13 +338,6 @@
(def ^:const local-pairing-action-sync-device 3)
(def ^:const local-pairing-action-pairing-installation 4)
(def ^:const serialization-key
"We pass this serialization key as a parameter to MultiformatSerializePublicKey
function at status-go, This key determines the output base of the serialization.
according to https://specs.status.im/spec/2#public-key-serialization we serialize
keys with base58btc encoding"
"z")
(def ^:const deserialization-key
"We pass this deserialization key as a parameter to MultiformatDeserializePublicKey
function at status-go, This key determines the output base of the deserialization.
@@ -29,7 +29,7 @@
{:icon :i/add-user
:accessibility-label :add-a-contact
:label (i18n/label :t/add-a-contact)
:sub-label (i18n/label :t/enter-chat-key)
:sub-label (i18n/label :t/enter-a-chat-key)
:add-divider? true
:on-press #(debounce/dispatch-and-chill
[:open-modal :new-contact]
@@ -1,7 +1,21 @@
(ns status-im.contexts.chat.home.add-new-contact.effects
(:require
[legacy.status-im.ethereum.ens :as ens]
[utils.re-frame :as rf]))
[native-module.core :as native-module]
[status-im.constants :as constants]
[utils.re-frame :as rf]
[utils.transforms :as transforms]))
(rf/reg-fx :effects.contacts/decompress-public-key
(fn [{:keys [compressed-key on-success on-error]}]
(native-module/compressed-key->public-key
compressed-key
constants/deserialization-key
(fn [resp]
(let [{:keys [error]} (transforms/json->clj resp)]
(if error
(on-error error)
(on-success (str "0x" (subs resp 5)))))))))
(rf/reg-fx :effects.contacts/resolve-public-key-from-ens
(fn [{:keys [chain-id ens on-success on-error]}]
@@ -104,7 +104,7 @@
:empty {:db (dissoc db :contacts/new-identity)}
(:valid :invalid) {:db (assoc db :contacts/new-identity contact)}
:decompress-key {:db (assoc db :contacts/new-identity contact)
:serialization/decompress-public-key
:effects.contacts/decompress-public-key
{:compressed-key id
:on-success
(dispatcher :contacts/set-new-identity-success input)
@@ -132,7 +132,7 @@
:type :compressed-key
:public-key nil ; not yet...
:state :decompress-key}))
:serialization/decompress-public-key
:effects.contacts/decompress-public-key
{:compressed-key user-ckey
:on-success [:contacts/set-new-identity-success user-ckey]
:on-error [:contacts/set-new-identity-error user-ckey]}})))
@@ -21,7 +21,7 @@
[]
{:size :heading-1
:weight :semi-bold
:style {:margin-top 28
:style {:margin-top 32
:margin-bottom 6
:color (colors/theme-colors colors/neutral-100 colors/white)}})
@@ -16,38 +16,33 @@
(defn- no-contacts-view
[{:keys [theme]}]
(let [customization-color (rf/sub [:profile/customization-color])]
[rn/view
{:style (style/no-contacts)}
[rn/image {:source (resources/get-themed-image :no-contacts-to-chat theme)}]
[quo/text
{:weight :semi-bold
:size :paragraph-1
:style {:margin-bottom 2
:margin-top 12}}
(i18n/label :t/you-have-no-contacts)]
[quo/text
{:weight :regular
:size :paragraph-2}
(i18n/label :t/dont-yell-at-me)]
[quo/button
{:customization-color customization-color
:theme theme
:type :primary
:size 32
:container-style {:margin-top 20
:margin-bottom 12}
:on-press #(rf/dispatch [:invite.events/share-link])}
(i18n/label :t/invite-friends)]
[quo/button
{:customization-color customization-color
:theme theme
:type :grey
:size 32
:on-press #(do
(rf/dispatch [:navigate-back])
(rf/dispatch [:open-modal :new-contact]))}
(i18n/label :t/add-a-contact)]]))
[rn/view
{:style (style/no-contacts)}
[rn/image {:source (resources/get-themed-image :no-contacts theme)}]
[quo/text
{:weight :semi-bold
:size :paragraph-1
:style {:margin-bottom 2
:margin-top 12}}
(i18n/label :t/you-have-no-contacts)]
[quo/text
{:weight :regular
:size :label}
(i18n/label :t/dont-yell-at-me)]
[quo/button
{:type :primary
:size 32
:container-style {:margin-top 20
:margin-bottom 12}
:on-press #(rf/dispatch [:invite.events/share-link])}
(i18n/label :t/invite-friends)]
[quo/button
{:type :grey
:size 32
:on-press #(do
(rf/dispatch [:navigate-back])
(rf/dispatch [:open-modal :new-contact]))}
(i18n/label :t/add-a-contact)]])
(defn contact-item-render
[_]
+3 -5
View File
@@ -73,7 +73,7 @@
:shared-value scroll-shared-value})}])))
(defn contact-item-render
[{:keys [public-key] :as item} theme]
[{:keys [public-key] :as item}]
(let [current-pk (rf/sub [:multiaccount/public-key])
show-profile-actions #(rf/dispatch [:show-bottom-sheet
{:content (fn [] [actions/contact-actions item])}])]
@@ -83,8 +83,7 @@
:on-long-press show-profile-actions
:accessory {:type :options
:on-press show-profile-actions}})
item
theme]))
item]))
(defn contacts
[{:keys [theme pending-contact-requests set-scroll-ref scroll-shared-value]}]
@@ -106,8 +105,7 @@
:sections items
:sticky-section-headers-enabled false
:render-section-header-fn contact-list/contacts-section-header
:render-fn (fn [data]
(contact-item-render data theme))
:render-fn contact-item-render
:scroll-event-throttle 8
:on-scroll #(common.banner/set-scroll-shared-value
{:scroll-input (oops/oget % "nativeEvent.contentOffset.y")
@@ -30,7 +30,7 @@
(js/setTimeout #(reanimated/set-shared-value background-y
(- window-height))
300)
(rf/dispatch [:chat.ui/send-current-message])
(rf/dispatch [:chat.ui/replace-mentions-and-send-current-message])
(rf/dispatch [:chat.ui/set-input-maximized false])
(rf/dispatch [:chat.ui/set-input-content-height comp-constants/input-height])
(rf/dispatch [:chat.ui/set-chat-input-text nil])
@@ -114,8 +114,9 @@
[{:keys [input-ref]}
{:keys [text-value saved-cursor-position cursor-position]}
{:keys [edit input-with-mentions]}
chat-screen-layout-calculations-complete?]
(let [mention? (some #(= :mention (first %)) (seq input-with-mentions))]
messages-list-on-layout-finished?]
(let [mention? (some #(= :mention (first %)) (seq input-with-mentions))
composer-just-opened? (not @messages-list-on-layout-finished?)]
(rn/use-effect
(fn []
(let [mention-text (reduce (fn [acc item]
@@ -127,9 +128,7 @@
;; NOTE: using text-value for cases when the user
;; leaves the app with an unfinished edit and re-opens
;; the chat.
(and (seq @text-value)
(not (reanimated/get-shared-value
chat-screen-layout-calculations-complete?)))
(and (seq @text-value) composer-just-opened?)
@text-value
:else (get-in edit [:content :text]))
selection-pos (count edit-text)
@@ -151,9 +150,7 @@
;; UI. This way, `on-focus` will trigger first without changing the height, after which
;; `on-content-size-change` will animate the height of the input based on the injected
;; text.
(js/setTimeout #(do (when (reanimated/get-shared-value
chat-screen-layout-calculations-complete?)
(.focus ^js @input-ref))
(js/setTimeout #(do (when @messages-list-on-layout-finished? (.focus ^js @input-ref))
(reagent/next-tick inject-edit-text))
600))))
[(:message-id edit)])))
@@ -162,12 +159,12 @@
[{:keys [input-ref]}
{:keys [container-opacity]}
{:keys [reply]}
chat-screen-layout-calculations-complete?]
messages-list-on-layout-finished?]
(rn/use-effect
(fn []
(when reply
(reanimated/animate container-opacity 1))
(when (and reply @input-ref (reanimated/get-shared-value chat-screen-layout-calculations-complete?))
(when (and reply @input-ref @messages-list-on-layout-finished?)
(js/setTimeout #(.focus ^js @input-ref) 600)))
[(:message-id reply)]))
@@ -207,12 +207,24 @@
(link-preview/reset-unfurled)
(cancel-message-edit)))
(rf/defn send-current-message
(rf/defn replace-mentions-and-send-current-message
"Sends message from current chat input"
{:events [:chat.ui/send-current-message]}
[{{:keys [current-chat-id] :as db} :db :as cofx}]
(let [{:keys [input-text metadata]} (get-in db [:chat/inputs current-chat-id])
editing-message (:editing-message metadata)]
(if editing-message
(send-edited-message cofx input-text editing-message)
(send-messages cofx input-text current-chat-id))))
{:events [:chat.ui/replace-mentions-and-send-current-message]}
[{{:keys [current-chat-id] :as db} :db}]
(let [{:keys [input-text metadata]} (get-in db [:chat/inputs current-chat-id])]
{:json-rpc/call [{:method "wakuext_chatMentionReplaceWithPublicKey"
:params [current-chat-id input-text]
:on-error #(log/error "[wakuext_chatMentionReplaceWithPublicKey] on-error" %)
:on-success #(rf/dispatch [:chat.ui/send-current-message-with-mentions
current-chat-id
(:editing-message metadata)
input-text
%])}]}))
(rf/defn send-current-message-with-mentions
{:events [:chat.ui/send-current-message-with-mentions]}
[{:keys [db] :as cofx} current-chat-id editing-message input-text new-text]
(rf/merge cofx
(if editing-message
(send-edited-message new-text editing-message)
(send-messages new-text current-chat-id))))
@@ -31,12 +31,12 @@
(defn sheet-component
[{:keys [insets
chat-list-scroll-y
chat-screen-layout-calculations-complete?
window-height
blur-height
opacity
background-y
theme]} props state]
theme
messages-list-on-layout-finished?]} props state]
(let [subscriptions (utils/init-subs)
content-height (reagent/atom (or (:input-content-height ; Actual text height
subscriptions)
@@ -75,8 +75,8 @@
animations
dimensions
subscriptions)
(effects/use-edit props state subscriptions chat-screen-layout-calculations-complete?)
(effects/use-reply props animations subscriptions chat-screen-layout-calculations-complete?)
(effects/use-edit props state subscriptions messages-list-on-layout-finished?)
(effects/use-reply props animations subscriptions messages-list-on-layout-finished?)
(effects/update-input-mention props state subscriptions)
(effects/link-previews props state animations subscriptions)
(effects/use-images props state animations subscriptions)
@@ -145,20 +145,22 @@
[:f> actions/view props state animations window-height insets subscriptions]]]]]))
(defn f-composer
[props]
[{:keys [insets chat-list-scroll-y messages-list-on-layout-finished?]}]
(let [window-height (:height (rn/get-window))
theme (quo.theme/use-theme-value)
opacity (reanimated/use-shared-value 0)
background-y (reanimated/use-shared-value (- window-height)) ; Y position of background
; overlay
blur-height (reanimated/use-shared-value (+ constants/composer-default-height
(:bottom (:insets props))))
extra-params (assoc props
:window-height window-height
:blur-height blur-height
:opacity opacity
:background-y background-y
:theme theme)
(:bottom insets)))
extra-params {:insets insets
:window-height window-height
:chat-list-scroll-y chat-list-scroll-y
:blur-height blur-height
:opacity opacity
:background-y background-y
:theme theme
:messages-list-on-layout-finished? messages-list-on-layout-finished?}
props (utils/init-non-reactive-state)
state (utils/init-reactive-state)]
[rn/view (when platform/ios? {:style {:z-index 1}})
@@ -1,6 +1,8 @@
(ns status-im.contexts.chat.messenger.messages.link-preview.events
(:require
[camel-snake-kebab.core :as csk]
[legacy.status-im.mailserver.core :as mailserver]
[schema.core :as schema]
[status-im.contexts.profile.settings.events :as profile.settings.events]
[taoensso.timbre :as log]
[utils.collection]
@@ -40,6 +42,96 @@
(boolean enabled?)
{}))
(defn community-resolved
[{:keys [db]} [community-id community]]
(when community
{:db (update db :communities/resolve-community-info dissoc community-id)
:fx [[:dispatch [:communities/handle-community community]]
[:dispatch
[:chat.ui/cache-link-preview-data (community-link community-id) community]]]}))
(rf/reg-event-fx :chat.ui/community-resolved community-resolved)
(defn community-failed-to-resolve
[{:keys [db]} [community-id]]
{:db (update db :communities/resolve-community-info dissoc community-id)})
(rf/reg-event-fx :chat.ui/community-failed-to-resolve community-failed-to-resolve)
(defn fetch-community
[{:keys [db]} [community-id]]
(when community-id
{:db (assoc-in db [:communities/resolve-community-info community-id] true)
:json-rpc/call [{:method "wakuext_fetchCommunity"
:params [{:CommunityKey community-id
:TryDatabase true
:WaitForResponse true}]
:on-success (fn [community]
(rf/dispatch [:chat.ui/community-resolved community-id community]))
:on-error (fn [err]
(rf/dispatch [:chat.ui/community-failed-to-resolve community-id])
(log/error {:message
"Failed to request community info from mailserver"
:error err}))}]}))
(schema/=> fetch-community
[:=>
[:catn
[:cofx :schema.re-frame/cofx]
[:args
[:schema [:catn [:community-id [:? :string]]]]]]
[:maybe
[:map
[:db map?]
[:json-rpc/call :schema.common/rpc-call]]]])
(rf/reg-event-fx :chat.ui/fetch-community fetch-community)
(defn spectate-community-success
[{:keys [db]} [{:keys [communities]}]]
(when-let [community (first communities)]
{:db (-> db
(assoc-in [:communities (:id community) :spectated] true)
(assoc-in [:communities (:id community) :spectating] false))
:fx [[:dispatch [:communities/handle-community community]]
[:dispatch [::mailserver/request-messages]]]}))
(rf/reg-event-fx :chat.ui/spectate-community-success spectate-community-success)
(defn spectate-community-failed
[{:keys [db]} [community-id]]
{:db (assoc-in db [:communities community-id :spectating] false)})
(rf/reg-event-fx :chat.ui/spectate-community-failed spectate-community-failed)
(defn spectate-community
[{:keys [db]} [community-id]]
(let [{:keys [spectated spectating joined]} (get-in db [:communities community-id])]
(when (and (not joined) (not spectated) (not spectating))
{:db (assoc-in db [:communities community-id :spectating] true)
:json-rpc/call [{:method "wakuext_spectateCommunity"
:params [community-id]
:on-success [:chat.ui/spectate-community-success]
:on-error (fn [err]
(log/error {:message
"Failed to spectate community"
:error err})
(rf/dispatch [:chat.ui/spectate-community-failed
community-id]))}]})))
(schema/=> spectate-community
[:=>
[:catn
[:cofx :schema.re-frame/cofx]
[:args
[:schema [:catn [:community-id [:? :string]]]]]]
[:maybe
[:map
[:db map?]
[:json-rpc/call :schema.common/rpc-call]]]])
(rf/reg-event-fx :chat.ui/spectate-community spectate-community)
(rf/defn save-link-preview-whitelist
{:events [:chat.ui/link-preview-whitelist-received]}
[{:keys [db]} whitelist]
@@ -0,0 +1,139 @@
(ns status-im.contexts.chat.messenger.messages.link-preview.events-test
(:require [cljs.test :as t]
[legacy.status-im.mailserver.core :as mailserver]
matcher-combinators.test
[status-im.contexts.chat.messenger.messages.link-preview.events :as sut]))
(t/deftest fetch-community
(t/testing "with community id"
(t/testing "update resolving indicator in db"
(t/is (match?
{:db {:communities/resolve-community-info {"community-id" true}}}
(sut/fetch-community {} ["community-id"]))))
(t/testing "call the fetch community rpc method with correct community id"
(t/is (match?
{:json-rpc/call [{:method "wakuext_fetchCommunity"
:params [{:CommunityKey "community-id"
:TryDatabase true
:WaitForResponse true}]}]}
(sut/fetch-community {} ["community-id"])))))
(t/testing "with no community id"
(t/testing "do nothing"
(t/is (match?
nil
(sut/fetch-community {} []))))))
(t/deftest community-failed-to-resolve
(t/testing "given a community id"
(t/testing "remove community id from resolving indicator in db"
(t/is (match?
nil
(get-in (sut/community-failed-to-resolve {:db {:communities/resolve-community-info
{"community-id" true}}}
["community-id"])
[:db :communities/resolve-community-info "community-id"]))))))
(t/deftest community-resolved
(with-redefs [sut/community-link (fn [id] (str "community-link+" id))]
(t/testing "given a community"
(let [cofx {:db {:communities/resolve-community-info {"community-id" true}}}
arg ["community-id" {:id "community-id"}]]
(t/testing "remove community id from resolving indicator in db"
(t/is (match?
nil
(get-in (sut/community-resolved cofx arg)
[:db :communities/resolve-community-info "community-id"]))))
(t/testing "dispatch fxs"
(t/is (match?
{:fx [[:dispatch [:communities/handle-community {:id "community-id"}]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id "community-id"}]]]}
(sut/community-resolved cofx arg))))))
(t/testing "given a joined community"
(let [cofx {:db {:communities/resolve-community-info {"community-id" true}}}
arg ["community-id" {:id "community-id" :joined true}]]
(t/testing "dispatch fxs, do not spectate community"
(t/is (match?
{:fx [[:dispatch [:communities/handle-community {:id "community-id"}]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id "community-id"}]]]}
(sut/community-resolved cofx arg))))))
(t/testing "given a token-gated community"
(let [cofx {:db {:communities/resolve-community-info {"community-id" true}}}
arg ["community-id" {:id "community-id" :tokenPermissions [1]}]]
(t/testing "dispatch fxs, do not spectate community"
(t/is (match?
{:fx [[:dispatch [:communities/handle-community {:id "community-id"}]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id "community-id"}]]]}
(sut/community-resolved cofx arg))))))
(t/testing "given nil community"
(t/testing "do nothing"
(t/is (match?
nil
(sut/community-resolved {} ["community-id" nil])))))))
(t/deftest spectate-community
(t/testing "given a joined community"
(t/testing "do nothing"
(t/is (match?
nil
(sut/spectate-community {:db {:communities {"community-id" {:joined true}}}}
["community-id"])))))
(t/testing "given a spectated community"
(t/testing "do nothing"
(t/is (match?
nil
(sut/spectate-community {:db {:communities {"community-id" {:spectated true}}}}
["community-id"])))))
(t/testing "given a spectating community"
(t/testing "do nothing"
(t/is (match?
nil
(sut/spectate-community {:db {:communities {"community-id" {:spectating true}}}}
["community-id"])))))
(t/testing "given a community"
(t/testing "mark community spectating"
(t/is (match?
{:db {:communities {"community-id" {:spectating true}}}}
(sut/spectate-community {:db {:communities {"community-id" {}}}} ["community-id"]))))
(t/testing "call spectate community rpc with correct community id"
(t/is (match?
{:json-rpc/call [{:method "wakuext_spectateCommunity"
:params ["community-id"]}]}
(sut/spectate-community {:db {:communities {"community-id" {}}}} ["community-id"]))))))
(t/deftest spectate-community-failed
(t/testing "mark community spectating false"
(t/is (match?
{:db {:communities {"community-id" {:spectating false}}}}
(sut/spectate-community-failed {} ["community-id"])))))
(t/deftest spectate-community-success
(t/testing "given communities"
(t/testing "mark first community spectating false"
(t/is (match?
{:db {:communities {"community-id" {:spectating false}}}}
(sut/spectate-community-success {} [{:communities [{:id "community-id"}]}]))))
(t/testing "mark first community spectated true"
(t/is (match?
{:db {:communities {"community-id" {:spectated true}}}}
(sut/spectate-community-success {} [{:communities [{:id "community-id"}]}]))))
(t/testing "dispatch fxs for first community"
(t/is (match?
{:fx [[:dispatch [:communities/handle-community {:id "community-id"}]]
[:dispatch [::mailserver/request-messages]]]}
(sut/spectate-community-success {} [{:communities [{:id "community-id"}]}])))))
(t/testing "given empty community"
(t/testing "do nothing"
(t/is (match?
nil
(sut/spectate-community-success {} [{:communities []}])))))
(t/testing "given nil community"
(t/testing "do nothing"
(t/is (match?
nil
(sut/spectate-community-success {} []))))))
@@ -81,7 +81,7 @@
(fn []
(when-not cached-preview-data
(let [community-id (community-id-from-link community-link)]
(rf/dispatch [:communities/fetch-community community-id]))))
(rf/dispatch [:chat.ui/fetch-community community-id]))))
:reagent-render
(fn []
(when cached-preview-data
@@ -267,7 +267,7 @@
(defn on-layout
[{:keys [event layout-height distance-atom distance-from-list-top
chat-screen-layout-calculations-complete?]}]
calculations-complete? messages-list-on-layout-finished?]}]
(let [layout-height-new (oops/oget event "nativeEvent.layout.height")
change (- layout-height-new @layout-height)
new-distance (- @distance-atom change)]
@@ -275,8 +275,9 @@
(reanimated/set-shared-value distance-from-list-top new-distance)
(reset! distance-atom new-distance)
(reset! layout-height layout-height-new))
(when-not (reanimated/get-shared-value chat-screen-layout-calculations-complete?)
(reanimated/set-shared-value chat-screen-layout-calculations-complete? true))))
(when-not (reanimated/get-shared-value calculations-complete?)
(reanimated/set-shared-value calculations-complete? true))
(js/setTimeout #(reset! messages-list-on-layout-finished? true) 1000)))
(defn on-scroll-fn
[distance-atom layout-height-atom]
@@ -287,7 +288,7 @@
(defn f-messages-list-content
[{:keys [insets distance-from-list-top content-height layout-height cover-bg-color distance-atom
chat-screen-layout-calculations-complete? chat-list-scroll-y]}]
calculations-complete? messages-list-on-layout-finished? chat-list-scroll-y]}]
(let [theme (quo.theme/use-theme-value)
chat (rf/sub [:chats/current-chat-chat-view])
{:keys [keyboard-shown]} (hooks/use-keyboard)
@@ -350,7 +351,8 @@
:layout-height layout-height
:distance-atom distance-atom
:distance-from-list-top distance-from-list-top
:chat-screen-layout-calculations-complete?
chat-screen-layout-calculations-complete?})
:calculations-complete? calculations-complete?
:messages-list-on-layout-finished?
messages-list-on-layout-finished?})
:scroll-enabled (not recording?)
:content-inset-adjustment-behavior :never}]]]))
@@ -18,7 +18,7 @@
[utils.worklets.chat.messenger.navigation :as worklets]))
(defn f-header-content-container
[{:keys [chat distance-from-list-top all-loaded? chat-screen-layout-calculations-complete?]}]
[{:keys [chat distance-from-list-top all-loaded? calculations-complete?]}]
(let [{:keys [chat-id group-chat chat-type chat-name
emoji]} chat
display-name (cond
@@ -34,7 +34,7 @@
header-opacity (worklets/navigation-header-opacity
distance-from-list-top
all-loaded?
chat-screen-layout-calculations-complete?
calculations-complete?
(if platform/ios?
messages.constants/content-animation-start-position-ios
messages.constants/content-animation-start-position-android))
@@ -104,7 +104,7 @@
:top-offset navigation-view-height}]]))
(defn f-view
[{:keys [distance-from-list-top chat-screen-layout-calculations-complete?]}]
[{:keys [distance-from-list-top calculations-complete?]}]
(let [{:keys [chat-id chat-type] :as chat} (rf/sub [:chats/current-chat-chat-view])
all-loaded? (reanimated/use-shared-value false)
all-loaded-sub (rf/sub [:chats/all-loaded? chat-id])
@@ -129,10 +129,10 @@
:on-press #(rf/dispatch [:navigate-back])}
(if (= chat-type constants/community-chat-type) :i/arrow-left :i/close)]
[:f> f-header-content-container
{:chat chat
:distance-from-list-top distance-from-list-top
:all-loaded? all-loaded?
:chat-screen-layout-calculations-complete? chat-screen-layout-calculations-complete?}]
{:chat chat
:distance-from-list-top distance-from-list-top
:all-loaded? all-loaded?
:calculations-complete? calculations-complete?}]
[quo/button
{:icon-only? true
:type :grey
@@ -3,6 +3,7 @@
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im.contexts.chat.messenger.composer.view :as composer.view]
[status-im.contexts.chat.messenger.messages.list.style :as style]
[status-im.contexts.chat.messenger.messages.list.view :as list.view]
@@ -14,47 +15,49 @@
;; improvement. Please avoid refactoring these files. Also if you are not already working on bug
;; fixes related to the composer, please skip them. And ping me, so I can address them while refactoring
(defn- f-chat-screen
[chat-screen-layout-calculations-complete?]
(let [insets (safe-area/get-insets)
content-height (atom 0)
layout-height (atom 0)
distance-atom (atom 0)
distance-from-list-top (reanimated/use-shared-value 0)
chat-list-scroll-y (reanimated/use-shared-value 0)]
[calculations-complete?]
(let [insets (safe-area/get-insets)
content-height (atom 0)
layout-height (atom 0)
distance-atom (atom 0)
messages-list-on-layout-finished? (reagent/atom false)
distance-from-list-top (reanimated/use-shared-value 0)
chat-list-scroll-y (reanimated/use-shared-value 0)]
[rn/keyboard-avoiding-view
{:style style/keyboard-avoiding-container
:keyboard-vertical-offset (- (:bottom insets))}
[:f> messages.navigation/f-view
{:distance-from-list-top distance-from-list-top
:chat-screen-layout-calculations-complete? chat-screen-layout-calculations-complete?}]
{:distance-from-list-top distance-from-list-top
:calculations-complete? calculations-complete?}]
[:f> list.view/f-messages-list-content
{:insets insets
:layout-height layout-height
:content-height content-height
:distance-atom distance-atom
:chat-screen-layout-calculations-complete? chat-screen-layout-calculations-complete?
:distance-from-list-top distance-from-list-top
:chat-list-scroll-y chat-list-scroll-y
:cover-bg-color :turquoise}]
{:insets insets
:layout-height layout-height
:content-height content-height
:distance-atom distance-atom
:calculations-complete? calculations-complete?
:distance-from-list-top distance-from-list-top
:chat-list-scroll-y chat-list-scroll-y
:messages-list-on-layout-finished? messages-list-on-layout-finished?
:cover-bg-color :turquoise}]
[composer.view/composer
{:insets insets
:chat-screen-layout-calculations-complete? chat-screen-layout-calculations-complete?
:chat-list-scroll-y chat-list-scroll-y}]]))
{:insets insets
:chat-list-scroll-y chat-list-scroll-y
:messages-list-on-layout-finished? messages-list-on-layout-finished?}]]))
(defn lazy-chat-screen
[chat-screen-layout-calculations-complete?]
[calculations-complete?]
(let [screen-loaded? (rf/sub [:shell/chat-screen-loaded?])]
(when-not screen-loaded?
(reanimated/set-shared-value chat-screen-layout-calculations-complete? false))
(reanimated/set-shared-value calculations-complete? false))
(when screen-loaded?
[:f> f-chat-screen chat-screen-layout-calculations-complete?])))
[:f> f-chat-screen calculations-complete?])))
(defn- f-chat
[]
(let [chat-screen-layout-calculations-complete? (reanimated/use-shared-value false)]
(let [calculations-complete? (reanimated/use-shared-value false)]
[:<>
[lazy-chat-screen chat-screen-layout-calculations-complete?]
[:f> placeholder.view/f-view chat-screen-layout-calculations-complete?]]))
[lazy-chat-screen calculations-complete?]
[:f> placeholder.view/f-view calculations-complete?]]))
(defn chat
[]
@@ -15,9 +15,9 @@
:animated? false}])
(defn f-view
[chat-screen-layout-calculations-complete?]
[calculations-complete?]
(let [top (safe-area/get-top)
opacity (worklets/placeholder-opacity chat-screen-layout-calculations-complete?)
z-index (worklets/placeholder-z-index chat-screen-layout-calculations-complete?)]
opacity (worklets/placeholder-opacity calculations-complete?)
z-index (worklets/placeholder-z-index calculations-complete?)]
[reanimated/view {:style (style/container top opacity z-index)}
[loading-skeleton]]))
@@ -23,8 +23,11 @@
[]
(let [{id :community-id} (rf/sub [:get-screen-params])
{:keys [name color images]} (rf/sub [:communities/community id])
airdrop-account (rf/sub [:communities/airdrop-account id])
selected-accounts (rf/sub [:communities/selected-permission-accounts id])]
airdrop-account (rf/sub [:communities/airdrop-account])
selected-accounts (rf/sub [:communities/selected-permission-accounts])]
(rn/use-effect (fn []
(rf/dispatch [:communities/initialize-permission-addresses]))
[])
[rn/view {:style style/container}
[quo/page-nav
{:text-align :left
@@ -8,7 +8,7 @@
[utils.re-frame :as rf]))
(defn- account-item
[item _ _ [selected-addresses community-id]]
[item _ _ selected-addresses]
[quo/account-permissions
{:account {:name (:name item)
:address (:address item)
@@ -17,7 +17,7 @@
:token-details []
:checked? (contains? selected-addresses (:address item))
:on-change #(rf/dispatch [:communities/toggle-selected-permission-address
(:address item) community-id])
(:address item)])
:container-style {:margin-bottom 8}}])
(defn view
@@ -25,7 +25,7 @@
(let [{id :community-id} (rf/sub [:get-screen-params])
{:keys [name color images]} (rf/sub [:communities/community id])
accounts (rf/sub [:wallet/accounts-with-customization-color])
selected-addresses (rf/sub [:communities/selected-permission-addresses id])]
selected-addresses (rf/sub [:communities/selected-permission-addresses])]
[rn/safe-area-view {:style style/container}
[quo/drawer-top
{:type :context-tag
@@ -38,7 +38,7 @@
[rn/flat-list
{:render-fn account-item
:render-data [selected-addresses id]
:render-data selected-addresses
:content-container-style {:padding 20}
:key-fn :address
:data accounts}]
@@ -60,7 +60,7 @@
{:type :grey
:container-style {:flex 1}
:on-press (fn []
(rf/dispatch [:communities/reset-selected-permission-addresses id])
(rf/dispatch [:communities/reset-selected-permission-addresses])
(rf/dispatch [:navigate-back]))}
(i18n/label :t/cancel)]
[quo/button
@@ -68,6 +68,6 @@
:customization-color color
:disabled? (empty? selected-addresses)
:on-press (fn []
(rf/dispatch [:communities/update-previous-permission-addresses id])
(rf/dispatch [:communities/update-previous-permission-addresses])
(rf/dispatch [:navigate-back]))}
(i18n/label :t/confirm-changes)]]]))
@@ -8,12 +8,12 @@
[utils.re-frame :as rf]))
(defn- render-item
[item _ _ [airdrop-address community-id]]
[item _ _ airdrop-address]
[quo/account-item
{:account-props item
:state (when (= airdrop-address (:address item)) :selected)
:on-press (fn []
(rf/dispatch [:communities/set-airdrop-address (:address item) community-id])
(rf/dispatch [:communities/set-airdrop-address (:address item)])
(rf/dispatch [:navigate-back]))
:emoji (:emoji item)}])
@@ -21,8 +21,8 @@
[]
(let [{id :community-id} (rf/sub [:get-screen-params])
{:keys [name images color]} (rf/sub [:communities/community id])
selected-accounts (rf/sub [:communities/selected-permission-accounts id])
airdrop-address (rf/sub [:communities/airdrop-address id])]
selected-accounts (rf/sub [:communities/selected-permission-accounts])
airdrop-address (rf/sub [:communities/airdrop-address])]
[:<>
[quo/drawer-top
{:type :context-tag
@@ -35,6 +35,6 @@
[rn/flat-list
{:data selected-accounts
:render-fn render-item
:render-data [airdrop-address id]
:render-data airdrop-address
:content-container-style style/account-list-container
:key-fn :address}]]))
@@ -6,8 +6,9 @@
[utils.re-frame :as rf]))
(defn token-requirements
[]
(fn [id]
[id]
(rf/dispatch [:communities/check-permissions-to-join-community id])
(fn []
(let [{:keys [can-request-access?
number-of-hold-tokens tokens]} (rf/sub [:community/token-gated-overview id])]
[rn/view {:style {:padding-horizontal 12}}
@@ -20,11 +20,11 @@
[quo/community-card-view-item
{:community (assoc item :cover cover)
:width width
:on-press #(rf/dispatch [:communities/navigate-to-community-overview (:id item)])}]
[quo/community-list
:on-press #(rf/dispatch [:navigate-to :community-overview (:id item)])}]
[quo/community-list-item
{:on-press (fn []
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:communities/navigate-to-community-overview (:id item)]))
(rf/dispatch [:navigate-to :community-overview (:id item)]))
:on-long-press #(rf/dispatch
[:show-bottom-sheet
{:content (fn []
@@ -142,13 +142,12 @@
(if (= view-type :card-view)
[quo/community-card-view-item
{:community (assoc community :cover cover)
:on-press #(rf/dispatch [:communities/navigate-to-community-overview (:id community)])}]
:on-press #(rf/dispatch [:navigate-to :community-overview (:id community)])}]
[quo/community-list
[quo/community-list-item
{:on-press (fn []
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:communities/navigate-to-community-overview
(:id community)]))
(rf/dispatch [:navigate-to :community-overview (:id community)]))
:on-long-press #(js/alert "TODO: to be implemented")}
community])]))
(if communities communities communities-ids))
+40 -178
View File
@@ -1,17 +1,12 @@
(ns status-im.contexts.communities.events
(:require [clojure.set :as set]
[clojure.string :as string]
[clojure.walk :as walk]
[legacy.status-im.data-store.chats :as data-store.chats]
[legacy.status-im.mailserver.core :as mailserver]
[react-native.platform :as platform]
[react-native.share :as share]
[schema.core :as schema]
[status-im.constants :as constants]
[status-im.contexts.chat.messenger.messages.link-preview.events :as link-preview.events]
status-im.contexts.communities.actions.community-options.events
status-im.contexts.communities.actions.leave.events
[status-im.navigation.events :as navigation]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -76,20 +71,14 @@
(when community-js
(let [{:keys [token-permissions
token-permissions-check joined id]
:as community} (<-rpc community-js)
has-channel-perm? (fn [id-perm-tuple]
(let [{:keys [type]} (second id-perm-tuple)]
(or (= type constants/community-token-permission-can-view-channel)
(=
type
constants/community-token-permission-can-view-and-post-channel))))]
:as community} (<-rpc community-js)
has-token-permissions? (not (seq token-permissions))]
{:db (assoc-in db [:communities id] community)
:fx [[:dispatch [:communities/initialize-permission-addresses id]]
(when (not joined)
:fx [(when (and has-token-permissions? (not joined))
[:dispatch [:chat.ui/spectate-community id]])
(when (nil? token-permissions-check)
(when (and has-token-permissions? (nil? token-permissions-check))
[:dispatch [:communities/check-permissions-to-join-community id]])
(when (some has-channel-perm? token-permissions)
(when (and has-token-permissions? (not (get-in db [:community-channels-permissions id])))
[:dispatch [:communities/check-all-community-channels-permissions id]])]}))))
(rf/defn handle-removed-chats
@@ -200,62 +189,54 @@
:on-error #(log/error "failed to fetch collapsed community categories" %)}]}))
(defn initialize-permission-addresses
[{:keys [db]} [community-id]]
(when community-id
(let [accounts (get-in db [:wallet :accounts])
sorted-accounts (sort-by :position (vals accounts))
addresses (set (map :address sorted-accounts))]
{:db (update-in db
[:communities community-id]
assoc
:previous-permission-addresses addresses
:selected-permission-addresses addresses
:airdrop-address (:address (first sorted-accounts)))})))
[{:keys [db]}]
(let [accounts (get-in db [:wallet :accounts])
sorted-accounts (sort-by :position (vals accounts))
addresses (set (map :address sorted-accounts))]
{:db (assoc db
:communities/previous-permission-addresses addresses
:communities/selected-permission-addresses addresses
:communities/airdrop-address (:address (first sorted-accounts)))}))
(rf/reg-event-fx :communities/initialize-permission-addresses
initialize-permission-addresses)
(defn update-previous-permission-addresses
[{:keys [db]} [community-id]]
(when community-id
(let [accounts (get-in db [:wallet :accounts])
sorted-accounts (sort-by :position (vals accounts))
selected-permission-addresses (get-in db
[:communities community-id
:selected-permission-addresses])
selected-accounts (filter #(contains? selected-permission-addresses (:address %))
sorted-accounts)
current-airdrop-address (get-in db [:communities community-id :airdrop-address])]
{:db (update-in db
[:communities community-id]
assoc
:previous-permission-addresses selected-permission-addresses
:airdrop-address (if (contains? selected-permission-addresses
current-airdrop-address)
current-airdrop-address
(:address (first selected-accounts))))})))
[{:keys [db]}]
(let [accounts (get-in db [:wallet :accounts])
sorted-accounts (sort-by :position (vals accounts))
selected-permission-addresses (get-in db [:communities/selected-permission-addresses])
selected-accounts (filter #(contains? selected-permission-addresses
(:address %))
sorted-accounts)
current-airdrop-address (get-in db [:communities/airdrop-address])]
{:db (assoc db
:communities/previous-permission-addresses selected-permission-addresses
:communities/airdrop-address (if (contains? selected-permission-addresses
current-airdrop-address)
current-airdrop-address
(:address (first selected-accounts))))}))
(rf/reg-event-fx :communities/update-previous-permission-addresses
update-previous-permission-addresses)
(defn toggle-selected-permission-address
[{:keys [db]} [address community-id]]
{:db (update-in db
[:communities community-id :selected-permission-addresses]
(fn [selected-addresses]
(if (contains? selected-addresses address)
(disj selected-addresses address)
(conj selected-addresses address))))})
[{:keys [db]} [address]]
{:db (update db
:communities/selected-permission-addresses
(fn [selected-addresses]
(if (contains? selected-addresses address)
(disj selected-addresses address)
(conj selected-addresses address))))})
(rf/reg-event-fx :communities/toggle-selected-permission-address
toggle-selected-permission-address)
(rf/reg-event-fx :communities/reset-selected-permission-addresses
(fn [{:keys [db]} [community-id]]
(when community-id
{:db (assoc-in db
[:communities community-id :selected-permission-addresses]
(get-in db [:communities community-id :previous-permission-addresses]))})))
(fn [{:keys [db]}]
{:db (assoc db
:communities/selected-permission-addresses
(get-in db [:communities/previous-permission-addresses]))}))
(rf/reg-event-fx :communities/share-community-channel-url-with-data
(fn [_ [chat-id]]
@@ -284,124 +265,5 @@
:event "share-community-channel-url-with-data"}))}]})))
(rf/reg-event-fx :communities/set-airdrop-address
(fn [{:keys [db]} [address community-id]]
{:db (assoc-in db [:communities community-id :airdrop-address] address)}))
(defn community-fetched
[{:keys [db]} [community-id community]]
(when community
{:db (update db :communities/fetching-community dissoc community-id)
:fx [[:dispatch [:communities/handle-community community]]
[:dispatch
[:chat.ui/cache-link-preview-data (link-preview.events/community-link community-id)
community]]]}))
(rf/reg-event-fx :chat.ui/community-fetched community-fetched)
(defn community-failed-to-fetch
[{:keys [db]} [community-id]]
{:db (update db :communities/fetching-community dissoc community-id)})
(rf/reg-event-fx :chat.ui/community-failed-to-fetch community-failed-to-fetch)
(defn fetch-community
[{:keys [db]} [community-id]]
(when (and community-id (not (get-in db [:communities/fetching-community community-id])))
{:db (assoc-in db [:communities/fetching-community community-id] true)
:json-rpc/call [{:method "wakuext_fetchCommunity"
:params [{:CommunityKey community-id
:TryDatabase true
:WaitForResponse true}]
:on-success (fn [community]
(rf/dispatch [:chat.ui/community-fetched community-id community]))
:on-error (fn [err]
(rf/dispatch [:chat.ui/community-failed-to-fetch community-id])
(log/error {:message
"Failed to request community info from mailserver"
:error err}))}]}))
(schema/=> fetch-community
[:=>
[:catn
[:cofx :schema.re-frame/cofx]
[:args
[:schema [:catn [:community-id [:? :string]]]]]]
[:maybe
[:map
[:db map?]
[:json-rpc/call :schema.common/rpc-call]]]])
(rf/reg-event-fx :communities/fetch-community fetch-community)
(defn spectate-community-success
[{:keys [db]} [{:keys [communities]}]]
(when-let [community (first communities)]
{:db (-> db
(assoc-in [:communities (:id community) :spectated] true)
(assoc-in [:communities (:id community) :spectating] false))
:fx [[:dispatch [:communities/handle-community community]]
[:dispatch [::mailserver/request-messages]]]}))
(rf/reg-event-fx :chat.ui/spectate-community-success spectate-community-success)
(defn spectate-community-failed
[{:keys [db]} [community-id]]
{:db (assoc-in db [:communities community-id :spectating] false)})
(rf/reg-event-fx :chat.ui/spectate-community-failed spectate-community-failed)
(defn spectate-community
[{:keys [db]} [community-id]]
(let [{:keys [spectated spectating joined]} (get-in db [:communities community-id])]
(when (and (not joined) (not spectated) (not spectating))
{:db (assoc-in db [:communities community-id :spectating] true)
:json-rpc/call [{:method "wakuext_spectateCommunity"
:params [community-id]
:on-success [:chat.ui/spectate-community-success]
:on-error (fn [err]
(log/error {:message
"Failed to spectate community"
:error err})
(rf/dispatch [:chat.ui/spectate-community-failed
community-id]))}]})))
(schema/=> spectate-community
[:=>
[:catn
[:cofx :schema.re-frame/cofx]
[:args
[:schema [:catn [:community-id [:? :string]]]]]]
[:maybe
[:map
[:db map?]
[:json-rpc/call :schema.common/rpc-call]]]])
(rf/reg-event-fx :chat.ui/spectate-community spectate-community)
(rf/defn navigate-to-serialized-community
[_ {:keys [community-id]}]
{:serialization/deserialize-and-compress-key
{:serialized-key community-id
:on-success #(rf/dispatch [:communities/navigate-to-community-overview %])
:on-error #(log/error {:message "Failed to decompress community-id"
:error %
:community-id community-id})}})
(rf/reg-event-fx :communities/navigate-to-community-overview
(fn [cofx [deserialized-key]]
(if (string/starts-with? deserialized-key constants/serialization-key)
(navigate-to-serialized-community cofx deserialized-key)
(rf/merge
cofx
{:fx [[:dispatch [:communities/fetch-community deserialized-key]]
[:dispatch [:navigate-to :community-overview deserialized-key]]]}
(navigation/pop-to-root :shell-stack)))))
(rf/reg-event-fx :communities/navigate-to-community-chat
(fn [{:keys [db]} [chat-id pop-to-root?]]
(let [{:keys [community-id]} (get-in db [:chats chat-id])]
{:fx [(when community-id
[:dispatch [:communities/fetch-community community-id]])
(if pop-to-root?
[:dispatch [:chat/pop-to-root-and-navigate-to-chat chat-id]]
[:dispatch [:chat/navigate-to-chat chat-id]])]})))
(fn [{:keys [db]} [address]]
{:db (assoc db :communities/airdrop-address address)}))
@@ -1,31 +1,25 @@
(ns status-im.contexts.communities.events-test
(:require [cljs.test :refer [deftest is testing]]
[legacy.status-im.mailserver.core :as mailserver]
(:require [cljs.test :refer [deftest is]]
matcher-combinators.test
[status-im.contexts.chat.messenger.messages.link-preview.events :as link-preview.events]
[status-im.contexts.communities.events :as events]))
(def community-id "community-id")
(deftest initialize-permission-addresses-test
(let [initial-db {:db {:wallet {:accounts {"0x1" {:address "0x1"
:position 0}
"0x2" {:address "0x2"
:position 1}}}}}
expected-db {:db (update-in (:db initial-db)
[:communities community-id]
assoc
:previous-permission-addresses #{"0x1" "0x2"}
:selected-permission-addresses #{"0x1" "0x2"}
:airdrop-address "0x1")}]
(is (match? expected-db (events/initialize-permission-addresses initial-db [community-id])))))
expected-db {:db (assoc (:db initial-db)
:communities/previous-permission-addresses #{"0x1" "0x2"}
:communities/selected-permission-addresses #{"0x1" "0x2"}
:communities/airdrop-address "0x1")}]
(is (match? expected-db (events/initialize-permission-addresses initial-db)))))
(deftest toggle-selected-permission-address-test
(let [initial-db {:db {:communities {community-id {:selected-permission-addresses #{"0x1" "0x2"}}}}}]
(is (match? {:db {:communities {community-id {:selected-permission-addresses #{"0x1"}}}}}
(events/toggle-selected-permission-address initial-db ["0x2" community-id])))
(is (match? {:db {:communities {community-id {:selected-permission-addresses #{"0x1" "0x2" "0x3"}}}}}
(events/toggle-selected-permission-address initial-db ["0x3" community-id])))))
(let [initial-db {:db {:communities/selected-permission-addresses #{"0x1" "0x2"}}}]
(is (match? {:db {:communities/selected-permission-addresses #{"0x1"}}}
(events/toggle-selected-permission-address initial-db ["0x2"])))
(is (match? {:db {:communities/selected-permission-addresses #{"0x1" "0x2" "0x3"}}}
(events/toggle-selected-permission-address initial-db ["0x3"])))))
(deftest update-previous-permission-addresses-test
(let [wallet {:accounts {"0x1" {:address "0x1"
@@ -34,162 +28,25 @@
:position 1}
"0x3" {:address "0x3"
:position 2}}}]
(let [initial-db {:db {:wallet wallet
:communities {community-id {:previous-permission-addresses #{"0x1" "0x2"}
:selected-permission-addresses #{"0x1" "0x2"
"0x3"}
:airdrop-address "0x1"}}}}
expected-db {:db {:wallet wallet
:communities {community-id {:previous-permission-addresses #{"0x1" "0x2"
"0x3"}
:selected-permission-addresses #{"0x1" "0x2"
"0x3"}
:airdrop-address "0x1"}}}}]
(let [initial-db {:db {:wallet wallet
:communities/previous-permission-addresses #{"0x1" "0x2"}
:communities/selected-permission-addresses #{"0x1" "0x2" "0x3"}
:communities/airdrop-address "0x1"}}
expected-db {:db {:wallet wallet
:communities/previous-permission-addresses #{"0x1" "0x2" "0x3"}
:communities/selected-permission-addresses #{"0x1" "0x2" "0x3"}
:communities/airdrop-address "0x1"}}]
(is
(match? expected-db
(events/update-previous-permission-addresses initial-db [community-id]))))
(let [initial-db {:db {:wallet wallet
:communities {community-id {:previous-permission-addresses #{"0x1" "0x2"}
:selected-permission-addresses #{"0x2" "0x3"}
:airdrop-address "0x1"}}}}
expected-db {:db {:wallet wallet
:communities {community-id {:previous-permission-addresses #{"0x2" "0x3"}
:selected-permission-addresses #{"0x2" "0x3"}
:airdrop-address "0x2"}}}}]
(events/update-previous-permission-addresses initial-db))))
(let [initial-db {:db {:wallet wallet
:communities/previous-permission-addresses #{"0x1" "0x2"}
:communities/selected-permission-addresses #{"0x2" "0x3"}
:communities/airdrop-address "0x1"}}
expected-db {:db {:wallet wallet
:communities/previous-permission-addresses #{"0x2" "0x3"}
:communities/selected-permission-addresses #{"0x2" "0x3"}
:communities/airdrop-address "0x2"}}]
(is
(match? expected-db
(events/update-previous-permission-addresses initial-db [community-id]))))))
(deftest fetch-community
(testing "with community id"
(testing "update fetching indicator in db"
(is (match?
{:db {:communities/fetching-community {community-id true}}}
(events/fetch-community {} [community-id]))))
(testing "call the fetch community rpc method with correct community id"
(is (match?
{:json-rpc/call [{:method "wakuext_fetchCommunity"
:params [{:CommunityKey community-id
:TryDatabase true
:WaitForResponse true}]}]}
(events/fetch-community {} [community-id])))))
(testing "with no community id"
(testing "do nothing"
(is (match?
nil
(events/fetch-community {} []))))))
(deftest community-failed-to-fetch
(testing "given a community id"
(testing "remove community id from fetching indicator in db"
(is (match?
nil
(get-in (events/community-failed-to-fetch {:db {:communities/fetching-community
{community-id true}}}
[community-id])
[:db :communities/fetching-community community-id]))))))
(deftest community-fetched
(with-redefs [link-preview.events/community-link (fn [id] (str "community-link+" id))]
(testing "given a community"
(let [cofx {:db {:communities/fetching-community {community-id true}}}
arg [community-id {:id community-id}]]
(testing "remove community id from fetching indicator in db"
(is (match?
nil
(get-in (events/community-fetched cofx arg)
[:db :communities/fetching-community community-id]))))
(testing "dispatch fxs"
(is (match?
{:fx [[:dispatch [:communities/handle-community {:id community-id}]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id community-id}]]]}
(events/community-fetched cofx arg))))))
(testing "given a joined community"
(let [cofx {:db {:communities/fetching-community {community-id true}}}
arg [community-id {:id community-id :joined true}]]
(testing "dispatch fxs, do not spectate community"
(is (match?
{:fx [[:dispatch [:communities/handle-community {:id community-id}]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id community-id}]]]}
(events/community-fetched cofx arg))))))
(testing "given a token-gated community"
(let [cofx {:db {:communities/fetching-community {community-id true}}}
arg [community-id {:id community-id :tokenPermissions [1]}]]
(testing "dispatch fxs, do not spectate community"
(is (match?
{:fx [[:dispatch [:communities/handle-community {:id community-id}]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id community-id}]]]}
(events/community-fetched cofx arg))))))
(testing "given nil community"
(testing "do nothing"
(is (match?
nil
(events/community-fetched {} [community-id nil])))))))
(deftest spectate-community
(testing "given a joined community"
(testing "do nothing"
(is (match?
nil
(events/spectate-community {:db {:communities {community-id {:joined true}}}}
[community-id])))))
(testing "given a spectated community"
(testing "do nothing"
(is (match?
nil
(events/spectate-community {:db {:communities {community-id {:spectated true}}}}
[community-id])))))
(testing "given a spectating community"
(testing "do nothing"
(is (match?
nil
(events/spectate-community {:db {:communities {community-id {:spectating true}}}}
[community-id])))))
(testing "given a community"
(testing "mark community spectating"
(is (match?
{:db {:communities {community-id {:spectating true}}}}
(events/spectate-community {:db {:communities {community-id {}}}} [community-id]))))
(testing "call spectate community rpc with correct community id"
(is (match?
{:json-rpc/call [{:method "wakuext_spectateCommunity"
:params [community-id]}]}
(events/spectate-community {:db {:communities {community-id {}}}} [community-id]))))))
(deftest spectate-community-failed
(testing "mark community spectating false"
(is (match?
{:db {:communities {community-id {:spectating false}}}}
(events/spectate-community-failed {} [community-id])))))
(deftest spectate-community-success
(testing "given communities"
(testing "mark first community spectating false"
(is (match?
{:db {:communities {community-id {:spectating false}}}}
(events/spectate-community-success {} [{:communities [{:id community-id}]}]))))
(testing "mark first community spectated true"
(is (match?
{:db {:communities {community-id {:spectated true}}}}
(events/spectate-community-success {} [{:communities [{:id community-id}]}]))))
(testing "dispatch fxs for first community"
(is (match?
{:fx [[:dispatch [:communities/handle-community {:id community-id}]]
[:dispatch [::mailserver/request-messages]]]}
(events/spectate-community-success {} [{:communities [{:id community-id}]}])))))
(testing "given empty community"
(testing "do nothing"
(is (match?
nil
(events/spectate-community-success {} [{:communities []}])))))
(testing "given nil community"
(testing "do nothing"
(is (match?
nil
(events/spectate-community-success {} []))))))
(events/update-previous-permission-addresses initial-db))))))
@@ -26,8 +26,7 @@
[quo/communities-membership-list-item
{:customization-color customization-color
:style {:padding-horizontal 20}
:on-press #(debounce/dispatch-and-chill [:communities/navigate-to-community-overview id]
500)
:on-press #(debounce/dispatch-and-chill [:navigate-to :community-overview id] 500)
:on-long-press #(rf/dispatch
[:show-bottom-sheet
{:content (fn []
@@ -144,12 +144,13 @@
(defn request-to-join-with-signatures-and-addresses
[{:keys [db]} [community-id signatures]]
(let [{:keys [airdrop-address selected-permission-addresses]} (get-in db [:communities community-id])]
(let [airdrop-address (get-in db [:communities/airdrop-address])
addresses-to-reveal (get-in db [:communities/selected-permission-addresses])]
{:fx [[:json-rpc/call
[{:method "wakuext_requestToJoinCommunity"
:params [{:communityId community-id
:signatures signatures
:addressesToReveal selected-permission-addresses
:addressesToReveal addresses-to-reveal
:airdropAddress airdrop-address}]
:js-response true
:on-success [:communities/requested-to-join]
@@ -172,7 +173,7 @@
[{:keys [db]}
[{:keys [community-id password]}]]
(let [pub-key (get-in db [:profile/profile :public-key])
addresses-to-reveal (get-in db [:communities community-id :selected-permission-addresses])]
addresses-to-reveal (get-in db [:communities/selected-permission-addresses])]
{:fx [[:json-rpc/call
[{:method "wakuext_generateJoiningCommunityRequestsForSigning"
:params [pub-key community-id addresses-to-reveal]
@@ -137,7 +137,8 @@
[quo/icon :i/info {:no-color true}]]])
(defn token-gates
[]
[{:keys [id]}]
(rf/dispatch [:communities/check-permissions-to-join-community id])
(fn [{:keys [id color]}]
(let [{:keys [can-request-access?
number-of-hold-tokens tokens]} (rf/sub [:community/token-gated-overview id])]
@@ -221,9 +222,8 @@
{:on-press (when joined-or-spectated
(fn []
(rf/dispatch [:dismiss-keyboard])
(debounce/dispatch-and-chill
[:communities/navigate-to-community-chat (str community-id id)]
1000)))
(debounce/dispatch-and-chill [:chat/navigate-to-chat (str community-id id)]
1000)))
:on-long-press #(rf/dispatch
[:show-bottom-sheet
{:content (fn []
@@ -370,10 +370,9 @@
(let [{:keys [id joined]
:as community} (rf/sub [:communities/community id])
pending? (rf/sub [:communities/my-pending-request-to-join id])]
(when community
(when joined
(rf/dispatch [:activity-center.notifications/dismiss-community-overview id]))
[community-scroll-page community pending?])))
(when joined
(rf/dispatch [:activity-center.notifications/dismiss-community-overview id]))
[community-scroll-page community pending?]))
(defn overview
[id]
@@ -1,4 +1,4 @@
(ns status-im.contexts.preview.quo.community.list-item
(ns status-im.contexts.preview.quo.list-items.community-list
(:require
[quo.core :as quo]
[quo.theme :as quo.theme]
@@ -95,7 +95,7 @@
:unread-count 5})]
(fn []
[preview/preview-container {:state state :descriptor (descriptors @state)}
[quo/community-list
[quo/community-list-item
(merge @state
{:container-style {:width 335}
:logo (resources/get-mock-image :status-logo)
@@ -41,4 +41,4 @@
:descriptor descriptor
:component-container-style {:padding-vertical 30
:padding-horizontal 15}}
[quo/user @state]])))
[quo/user-list @state]])))
+3 -2
View File
@@ -41,7 +41,6 @@
:as community-membership-list-view]
[status-im.contexts.preview.quo.community.community-stat :as community-stat]
[status-im.contexts.preview.quo.community.discover-card :as discover-card]
[status-im.contexts.preview.quo.community.list-item :as community-list-item]
[status-im.contexts.preview.quo.community.token-gating :as token-gating]
[status-im.contexts.preview.quo.counter.counter :as counter]
[status-im.contexts.preview.quo.counter.step :as step]
@@ -93,6 +92,8 @@
account-list-card]
[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.community-list :as
community-list]
[status-im.contexts.preview.quo.list-items.dapp :as dapp]
[status-im.contexts.preview.quo.list-items.preview-lists :as preview-lists]
[status-im.contexts.preview.quo.list-items.quiz-item :as quiz-item]
@@ -348,7 +349,7 @@
:component channel/view}
{:name :community-list
:options {:insets {:top? true}}
:component community-list-item/view}
:component community-list/view}
{:name :dapp
:component dapp/preview}
{:name :preview-lists
@@ -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]))
@@ -24,17 +25,29 @@
(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}]])))
+2 -5
View File
@@ -1,6 +1,5 @@
(ns status-im.contexts.profile.events
(:require
[legacy.status-im.data-store.settings :as data-store.settings]
[native-module.core :as native-module]
[re-frame.core :as re-frame]
[status-im.contexts.profile.edit.name.events]
@@ -53,10 +52,8 @@
(rf/defn update-setting-from-backup
{:events [:profile/update-setting-from-backup]}
[{:keys [db]} {:keys [backedUpSettings]}]
(let [setting (update backedUpSettings :name keyword)
{:keys [name value]} (data-store.settings/rpc->setting-value setting)]
{:db (assoc-in db [:profile/profile name] value)}))
[{:keys [db]} {{:keys [name value]} :backedUpSettings}]
{:db (assoc-in db [:profile/profile (keyword name)] value)})
(rf/defn update-profile-from-backup
{:events [:profile/update-profile-from-backup]}
@@ -1,42 +1,65 @@
(ns status-im.contexts.profile.settings.header.avatar
(:require [quo.core :as quo]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[status-im.contexts.profile.settings.header.style :as style]))
[status-im.contexts.profile.settings.header.style :as style]
["react-native-reanimated" :as animated]
))
(def scroll-animation-input-range [0 50])
(def header-extrapolation-option
#_(def header-extrapolation-option
{:extrapolateLeft "clamp"
:extrapolateRight "clamp"})
(defn f-avatar
[{:keys [scroll-y full-name online? profile-picture customization-color]}]
(let [image-scale-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[1 0.4]
header-extrapolation-option)
image-top-margin-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[0 20]
header-extrapolation-option)
image-side-margin-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[0 -20]
header-extrapolation-option)
theme (quo.theme/get-theme)]
[reanimated/view
{:style (style/avatar-container theme
image-scale-animation
image-top-margin-animation
image-side-margin-animation)}
[quo/user-avatar
{:full-name full-name
:online? online?
:profile-picture profile-picture
:status-indicator? true
:ring? true
:customization-color customization-color
:size :big}]]))
(defn f-avatar [a]
(let [sv (reanimated/use-shared-value 0)
THIS-THING (animated/useAnimatedStyle
(fn HEEEEEEY []
(js* "'worklet;'")
(js/console.log "hola")
#js{:transform #js[#js{:translateX (.-value sv)}]}
))
;image-scale-animation (reanimated/interpolate scroll-y
; scroll-animation-input-range
; [1 0.4]
; header-extrapolation-option)
;image-top-margin-animation (reanimated/interpolate scroll-y
; scroll-animation-input-range
; [0 20]
; header-extrapolation-option)
;image-side-margin-animation (reanimated/interpolate scroll-y
; scroll-animation-input-range
; [0 -20]
; header-extrapolation-option)
;theme (quo.theme/get-theme)
]
[rn/view
[quo/button {:size 56
:above :i/placeholder
:on-press (fn []
(set! (.-value sv) (reanimated/with-timing 200 #js{:duration 2000}))
)}
"Trigger change"]
[reanimated/view {:style [THIS-THING ;{:transform [{:translate-x sv}]}
{:background-color "red"
:width 20
:height 20}]
#_(style/avatar-container theme
image-scale-animation
image-top-margin-animation
image-side-margin-animation)}
#_[quo/user-avatar
{:full-name full-name
:online? online?
:profile-picture profile-picture
:status-indicator? true
:ring? true
:customization-color customization-color
:size :big}]]
]))
(defn view
[props]
@@ -71,7 +71,7 @@
[gesture/touchable-without-feedback
{:on-press (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:communities/navigate-to-community-overview community-id]))}
(rf/dispatch [:navigate-to :community-overview community-id]))}
[quo/activity-log
{:title header-text
:customization-color customization-color
@@ -197,10 +197,10 @@
(rf/dispatch [:chat/navigate-to-chat id])
(= card-type shell.constants/community-channel-card)
(rf/dispatch [:communities/navigate-to-community-chat channel-id])
(rf/dispatch [:chat/navigate-to-chat channel-id])
(= card-type shell.constants/community-card)
(rf/dispatch [:communities/navigate-to-community-overview id])))
(rf/dispatch [:navigate-to :community-overview id])))
(defn calculate-card-position-and-open-screen
[card-ref card-type id channel-id]
@@ -67,7 +67,7 @@
[]
(let [{:keys [customization-color] :as profile} (rf/sub [:profile/profile-with-image])
{:keys [address path watch-only?]} (rf/sub [:wallet/current-viewing-account])
networks (rf/sub [:wallet/network-preference-details])]
networks (rf/sub [:wallet/network-details])]
[rn/scroll-view
{:style style/about-tab
:content-container-style {:padding-bottom 20}}
@@ -18,7 +18,7 @@
:assets [assets/view]
:collectibles [collectibles/view
{:collectibles collectible-list
:on-collectible-press (fn [{:keys [id]}]
:on-collectible-press (fn [id]
(rf/dispatch [:wallet/get-collectible-details id])
(rf/dispatch [:navigate-to :wallet-collectible]))}]
:activity [activity/view]
@@ -33,7 +33,6 @@
:render-fn (fn [{:keys [preview-url] :as collectible}]
[quo/collectible
{:images [preview-url]
:on-press #(when on-collectible-press
(on-collectible-press collectible))}])}])))
:on-press #(on-collectible-press collectible)}])}])))
(def view (quo.theme/with-theme view-internal))
@@ -89,7 +89,7 @@
(rf/dispatch [:hide-bottom-sheet])
(js/setTimeout
#(rf/dispatch [:wallet/share-account
{:title share-title :content multichain-address}])
{:title share-title :content address}])
600))}
{:add-divider? (not show-account-selector?)
:icon :i/delete
@@ -65,12 +65,6 @@
"")
""))))
(defn get-crypto-decimals-count
[{:keys [market-values-per-currency]}]
(let [price (get-in market-values-per-currency [:usd :price])
one-cent-value (if (pos? price) (/ 0.01 price) 0)]
(calc-max-crypto-decimals one-cent-value)))
(defn get-standard-crypto-format
"For full details: https://github.com/status-im/status-mobile/issues/18225"
[{:keys [market-values-per-currency]} token-units]
@@ -96,13 +90,10 @@
(defn total-token-fiat-value
"Returns the total token fiat value taking into account all token's chains."
[currency {:keys [market-values-per-currency] :as token}]
(let [price (or (get-in market-values-per-currency
[currency :price])
(get-in market-values-per-currency
[constants/profile-default-currency :price])
;; NOTE: adding fallback value (zero) in case prices are
;; unavailable and to prevent crash on calculating fiat value
0)
(let [price (get-in market-values-per-currency
[currency :price]
(get-in market-values-per-currency
[constants/profile-default-currency :price]))
total-units-in-all-chains (total-token-units-in-all-chains token)]
(money/crypto->fiat total-units-in-all-chains price)))
@@ -178,12 +169,9 @@
address))
(def id->network
{constants/mainnet-chain-id :ethereum
constants/goerli-chain-id :ethereum
constants/optimism-chain-id :optimism
constants/optimism-test-chain-id :optimism
constants/arbitrum-chain-id :arbitrum
constants/arbitrum-test-chain-id :arbitrum})
{constants/mainnet-chain-id :ethereum
constants/optimism-chain-id :optimism
constants/arbitrum-chain-id :arbitrum})
(defn get-standard-fiat-format
[crypto-value currency-symbol fiat-value]
@@ -57,18 +57,11 @@
(update :balances-per-chain update-vals #(update % :raw-balance money/bignumber))
(update :balances-per-chain update-keys (comp utils.number/parse-int name))))
(defn- remove-tokens-with-empty-values
[tokens]
(remove
#(or (string/blank? (:symbol %)) (string/blank? (:name %)))
tokens))
(defn rpc->tokens
[tokens]
(-> tokens
(update-keys name)
(update-vals #(cske/transform-keys csk/->kebab-case %))
(update-vals remove-tokens-with-empty-values)
(update-vals #(mapv rpc->balances-per-chain %))))
(defn rpc->network
@@ -15,7 +15,7 @@
:assets [assets/view]
:collectibles [collectibles/view
{:collectibles collectible-list
:on-collectible-press (fn [{:keys [id]}]
:on-collectible-press (fn [id]
(rf/dispatch [:wallet/get-collectible-details id])
(rf/dispatch [:navigate-to :wallet-collectible]))}]
[activity/view])]))
@@ -67,9 +67,7 @@
(rf/reg-event-fx :wallet/send-select-token
(fn [{:keys [db]} [{:keys [token stack-id]}]]
{:db (assoc-in db [:wallet :ui :send :token] token)
:fx [[:dispatch-later
{:ms 1
:dispatch [:navigate-to-within-stack [:wallet-send-input-amount stack-id]]}]]}))
:fx [[:navigate-to-within-stack [:wallet-send-input-amount stack-id]]]}))
(rf/reg-event-fx :wallet/send-select-token-drawer
(fn [{:keys [db]} [{:keys [token]}]]
@@ -39,9 +39,7 @@
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x04371e2d9d66b82f056bc128064"
:removed false}
:wallet/wallet-send-token {:symbol :eth
:total-balance 100
:market-values-per-currency {:usd {:price 10}}}
:wallet/wallet-send-token {:symbol :eth}
:wallet/wallet-send-loading-suggested-routes? false
:wallet/wallet-send-route {:route []}
:wallet/wallet-send-suggested-routes {:candidates []}})
@@ -51,9 +49,7 @@
(h/test "Default render"
(h/setup-subs sub-mocks)
(h/render [input-amount/view
{:crypto-decimals 2
:limit-crypto 250}])
(h/render [input-amount/view {}])
(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"))
@@ -63,9 +59,9 @@
(h/setup-subs sub-mocks)
(let [on-confirm (h/mock-fn)]
(h/render [input-amount/view
{:on-confirm on-confirm
:crypto-decimals 10
:limit-crypto 1000}])
{:on-confirm on-confirm
:rate 10
:limit 1000}])
(h/fire-event :press (h/query-by-label-text :keyboard-key-1))
(h/fire-event :press (h/query-by-label-text :keyboard-key-2))
@@ -85,9 +81,9 @@
(let [on-confirm (h/mock-fn)]
(h/render [input-amount/view
{:crypto-decimals 10
:limit-crypto 1000
:on-confirm on-confirm}])
{:rate 10
:limit 1000
:on-confirm on-confirm}])
(h/fire-event :press (h/query-by-label-text :keyboard-key-1))
(h/fire-event :press (h/query-by-label-text :keyboard-key-2))
@@ -105,8 +101,8 @@
(h/test "Try to fill more than limit"
(h/setup-subs sub-mocks)
(h/render [input-amount/view
{:crypto-decimals 10
:limit-crypto 286}])
{:rate 10
:limit 286}])
(h/fire-event :press (h/query-by-label-text :keyboard-key-2))
(h/fire-event :press (h/query-by-label-text :keyboard-key-9))
@@ -122,9 +118,9 @@
(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 #()}])
{:rate 10
:limit 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))
@@ -140,9 +136,9 @@
(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
:on-confirm #()}])
{:rate 10
:limit 250
: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))
@@ -153,7 +149,7 @@
(.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"))))
(h/wait-for #(h/get-by-text "205.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/get-by-text "205.50 ETH")))))))
@@ -7,7 +7,6 @@
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.send.input-amount.style :as style]
[status-im.contexts.wallet.send.routes.view :as routes]
[utils.debounce :as debounce]
@@ -62,18 +61,15 @@
(map first)))
(defn- f-view-internal
;; crypto-decimals and limit-crypto args are needed for component tests only
[{:keys [crypto-decimals limit-crypto]}]
[{:keys [rate limit]}]
(let [bottom (safe-area/get-bottom)
{:keys [currency]} (rf/sub [:profile/profile])
token (rf/sub [:wallet/wallet-send-token])
loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
token-symbol (:symbol token)
limit-crypto (or limit-crypto
(utils/get-standard-crypto-format token (:total-balance token)))
conversion-rate (get-in token [:market-values-per-currency :usd :price])
limit-fiat (.toFixed (* (:total-balance token) conversion-rate) 2)
crypto-decimals (or crypto-decimals (utils/get-crypto-decimals-count token))
limit-crypto (or (:total-balance token) limit)
conversion-rate (or rate 10)
limit-fiat (* limit-crypto conversion-rate)
input-value (reagent/atom "")
current-limit (reagent/atom {:amount limit-crypto
:currency token-symbol})
@@ -144,7 +140,6 @@
{:container-style style/input-container
:token token-symbol
:currency currency
:crypto-decimals crypto-decimals
:networks (:networks token)
:title (i18n/label :t/send-limit {:limit limit-label})
:conversion conversion-rate
+7 -3
View File
@@ -81,12 +81,16 @@
(def transparent-screen-options
(merge
(statusbar-and-navbar-root)
{:modalPresentationStyle :overCurrentContext
:theme :dark
:layout {:componentBackgroundColor :transparent
:orientation ["portrait"]
:backgroundColor :transparent}}))
:backgroundColor :transparent}}
(if platform/android?
{:statusBar {:backgroundColor :transparent
:style :light
:drawBehind true}}
{:statusBar {:style :light}})))
(def sheet-options
{:layout {:componentBackgroundColor :transparent
@@ -101,7 +105,7 @@
{})})
(def dark-screen
(merge (statusbar-and-navbar-root)
(merge (statusbar true)
{:theme :dark
:layout {:componentBackgroundColor colors/neutral-95
:orientation ["portrait"]
+20 -30
View File
@@ -119,7 +119,7 @@
:component lightbox/lightbox}
{:name :photo-selector
:options (merge {:sheet? true} (options/statusbar-and-navbar-root))
:options {:sheet? true}
:component photo-selector/photo-selector}
{:name :camera-screen
@@ -202,17 +202,14 @@
:component create-password/create-password}
{:name :enable-biometrics
:options (merge
(options/statusbar-and-navbar-root)
{:theme :dark
:layout options/onboarding-transparent-layout
:animations (merge
transitions/new-to-status-modal-animations
transitions/push-animations-for-transparent-background)
:popGesture false
:modalPresentationStyle :overCurrentContext
:hardwareBackButton {:dismissModalOnPress false
:popStackOnPress false}})
:options {:theme :dark
:layout options/onboarding-transparent-layout
:animations (merge transitions/new-to-status-modal-animations
transitions/push-animations-for-transparent-background)
:popGesture false
:modalPresentationStyle :overCurrentContext
:hardwareBackButton {:dismissModalOnPress false
:popStackOnPress false}}
:component enable-biometrics/view}
{:name :generating-keys
@@ -232,14 +229,11 @@
:component enter-seed-phrase/enter-seed-phrase}
{:name :enable-notifications
:options (merge
(options/statusbar-and-navbar-root)
{:theme :dark
:layout options/onboarding-transparent-layout
:animations (merge
transitions/new-to-status-modal-animations
transitions/push-animations-for-transparent-background)
:modalPresentationStyle :overCurrentContext})
:options {:theme :dark
:layout options/onboarding-transparent-layout
:animations (merge transitions/new-to-status-modal-animations
transitions/push-animations-for-transparent-background)
:modalPresentationStyle :overCurrentContext}
:component enable-notifications/view}
{:name :identifiers
@@ -270,11 +264,9 @@
:component sign-in/view}
{:name :syncing-progress
:options (merge
(options/statusbar-and-navbar-root)
{:theme :dark
:layout options/onboarding-layout
:popGesture false})
:options {:theme :dark
:layout options/onboarding-layout
:popGesture false}
:component syncing-devices/view}
{:name :syncing-progress-intro
@@ -289,11 +281,9 @@
:component syncing-results/view}
{:name :welcome
:options (merge
(options/statusbar-and-navbar-root)
{:theme :dark
:layout options/onboarding-transparent-layout
:animations transitions/push-animations-for-transparent-background})
:options {:theme :dark
:layout options/onboarding-transparent-layout
:animations transitions/push-animations-for-transparent-background}
:component welcome/view}
{:name :emoji-picker
+9 -25
View File
@@ -8,7 +8,7 @@
(re-frame/reg-sub
:communities/fetching-community
:<- [:communities/fetching-community]
:<- [:communities/resolve-community-info]
(fn [info [_ id]]
(get info id)))
@@ -337,31 +337,15 @@
(get-in communities [community-id :intro-message])))
(re-frame/reg-sub
:communities/selected-permission-addresses
(fn [[_ community-id]]
[(re-frame/subscribe [:communities/community community-id])])
(fn [[{:keys [selected-permission-addresses]}] _]
selected-permission-addresses))
:communities/airdrop-account
:<- [:communities/airdrop-address]
:<- [:wallet/accounts-with-customization-color]
(fn [[airdrop-address accounts]]
(first (filter #(= (:address %) airdrop-address) accounts))))
(re-frame/reg-sub
:communities/selected-permission-accounts
(fn [[_ community-id]]
[(re-frame/subscribe [:wallet/accounts-with-customization-color])
(re-frame/subscribe [:communities/selected-permission-addresses community-id])])
(fn [[accounts selected-permission-addresses]]
:<- [:communities/selected-permission-addresses]
:<- [:wallet/accounts-with-customization-color]
(fn [[selected-permission-addresses accounts]]
(filter #(contains? selected-permission-addresses (:address %)) accounts)))
(re-frame/reg-sub
:communities/airdrop-address
(fn [[_ community-id]]
[(re-frame/subscribe [:communities/community community-id])])
(fn [[{:keys [airdrop-address]}] _]
airdrop-address))
(re-frame/reg-sub
:communities/airdrop-account
(fn [[_ community-id]]
[(re-frame/subscribe [:wallet/accounts-with-customization-color])
(re-frame/subscribe [:communities/airdrop-address community-id])])
(fn [[accounts airdrop-address]]
(first (filter #(= (:address %) airdrop-address) accounts))))
+21 -17
View File
@@ -463,33 +463,37 @@
(h/deftest-sub :communities/airdrop-account
[sub-name]
(testing "returns airdrop account"
(swap! rf-db/app-db assoc-in [:communities community-id :airdrop-address] "0x1")
(swap! rf-db/app-db assoc
:wallet
{:accounts {"0x1" {:address "0x1"
:color :blue
:name "account1"}
"0x2" {:address "0x2"
:color :orange
:name "account2"}}})
:communities/airdrop-address
"0x1"
:wallet {:accounts {"0x1" {:address "0x1"
:color :blue
:name "account1"}
"0x2" {:address "0x2"
:color :orange
:name "account2"}}})
(is (match? {:address "0x1"
:network-preferences-names #{}
:name "account1"
:color :blue
:customization-color :blue}
(rf/sub [sub-name community-id])))))
(rf/sub [sub-name])))))
(h/deftest-sub :communities/selected-permission-accounts
[sub-name]
(testing "returns selected permission accounts"
(swap! rf-db/app-db assoc-in
[:communities community-id :selected-permission-addresses]
#{"0x1" "0x3"})
(swap! rf-db/app-db assoc
:wallet
{:accounts {"0x1" {:address "0x1" :color :blue :name "account1"}
"0x2" {:address "0x2" :color :orange :name "account2"}
"0x3" {:address "0x3" :color :purple :name "account3"}}})
:communities/selected-permission-addresses
#{"0x1" "0x3"}
:wallet {:accounts {"0x1" {:address "0x1"
:color :blue
:name "account1"}
"0x2" {:address "0x2"
:color :orange
:name "account2"}
"0x3" {:address "0x3"
:color :purple
:name "account3"}}})
(is (match? [{:address "0x1"
:color :blue
:customization-color :blue
@@ -500,4 +504,4 @@
:customization-color :purple
:network-preferences-names #{}
:name "account3"}]
(rf/sub [sub-name community-id])))))
(rf/sub [sub-name])))))
+3 -1
View File
@@ -140,11 +140,13 @@
(reg-root-key-sub :communities/channels-permissions :community-channels-permissions)
(reg-root-key-sub :communities/requests-to-join :communities/requests-to-join)
(reg-root-key-sub :communities/community-id-input :communities/community-id-input)
(reg-root-key-sub :communities/fetching-community :communities/fetching-community)
(reg-root-key-sub :communities/resolve-community-info :communities/resolve-community-info)
(reg-root-key-sub :communities/my-pending-requests-to-join :communities/my-pending-requests-to-join)
(reg-root-key-sub :communities/collapsed-categories :communities/collapsed-categories)
(reg-root-key-sub :communities/selected-tab :communities/selected-tab)
(reg-root-key-sub :contract-communities :contract-communities)
(reg-root-key-sub :communities/selected-permission-addresses :communities/selected-permission-addresses)
(reg-root-key-sub :communities/airdrop-address :communities/airdrop-address)
;;activity center
(reg-root-key-sub :activity-center :activity-center)
@@ -3,11 +3,11 @@
(def ^:private worklets (js/require "../src/js/worklets/chat/messenger/navigation.js"))
(defn navigation-header-opacity
[distance-from-list-top all-loaded? chat-screen-layout-calculations-complete? start-position]
[distance-from-list-top all-loaded? calculations-complete? start-position]
(.navigationHeaderOpacity ^js worklets
distance-from-list-top
all-loaded?
chat-screen-layout-calculations-complete?
calculations-complete?
start-position))
(defn navigation-header-position
@@ -3,9 +3,9 @@
(def ^:private worklets (js/require "../src/js/worklets/chat/messenger/placeholder.js"))
(defn placeholder-opacity
[chat-screen-layout-calculations-complete?]
(.placeholderOpacity ^js worklets chat-screen-layout-calculations-complete?))
[calculations-complete?]
(.placeholderOpacity ^js worklets calculations-complete?))
(defn placeholder-z-index
[chat-screen-layout-calculations-complete?]
(.placeholderZIndex ^js worklets chat-screen-layout-calculations-complete?))
[calculations-complete?]
(.placeholderZIndex ^js worklets calculations-complete?))
+3 -3
View File
@@ -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.2",
"commit-sha1": "5cb1972261de90fee1469ae60ffb7f25900a9850",
"src-sha256": "1z37yinlxwpzprd10h2f4vzs5k2a1k85ks9lvl067lb4rqflcwny"
}
+101
View File
@@ -0,0 +1,101 @@
//import {useAnimatedStyle, useDerivedValue} from 'react-native-reanimated';
const babel = require('@babel/core');
const plugin = require('./node_modules/react-native-reanimated/plugin');
// const codeString = "goog.provide(\x27status_im.contexts.profile.settings.header.avatar\x27);\nstatus_im.contexts.profile.settings.header.avatar.f_avatar \x3d (function status_im$contexts$profile$settings$header$avatar$f_avatar(a){\nvar sv \x3d react_native.reanimated.use_shared_value.call(null,(0));\nvar THIS_THING \x3d shadow.js.shim.module$react_native_reanimated.useAnimatedStyle((function status_im$contexts$profile$settings$header$avatar$f_avatar_$_HEEEEEEY(){\n\x27worklet;\x27;\n\nconsole.log(\x22hola\x22);\n\nreturn ({\x22transform\x22: [({\x22translateX\x22: sv.value})]});\n}));\nreturn null;\n});\nstatus_im.contexts.profile.settings.header.avatar.view \x3d (function status_im$contexts$profile$settings$header$avatar$view(props){\nreturn new cljs.core.PersistentVector(null, 3, 5, cljs.core.PersistentVector.EMPTY_NODE, [new cljs.core.Keyword(null,\x22f\x3e\x22,\x22f\x3e\x22,1484564198),status_im.contexts.profile.settings.header.avatar.f_avatar,props], null);\n});\n"
//
// const fs = require('fs');
//
// function workletize(s) {
// return babel.transformSync(eval(s), {
// filename: '/dev/null', compact: false, plugins: [plugin]
// }).code
// }
//
// function extractStrings(filePath) {
// try {
// // Read the content of the file
// const fileContent = fs.readFileSync(filePath, 'utf8');
//
// // Use a regular expression to find all strings enclosed in double quotes
// const stringMatches = fileContent.match(
// /(?<!\\)"(goog\.provide\(.+?)"/g
// );
//
// // transforms the code
// const mod = stringMatches.map(workletize);
//
// // Return the array of matched strings
// return mod.filter(str => str !== "") || [];
// } catch (err) {
// console.error('Error reading the file:', err.message);
// return [];
// }
// }
//
// const filePath = './result/index.js';
// const result = extractStrings(filePath);
//
//
// console.log('Strings found in the file:');
// result.forEach((str, index) => {
// console.log(`${index + 1}: ${str}`);
// });
//
// // console.log(codeString);
//
// // transformedCode = babel.transformSync(codeString, {
// // filename: '/dev/null',
// // compact: false,
// // plugins: [plugin]
// // }).code
// //
// // console.log(transformedCode);
//
// // SHADOW_ENV.evalLoad
const fs = require('fs');
function transformString(inputString) {
// Customize this function based on your transformation logic
return babel.transformSync(eval(inputString), {
filename: '/dev/null', compact: false, plugins: [plugin]
}).code
}
function processFile(filePath) {
try {
// Read the content of the file
let fileContent = fs.readFileSync(filePath, 'utf8');
// Use a regular expression to find strings in the file
const stringMatches = fileContent.match(
/(?<!\\)"(goog\.provide\(.+?)"/g
);
// Apply the transformation function to each matched string
if (stringMatches) {
stringMatches.forEach(match => {
if (match.indexOf("HEEEEEEY") !== -1){
const transformedString = transformString(match);
fileContent = fileContent.replace(match, JSON.stringify(transformedString));
}
});
// Write the modified content back to the file
fs.writeFileSync(filePath, fileContent, 'utf8');
console.log('File successfully processed.');
} else {
console.log('No strings found in the file.');
}
} catch (err) {
console.error('Error processing the file:', err.message);
}
}
// Example usage
const filePath = "./result/index.js";
processFile(filePath);
+1 -1
View File
@@ -1622,7 +1622,7 @@
"not-enough-snt": "Not enough SNT",
"add-new-contact": "Add new contact",
"add-a-contact": "Add a contact",
"enter-chat-key": "Enter chat key or scan a QR",
"enter-a-chat-key": "Add a chatkey or scan a QR",
"you-dont-have-contacts": "You dont have any contacts yet.",
"set-max": "Set max",
"continue-anyway": "Continue anyway",