Compare commits

...
Author SHA1 Message Date
Ibrkhalil 5328711e6f Bump go 2023-12-15 21:56:34 +02:00
Ibrkhalil f76e979333 Bump go 2023-12-15 21:56:34 +02:00
Ibrahem Khalil 9e6483d54a Merge branch 'develop' into fix-everyone-mention 2023-12-15 20:37:25 +02:00
Ibrkhalil 5b4026f3de bump go 2023-12-15 20:34:03 +02:00
Ibrahem Khalil f8e935c58d Close chat when closing group chat details (#18149) 2023-12-15 20:28:30 +02:00
Ajay Sivan 5507ae4fa2 Community: Request to join - Show addresses shared (#18180) 2023-12-15 09:13:32 -08:00
Volodymyr Kozieiev 2a5c102b1c Add collectible menu (#18185) 2023-12-15 15:37:08 +00:00
Parvesh Monu 9e27a36f5e Fix empty chat in opened on pressing hashtag in a community channel (#18111) 2023-12-15 18:14:08 +05:30
Ibrahem Khalil 07d8bf0d19 Share community via URL with any privileges (#18131) 2023-12-15 14:29:13 +02:00
Ajay Sivan 31dea1ca13 Quo Wallet/Required-Tokens Component (#18164) 2023-12-14 23:54:42 -08:00
Omar Basem 6f3bf98e83 Wallet: share address (#18121)
* wallet: share address
2023-12-15 08:11:06 +04:00
Mohamed Javid ed53fecf47 Added support for different currencies in wallet accounts price calculation (#18078)
This commit:

- adds support for different currencies in token price calculation in the new wallet UI.
- fixes the token units and prices displayed in the individual account screen

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2023-12-15 01:08:16 +05:30
flexsurfer 16a52b38e8 move input events (#18183) 2023-12-14 16:24:36 +01:00
Ajay Sivan c1a17d9d53 Show component name in quo preview header (#18175) 2023-12-14 04:43:06 -08:00
Lungu Cristian e790f7177d Chat fixes based on design feedback (#18059)
* fix: chat header position when only a few messages

* fix: system_message add contact icon margin

* fix: fixed last grouped message vertical padding

* fix: show message user info on long press of grouped message

* feat: added mute button to chat's channel-actions

* fix: no custom color in message list background

* fix: composer placeholder color (light theme)

* draft: fix android initial chat position

* fix: scrolling chat to top changed content size

* fix: chat message list header animation and behavior

* fix: android initial chat state

* fix: adjusted the chat avatar animation position

* fix: chat content change with keyboard visible

* ref: small refactor and added some notes

* fix: removed broken require

* fix: mute label for channel chat

* fix: merge conflict fixes
2023-12-14 13:03:21 +02:00
Mohamed Javid b668e4dea4 [Feature] Wallet - Account Switcher for send flow (#18100)
This commit:

- adds another variant ("Select account" bottom sheet) of the account switcher for wallet - send flow
- adds watch-only? key in the account to prevent repetitive account type checks across the codebase

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2023-12-13 22:49:54 +05:30
Parvesh Monu 879a82c35f Add comment related to refactoring (#18171) 2023-12-13 22:05:00 +05:30
flexsurfer 0eb424bb74 Feature/clean metro logs remove old wallet UI (#18165) 2023-12-13 16:11:30 +01:00
77 changed files with 1344 additions and 694 deletions
@@ -14,6 +14,8 @@
[react-native.core :as rn]
[utils.i18n :as i18n]))
(def ^:private left-image-supported-types #{:account :keypair :default-keypair})
(defn- left-image
[{:keys [type customization-color account-avatar-emoji icon-avatar profile-picture]}]
(case type
@@ -165,13 +167,14 @@
button-disabled? account-avatar-emoji customization-color icon-avatar
profile-picture keycard? networks label]}]
[rn/view {:style style/container}
[rn/view {:style style/left-container}
[left-image
{:type type
:customization-color customization-color
:account-avatar-emoji account-avatar-emoji
:icon-avatar icon-avatar
:profile-picture profile-picture}]]
(when (left-image-supported-types type)
[rn/view {:style style/left-container}
[left-image
{:type type
:customization-color customization-color
:account-avatar-emoji account-avatar-emoji
:icon-avatar icon-avatar
:profile-picture profile-picture}]])
[rn/view {:style style/body-container}
[left-title
{:type type
@@ -71,6 +71,7 @@
(def system-message-contact-request-account-wrapper
{:flex-direction :row
:align-items :center
:margin-left 4
:flex-shrink 1})
(def system-message-contact-request-account-name
+1 -1
View File
@@ -15,7 +15,7 @@
[: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 string? map?]]
[: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])
@@ -0,0 +1,30 @@
(ns quo.components.wallet.required-tokens.component-spec
(:require
[quo.components.wallet.required-tokens.view :as required-tokens]
[test-helpers.component :as h]))
(defn render
[component]
(h/render-with-theme-provider component :light))
(h/describe "Wallet: Required Tokens"
(h/test "basic render"
(render [required-tokens/view
{:token "SNT"
:type :token
:amount 100}])
(h/is-truthy (h/get-by-label-text :wallet-required-tokens)))
(h/test "render collectible"
(render [required-tokens/view
{:type :collectible
:collectible-img-src (js/require "../resources/images/mock2/collectible.png")
:collectible-name "Diamond"}])
(h/is-truthy (h/get-by-text "Diamond")))
(h/test "render token with correct amount & symbol"
(render [required-tokens/view
{:type :token
:token "ETH"
:amount 100}])
(h/is-truthy (h/get-by-text "100 ETH"))))
@@ -0,0 +1,21 @@
(ns quo.components.wallet.required-tokens.style
(:require [quo.foundations.colors :as colors]))
(def container
{:align-items :center
:flex-direction :row})
(def collectible-img
{:width 14
:height 14
:border-radius 4})
(defn divider
[theme]
{:width 2
:height 2
:border-radius 1
:margin-left 8
:background-color (colors/theme-colors colors/neutral-40
colors/neutral-50
theme)})
@@ -0,0 +1,56 @@
(ns quo.components.wallet.required-tokens.view
(:require [quo.components.markdown.text :as text]
[quo.components.utilities.token.view :as token]
[quo.components.wallet.required-tokens.style :as style]
quo.theme
[react-native.core :as rn]
[schema.core :as schema]))
(def ?schema
[:=>
[:catn
[:props
[:map {:closed true}
[:type [:enum :token :collectible]]
[:amount {:optional true} [:maybe [:or :string :int]]]
[:token {:optional true} [:maybe :string]]
[:token-img-src {:optional true} [:maybe :schema.common/image-source]]
[:collectible-img-src {:optional true} :schema.common/image-source]
[:collectible-name {:optional true} [:maybe :string]]
[:divider? {:optional true} [:maybe :boolean]]
[:theme :schema.common/theme]
[:container-style {:optional true} [:maybe :map]]]]]
:any])
(defn- view-internal
[{:keys [type amount token token-img-src collectible-img-src collectible-name divider? theme
container-style]}]
[rn/view
{:style (merge style/container container-style)
:accessibility-label :wallet-required-tokens}
(case type
:token [token/view
(assoc (if token-img-src
{:image-source token-img-src}
{:token token})
:size
14)]
:collectible [rn/image
{:style style/collectible-img
:source collectible-img-src}]
nil)
[text/text
{:size :paragraph-2
:weight :medium
:style {:margin-left 4}}
(case type
:token (str amount " " token)
:collectible collectible-name
nil)]
(when divider?
[rn/view
{:style (style/divider theme)}])])
(def view
(quo.theme/with-theme
(schema/instrument #'view-internal ?schema)))
+2
View File
@@ -155,6 +155,7 @@
quo.components.wallet.network-link.view
quo.components.wallet.network-routing.view
quo.components.wallet.progress-bar.view
quo.components.wallet.required-tokens.view
quo.components.wallet.summary-info.view
quo.components.wallet.token-input.view
quo.components.wallet.transaction-progress.view
@@ -403,6 +404,7 @@
(def network-bridge quo.components.wallet.network-bridge.view/view)
(def network-routing quo.components.wallet.network-routing.view/view)
(def progress-bar quo.components.wallet.progress-bar.view/view)
(def required-tokens quo.components.wallet.required-tokens.view/view)
(def summary-info quo.components.wallet.summary-info.view/view)
(def network-link quo.components.wallet.network-link.view/view)
(def token-input quo.components.wallet.token-input.view/view)
+1
View File
@@ -87,6 +87,7 @@
[quo.components.wallet.network-bridge.component-spec]
[quo.components.wallet.network-routing.component-spec]
[quo.components.wallet.progress-bar.component-spec]
[quo.components.wallet.required-tokens.component-spec]
[quo.components.wallet.summary-info.component-spec]
[quo.components.wallet.token-input.component-spec]
[quo.components.wallet.transaction-progress.component-spec]
+7 -5
View File
@@ -3,8 +3,10 @@
["react-native-share" :default react-native-share]))
(defn open
[options on-success on-error]
(-> ^js react-native-share
(.open (clj->js options))
(.then on-success)
(.catch on-error)))
([options]
(open options #() #()))
([options on-success on-error]
(-> ^js react-native-share
(.open (clj->js options))
(.then on-success)
(.catch on-error))))
+7
View File
@@ -11,6 +11,12 @@
(def ^:private ?public-key
[:re #"^0x04[0-9a-f]{128}$"])
(def ^:private ?image-source
[:or
[:int]
[:map
[:uri [:maybe [:string]]]]])
(def ^:private ?rpc-call
[:sequential
{:min 1}
@@ -27,4 +33,5 @@
(registry/register ::theme ?theme)
(registry/register ::customization-color ?customization-color)
(registry/register ::public-key ?public-key)
(registry/register ::image-source ?image-source)
(registry/register ::rpc-call ?rpc-call))
+2
View File
@@ -17,6 +17,7 @@
[status-im.utils.deprecated-types :as types]
[status-im.utils.random :as random]
[status-im2.constants :as constants]
[status-im2.contexts.chat.events :as chat.events]
[status-im2.navigation.events :as navigation]
[taoensso.timbre :as log]
[utils.address :as address]
@@ -310,6 +311,7 @@
{:browser-id (:browser-id browser)}
:browser/screen-id :browser)}
(navigation/pop-to-root :shell-stack)
(chat.events/close-chat)
(navigation/change-tab :browser-stack)
(update-browser browser)
(resolve-url nil)))))
-10
View File
@@ -1,10 +0,0 @@
(ns status-im.chat.models.input-test
(:require
[cljs.test :refer-macros [deftest is]]
[status-im.chat.models.input :as input]))
(deftest text->emoji
(is (nil? (input/text->emoji nil)))
(is (= "" (input/text->emoji "")))
(is (= "test" (input/text->emoji "test")))
(is (= "word1 \uD83D\uDC4D word2" (input/text->emoji "word1 :+1: word2"))))
+15
View File
@@ -161,3 +161,18 @@
:on-error #(log/error "Error while calling wakuext_chatMentionClearMentions"
{:error %})}]}
(clear-suggestions))))
(rf/defn select-mention
{:events [:chat.ui/select-mention]}
[{:keys [db]} {:keys [primary-name searched-text match public-key] :as user}]
(let [chat-id (:current-chat-id db)
text (get-in db [:chat/inputs chat-id :input-text])
method "wakuext_chatMentionSelectMention"
params [chat-id text primary-name public-key]]
{:json-rpc/call [{:method method
:params params
:on-success #(rf/dispatch [:mention/on-select-mention-success %
primary-name match searched-text public-key])
:on-error #(rf/dispatch [:mention/on-error
{:method method
:params params} %])}]}))
+2 -1
View File
@@ -15,5 +15,6 @@
(multiaccounts.update/multiaccount-update
:currency
currency
{})
;; on changing currency, we should fetch tokens prices again
{:on-success #(rf/dispatch [:wallet/get-wallet-token])})
(prices/update-prices)))
+5 -5
View File
@@ -69,10 +69,10 @@
(rf/defn new-wallet-event
[cofx {:keys [type blockNumber accounts] :as event}]
(log/info "[wallet-subs] new-wallet-event"
"event-type" type
"blockNumber" blockNumber
"accounts" accounts)
(log/debug "[wallet-subs] new-wallet-event"
"event-type" type
"blockNumber" blockNumber
"accounts" accounts)
(case type
"new-transfers" (new-transfers cofx blockNumber accounts)
"recent-history-fetching" (recent-history-fetching-started cofx accounts)
@@ -85,4 +85,4 @@
"wallet-get-collectibles-details-done" {:fx [[:dispatch
[:wallet/get-collectible-details-done
event]]]}
(log/warn ::unknown-wallet-event :type type :event event)))
(log/debug ::unknown-wallet-event :type type :event event)))
-1
View File
@@ -10,7 +10,6 @@
status-im.bootnodes.core
status-im.browser.core
status-im.browser.permissions
status-im.chat.models.input
status-im.chat.models.loading
status-im.contact.block
status-im.currency.core
+2 -2
View File
@@ -17,7 +17,7 @@
{:events [:navigate-chat-updated]}
[cofx chat-id]
(when (get-in cofx [:db :chats chat-id])
(chat.events/navigate-to-chat cofx chat-id nil)))
(chat.events/pop-to-root-and-navigate-to-chat cofx chat-id nil)))
(rf/defn handle-chat-removed
{:events [:chat-removed]}
@@ -80,7 +80,7 @@
{:events [:group-chats/create-from-link]}
[cofx {:keys [chat-id invitation-admin chat-name]}]
(if (get-in cofx [:db :chats chat-id])
{:dispatch [:chat/navigate-to-chat chat-id]}
{:dispatch [:chat/pop-to-root-and-navigate-to-chat chat-id]}
{:json-rpc/call [{:method "wakuext_createGroupChatFromInvitation"
:params [chat-name chat-id invitation-admin]
:js-response true
+6 -14
View File
@@ -1153,26 +1153,18 @@
#(async-storage/set-item! :invalid-ens-name-seen true)))))
nil)
(re-frame/reg-fx
::enable-local-notifications
(fn []
(native-module/start-local-notifications)))
(rf/defn initialize-wallet
{:events [:wallet-legacy/initialize-wallet]}
[{:keys [db] :as cofx} accounts tokens custom-tokens
favourites scan-all-tokens? new-account?]
(rf/merge
cofx
{:db (assoc db
:profile/wallet-accounts
(rpc->accounts accounts))
;; NOTE: Local notifications should be enabled only after wallet was started
::enable-local-notifications nil
:dispatch-n [(when (or (not (utils.mobile-sync/syncing-allowed? cofx))
(chain/binance-chain? db))
[:transaction/get-fetched-transfers])]
:dispatch [:wallet/get-accounts-success accounts]}
{:db (assoc db
:profile/wallet-accounts
(rpc->accounts accounts))
:dispatch-n [(when (or (not (utils.mobile-sync/syncing-allowed? cofx))
(chain/binance-chain? db))
[:transaction/get-fetched-transfers])]}
(check-invalid-ens)
(initialize-tokens tokens custom-tokens)
(initialize-favourites favourites)
+8 -2
View File
@@ -15,6 +15,10 @@
[ids]
(string/join constants/chain-id-separator ids))
(defn add-keys-to-account
[account]
(assoc account :watch-only? (= (:type account) :watch)))
(defn rpc->account
[account]
(-> account
@@ -25,7 +29,8 @@
(update :prod-preferred-chain-ids chain-ids-string->set)
(update :test-preferred-chain-ids chain-ids-string->set)
(update :type keyword)
(update :color #(if (seq %) (keyword %) constants/account-default-customization-color))))
(update :color #(if (seq %) (keyword %) constants/account-default-customization-color))
add-keys-to-account))
(defn rpc->accounts
[accounts]
@@ -40,7 +45,8 @@
:test-preferred-chain-ids :testPreferredChainIds
:color :colorId})
(update :prodPreferredChainIds chain-ids-set->string)
(update :testPreferredChainIds chain-ids-set->string)))
(update :testPreferredChainIds chain-ids-set->string)
(dissoc :watch-only?)))
(defn <-rpc
[network]
+1 -1
View File
@@ -69,7 +69,7 @@
(rf/defn handle-community-chat
[cofx {:keys [chat-id]}]
(log/info "universal-links: handling community chat" chat-id)
{:dispatch [:chat/navigate-to-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]}]
+1
View File
@@ -105,6 +105,7 @@
(def ^:const profile-default-color :blue)
(def ^:const profile-name-max-length 24)
(def ^:const profile-default-currency :usd)
(def ^:const profile-pictures-show-to-contacts-only 1)
(def ^:const profile-pictures-show-to-everyone 2)
@@ -32,7 +32,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])
@@ -1,41 +1,25 @@
(ns status-im.chat.models.input
(:require
["emojilib" :as emojis]
[clojure.string :as string]
[goog.object :as object]
[re-frame.core :as re-frame]
[status-im.chat.models.mentions :as mentions]
[status-im.data-store.messages :as data-store-messages]
[status-im2.constants :as constants]
[status-im2.contexts.chat.composer.link-preview.events :as link-preview]
[status-im2.contexts.chat.messages.transport.events :as messages.transport]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[utils.string :as utils.string]))
(defn text->emoji
"Replaces emojis in a specified `text`"
[text]
(utils.string/safe-replace text
#":([a-z_\-+0-9]*):"
(fn [[original emoji-id]]
(if-let [emoji-map (object/get (.-lib emojis) emoji-id)]
(.-char ^js emoji-map)
original))))
;; effects
(ns status-im2.contexts.chat.composer.events
(:require [clojure.string :as string]
[status-im.chat.models.mentions :as mentions]
[status-im.data-store.messages :as data-store-messages]
[status-im2.constants :as constants]
[status-im2.contexts.chat.composer.link-preview.events :as link-preview]
[status-im2.contexts.chat.messages.transport.events :as messages.transport]
[taoensso.timbre :as log]
[utils.emojilib :as emoji]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
utils.string))
(rf/defn set-chat-input-text
"Set input text for current-chat. Takes db and input text and cofx
as arguments and returns new fx. Always clear all validation messages."
{:events [:chat.ui/set-chat-input-text]}
[{:keys [db] :as cofx} new-input chat-id]
(let [current-chat-id (or chat-id (:current-chat-id db))]
(rf/merge cofx
{:db (assoc-in db [:chat/inputs current-chat-id :input-text] (text->emoji new-input))}
(when (empty? new-input)
(mentions/clear-mentions)))))
(rf/merge
cofx
{:db (assoc-in db [:chat/inputs current-chat-id :input-text] (emoji/text->emoji new-input))}
(when (empty? new-input)
(mentions/clear-mentions)))))
(rf/defn set-input-content-height
{:events [:chat.ui/set-input-content-height]}
@@ -66,27 +50,6 @@
[{db :db} recording?]
{:db (assoc db :chats/recording? recording?)})
(rf/defn select-mention
{:events [:chat.ui/select-mention]}
[{:keys [db] :as cofx} text-input-ref {:keys [primary-name searched-text match public-key] :as user}]
(let [chat-id (:current-chat-id db)
text (get-in db [:chat/inputs chat-id :input-text])
method "wakuext_chatMentionSelectMention"
params [chat-id text primary-name public-key]]
{:json-rpc/call [{:method method
:params params
:on-success #(rf/dispatch [:mention/on-select-mention-success %
primary-name match searched-text public-key])
:on-error #(rf/dispatch [:mention/on-error
{:method method
:params params} %])}]}))
(rf/defn disable-chat-cooldown
"Turns off chat cooldown (protection against message spamming)"
{:events [:chat/disable-cooldown]}
[{:keys [db]}]
{:db (assoc db :chat/cooldown-enabled? false)})
(rf/defn reply-to-message
"Sets reference to previous chat message and focuses on input"
{:events [:chat.ui/reply-to-message]}
@@ -103,9 +66,10 @@
(rf/defn edit-message
"Sets reference to previous chat message and focuses on input"
{:events [:chat.ui/edit-message]}
[{:keys [db] :as cofx} message]
[{:keys [db]} message]
(let [current-chat-id (:current-chat-id db)
text (get-in message [:content :text])]
text (get-in message [:content :text])
text (string/replace text #"@0x00001" "@everyone")]
{:db (-> db
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message]
message)
@@ -116,21 +80,6 @@
:dispatch-n [[:chat.ui/set-chat-input-text nil current-chat-id]
[:mention/to-input-field text current-chat-id]]}))
(rf/defn show-contact-request-input
"Sets reference to previous chat message and focuses on input"
{:events [:chat.ui/send-contact-request]}
[{:keys [db]}]
(let [current-chat-id (:current-chat-id db)]
{:db (-> db
(assoc-in [:chat/inputs current-chat-id :metadata :sending-contact-request]
current-chat-id)
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message]
nil)
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message] nil)
(update-in [:chat/inputs current-chat-id :metadata]
dissoc
:sending-image))}))
(rf/defn cancel-message-reply
"Cancels stage message reply"
{:events [:chat.ui/cancel-message-reply]}
@@ -138,49 +87,6 @@
(let [current-chat-id (:current-chat-id db)]
{:db (assoc-in db [:chat/inputs current-chat-id :metadata :responding-to-message] nil)}))
(defn emoji-only-content?
"Determines if text is just an emoji"
[{:keys [text response-to]}]
(and (not response-to)
(string? text)
(re-matches constants/regx-emoji text)))
(defn build-text-message
[{:keys [db]} input-text current-chat-id]
(when-not (string/blank? input-text)
(let [{:keys [message-id]}
(get-in db [:chat/inputs current-chat-id :metadata :responding-to-message])
preferred-name (get-in db [:profile/profile :preferred-name])
emoji? (emoji-only-content? {:text input-text
:response-to message-id})]
{:chat-id current-chat-id
:content-type (if emoji?
constants/content-type-emoji
constants/content-type-text)
:text input-text
:response-to message-id
:ens-name preferred-name
:link-previews (map #(select-keys % [:url :title :description :thumbnail])
(get-in db [:chat/link-previews :unfurled]))})))
(defn build-image-messages
[{db :db} chat-id input-text]
(let [images (get-in db [:chat/inputs chat-id :metadata :sending-image])
{:keys [message-id]} (get-in db [:chat/inputs chat-id :metadata :responding-to-message])
album-id (str (random-uuid))]
(mapv (fn [[_ {:keys [resized-uri width height]}]]
{:chat-id chat-id
:album-id album-id
:content-type constants/content-type-image
:image-path (utils.string/safe-replace resized-uri #"file://" "")
:image-width width
:image-height height
:text input-text
:link-previews (map #(select-keys % [:url :title :description :thumbnail])
(get-in db [:chat/link-previews :unfurled]))
:response-to message-id})
images)))
(rf/defn clean-input
[{:keys [db] :as cofx} current-chat-id]
(rf/merge cofx
@@ -201,6 +107,50 @@
(link-preview/reset-unfurled)
(mentions/clear-mentions))))
(defn emoji-only-content?
"Determines if text is just an emoji"
[{:keys [text response-to]}]
(and (not response-to)
(string? text)
(re-matches constants/regx-emoji text)))
(defn build-image-messages
[{db :db} chat-id input-text]
(let [images (get-in db [:chat/inputs chat-id :metadata :sending-image])
{:keys [message-id]} (get-in db [:chat/inputs chat-id :metadata :responding-to-message])
album-id (str (random-uuid))]
(mapv (fn [[_ {:keys [resized-uri width height]}]]
{:chat-id chat-id
:album-id album-id
:content-type constants/content-type-image
:image-path (utils.string/safe-replace resized-uri #"file://" "")
:image-width width
:image-height height
:text input-text
:link-previews (map #(select-keys % [:url :title :description :thumbnail])
(get-in db [:chat/link-previews :unfurled]))
:response-to message-id})
images)))
(defn build-text-message
[{:keys [db]} input-text current-chat-id]
(when-not (string/blank? input-text)
(let [{:keys [message-id]}
(get-in db [:chat/inputs current-chat-id :metadata :responding-to-message])
preferred-name (get-in db [:profile/profile :preferred-name])
emoji? (emoji-only-content? {:text input-text
:response-to message-id})]
{:chat-id current-chat-id
:content-type (if emoji?
constants/content-type-emoji
constants/content-type-text)
:text input-text
:response-to message-id
:ens-name preferred-name
:link-previews (map #(select-keys % [:url :title :description :thumbnail])
(get-in db [:chat/link-previews :unfurled]))})))
(rf/defn send-messages
[{:keys [db] :as cofx} input-text current-chat-id]
(let [image-messages (build-image-messages cofx current-chat-id input-text)
@@ -214,8 +164,10 @@
(messages.transport/send-chat-messages messages)))))
(rf/defn send-audio-message
[{:keys [db] :as cofx} audio-path duration current-chat-id]
(let [{:keys [message-id]}
{:events [:chat/send-audio]}
[{:keys [db] :as cofx} audio-path duration]
(let [{:keys [current-chat-id]} db
{:keys [message-id]}
(get-in db [:chat/inputs current-chat-id :metadata :responding-to-message])]
(when-not (string/blank? audio-path)
(rf/merge
@@ -230,17 +182,6 @@
(when message-id
{:response-to message-id}))])))))
(rf/defn send-sticker-message
[cofx {:keys [hash packID pack]} current-chat-id]
(when-not (or (string/blank? hash) (and (string/blank? packID) (string/blank? pack)))
(messages.transport/send-chat-messages
cofx
[{:chat-id current-chat-id
:content-type constants/content-type-sticker
:sticker {:hash hash
:pack (int (if (string/blank? packID) pack packID))}
:text (i18n/label :t/update-to-see-sticker {"locale" "en"})}])))
(rf/defn send-edited-message
[{:keys [db]
:as cofx} text {:keys [message-id quoted-message chat-id]}]
@@ -262,79 +203,29 @@
:js-response true
:on-error #(log/error "failed to edit message " %)
:on-success (fn [result]
(re-frame/dispatch [:sanitize-messages-and-process-response
result]))}]}
(rf/dispatch [:sanitize-messages-and-process-response
result]))}]}
(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)
method "wakuext_chatMentionReplaceWithPublicKey"
params [current-chat-id input-text]]
{:json-rpc/call [{:method method
:params params
:on-error #(rf/dispatch [:mention/on-error {:method method :params params} %])
:on-success #(rf/dispatch [:mention/on-replace-with-public-key-success
{: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
(:editing-message metadata)
input-text
%])}]}))
(rf/defn on-replace-with-public-key-success
{:events [:mention/on-replace-with-public-key-success]}
(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]
(log/debug "[mentions] on-replace-with-public-key-success"
{:chat-id current-chat-id
:editing-message editing-message
:input-text input-text
:new-text new-text})
(rf/merge cofx
(if editing-message
(send-edited-message new-text editing-message)
(send-messages new-text current-chat-id))))
(rf/defn send-contact-request
{:events [:contacts/send-contact-request]}
[{:keys [db] :as cofx} public-key message]
(rf/merge cofx
{:chat.ui/clear-inputs nil
:json-rpc/call [{:method "wakuext_sendContactRequest"
:js-response true
:params [{:id public-key :message message}]
:on-error #(log/warn "failed to send a contact request" %)
:on-success #(re-frame/dispatch [:transport/message-sent %])}]}
(mentions/clear-mentions)
(clean-input (:current-chat-id db))))
(rf/defn cancel-contact-request
"Cancels contact request"
{:events [:chat.ui/cancel-contact-request]}
[{:keys [db] :as cofx}]
(let [current-chat-id (:current-chat-id db)]
(rf/merge cofx
{:db (assoc-in db [:chat/inputs current-chat-id :metadata :sending-contact-request] nil)}
(mentions/clear-mentions)
(clean-input (:current-chat-id db)))))
(rf/defn chat-send-sticker
{:events [:chat/send-sticker]}
[{{:keys [current-chat-id] :as db} :db :as cofx} {:keys [hash packID pack] :as sticker}]
(rf/merge
cofx
{:db (update db
:stickers/recent-stickers
(fn [recent]
(conj (remove #(= hash (:hash %)) recent) sticker)))
:json-rpc/call [{:method "stickers_addRecent"
:params [(int (if (string/blank? packID) pack packID)) hash]
:on-success #()}]}
(send-sticker-message sticker current-chat-id)))
(rf/defn chat-send-audio
{:events [:chat/send-audio]}
[{{:keys [current-chat-id] :as db} :db :as cofx} audio-path duration]
(send-audio-message cofx audio-path duration current-chat-id))
@@ -25,7 +25,7 @@
[user _ _ render-data]
[contact-list-item/contact-list-item
{:on-press (fn []
(rf/dispatch [:chat.ui/select-mention nil user])
(rf/dispatch [:chat.ui/select-mention user])
(update-cursor user render-data))}
user])
@@ -133,7 +133,7 @@
:max-font-size-multiplier 1
:multiline true
:placeholder (i18n/label :t/type-something)
:placeholder-text-color (colors/theme-colors colors/neutral-30 colors/neutral-50)
:placeholder-text-color (colors/theme-colors colors/neutral-40 colors/neutral-50)
:style (style/input-text props
state
{:max-height max-height
+1 -1
View File
@@ -14,5 +14,5 @@
:key-uid
(fn [stored-key-uid]
(when (= stored-key-uid key-uid)
(rf/dispatch [:chat/navigate-to-chat chat-id
(rf/dispatch [:chat/pop-to-root-and-navigate-to-chat chat-id
shell.constants/open-screen-without-animation])))))))))
+9 -3
View File
@@ -208,8 +208,6 @@
[{db :db :as cofx} chat-id animation]
(rf/merge cofx
{:dispatch [(if animation :shell/navigate-to :navigate-to) :chat chat-id animation]}
(when-not (#{:community :community-overview :shell} (:view-id db))
(navigation/pop-to-root :shell-stack))
(close-chat)
(force-close-chat chat-id)
(fn [{:keys [db]}]
@@ -218,6 +216,14 @@
#(when (group-chat? cofx chat-id)
(loading/load-chat % chat-id))))
(rf/defn pop-to-root-and-navigate-to-chat
{:events [:chat/pop-to-root-and-navigate-to-chat]}
[cofx chat-id animation]
(rf/merge
cofx
(navigation/pop-to-root :shell-stack)
(navigate-to-chat chat-id animation)))
(rf/defn handle-clear-history-response
{:events [:chat/history-cleared]}
[{:keys [db]} chat-id response]
@@ -237,7 +243,7 @@
(assoc-in [:chats chat-id] chat)
:always
(update :chats-home-list conj chat-id))
:dispatch [:chat/navigate-to-chat chat-id]}))
:dispatch [:chat/pop-to-root-and-navigate-to-chat chat-id]}))
(rf/defn decrease-unviewed-count
{:events [:chat/decrease-unviewed-count]}
@@ -20,7 +20,9 @@
:icon-only? true
:container-style {:margin-left 20}
:accessibility-label :back-button
:on-press #(rf/dispatch [:navigate-back])}
:on-press (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:chat/close]))}
:i/arrow-left])
(defn options-button
@@ -149,77 +151,84 @@
:on-press show-profile-actions}})
item]))
(defn f-group-details
[]
(fn []
(rn/use-effect (fn []
#(rf/dispatch [:chat/close])))
(let [{:keys [admins chat-id chat-name color public?
muted contacts]} (rf/sub [:chats/current-chat])
members (rf/sub [:contacts/group-members-sections])
pinned-messages (rf/sub [:chats/pinned chat-id])
current-pk (rf/sub [:multiaccount/public-key])
admin? (get admins current-pk)]
[rn/view
{:style {:flex 1
:background-color (colors/theme-colors colors/white colors/neutral-95)}}
[quo/header
{:left-component [back-button]
:right-component [options-button]
:background (colors/theme-colors colors/white colors/neutral-95)}]
[rn/view
{:style {:flex-direction :row
:margin-top 24
:padding-horizontal 20}}
[quo/group-avatar
{:customization-color color
:size :size-32}]
[quo/text
{:weight :semi-bold
:size :heading-1
:style {:margin-horizontal 8}} chat-name]
[rn/view {:style {:margin-top 8}}
[quo/icon (if public? :i/world :i/privacy)
{:size 20 :color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]]]
[rn/view {:style (style/actions-view)}
[rn/touchable-opacity
{:style (style/action-container color)
:accessibility-label :pinned-messages
:on-press (fn []
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:pin-message/show-pins-bottom-sheet chat-id]))}
[rn/view
{:style {:flex-direction :row
:justify-content :space-between}}
[quo/icon :i/pin {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[count-container (count pinned-messages) :pinned-count]]
[quo/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium}
(i18n/label :t/pinned-messages)]]
[rn/touchable-opacity
{:style (style/action-container color)
:accessibility-label :toggle-mute
:on-press #(rf/dispatch [:chat.ui/mute chat-id (not muted)
(when-not muted constants/mute-till-unmuted)])}
[quo/icon (if muted :i/muted :i/activity-center)
{:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[quo/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium}
(i18n/label (if muted :unmute-group :mute-group))]]
[rn/touchable-opacity
{:style (style/action-container color)
:accessibility-label :manage-members
:on-press (fn []
(rf/dispatch [:group/clear-added-participants])
(rf/dispatch [:group/clear-removed-members])
(rf/dispatch [:open-modal :group-add-manage-members]))}
[rn/view
{:style {:flex-direction :row
:justify-content :space-between}}
[quo/icon :i/add-user {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[count-container (count contacts) :members-count]]
[quo/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium}
(i18n/label (if admin? :t/manage-members :t/add-members))]]]
[rn/section-list
{:key-fn :title
:sticky-section-headers-enabled false
:sections members
:render-section-header-fn contacts-section-header
:render-data {:chat-id chat-id
:admin? admin?}
:render-fn contact-item-render}]])))
(defn group-details
[]
(let [{:keys [admins chat-id chat-name color public?
muted contacts]} (rf/sub [:chats/current-chat])
members (rf/sub [:contacts/group-members-sections])
pinned-messages (rf/sub [:chats/pinned chat-id])
current-pk (rf/sub [:multiaccount/public-key])
admin? (get admins current-pk)]
[rn/view
{:style {:flex 1
:background-color (colors/theme-colors colors/white colors/neutral-95)}}
[quo/header
{:left-component [back-button]
:right-component [options-button]
:background (colors/theme-colors colors/white colors/neutral-95)}]
[rn/view
{:style {:flex-direction :row
:margin-top 24
:padding-horizontal 20}}
[quo/group-avatar
{:customization-color color
:size :size-32}]
[quo/text
{:weight :semi-bold
:size :heading-1
:style {:margin-horizontal 8}} chat-name]
[rn/view {:style {:margin-top 8}}
[quo/icon (if public? :i/world :i/privacy)
{:size 20 :color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]]]
[rn/view {:style (style/actions-view)}
[rn/touchable-opacity
{:style (style/action-container color)
:accessibility-label :pinned-messages
:on-press (fn []
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:pin-message/show-pins-bottom-sheet chat-id]))}
[rn/view
{:style {:flex-direction :row
:justify-content :space-between}}
[quo/icon :i/pin {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[count-container (count pinned-messages) :pinned-count]]
[quo/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium}
(i18n/label :t/pinned-messages)]]
[rn/touchable-opacity
{:style (style/action-container color)
:accessibility-label :toggle-mute
:on-press #(rf/dispatch [:chat.ui/mute chat-id (not muted)
(when-not muted constants/mute-till-unmuted)])}
[quo/icon (if muted :i/muted :i/activity-center)
{:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[quo/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium}
(i18n/label (if muted :unmute-group :mute-group))]]
[rn/touchable-opacity
{:style (style/action-container color)
:accessibility-label :manage-members
:on-press (fn []
(rf/dispatch [:group/clear-added-participants])
(rf/dispatch [:group/clear-removed-members])
(rf/dispatch [:open-modal :group-add-manage-members]))}
[rn/view
{:style {:flex-direction :row
:justify-content :space-between}}
[quo/icon :i/add-user {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[count-container (count contacts) :members-count]]
[quo/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium}
(i18n/label (if admin? :t/manage-members :t/add-members))]]]
[rn/section-list
{:key-fn :title
:sticky-section-headers-enabled false
:sections members
:render-section-header-fn contacts-section-header
:render-data {:chat-id chat-id
:admin? admin?}
:render-fn contact-item-render}]]))
[:f> f-group-details])
@@ -16,12 +16,10 @@
(assoc :margin-top 4))))
(defn user-message-content
[{:keys [first-in-group? outgoing outgoing-status]}]
[{:keys [outgoing outgoing-status]}]
{:border-radius 16
:padding-horizontal 8
:padding-vertical (if first-in-group?
8
4)
:padding-vertical 4
:opacity (if (and outgoing (= outgoing-status :sending))
0.5
1)})
@@ -32,10 +32,11 @@
(defn avatar-container
[{:keys [content last-in-group? pinned-by quoted-message from]} show-reactions?
in-reaction-and-action-menu? in-pinned-view?]
in-reaction-and-action-menu? show-user-info? in-pinned-view?]
(if (or (and (seq (:response-to content))
quoted-message)
last-in-group?
show-user-info?
pinned-by
(not show-reactions?)
in-reaction-and-action-menu?)
@@ -54,10 +55,12 @@
from
timestamp]}
show-reactions?
in-reaction-and-action-menu?]
in-reaction-and-action-menu?
show-user-info?]
(when (or (and (seq response-to) quoted-message)
last-in-group?
pinned-by
show-user-info?
(not show-reactions?)
in-reaction-and-action-menu?)
(let [[primary-name secondary-name] (rf/sub [:contacts/contact-two-names-by-identity from])
@@ -116,7 +119,7 @@
[]
(let [show-delivery-state? (reagent/atom false)]
(fn [{:keys [message-data context keyboard-shown? show-reactions? in-reaction-and-action-menu?
theme]}]
show-user-info? theme]}]
(let [{:keys [content-type quoted-message content
outgoing outgoing-status pinned-by]} message-data
first-image (first (:album message-data))
@@ -170,7 +173,7 @@
[rn/view
{:style {:padding-horizontal 4
:flex-direction :row}}
[avatar-container message-data show-reactions? in-reaction-and-action-menu?
[avatar-container message-data show-reactions? in-reaction-and-action-menu? show-user-info?
(:in-pinned-view? context)]
(into
(if show-reactions?
@@ -180,7 +183,7 @@
:flex 1
:max-height (when-not show-reactions?
(* 0.4 height))}}
[author message-data show-reactions? in-reaction-and-action-menu?]
[author message-data show-reactions? in-reaction-and-action-menu? show-user-info?]
(condp = content-type
constants/content-type-text
[content.text/text-content message-data context]
@@ -45,12 +45,11 @@
:margin-bottom header-avatar-top-offset})
(defn header-image
[scale-animation top-margin-animation side-margin-animation]
[scale-animation side-animation bottom-animation]
(reanimated/apply-animations-to-style
{:transform [{:scale scale-animation}]
:margin-top top-margin-animation
:margin-left side-margin-animation
:margin-bottom side-margin-animation}
{:transform [{:scale scale-animation}
{:translate-x side-animation}
{:translate-y bottom-animation}]}
{:align-items :flex-start}))
(def bio
@@ -6,11 +6,11 @@
[quo.theme :as quo.theme]
[react-native.background-timer :as background-timer]
[react-native.core :as rn]
[react-native.hooks :as hooks]
[react-native.platform :as platform]
[react-native.react-native-intersection-observer :as rnio]
[react-native.reanimated :as reanimated]
[status-im.ui.screens.chat.group :as chat.group]
[status-im2.common.home.actions.view :as home.actions]
[status-im2.constants :as constants]
[status-im2.contexts.chat.composer.constants :as composer.constants]
[status-im2.contexts.chat.messages.content.view :as message]
@@ -21,12 +21,13 @@
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defonce ^:const card-border-radius 16)
(defonce ^:const threshold-percentage-to-show-floating-scroll-down-button 75)
(defonce ^:const loading-indicator-extra-spacing 250)
(defonce ^:const loading-indicator-page-loading-height 100)
(defonce ^:const scroll-animation-input-range [0 50])
(defonce ^:const min-message-height 32)
(defonce ^:const topbar-visible-scroll-y-value 85)
(defonce ^:const topbar-visible-scroll-y-value 50)
(defonce ^:const topbar-invisible-scroll-y-value 135)
(defonce ^:const minimum-scroll-y-topbar-overlaying-avatar 400)
(def root-margin-for-big-name-visibility-detector {:bottom -35})
@@ -131,36 +132,38 @@
;; https://github.com/status-im/status-mobile/issues/17426
[quo/skeleton-list (skeleton-list-props :messages parent-height platform/ios?)]])))
(defn calc-list-header-height
[insets able-to-send-message? images]
(if able-to-send-message?
(+ composer.constants/composer-default-height
jump-to.constants/floating-shell-button-height
(if (seq images) composer.constants/images-container-height 0)
(:bottom insets))
(- 70 (:bottom insets))))
(defn list-header
[insets able-to-send-message? theme]
(let [images (rf/sub [:chats/sending-image])]
[insets able-to-send-message? images theme]
(let [height (calc-list-header-height insets able-to-send-message? images)]
[rn/view
{:background-color (colors/theme-colors colors/white colors/neutral-95 theme)
:height (if able-to-send-message?
(+ composer.constants/composer-default-height
jump-to.constants/floating-shell-button-height
(if (seq images) composer.constants/images-container-height 0)
(:bottom insets))
(- 70 (:bottom insets)))}]))
:height height}]))
(defn f-list-footer-avatar
[{:keys [scroll-y display-name online? profile-picture]}]
(let [image-scale-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[1 0.5]
header-extrapolation-option)
image-top-margin-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[0 40]
header-extrapolation-option)
image-side-margin-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[0 -20]
header-extrapolation-option)]
(let [image-scale-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[1 0.5]
header-extrapolation-option)
image-bottom-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[0 56]
header-extrapolation-option)
image-side-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[0 -40]
header-extrapolation-option)]
[reanimated/view
{:style (style/header-image image-scale-animation
image-top-margin-animation
image-side-margin-animation)}
{:style (style/header-image image-scale-animation image-side-animation image-bottom-animation)}
[quo/user-avatar
{:full-name display-name
:online? online?
@@ -174,8 +177,13 @@
(defn actions
[chat-id cover-bg-color]
(let [latest-pin-text (rf/sub [:chats/last-pinned-message-text chat-id])
pins-count (rf/sub [:chats/pin-messages-count chat-id])]
(let [latest-pin-text (rf/sub [:chats/last-pinned-message-text chat-id])
pins-count (rf/sub [:chats/pin-messages-count chat-id])
{:keys [muted muted-till chat-type]} (rf/sub [:chat-by-id chat-id])
community-channel? (= constants/community-chat-type chat-type)
muted? (and muted (some? muted-till))
mute-chat-label (if community-channel? :t/mute-channel :t/mute-chat)
unmute-chat-label (if community-channel? :t/unmute-channel :t/unmute-chat)]
[quo/channel-actions
{:style {:margin-top 16}
:actions [{:accessibility-label :action-button-pinned
@@ -187,7 +195,19 @@
:on-press (fn []
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:pin-message/show-pins-bottom-sheet
chat-id]))}]}]))
chat-id]))}
{:accessibility-label :action-button-mute
:label (i18n/label (if muted
unmute-chat-label
mute-chat-label))
:color cover-bg-color
:icon (if muted? :i/muted :i/activity-center)
:on-press (fn []
(if muted?
(home.actions/unmute-chat-action chat-id)
(home.actions/mute-chat-action chat-id
chat-type
muted?)))}]}]))
(defn f-list-footer
[{:keys [chat scroll-y cover-bg-color on-layout theme messages-view-height
@@ -207,8 +227,8 @@
(rf/sub [:contacts/contact-by-address chat-id]))
photo-path (rf/sub [:chats/photo-path chat-id])
border-animation (reanimated/interpolate scroll-y
[30 125]
[14 0]
[30 50]
[card-border-radius 0]
header-extrapolation-option)]
[rn/view {:flex 1}
[rn/view
@@ -269,21 +289,23 @@
:else
[message/message message-data context keyboard-shown?])]))
(defn scroll-handler
[event scroll-y animate-topbar-opacity? on-end-reached? animate-topbar-name?]
(let [content-size-y (- (oops/oget event "nativeEvent.contentSize.height")
(oops/oget event "nativeEvent.layoutMeasurement.height"))
current-y (oops/oget event "nativeEvent.contentOffset.y")
scroll-distance (- content-size-y current-y)]
(when (and @on-end-reached? (pos? scroll-distance))
(defn use-scroll-handler
[{:keys [scroll-y-animated-value
content-size-animated-value
animate-topbar-opacity?
on-end-reached?
animate-topbar-name?]}]
(fn [new-scroll-y new-content-size]
(when (and @on-end-reached? (pos? new-scroll-y))
(reset! on-end-reached? false))
(if (< topbar-visible-scroll-y-value scroll-distance)
(if (< topbar-visible-scroll-y-value new-scroll-y)
(reset! animate-topbar-opacity? true)
(reset! animate-topbar-opacity? false))
(if (< topbar-invisible-scroll-y-value scroll-distance)
(if (< topbar-invisible-scroll-y-value new-scroll-y)
(reset! animate-topbar-name? true)
(reset! animate-topbar-name? false))
(reanimated/set-shared-value scroll-y scroll-distance)))
(reanimated/set-shared-value content-size-animated-value new-content-size)
(reanimated/set-shared-value scroll-y-animated-value (max new-scroll-y 0))))
(defn f-messages-list-content
[{:keys [chat insets scroll-y content-height cover-bg-color keyboard-shown? inner-state-atoms
@@ -297,14 +319,21 @@
[composer-active? @on-end-reached? @animate-topbar-opacity?])
(let [theme (quo.theme/use-theme-value)
{window-height :height} (rn/get-window)
{:keys [keyboard-height]} (hooks/use-keyboard)
context (rf/sub [:chats/current-chat-message-list-view-context])
messages (rf/sub [:chats/raw-chat-messages-stream (:chat-id chat)])
images (rf/sub [:chats/sending-image])
recording? (rf/sub [:chats/recording?])
all-loaded? (rf/sub [:chats/all-loaded? (:chat-id chat)])
{:keys [show-floating-scroll-down-button?
messages-scroll-y-value-initialized?
messages-view-height
messages-view-header-height]} inner-state-atoms]
messages-view-header-height]} inner-state-atoms
scroll-handler (use-scroll-handler
{:animate-topbar-name? animate-topbar-name?
:animate-topbar-opacity? animate-topbar-opacity?
:on-end-reached? on-end-reached?
:scroll-y-animated-value scroll-y
:content-size-animated-value
content-height})]
[rn/view {:style {:flex 1}}
[rnio/flat-list
{:root-margin root-margin-for-big-name-visibility-detector
@@ -312,7 +341,7 @@
:ref list-ref
:bounces false
:header [:<>
[list-header insets (:able-to-send-message? context) theme]
[list-header insets (:able-to-send-message? context) images theme]
(when (= (:chat-type chat) constants/private-group-chat-type)
[list-group-chat-header chat])]
:footer [list-footer
@@ -333,37 +362,61 @@
:insets insets}
:render-fn render-fn
:on-viewable-items-changed on-viewable-items-changed
:on-content-size-change (fn [_ y]
(if (or
(< minimum-scroll-y-topbar-overlaying-avatar
(reanimated/get-shared-value scroll-y))
(< topbar-visible-scroll-y-value
(reanimated/get-shared-value scroll-y)))
(reset! animate-topbar-opacity? true)
(reset! animate-topbar-opacity? false))
(when-not (or
(not @big-name-visible?)
(= :initial-render @big-name-visible?)
(pos? (reanimated/get-shared-value
scroll-y)))
(reset! on-end-reached? false))
;; NOTE(alwx): here we set the initial value of
;; `scroll-y` which is needed because by default the
;; chat is scrolled to the bottom and no initial
;; `on-scroll` event is getting triggered
(let [scroll-y-shared (reanimated/get-shared-value
scroll-y)
content-height-shared (reanimated/get-shared-value
content-height)]
(when (or (= scroll-y-shared 0)
(> (Math/abs (- content-height-shared y))
min-message-height))
(reanimated/set-shared-value scroll-y
(- y
window-height
(- (when keyboard-shown?
keyboard-height))))
(reanimated/set-shared-value content-height y))))
:on-content-size-change
(fn [_ y]
(if (or
(< minimum-scroll-y-topbar-overlaying-avatar
(reanimated/get-shared-value scroll-y))
(< topbar-visible-scroll-y-value
(reanimated/get-shared-value scroll-y)))
(reset! animate-topbar-opacity? true)
(reset! animate-topbar-opacity? false))
(when-not (or
(not @big-name-visible?)
(= :initial-render @big-name-visible?)
(pos? (reanimated/get-shared-value
scroll-y)))
(reset! on-end-reached? false))
;; NOTE(alwx): here we set the initial value of `scroll-y` which is needed because by
;; default the chat is scrolled to the bottom and no initial `on-scroll` event is getting
;; triggered. Also makes sure changes in the content size are reflected in `scroll-y` e.g.
;; incoming messages scrolling the content up, which should affect the header
;; animations/interpolations.
(let [content-size-shared (reanimated/get-shared-value
content-height)
scroll-y-shared (if
@messages-scroll-y-value-initialized?
(reanimated/get-shared-value
scroll-y)
y)
;; NOTE: when the keyboard is shown and the message list
;; doesn't fill the screen, we use a different value for
;; scroll-y, which would make sure the avatar is minimized
;; appropriately and the header is shown.
keyboard-shown-with-unfilled-list? (< y window-height)
keyboard-space (- window-height y)
keyboard-scroll-value (- y keyboard-space keyboard-space)
;; NOTE: doing the calculations as we would in `on-scroll`, so the animations
;; and interpolations are triggered properly.
content-size (- y
window-height
;; NOTE: for some reason android insets are
;; included in the content size `y`, while iOS
;; are not.
(when platform/android? (:top insets)))
current-y (max (- content-size-shared
scroll-y-shared)
0)
new-scroll-value (if keyboard-shown-with-unfilled-list?
keyboard-scroll-value
(- content-size
current-y))]
(when (and (>= new-scroll-value 0)
(or (= scroll-y-shared 0)
(> (Math/abs (- content-size-shared y))
min-message-height)))
(reset! messages-scroll-y-value-initialized? true)
(scroll-handler new-scroll-value content-size))))
:on-end-reached #(list-on-end-reached scroll-y on-end-reached?)
:on-scroll-to-index-failed identity
:scroll-indicator-insets {:top (if (:able-to-send-message? context)
@@ -378,26 +431,21 @@
:on-momentum-scroll-end state/stop-scrolling
:scroll-event-throttle 16
:on-scroll (fn [event]
(scroll-handler event
scroll-y
animate-topbar-opacity?
on-end-reached?
animate-topbar-name?)
(let [content-size-y
(- (oops/oget event "nativeEvent.contentSize.height")
(oops/oget event
"nativeEvent.layoutMeasurement.height"))
current-y (oops/oget event
"nativeEvent.contentOffset.y")
scroll-distance (- content-size-y current-y)]
(scroll-handler scroll-distance content-size-y))
(on-scroll event show-floating-scroll-down-button?))
:style
{:background-color (if all-loaded?
(colors/theme-colors
(colors/custom-color cover-bg-color
50
20)
(colors/custom-color cover-bg-color
50
40)
theme)
(colors/theme-colors
colors/white
colors/neutral-95
theme))}
:content-container-style {:justify-content :flex-end
:min-height @messages-view-height}
:style {:background-color (colors/theme-colors
colors/white
colors/neutral-95
theme)}
:inverted true
:on-layout (fn [e]
;; FIXME: the 1s timeout is to assure all effects with
@@ -99,7 +99,6 @@
[rn/view {:style (style/navigation-view chat-screen-loaded?)}
[reanimated/view
{:style (style/animated-background-view all-loaded? opacity-animation nil)}]
[reanimated/view {:style (style/animated-blur-view all-loaded? opacity-animation)}
[blur/view
{:blur-amount 20
@@ -13,6 +13,10 @@
[status-im2.contexts.chat.messages.navigation.view :as messages.navigation]
[utils.re-frame :as rf]))
;; NOTE(parvesh) - I am working on refactoring/optimization of the chat screen for performance
;; improvement. Please avoid refactoring these files. Also if you are not already working on bug
;; fixes related to the chat navigation bar, please skip them.
;; And ping me, so I can address them while refactoring
(defn f-chat
[{:keys [show-floating-scroll-down-button? animate-topbar-name?
big-name-visible? animate-topbar-opacity? on-end-reached? messages-list-on-layout-finished?]
@@ -94,13 +98,14 @@
(defn chat
[]
(let [inner-state-atoms
{:extra-keyboard-height (reagent/atom 0)
:show-floating-scroll-down-button? (reagent/atom false)
:messages-view-height (reagent/atom 0)
:messages-view-header-height (reagent/atom 0)
:animate-topbar-name? (reagent/atom false)
:big-name-visible? (reagent/atom :initial-render)
:animate-topbar-opacity? (reagent/atom false)
:on-end-reached? (reagent/atom false)
:messages-list-on-layout-finished? (reagent/atom false)}]
{:extra-keyboard-height (reagent/atom 0)
:show-floating-scroll-down-button? (reagent/atom false)
:messages-scroll-y-value-initialized? (reagent/atom false)
:messages-view-height (reagent/atom 0)
:messages-view-header-height (reagent/atom 0)
:animate-topbar-name? (reagent/atom false)
:big-name-visible? (reagent/atom :initial-render)
:animate-topbar-opacity? (reagent/atom false)
:on-end-reached? (reagent/atom false)
:messages-list-on-layout-finished? (reagent/atom false)}]
[:f> f-chat inner-state-atoms]))
@@ -62,7 +62,8 @@
[quo/category
{:list-type :settings
:data [{:title (i18n/label :t/join-as-a-member)
:on-press not-implemented/alert
:on-press #(rf/dispatch [:open-modal :addresses-for-permissions
{:community-id id}])
:description :text
:action :arrow
:label :preview
@@ -0,0 +1,22 @@
(ns status-im2.contexts.communities.actions.addresses-for-permissions.style
(:require [quo.foundations.colors :as colors]))
(def container {:flex 1})
(def account-item-container
{:font-size 30
:border-radius 16
:flex-direction :row
:border-width 1
:height 56
:padding-horizontal 12
:align-items :center
:margin-bottom 8
:gap 8
:border-color colors/neutral-90})
(def buttons
{:flex-direction :row
:gap 12
:padding-horizontal 20
:padding-vertical 12})
@@ -0,0 +1,58 @@
(ns status-im2.contexts.communities.actions.addresses-for-permissions.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im2.common.not-implemented :as not-implemented]
[status-im2.contexts.communities.actions.addresses-for-permissions.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- account-item
[item]
[rn/view
{:style style/account-item-container}
[quo/account-avatar (assoc item :size 32)]
[rn/view
[quo/text
{:size :paragraph-1
:weight :semi-bold}
(:name item)]
[quo/address-text
{:address (:address item)
:format :short}]]])
(defn view
[]
(let [{id :community-id} (rf/sub [:get-screen-params])
{:keys [name color images]} (rf/sub [:communities/community id])
accounts (->> (rf/sub [:wallet])
:accounts
vals
(map #(assoc % :customization-color (:color %))))]
[rn/safe-area-view {:style style/container}
[quo/drawer-top
{:type :context-tag
:title (i18n/label :t/addresses-for-permissions)
:community-name name
:button-icon :i/info
:on-button-press not-implemented/alert
:community-logo (get-in images [:thumbnail :uri])
:customization-color color}]
[rn/flat-list
{:render-fn account-item
:content-container-style {:padding 20}
:key-fn :key-uid
:data accounts}]
[rn/view {:style style/buttons}
[quo/button
{:type :grey
:container-style {:flex 1}
:on-press #(rf/dispatch [:navigate-back])}
(i18n/label :t/cancel)]
[quo/button
{:container-style {:flex 1}
:customization-color color
:on-press #(rf/dispatch [:navigate-back])}
(i18n/label :t/confirm-changes)]]]))
@@ -9,3 +9,7 @@
;;"node.login" signal will be triggered as a callback
(native-module/login-account
(assoc (profile.config/login) :keyUid key-uid :password hashed-password))))
(rf/reg-fx :effects.profile/enable-local-notifications
(fn []
(native-module/start-local-notifications)))
@@ -112,31 +112,29 @@
current-network-config (get networks current-network)
network-id (str (get-in networks
[current-network :config :NetworkId]))]
(rf/merge cofx
(cond-> {:json-rpc/call [{:method "wakuext_startMessenger"
:on-success #(re-frame/dispatch [:messenger-started %])
:on-error #(log/error "failed to start messenger")}]
:wallet-legacy/initialize-transactions-management-enabled nil
:wallet-legacy/initialize-wallet
[network-id
current-network-config
(fn [accounts tokens custom-tokens favourites]
(re-frame/dispatch [:wallet-legacy/initialize-wallet
accounts tokens custom-tokens favourites]))]
:check-eip1559-activation {:network-id network-id}}
(not (:universal-links/handling db))
(assoc :effects.chat/open-last-chat (get-in db [:profile/profile :key-uid]))
notifications-enabled?
(assoc :effects/push-notifications-enable nil))
(contacts/initialize-contacts)
(browser/initialize-browser)
(mobile-network/on-network-status-change)
(group-chats/get-group-chat-invitations)
(profile.settings.events/get-profile-picture)
(profile.settings.events/change-preview-privacy)
(link-preview/request-link-preview-whitelist)
(visibility-status-updates-store/fetch-visibility-status-updates-rpc)
(switcher-cards-store/fetch-switcher-cards-rpc))))
(rf/merge
cofx
(cond-> {:json-rpc/call [{:method "wakuext_startMessenger"
:on-success #(re-frame/dispatch
[:messenger-started %])
:on-error #(log/error
"failed to start messenger")}]
:check-eip1559-activation {:network-id network-id}
:effects.profile/enable-local-notifications nil
:dispatch-n [[:wallet/get-accounts]]}
(not (:universal-links/handling db))
(assoc :effects.chat/open-last-chat (get-in db [:profile/profile :key-uid]))
notifications-enabled?
(assoc :effects/push-notifications-enable nil))
(contacts/initialize-contacts)
(browser/initialize-browser)
(mobile-network/on-network-status-change)
(group-chats/get-group-chat-invitations)
(profile.settings.events/get-profile-picture)
(profile.settings.events/change-preview-privacy)
(link-preview/request-link-preview-whitelist)
(visibility-status-updates-store/fetch-visibility-status-updates-rpc)
(switcher-cards-store/fetch-switcher-cards-rpc))))
(rf/defn messenger-started
{:events [:messenger-started]}
@@ -178,6 +178,7 @@
[status-im2.contexts.quo-preview.wallet.network-link :as network-link]
[status-im2.contexts.quo-preview.wallet.network-routing :as network-routing]
[status-im2.contexts.quo-preview.wallet.progress-bar :as progress-bar]
[status-im2.contexts.quo-preview.wallet.required-tokens :as required-tokens]
[status-im2.contexts.quo-preview.wallet.summary-info :as summary-info]
[status-im2.contexts.quo-preview.wallet.token-input :as token-input]
[status-im2.contexts.quo-preview.wallet.transaction-progress :as transaction-progress]
@@ -477,6 +478,8 @@
{:name :network-link :component network-link/view}
{:name :network-routing :component network-routing/view}
{:name :progress-bar :component progress-bar/view}
{:name :required-tokens
:component required-tokens/view}
{:name :summary-info :component summary-info/view}
{:name :token-input :component token-input/view}
{:name :wallet-activity :component wallet-activity/view}
@@ -5,6 +5,7 @@
[quo.core :as quo]
[quo.foundations.colors :as colors]
[quo.theme :as quo.theme]
[re-frame.core :as rf]
[react-native.blur :as blur]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
@@ -320,9 +321,10 @@
[{:keys [title state descriptor blur? blur-dark-only?
component-container-style
blur-container-style blur-view-props blur-height show-blur-background?]
:or {blur-height 200 title "quo component"}}
:or {blur-height 200}}
& children]
(let [theme (quo.theme/use-theme-value)]
(let [theme (quo.theme/use-theme-value)
title (or title @(rf/subscribe [:view-id]))]
(rn/use-effect (fn []
(when blur-dark-only?
(if blur?
@@ -8,8 +8,7 @@
(def mock-data
[{:id 1
:type types/item
:data {:on-press (println "pressed")
:image (resources/get-mock-image :diamond)
:data {:image (resources/get-mock-image :diamond)
:image-size 21
:right-icon :i/world
:title "Trip to Bahamas"}}
@@ -0,0 +1,47 @@
(ns status-im2.contexts.quo-preview.wallet.required-tokens
(:require
[quo.core :as quo]
[reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im2.contexts.quo-preview.preview :as preview]))
(def descriptor
[{:key :type
:type :select
:options [{:key :token}
{:key :collectible}]}
{:key :divider?
:type :boolean}])
(def token-descriptor
[{:key :amount
:type :text}
{:key :token
:type :select
:options [{:key "SNT"}
{:key "ETH"}]}])
(def collectible-descriptor
[{:key :collectible-name
:type :text}])
(defn view
[]
(let
[state
(reagent/atom
{:type :token
:collectible-img-src (resources/mock-images :collectible)
:collectible-name "Collectible name"
:token "SNT"
:amount "100"
:divider? false})]
(fn []
[preview/preview-container
{:state state
:descriptor (concat descriptor
(case (:type @state)
:token token-descriptor
:collectible collectible-descriptor
nil))}
[quo/required-tokens @state]])))
@@ -14,7 +14,7 @@
[gesture/touchable-without-feedback
{:on-press (fn []
(rf/dispatch [:hide-popover])
(rf/dispatch [:chat/navigate-to-chat chat-id]))}
(rf/dispatch [:chat/pop-to-root-and-navigate-to-chat chat-id]))}
child]
child))
@@ -52,7 +52,7 @@
[gesture/touchable-without-feedback
{:on-press (fn []
(rf/dispatch [:hide-popover])
(rf/dispatch [:chat/navigate-to-chat chat-id]))}
(rf/dispatch [:chat/pop-to-root-and-navigate-to-chat chat-id]))}
[quo/activity-log
{:title (i18n/label :t/mention)
:customization-color customization-color
@@ -74,7 +74,7 @@
[gesture/touchable-without-feedback
{:on-press (fn []
(rf/dispatch [:hide-popover])
(rf/dispatch [:chat/navigate-to-chat chat-id]))}
(rf/dispatch [:chat/pop-to-root-and-navigate-to-chat chat-id]))}
[quo/activity-log
{:title (i18n/label :t/message-reply)
:customization-color customization-color
@@ -33,10 +33,6 @@
(assoc :test-ID stack-id
:icon icon
:icon-color-anim icon-color
;NOTE temporary use of on long press while we support old wallet
:on-long-press #(when (= stack-id :wallet-stack)
(swap! state/load-new-wallet? not)
(animation/bottom-tab-on-press stack-id true))
:on-press #(animation/bottom-tab-on-press stack-id true)
:accessibility-label (str (name stack-id) "-tab")
:customization-color customization-color))]))
@@ -3,7 +3,6 @@
[quo.theme :as quo.theme]
[react-native.reanimated :as reanimated]
[status-im.ui.screens.browser.stack :as browser.stack]
[status-im.ui.screens.wallet.accounts.views :as wallet.accounts]
[status-im2.contexts.chat.home.view :as chat]
[status-im2.contexts.communities.home.view :as communities]
[status-im2.contexts.shell.jump-to.components.home-stack.style :as style]
@@ -32,10 +31,7 @@
(case stack-id
:communities-stack [:f> communities/view]
:chats-stack [:f> chat/view]
;NOTE temporary while we support old wallet
:wallet-stack (if @state/load-new-wallet?
[wallet-new/view]
[wallet.accounts/accounts-overview-old])
:wallet-stack [wallet-new/view]
:browser-stack [browser.stack/browser-stack]
[:<>])])
@@ -17,5 +17,3 @@
(def load-chats-stack? (reagent/atom false))
(def load-wallet-stack? (reagent/atom false))
(def load-browser-stack? (reagent/atom false))
;NOTE temporary while we support old wallet
(def load-new-wallet? (reagent/atom true))
@@ -2,6 +2,8 @@
(:require
[quo.core :as quo]
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.share :as share]
[status-im2.contexts.profile.utils :as profile.utils]
[status-im2.contexts.wallet.account.tabs.about.style :as style]
[utils.i18n :as i18n]
@@ -9,35 +11,51 @@
(defn about-options
[]
[quo/action-drawer
[[{:icon :i/link
:accessibility-label :view-on-eth
:label (i18n/label :t/view-on-eth)
:right-icon :i/external}
{:icon :i/link
:accessibility-label :view-on-opt
:label (i18n/label :t/view-on-opt)
:right-icon :i/external}
{:icon :i/link
:accessibility-label :view-on-arb
:label (i18n/label :t/view-on-arb)
:right-icon :i/external}
{:icon :i/copy
:accessibility-label :copy-address
:label (i18n/label :t/copy-address)}
{:icon :i/qr-code
:accessibility-label :show-address-qr
:label (i18n/label :t/show-address-qr)}
{:icon :i/share
:accessibility-label :share-address
:label (i18n/label :t/share-address)}]]])
(let [{:keys [address] :as account} (rf/sub [:wallet/current-viewing-account])
share-title (str (:name account) " " (i18n/label :t/address))]
[quo/action-drawer
[[{:icon :i/link
:accessibility-label :view-on-eth
:label (i18n/label :t/view-on-eth)
:right-icon :i/external}
{:icon :i/link
:accessibility-label :view-on-opt
:label (i18n/label :t/view-on-opt)
:right-icon :i/external}
{:icon :i/link
:accessibility-label :view-on-arb
:label (i18n/label :t/view-on-arb)
:right-icon :i/external}
{:icon :i/copy
:accessibility-label :copy-address
:label (i18n/label :t/copy-address)}
{:icon :i/qr-code
:accessibility-label :show-address-qr
:label (i18n/label :t/show-address-qr)}
{:icon :i/share
:accessibility-label :share-address
:label (i18n/label :t/share-address)
:on-press (fn []
(rf/dispatch [:hide-bottom-sheet])
(js/setTimeout
#(share/open
(if platform/ios?
{:activityItemSources [{:placeholderItem {:type "text"
:content address}
:item {:default {:type "text"
:content
address}}
:linkMetadata {:title share-title}}]}
{:title share-title
:subject share-title
:message address}))
600))}]]]))
(defn view
[]
(let [{:keys [customization-color] :as profile} (rf/sub [:profile/profile-with-image])
{:keys [type address path]} (rf/sub [:wallet/current-viewing-account])
networks (rf/sub [:wallet/network-details])
watch-only? (= type :watch)]
{:keys [address path watch-only?]} (rf/sub [:wallet/current-viewing-account])
networks (rf/sub [:wallet/network-details])]
[rn/view {:style style/about-tab}
[quo/data-item
{:description :default
@@ -16,6 +16,7 @@
(case selected-tab
:assets [rn/flat-list
{:render-fn token-value/view
:style {:flex 1}
:data tokens
:content-container-style {:padding-horizontal 8}}]
:collectibles [collectibles/view]
@@ -35,12 +35,12 @@
[]
(let [selected-tab (reagent/atom first-tab-id)]
(fn []
(let [{:keys [name color balance type]} (rf/sub [:wallet/current-viewing-account])
watch-only? (= type :watch)]
(let [{:keys [name color balance watch-only?]} (rf/sub [:wallet/current-viewing-account])
currency-symbol (rf/sub [:profile/currency-symbol])]
[rn/view {:style {:flex 1}}
[account-switcher/view {:on-press #(rf/dispatch [:wallet/close-account-page])}]
[quo/account-overview
{:current-value (utils/prettify-balance balance)
{:current-value (utils/prettify-balance currency-symbol balance)
:account-name name
:account (if watch-only? :watched-address :default)
:customization-color color}]
@@ -3,6 +3,7 @@
[clojure.string :as string]
[quo.core :as quo]
[quo.foundations.resources :as quo.resources]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[status-im2.common.scroll-page.view :as scroll-page]
[status-im2.contexts.wallet.collectible.style :as style]
@@ -10,11 +11,11 @@
[utils.re-frame :as rf]))
(defn header
[{:keys [name description] :as _collectible-details} collection-image-url]
[collectible-name description collection-image-url]
[rn/view {:style style/header}
[quo/text
{:weight :semi-bold
:size :heading-1} name]
:size :heading-1} collectible-name]
[rn/view {:style style/collection-container}
[rn/view {:style style/collection-avatar-container}
[quo/collection-avatar {:image collection-image-url}]]
@@ -86,7 +87,8 @@
(let [network (rf/sub [:wallet/network-details-by-chain-id
chain-id])
network-keyword (get network :network-name)
network-name (string/capitalize (name network-keyword))]
network-name (when network-keyword
(string/capitalize (name network-keyword)))]
[rn/view
{:style style/info-container}
[rn/view {:style style/account}
@@ -110,29 +112,55 @@
:subtitle network-name
:subtitle-type :network}]]]))
(defn view
(defn collectible-actions-sheet
[]
(let [collectible (rf/sub [:wallet/last-collectible-details])
[quo/action-drawer
[[{:icon :i/messages
:accessibility-label :share-opensea-link
:label (i18n/label :t/share-opensea-link)}
{:icon :i/link
:accessibility-label :view-on-eth
:label (i18n/label :t/view-on-eth)}
{:icon :i/download
:accessibility-label :save-image-to-photos
:label (i18n/label :t/save-image-to-photos)}
{:icon :i/copy
:accessibility-label :copy-all-details
:label (i18n/label :t/copy-all-details)}
{:icon :i/share
:accessibility-label :share-details
:label (i18n/label :t/share-details)}]]])
(defn view-internal
[{:keys [theme] :as _props}]
(let [collectible (rf/sub [:wallet/last-collectible-details])
{:keys [collectible-data preview-url
collection-data]} collectible
{:keys [traits description]} collectible-data
chain-id (rf/sub [:wallet/last-collectible-chain-id])]
collection-data]} collectible
{traits :traits
collectible-name :name
description :description} collectible-data
chain-id (rf/sub [:wallet/last-collectible-chain-id])]
[scroll-page/scroll-page
{:navigate-back? true
:height 148
:page-nav-props {:type :title-description
:title name
:title collectible-name
:description description
:right-side [{:icon-name :i/options
:on-press #(js/alert "pressed")}]
:on-press #(rf/dispatch
[:show-bottom-sheet
{:content collectible-actions-sheet
:theme theme}])}]
:picture preview-url}}
[rn/view {:style style/container}
[rn/view {:style style/preview-container}
[rn/image
{:source preview-url
:style style/preview}]]
[header collectible-data (:image-url collection-data)]
[header collectible-name description (:image-url collection-data)]
[cta-buttons]
[tabs]
[info chain-id]
[traits-section traits]]]))
(def view (quo.theme/with-theme view-internal))
@@ -1,14 +1,26 @@
(ns status-im2.contexts.wallet.common.account-switcher.view
(:require [quo.core :as quo]
[status-im2.contexts.wallet.common.sheets.account-options.view :as account-options]
[status-im2.contexts.wallet.common.sheets.select-account.view :as select-account]
[utils.re-frame :as rf]))
(defn get-bottom-sheet-args
[switcher-type]
(case switcher-type
:account-options {:content account-options/view
:hide-handle? true}
:select-account {:content select-account/view}
nil))
(defn view
[{:keys [on-press accessibility-label] :or {accessibility-label :top-bar}}]
[{:keys [on-press accessibility-label icon-name switcher-type]
:or {icon-name :i/close
accessibility-label :top-bar
switcher-type :account-options}}]
(let [{:keys [color emoji]} (rf/sub [:wallet/current-viewing-account])
networks (rf/sub [:wallet/network-details])]
[quo/page-nav
{:icon-name :i/close
{:icon-name icon-name
:background :blur
:on-press on-press
:accessibility-label accessibility-label
@@ -17,6 +29,5 @@
:right-side :account-switcher
:account-switcher {:customization-color color
:on-press #(rf/dispatch [:show-bottom-sheet
{:content account-options/view
:hide-handle? true}])
(get-bottom-sheet-args switcher-type)])
:emoji emoji}}]))
@@ -0,0 +1,4 @@
(ns status-im2.contexts.wallet.common.sheets.select-account.style)
(def list-container
{:margin-horizontal 8})
@@ -0,0 +1,33 @@
(ns status-im2.contexts.wallet.common.sheets.select-account.view
(:require [quo.core :as quo]
quo.theme
[react-native.gesture :as gesture]
[status-im2.contexts.wallet.common.sheets.select-account.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- render-account-item
[{:keys [color address] :as account} _ _ {:keys [selected-account-address]}]
[quo/account-item
{:type :default
:account-props (assoc account :customization-color color)
:customization-color color
:state (if (= address selected-account-address) :selected :default)
:on-press (fn []
(rf/dispatch [:wallet/switch-current-viewing-account address])
(rf/dispatch [:hide-bottom-sheet]))}])
(defn- view-internal
[]
(let [selected-account-address (rf/sub [:wallet/current-viewing-account-address])
accounts (rf/sub [:wallet/accounts-without-watched-accounts])]
[:<>
[quo/drawer-top {:title (i18n/label :t/select-account)}]
[gesture/flat-list
{:data accounts
:render-fn render-account-item
:render-data {:selected-account-address selected-account-address}
:content-container-style style/list-container
:shows-vertical-scroll-indicator false}]]))
(def view (quo.theme/with-theme view-internal))
@@ -9,13 +9,13 @@
(first (string/split full-name #" ")))
(defn prettify-balance
[balance]
[currency-symbol balance]
(let [valid-balance? (and balance
(or (number? balance) (.-toFixed balance)))]
(as-> balance $
(if valid-balance? $ 0)
(.toFixed $ 2)
(str "$" $))))
(str currency-symbol $))))
(defn get-derivation-path
[number-of-accounts]
@@ -60,15 +60,18 @@
(defn total-token-fiat-value
"Returns the total token fiat value taking into account all token's chains."
[{:keys [market-values-per-currency] :as token}]
(let [usd-price (-> market-values-per-currency :usd :price)
[currency {:keys [market-values-per-currency] :as token}]
(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 usd-price)))
(money/crypto->fiat total-units-in-all-chains price)))
(defn calculate-balance-for-account
[{:keys [tokens] :as _account}]
[currency {:keys [tokens] :as _account}]
(->> tokens
(map total-token-fiat-value)
(map #(total-token-fiat-value currency %))
(reduce money/add)))
(defn network-list
+17 -6
View File
@@ -67,6 +67,10 @@
db
(data-store/rpc->accounts wallet-accounts))
:fx [[:dispatch [:wallet/get-wallet-token]]
[:dispatch
[:wallet/request-collectibles
{:start-at-index 0
:new-request? true}]]
(when new-account?
[:dispatch [:wallet/navigate-to-new-account navigate-to-account]])]})))
@@ -100,14 +104,21 @@
(let [addresses (->> (get-in db [:wallet :accounts])
vals
(map :address))]
{:fx [[:json-rpc/call
{:db (assoc-in db [:wallet :ui :tokens-loading?] true)
:fx [[:json-rpc/call
[{:method "wallet_getWalletToken"
:params [addresses]
:on-success [:wallet/store-wallet-token]
:on-error #(log/info "failed to get wallet token "
{:error %
:event :wallet/get-wallet-token
:params addresses})}]]]})))
:on-error [:wallet/get-wallet-token-failed addresses]}]]]})))
(rf/reg-event-fx
:wallet/get-wallet-token-failed
(fn [{:keys [db]} [params error]]
(log/info "failed to get wallet token "
{:error error
:event :wallet/get-wallet-token
:params params})
{:db (assoc-in db [:wallet :ui :tokens-loading?] false)}))
(defn- fix-balances-per-chain
[token]
@@ -269,7 +280,7 @@
:max-cache-age-seconds max-cache-age-seconds}
request-params [request-id
[(chain/chain-id db)]
(map :address (:profile/wallet-accounts db))
(keys (get-in db [:wallet :accounts]))
collectibles-filter
start-at-index
collectibles-request-batch-size
+13 -1
View File
@@ -1,4 +1,6 @@
(ns status-im2.contexts.wallet.home.style)
(ns status-im2.contexts.wallet.home.style
(:require
[react-native.safe-area :as safe-area]))
(def tabs
{:padding-horizontal 20
@@ -23,3 +25,13 @@
{:justify-content :center
:flex 1
:margin-bottom 44})
(def separator
{:width 12})
(def selected-tab-container
{:padding-horizontal 8})
(def home-container
{:margin-top (safe-area/get-top)
:flex 1})
@@ -2,8 +2,8 @@
(:require
[quo.core :as quo]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im.ui.screens.wallet.components.styles :as styles]
[status-im2.common.home.top-nav.view :as common.top-nav]
[status-im2.contexts.wallet.common.activity-tab.view :as activity]
[status-im2.contexts.wallet.common.collectibles-tab.view :as collectibles]
@@ -40,16 +40,12 @@
(defn view
[]
(rf/dispatch [:wallet/request-collectibles
{:start-at-index 0
:new-request? true}])
(let [top (safe-area/get-top)
selected-tab (reagent/atom (:id (first tabs-data)))]
(let [selected-tab (reagent/atom (:id (first tabs-data)))]
(fn []
(let [networks (rf/sub [:wallet/network-details])
account-cards-data (rf/sub [:wallet/account-cards-data])
cards (conj account-cards-data (new-account-card-data))]
[rn/view {:style {:margin-top top :flex 1}}
[rn/view {:style style/home-container}
[common.top-nav/view]
[rn/view {:style style/overview-container}
[quo/wallet-overview (temp/wallet-overview-state networks)]]
@@ -59,7 +55,7 @@
:content-container-style style/accounts-list-container
:data cards
:horizontal true
:separator [rn/view {:style {:width 12}}]
:separator [rn/view {:style styles/separator}]
:render-fn quo/account-card
:shows-horizontal-scroll-indicator false}]
[quo/tabs
@@ -73,6 +69,6 @@
{:render-fn quo/token-value
:data temp/tokens
:key :assets-list
:content-container-style {:padding-horizontal 8}}]
:content-container-style style/selected-tab-container}]
:collectibles [collectibles/view]
[activity/view])]))))
@@ -12,12 +12,33 @@
(fn [_] (val keyval)))))
(def sub-mocks
{:profile/profile {:currency :usd}
:wallet/network-details [{:source 525
:short-name "eth"
:network-name :ethereum
:chain-id 1
:related-chain-id 5}]})
{:profile/profile {:currency :usd}
:wallet/network-details [{:source 525
:short-name "eth"
:network-name :ethereum
:chain-id 1
:related-chain-id 5}]
:wallet/current-viewing-account {:path "m/44'/60'/0'/0/1"
:emoji "💎"
:key-uid "0x2f5ea39"
:address "0x1"
:wallet false
:name "Account One"
:type :generated
:watch-only? false
:chat false
:test-preferred-chain-ids #{5 420 421613}
:color :purple
:hidden false
:prod-preferred-chain-ids #{1 10 42161}
:network-preferences-names #{:ethereum :arbitrum :optimism}
:position 1
:clock 1698945829328
:created-at 1698928839000
:operable "fully"
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x04371e2d9d66b82f056bc128064"
:removed false}})
(h/describe "Send > input amount screen"
(h/test "Default render"
@@ -6,6 +6,7 @@
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im2.contexts.wallet.common.account-switcher.view :as account-switcher]
[status-im2.contexts.wallet.send.input-amount.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -101,14 +102,10 @@
#(.remove app-keyboard-listener))))
[rn/view
{:style style/screen}
[quo/page-nav
{:background :blur
:icon-name :i/arrow-left
:on-press #(rf/dispatch [:navigate-back])
:right-side :account-switcher
:account-switcher {:customization-color :yellow
:emoji "🎮"
:on-press #(js/alert "Switch account")}}]
[account-switcher/view
{:icon-name :i/arrow-left
:on-press #(rf/dispatch [:navigate-back])
:switcher-type :select-account}]
[quo/token-input
{:container-style style/input-container
:token token
@@ -128,7 +128,9 @@
{:content-container-style style/container
:keyboard-should-persist-taps :handled
:scroll-enabled false}
[account-switcher/view {:on-press on-close}]
[account-switcher/view
{:on-press on-close
:switcher-type :select-account}]
[quo/text-combinations
{:title (i18n/label :t/send-to)
:container-style style/title-container
@@ -20,7 +20,7 @@
(let [on-press #(js/alert "Not implemented yet")
total-balance-formatted (.toFixed (:total-balance token) 2)
balance-fiat-formatted (.toFixed (:total-balance-fiat token) 2)
currency-symbol "$"]
currency-symbol (rf/sub [:profile/currency-symbol])]
[quo/token-network
{:token (:symbol token)
:label (:name token)
@@ -75,7 +75,10 @@
{:content-container-style {:flex 1}
:keyboard-should-persist-taps :handled
:scroll-enabled false}
[account-switcher/view {:on-press on-close}]
[account-switcher/view
{:icon-name :i/arrow-left
:on-press on-close
:switcher-type :select-account}]
[quo/text-combinations
{:title (i18n/label :t/select-asset)
:container-style style/title-container
+1
View File
@@ -11,6 +11,7 @@
status-im2.common.theme.events
[status-im2.common.toasts.events]
[status-im2.contexts.add-new-contact.events]
status-im2.contexts.chat.composer.events
status-im2.contexts.chat.events
status-im2.contexts.chat.photo-selector.events
status-im2.contexts.communities.overview.events
+6 -9
View File
@@ -60,15 +60,12 @@
(rf/defn pop-to-root
{:events [:pop-to-root]}
[{:keys [db]} tab]
(merge
{:pop-to-root-fx tab
:db (-> db
(dissoc :shell/floating-screens)
(dissoc :shell/loaded-screens)
(assoc :view-id (or @shell.state/selected-stack-id :shell)))
:effects.shell/pop-to-root nil}
(when (:current-chat-id db)
{:dispatch-n [[:chat/close]]})))
{:pop-to-root-fx tab
:db (-> db
(dissoc :shell/floating-screens)
(dissoc :shell/loaded-screens)
(assoc :view-id (or @shell.state/selected-stack-id :shell)))
:effects.shell/pop-to-root nil})
(rf/defn init-root
{:events [:init-root]}
+6 -1
View File
@@ -11,6 +11,8 @@
[status-im2.contexts.chat.new-chat.view :as new-chat]
[status-im2.contexts.chat.photo-selector.view :as photo-selector]
[status-im2.contexts.communities.actions.accounts-selection.view :as communities.accounts-selection]
[status-im2.contexts.communities.actions.addresses-for-permissions.view :as
addresses-for-permissions]
[status-im2.contexts.communities.actions.request-to-join.view :as join-menu]
[status-im2.contexts.communities.discover.view :as communities.discover]
[status-im2.contexts.communities.overview.view :as communities.overview]
@@ -98,6 +100,10 @@
:options {:sheet? true}
:component communities.accounts-selection/view}
{:name :addresses-for-permissions
:options {:sheet? true}
:component addresses-for-permissions/view}
{:name :lightbox
:options options/lightbox
:component lightbox/lightbox}
@@ -352,4 +358,3 @@
(when config/quo-preview-enabled?
status-im-preview/main-screens)))
+14
View File
@@ -6,6 +6,7 @@
[re-frame.core :as re-frame]
[status-im.fleet.core :as fleet]
[status-im.multiaccounts.db :as multiaccounts.db]
[status-im.utils.currency :as currency]
[status-im.wallet.utils :as wallet.utils]
[status-im2.constants :as constants]
[utils.address :as address]
@@ -18,6 +19,19 @@
(fn [{:keys [customization-color]}]
(or customization-color constants/profile-default-color)))
(re-frame/reg-sub
:profile/currency
:<- [:profile/profile]
(fn [{:keys [currency]}]
(or currency constants/profile-default-currency)))
(re-frame/reg-sub
:profile/currency-symbol
:<- [:profile/currency]
(fn [currency-id]
(-> (get currency/currencies currency-id)
:symbol)))
(re-frame/reg-sub
:profile/onboarding-placeholder-avatar
:<- [:mediaserver/port]
+114
View File
@@ -0,0 +1,114 @@
(ns status-im2.subs.profile-test
(:require [cljs.test :refer [is testing use-fixtures]]
[re-frame.db :as rf-db]
status-im2.subs.root
[test-helpers.unit :as h]
[utils.re-frame :as rf]))
(use-fixtures :each
{:before #(reset! rf-db/app-db {})})
(def sample-profile
{:keycard-pairing nil
:send-push-notifications? true
:send-status-updates? true
:key-uid "0x2285f5c1ffd94ade0aa3568bff85f6c06f2860391ba65ccf56276cbc6829a22a"
:backup-enabled? true
:address "0x70F8913fbE0Ca5687F1Fb73068944d6e99B27804"
:mnemonic "lucky veteran business source debris large priority color endless answer strong pave"
:preview-privacy? true
:identicon ""
:use-mailservers? true
:signing-phrase "polo rush vest"
:url-unfurling-mode 1
:custom-bootnodes-enabled? {}
:log-level "INFO"
:profile-pictures-visibility 2
:messages-from-contacts-only false
:pinned-mailservers {}
:eip1581-address "0x15636c0aa4036b9f984e8998db085328795b26d8"
:images [{:keyUid "0x2285f5c1ffd94ade0aa3568bff85f6c06f2860391ba65ccf56276cbc6829a22a"
:type "large"
:uri "data:image/jpeg;base64,/9j/2wCEAAgGBgcGBQgHBwcJC="
:width 240
:height 240
:fileSize 15973
:resizeTarget 240
:clock 0}
{:keyUid "0x2285f5c1ffd94ade0aa3568bff85f6c06f2860391ba65ccf56276cbc6829a22a"
:type "thumbnail"
:uri "data:image/jpeg;base64,/9j/2wCEAAgGBgcGBQgHBwcJC="
:width 80
:height 240
:fileSize 2558
:resizeTarget 80
:clock 0}]
:name "Plush Shiny Songbird"
:latest-derived-path 0
:compressed-key "zQ3shS6tp3NsQT4RSUFtnTqnBQzC5kt2SZzxZmnPEiNkHetwj"
:wallet-legacy/visible-tokens {:mainnet #{:SNT}}
:kdfIterations 3200
:ens-name? false
:emoji-hash ["👮" "🧑🏿‍🏭" "📬" "👰‍♀️" "🦚" "💳" "👨🏿‍🍳" "☝️" "🤰🏾" "🍊" "☁️" "☔" "👷🏽" "🤹🏾"]
:wallet-root-address "0x704c9a261b918cb8e522f7fc2bc477c12d0c74ac"
:last-backup 1701832050
:link-previews-enabled-sites #{}
:networks/networks {}
:wakuv2-config {:Port 0
:DataDir ""
:LightClient true
:AutoUpdate true
:MaxMessageSize 0
:KeepAliveInterval 0
:Nameserver ""
:UseShardAsDefaultTopic false
:PeerExchange true
:StoreCapacity 0
:UDPPort 0
:EnableStore false
:EnableFilterFullNode false
:Enabled true
:EnableConfirmations false
:Host "0.0.0.0"
:CustomNodes {}
:FullNode false
:EnableDiscV5 true
:DiscoveryLimit 20
:StoreSeconds 0}
:current-user-visibility-status {:clock 1701798568
:text ""
:status-type 1}
:gifs/api-key ""
:currency :usd
:gifs/favorite-gifs nil
:customization-color :magenta
:default-sync-period 777600
:photo-path ""
:dapps-address "0x52fB56556A039244CED121AFB9ec829788Db78c8"
:custom-bootnodes {}
:display-name "Alisher Y"
:gifs/recent-gifs nil
:appearance 0
:link-preview-request-enabled true
:profile-pictures-show-to 2
:timestamp 1701798892
:device-name ""
:colorId 2
:networks/current-network "mainnet_rpc"
:mutual-contact-enabled? false
:public-key
"0x0445b4d3a20f9fcf95b9e669857f83a073e7fdb7b79d0ac03ffb601d6889c413fa86282a2b2bed46ecf7d499807c1567549367a4eaa2b7b925067d44562d93cfa6"
:colorHash [[3 25] [4 3] [5 4] [2 0] [1 10] [5 2] [2 4] [1 17] [3 23] [2 19] [4 1]]
:installation-id "cee7e269-1ca7-4468-a1dd-e60e5cfb0894"})
(h/deftest-sub :profile/currency
[sub-name]
(testing "returns the selected currency of user"
(swap! rf-db/app-db #(assoc % :profile/profile sample-profile))
(is (match? :usd (rf/sub [sub-name])))))
(h/deftest-sub :profile/currency-symbol
[sub-name]
(testing "returns the symbol of the user's selected currency"
(swap! rf-db/app-db #(assoc % :profile/profile sample-profile))
(is (match? "$" (rf/sub [sub-name])))))
+37 -27
View File
@@ -1,6 +1,7 @@
(ns status-im2.subs.wallet.wallet
(:require [clojure.string :as string]
[re-frame.core :as rf]
[status-im2.constants :as constants]
[status-im2.contexts.wallet.common.utils :as utils]
[utils.number]))
@@ -69,23 +70,25 @@
(rf/reg-sub
:wallet/balances
:<- [:wallet/accounts]
(fn [accounts]
:<- [:profile/currency]
(fn [[accounts currency]]
(zipmap (map :address accounts)
(map utils/calculate-balance-for-account accounts))))
(map #(utils/calculate-balance-for-account currency %) accounts))))
(rf/reg-sub
:wallet/account-cards-data
:<- [:wallet/accounts]
:<- [:wallet/balances]
:<- [:wallet/tokens-loading?]
(fn [[accounts balances tokens-loading?]]
(mapv (fn [{:keys [color address type] :as account}]
:<- [:profile/currency-symbol]
(fn [[accounts balances tokens-loading? currency-symbol]]
(mapv (fn [{:keys [color address watch-only?] :as account}]
(assoc account
:customization-color color
:type (if (= type :watch) :watch-only :empty)
:type (if watch-only? :watch-only :empty)
:on-press #(rf/dispatch [:wallet/navigate-to-account address])
:loading? tokens-loading?
:balance (utils/prettify-balance (get balances address))))
:balance (utils/prettify-balance currency-symbol (get balances address))))
accounts)))
(rf/reg-sub
@@ -124,32 +127,39 @@
(fn [[accounts current-viewing-account-address]]
(remove #(= (:address %) current-viewing-account-address) accounts)))
(rf/reg-sub
:wallet/accounts-without-watched-accounts
:<- [:wallet/accounts]
(fn [accounts]
(remove #(:watch-only? %) accounts)))
(defn- calc-token-value
[{:keys [market-values-per-currency] :as item} chain-id]
(let [crypto-value (utils/token-value-in-chain item chain-id)
market-values (:usd market-values-per-currency)
{:keys [price change-pct-24hour]} market-values
fiat-change (utils/calculate-fiat-change crypto-value change-pct-24hour)]
(when (and crypto-value (seq (:name item)))
{:token (keyword (string/lower-case (:symbol item)))
:token-name (:name item)
:state :default
:status (cond
(pos? change-pct-24hour) :positive
(neg? change-pct-24hour) :negative
:else :empty)
:customization-color :blue
:values {:crypto-value crypto-value
:fiat-value (utils/prettify-balance (* crypto-value price))
:percentage-change (.toFixed change-pct-24hour 2)
:fiat-change (utils/prettify-balance fiat-change)}})))
[{:keys [market-values-per-currency] :as token} color currency currency-symbol]
(let [token-units (utils/total-token-units-in-all-chains token)
fiat-value (utils/total-token-fiat-value currency token)
market-values (get market-values-per-currency
currency
(get market-values-per-currency
constants/profile-default-currency))
{:keys [change-pct-24hour]} market-values]
{:token (:symbol token)
:token-name (:name token)
:state :default
:status (cond
(pos? change-pct-24hour) :positive
(neg? change-pct-24hour) :negative
:else :empty)
:customization-color color
:values {:crypto-value token-units
:fiat-value (utils/prettify-balance currency-symbol fiat-value)}}))
(rf/reg-sub
:wallet/account-token-values
:<- [:wallet/current-viewing-account]
:<- [:chain-id]
(fn [[current-account chain-id]]
(mapv #(calc-token-value % chain-id) (:tokens current-account))))
:<- [:profile/currency]
:<- [:profile/currency-symbol]
(fn [[{:keys [tokens color]} currency currency-symbol]]
(mapv #(calc-token-value % color currency currency-symbol) tokens)))
(rf/reg-sub
:wallet/network-preference-details
+221 -78
View File
@@ -40,6 +40,22 @@
3 {:raw-balance (money/bignumber "<nil>") :has-error false}}
:market-values-per-currency {:usd {:price 1000}}}])
(def tokens-0x3
[{:decimals 3
:symbol "ETH"
:name "Ether"
:balances-per-chain {1 {:raw-balance (money/bignumber "5000") :has-error false}
2 {:raw-balance (money/bignumber "2000") :has-error false}
3 {:raw-balance (money/bignumber "<nil>") :has-error false}}
:market-values-per-currency {:usd {:price 200}}}
{:decimals 10
:symbol "DAI"
:name "Dai Stablecoin"
:balances-per-chain {1 {:raw-balance (money/bignumber "10000000000") :has-error false}
2 {:raw-balance (money/bignumber "0") :has-error false}
3 {:raw-balance (money/bignumber "<nil>") :has-error false}}
:market-values-per-currency {:usd {:price 1000}}}])
(def accounts
{"0x1" {:path "m/44'/60'/0'/0/0"
:emoji "😃"
@@ -48,6 +64,7 @@
:wallet false
:name "Account One"
:type :generated
:watch-only? false
:chat false
:test-preferred-chain-ids #{5 420 421613}
:color :blue
@@ -68,6 +85,7 @@
:wallet false
:name "Account Two"
:type :generated
:watch-only? false
:chat false
:test-preferred-chain-ids #{5 420 421613}
:color :purple
@@ -80,7 +98,28 @@
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x04371e2d9d66b82f056bc128064"
:removed false
:tokens tokens-0x2}})
:tokens tokens-0x2}
"0x3" {:path ""
:emoji "🎉"
:key-uid "0x2f5ea39"
:address "0x3"
:wallet false
:name "Watched Account 1"
:type :watch
:watch-only? true
:chat false
:test-preferred-chain-ids #{0}
:color :magenta
:hidden false
:prod-preferred-chain-ids #{0}
:position 2
:clock 1698945829328
:created-at 1698928839000
:operable "fully"
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x"
:removed false
:tokens tokens-0x3}})
(def network-data
{:test [{:test? true
@@ -115,10 +154,12 @@
(swap! rf-db/app-db #(assoc-in % [:wallet :accounts] accounts))
(let [result (rf/sub [sub-name])
balance-0x1 (money/bignumber 3250)
balance-0x2 (money/bignumber 2100)]
balance-0x2 (money/bignumber 2100)
balance-0x3 (money/bignumber 2400)]
(is (money/equal-to balance-0x1 (get result "0x1")))
(is (money/equal-to balance-0x2 (get result "0x2"))))))
(is (money/equal-to balance-0x2 (get result "0x2")))
(is (money/equal-to balance-0x3 (get result "0x3"))))))
(h/deftest-sub :wallet/accounts
[sub-name]
@@ -128,55 +169,81 @@
(assoc-in [:wallet :accounts] accounts)
(assoc :wallet/networks network-data)))
(is
(= (list {:path "m/44'/60'/0'/0/0"
:emoji "😃"
:key-uid "0x2f5ea39"
:address "0x1"
:wallet false
:name "Account One"
:type :generated
:chat false
:test-preferred-chain-ids #{5 420 421613}
:color :blue
:hidden false
:prod-preferred-chain-ids #{1 10 42161}
:network-preferences-names #{:ethereum :arbitrum :optimism}
:position 0
:clock 1698945829328
:created-at 1698928839000
:operable "fully"
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x04371e2d9d66b82f056bc128064"
:removed false
:tokens tokens-0x1}
{:path "m/44'/60'/0'/0/1"
:emoji "💎"
:key-uid "0x2f5ea39"
:address "0x2"
:wallet false
:name "Account Two"
:type :generated
:chat false
:test-preferred-chain-ids #{5 420 421613}
:color :purple
:hidden false
:prod-preferred-chain-ids #{1 10 42161}
:network-preferences-names #{:ethereum :arbitrum :optimism}
:position 1
:clock 1698945829328
:created-at 1698928839000
:operable "fully"
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x04371e2d9d66b82f056bc128064"
:removed false
:tokens tokens-0x2})
(rf/sub [sub-name])))))
(=
(list {:path "m/44'/60'/0'/0/0"
:emoji "😃"
:key-uid "0x2f5ea39"
:address "0x1"
:wallet false
:name "Account One"
:type :generated
:watch-only? false
:chat false
:test-preferred-chain-ids #{5 420 421613}
:color :blue
:hidden false
:prod-preferred-chain-ids #{1 10 42161}
:network-preferences-names #{:ethereum :arbitrum :optimism}
:position 0
:clock 1698945829328
:created-at 1698928839000
:operable "fully"
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x04371e2d9d66b82f056bc128064"
:removed false
:tokens tokens-0x1}
{:path "m/44'/60'/0'/0/1"
:emoji "💎"
:key-uid "0x2f5ea39"
:address "0x2"
:wallet false
:name "Account Two"
:type :generated
:watch-only? false
:chat false
:test-preferred-chain-ids #{5 420 421613}
:color :purple
:hidden false
:prod-preferred-chain-ids #{1 10 42161}
:network-preferences-names #{:ethereum :arbitrum :optimism}
:position 1
:clock 1698945829328
:created-at 1698928839000
:operable "fully"
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x04371e2d9d66b82f056bc128064"
:removed false
:tokens tokens-0x2}
{:path ""
:emoji "🎉"
:key-uid "0x2f5ea39"
:address "0x3"
:wallet false
:name "Watched Account 1"
:type :watch
:watch-only? true
:chat false
:test-preferred-chain-ids #{0}
:color :magenta
:hidden false
:prod-preferred-chain-ids #{0}
:network-preferences-names #{}
:position 2
:clock 1698945829328
:created-at 1698928839000
:operable "fully"
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x"
:removed false
:tokens tokens-0x3})
(rf/sub [sub-name])))))
(h/deftest-sub :wallet/current-viewing-account-address
[sub-name]
(testing "returns current viewing account address"
(swap! rf-db/app-db #(assoc-in % [:wallet :current-viewing-account-address] "0x1"))
(is (= "0x1" (rf/sub [sub-name])))))
(testing "returns the address of the current viewing account"
(let [viewing-address "0x1"]
(swap! rf-db/app-db #(assoc-in % [:wallet :current-viewing-account-address] viewing-address))
(is (match? viewing-address (rf/sub [sub-name]))))))
(h/deftest-sub :wallet/current-viewing-account
[sub-name]
@@ -186,6 +253,7 @@
(assoc-in [:wallet :accounts] accounts)
(assoc-in [:wallet :current-viewing-account-address] "0x1")
(assoc :wallet/networks network-data)))
(let [result (rf/sub [sub-name])]
(is
(= {:path "m/44'/60'/0'/0/0"
@@ -195,6 +263,7 @@
:wallet false
:name "Account One"
:type :generated
:watch-only? false
:chat false
:test-preferred-chain-ids #{5 420 421613}
:color :blue
@@ -216,26 +285,22 @@
(h/deftest-sub :wallet/addresses
[sub-name]
(testing "returns all addresses"
(swap! rf-db/app-db
#(-> %
(assoc-in [:wallet :accounts] accounts)
(assoc-in [:wallet :current-viewing-account-address] "0x1")))
(is
(= (set ["0x1" "0x2"])
(rf/sub [sub-name])))))
(swap! rf-db/app-db #(assoc-in % [:wallet :accounts] accounts))
(is (match? #{"0x1" "0x2" "0x3"}
(rf/sub [sub-name])))))
(h/deftest-sub :wallet/watch-address-activity-state
[sub-name]
(testing "watch address activity state with nil value"
(is (= nil (rf/sub [sub-name]))))
(is (nil? (rf/sub [sub-name]))))
(testing "watch address activity state with no-activity value"
(swap! rf-db/app-db #(assoc-in % [:wallet :ui :watch-address-activity-state] :no-activity))
(is (= :no-activity (rf/sub [sub-name]))))
(is (match? :no-activity (rf/sub [sub-name]))))
(testing "watch address activity state with has-activity value"
(swap! rf-db/app-db #(assoc-in % [:wallet :ui :watch-address-activity-state] :has-activity))
(is (= :has-activity (rf/sub [sub-name])))))
(is (match? :has-activity (rf/sub [sub-name])))))
(h/deftest-sub :wallet/accounts-without-current-viewing-account
[sub-name]
@@ -254,6 +319,7 @@
:wallet false
:name "Account One"
:type :generated
:watch-only? false
:chat false
:test-preferred-chain-ids #{5 420 421613}
:color :blue
@@ -267,7 +333,84 @@
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x04371e2d9d66b82f056bc128064"
:removed false
:tokens tokens-0x1})
:tokens tokens-0x1}
{:path ""
:emoji "🎉"
:key-uid "0x2f5ea39"
:address "0x3"
:wallet false
:name "Watched Account 1"
:type :watch
:watch-only? true
:chat false
:test-preferred-chain-ids #{0}
:color :magenta
:hidden false
:prod-preferred-chain-ids #{0}
:network-preferences-names #{}
:position 2
:clock 1698945829328
:created-at 1698928839000
:operable "fully"
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x"
:removed false
:tokens tokens-0x3})
(rf/sub [sub-name])))))
(h/deftest-sub :wallet/accounts-without-watched-accounts
[sub-name]
(testing "returns the accounts list without the watched accounts in it"
(swap! rf-db/app-db
#(-> %
(assoc-in [:wallet :accounts] accounts)
(assoc :wallet/networks network-data)))
(is
(= (list
{:path "m/44'/60'/0'/0/0"
:emoji "😃"
:key-uid "0x2f5ea39"
:address "0x1"
:wallet false
:name "Account One"
:type :generated
:watch-only? false
:chat false
:test-preferred-chain-ids #{5 420 421613}
:color :blue
:hidden false
:prod-preferred-chain-ids #{1 10 42161}
:network-preferences-names #{:ethereum :arbitrum :optimism}
:position 0
:clock 1698945829328
:created-at 1698928839000
:operable "fully"
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x04371e2d9d66b82f056bc128064"
:removed false
:tokens tokens-0x1}
{:path "m/44'/60'/0'/0/1"
:emoji "💎"
:key-uid "0x2f5ea39"
:address "0x2"
:wallet false
:name "Account Two"
:type :generated
:watch-only? false
:chat false
:test-preferred-chain-ids #{5 420 421613}
:color :purple
:hidden false
:prod-preferred-chain-ids #{1 10 42161}
:network-preferences-names #{:ethereum :arbitrum :optimism}
:position 1
:clock 1698945829328
:created-at 1698928839000
:operable "fully"
:mixedcase-address "0x7bcDfc75c431"
:public-key "0x04371e2d9d66b82f056bc128064"
:removed false
:tokens tokens-0x2})
(rf/sub [sub-name])))))
(h/deftest-sub :wallet/network-preference-details
@@ -279,21 +422,21 @@
(assoc-in [:wallet :current-viewing-account-address] "0x1")
(assoc :wallet/networks network-data)))
(is
(= [{:short-name "eth"
:network-name :ethereum
:chain-id 1
:related-chain-id nil
:layer 1}
{:short-name "arb1"
:network-name :arbitrum
:chain-id 42161
:related-chain-id nil
:layer 2}
{:short-name "opt"
:network-name :optimism
:chain-id 10
:related-chain-id nil
:layer 2}]
(->> (rf/sub [sub-name])
;; Removed `#js source` property for correct compare
(map #(dissoc % :source)))))))
(match? [{:short-name "eth"
:network-name :ethereum
:chain-id 1
:related-chain-id nil
:layer 1}
{:short-name "arb1"
:network-name :arbitrum
:chain-id 42161
:related-chain-id nil
:layer 2}
{:short-name "opt"
:network-name :optimism
:chain-id 10
:related-chain-id nil
:layer 2}]
(->> (rf/sub [sub-name])
;; Removed `#js source` property for correct compare
(map #(dissoc % :source)))))))
+19
View File
@@ -0,0 +1,19 @@
(ns utils.emojilib
(:require ["emojilib" :as emojis]
[goog.object :as object]
utils.string))
(def lib (.-lib emojis))
(defn get-char
[emoji-id]
(when-let [emoji-map (object/get lib emoji-id)]
(.-char ^js emoji-map)))
(defn text->emoji
"Replaces emojis in a specified `text`"
[text]
(utils.string/safe-replace text
#":([a-z_\-+0-9]*):"
(fn [[original emoji-id]]
(or (get-char emoji-id) original))))
+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.171.31",
"commit-sha1": "271778a1e07e585a12790b4e2226f13e36ea89f4",
"src-sha256": "1c998kyhya98a0zp795i3xrx2r08yjdaifb32ylr4snjjln6k34c"
"version": "fix-mention-everyone",
"commit-sha1": "3c8591a166b6731f975beff5ad513a027b933983",
"src-sha256": "19k0vsgg9s9y6zhr5nf6c5m59f0hw6zzhr5hg3rv9f0m4hldid7v"
}
@@ -245,7 +245,6 @@ class TestActivityMultipleDevicePR(MultipleSharedDeviceTestCase):
self.home_1.get_to_community_channel_from_home(self.community_name)
self.chat_2 = self.home_2.get_chat(self.username_1).click()
self.chat_2.chat_element_by_text(self.community_name).view_community_button.click()
self.community_2.join_community()
self.channel_2 = self.community_2.get_channel(self.channel_name).click()
@@ -387,7 +386,6 @@ class TestActivityMultipleDevicePRTwo(MultipleSharedDeviceTestCase):
self.home_1.get_to_community_channel_from_home(self.community_name)
self.chat_2 = self.home_2.get_chat(self.username_1).click()
self.chat_2.chat_element_by_text(self.community_name).view_community_button.click()
self.community_2.join_community()
self.channel_2 = self.community_2.get_channel(self.channel_name).click()
self.channel_2.chat_message_input.wait_for_visibility_of_element(20)
@@ -448,7 +446,6 @@ class TestActivityMultipleDevicePRTwo(MultipleSharedDeviceTestCase):
self.home_2.navigate_back_to_home_view()
self.home_2.chats_tab.click()
self.chat_2 = self.home_2.get_chat(self.username_1).click()
self.chat_2.chat_element_by_text(community_name).view_community_button.wait_and_click(sec=60)
self.community_2.join_community(open_community=False)
for home in self.home_1, self.home_2:
home.navigate_back_to_home_view()
@@ -317,7 +317,6 @@ class TestCommunityMultipleDeviceMerged(MultipleSharedDeviceTestCase):
self.home_2.just_fyi("Send message to contact (need for blocking contact) test")
self.chat_2.send_message(self.text_message)
self.chat_2.chat_element_by_text(self.community_name).view_community_button.click()
self.community_2.join_community()
self.channel_2 = self.community_2.get_channel(self.channel_name).click()
self.channel_2.chat_message_input.wait_for_visibility_of_element(20)
@@ -838,7 +837,6 @@ class TestCommunityMultipleDeviceMergedTwo(MultipleSharedDeviceTestCase):
self.home_2.just_fyi("Send message to contact (need for blocking contact) test")
self.chat_2.send_message(self.text_message)
self.chat_2.chat_element_by_text(self.community_name).view_community_button.click()
self.community_2.join_community()
self.channel_2 = self.community_2.get_channel(self.channel_name).click()
@@ -1014,7 +1012,6 @@ class TestCommunityMultipleDeviceMergedTwo(MultipleSharedDeviceTestCase):
self.home_2.get_chat(self.username_1).click()
control_message_1_1_chat = "it is just a message text"
self.chat_2.send_message(control_message_1_1_chat)
self.chat_2.chat_element_by_text(community_name).view_community_button.click()
self.community_2.join_community(open_community=False)
self.home_1.just_fyi("Device 1 accepts the community request")
@@ -1098,7 +1095,6 @@ class TestCommunityMultipleDeviceMergedTwo(MultipleSharedDeviceTestCase):
self.home_2.just_fyi("Device 2 requests to join the community")
self.home_2.jump_to_messages_home()
self.home_2.get_chat(self.username_1).click()
self.chat_2.chat_element_by_text(community_name).view_community_button.click()
self.community_2.join_community(open_community=False)
exp_text = "You requested to join “%s" % community_name
if self.community_2.toast_content_element.is_element_displayed(10):
+1 -4
View File
@@ -322,10 +322,6 @@ class ChatElementByText(Text):
return PinnedByLabelText(self.driver, self.locator)
@property
def view_community_button(self):
return BaseElement(self.driver, xpath=self.locator + "//*[@text='View']")
class UsernameOptions(Button):
def __init__(self, driver, username):
@@ -425,6 +421,7 @@ class CommunityView(HomeView):
def join_community(self, password=common_password, open_community=True):
self.driver.info("Joining community")
ChatView(self.driver).chat_element_by_text("https://status.app/c/").click_on_link_inside_message_body()
self.join_button.click()
self.join_community_button.scroll_and_click()
self.password_input.send_keys(password)
+7 -1
View File
@@ -178,6 +178,8 @@
},
"community-rules": "Community rules",
"address-to-share": "Addresses to share",
"addresses-for-permissions": "Addresses for permissions",
"confirm-changes": "Confirm changes",
"join-as-a-member": "Join as a Member",
"all-addresses": "All addresses",
"for-airdrops": "For airdrops",
@@ -2429,5 +2431,9 @@
"backup-step-4": "I know I can only see it once",
"reveal-phrase": "Reveal phrase",
"i-have-written": "I have written it down on paper",
"next-you-will": "Next, you will be asked to confirm the position of certain words in your recovery phrase"
"next-you-will": "Next, you will be asked to confirm the position of certain words in your recovery phrase",
"share-opensea-link": "Share OpenSea link",
"save-image-to-photos": "Save image to Photos",
"copy-all-details": "Copy all details",
"share-details": "Share details"
}