Compare commits

...
36 Commits
Author SHA1 Message Date
Ibrkhalil 50759346c4 lint 2024-01-25 10:02:04 +02:00
Ibrkhalil 98811e3511 PR comments 2024-01-25 09:33:11 +02:00
Ibrkhalil 818b9e2bdf approach 2024-01-25 09:33:10 +02:00
Ibrkhalil a79c3ad0bf Text Jumping Issue in Maximized Composer on iOS 17.x 2024-01-25 09:33:08 +02:00
mmilad75 ed7463132a The collectibles are not supported on Optimism and Arbitrum #18507 (#18562)
* add chain id to the request

* add tests

* fix lint issues

* remove OPENSEA_API_KEY

* move subscription to a helper method for chain-ids
2024-01-24 19:17:08 +03:30
Brian Sztamfater d20f10cf8b fix: fix slide button padding on transaction confirmation page (#18585)
Signed-off-by: Brian Sztamfater <brian@status.im>
2024-01-24 10:40:53 -03:00
Brian Sztamfater ebbae051bd fix: fix button color on input amount screen (#18572)
Signed-off-by: Brian Sztamfater <brian@status.im>
2024-01-24 10:27:00 -03:00
mmilad75 521f39b6fb No ability to enter/paste assets exceeds the users's balance #18526 (#18599)
* change functionality

* fix handle-swap

* fix lint issues

* update tests

* change error to error?

* change reset-input-error

* update tests

* fix lint issues
2024-01-24 16:37:47 +03:30
Siddarth Kumar ee1f93defb fix: xcbeautify usage without omitting crucial logs (#18605)
## Summary

I introduced `xcbeautify` inside `make run-ios` command which would sometimes skip spitting crucial logs to the terminal.
In cases where the `react-native-cli` would prompt me of a port being used by another metro server, those prompts would also never reach me since they were piped into `xcbeautify` essentially giving me the impression that `make run-ios` is still doing something when it was actually hung.

This is how `react-native-community/cli` looks for `xcbeautify` ->
https://github.com/react-native-community/cli/blob/main/packages/cli-platform-apple/src/commands/buildCommand/buildProject.ts#L139

This commit fixes the problem by exporting an env variable making `react-native-cli` aware that we have `xcbeautify` installed and this way we now get the full log output we were used to.
2024-01-24 15:28:42 +05:30
John Ngei 3665fe26da fixed: mute-icon when channel is muted 2024-01-24 00:25:16 +01:00
John Ngei 3ec7209fcc Update default wallet name
* updated default wallet name to 'Account 1'

https://github.com/status-im/status-go/compare/ea3e59ff...64c8ce2e

* updated status go
2024-01-23 23:44:47 +01:00
Paul FitzgeraldandAjay Sivan 195826a7f4 chore(quo): add component list item - network list to design system (#18547)
---------

Co-authored-by: Ajay Sivan <ajayesivan@gmail.com>
2024-01-23 11:41:20 -08:00
Ibrahem KhalilandYevheniia Berdnyk 5bb4f3632a [17514] Use OS emojis in emoji picker (#18397)
---------

Co-authored-by: Yevheniia Berdnyk <ie.berdnyk@gmail.com>
2024-01-23 14:41:43 +02:00
Mohamed Javid 4fe62553ca Wallet - Refresh tokens and prices (#18456)
This commit adds

- RPC call for start wallet which will signal the client to refresh data (tokens, prices, ...etc) every 10 minutes
- Refreshes tokens and prices every 10 minutes on receiving the "wallet-tick-reload" signal

---------

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2024-01-23 17:59:29 +05:30
BalogunofAfrica cb586c8676 fix: make identifier carousel swipe-able (#18515) 2024-01-23 12:25:03 +01:00
Ibrahem Khalil fd50e4281c Add scroll view to profile tab (#18448) 2024-01-23 12:52:34 +02:00
Ulises Manuel dcbb080217 [#18458] Token input fixes (#18520)
* Add custom keyboard to token-input preview
* Fix token input flickering
2024-01-22 20:01:00 -06:00
Parvesh Monu 97d1b3faa1 fix cannot add existing ENS owned by user (#18567) 2024-01-23 04:42:56 +05:30
Nikolay 9c322397a2 chore(wallet): remove account confirmation UI (#18518) 2024-01-22 10:00:07 -08:00
Mohsen ca2b1d5c8e fix: remove quo preview from nightly builds (#18556) 2024-01-22 19:08:34 +03:30
Jamie Caprani 9a4bc7e250 feat(wallet): connect backend to transaction progress page (#18506) 2024-01-22 14:40:13 +00:00
Paul Fitzgerald c6dbfb6244 chore: add background color gradient to share qr code component (#18503) 2024-01-22 06:08:43 -08:00
Omar Basem 826ab6625e Wallet: token input conversion (#18539)
Wallet: token input conversion
2024-01-20 10:23:19 +04:00
Ulises Manuel a9ec2ca7ba Add support to display token images in token gated communities (#18174) 2024-01-19 20:51:50 -06:00
Parvesh Monu 1e11edc442 Remove last reagent atom from messages/view file (#18551) 2024-01-19 21:41:02 +05:30
codemaster bf8461f007 fix: wrong navigation bar color in transparent screens (#18451) 2024-01-19 07:19:58 -08:00
Mohamed Javid 5926426672 [Fix] Currency symbol on recovered profile (#18433)
This commit fixes the currency symbol not shown on the recovered profile.

--

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2024-01-19 20:03:28 +05:30
yqrashawn e871357b67 refactor: move perm/airdrop addrs into community (#18571)
Signed-off-by: yqrashawn <namy.19@gmail.com>
2024-01-19 20:44:17 +08:00
Omar Basem 9f5e53cc63 wallet: fix address inconsistencies (#18558)
wallet: fix address inconsistencies
2024-01-19 15:45:17 +04:00
yqrashawn 61c0650cec fix: do not show community view until it's loaded (#18570) 2024-01-19 16:36:14 +08:00
Omar Basem 7cc570b6d0 wallet: fix route test net (#18553)
wallet: fix route test net
2024-01-19 07:47:37 +04:00
Brian Sztamfater e609e2ff6a fix: crash when selecting a collectible (#18541)
Signed-off-by: Brian Sztamfater <brian@status.im>
2024-01-18 16:05:09 -03:00
Alexander f8cdb3bd7b Style fix (#18191) 2024-01-18 16:23:42 +01:00
yqrashawn fe9a4eac59 feat: re-fetch community info in community overview and channel (#18465)
Signed-off-by: yqrashawn <namy.19@gmail.com>
2024-01-18 22:05:31 +08:00
frank d934dc26ef Remove the invocation of wakuext_chatMentionReplaceWithPublicKey (#18533) 2024-01-18 21:33:37 +08:00
Mohamed Javid ed3cb42572 Wallet - Add token filter and prices fallback for fiat amount calculation (#18398)
This commit:

- Adds a filter to remove tokens with no name or symbol to prevent displaying tokens with no data
- Adds a fallback value (zero) for token fiat value calculation and to prevent crash on token price calculation

---------

Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
2024-01-18 15:16:00 +05:30
139 changed files with 1948 additions and 1189 deletions
+3 -2
View File
@@ -282,11 +282,12 @@ SIMULATOR=iPhone 13
# TODO: fix IOS_STATUS_GO_TARGETS to be either amd64 or arm64 when RN is upgraded # TODO: fix IOS_STATUS_GO_TARGETS to be either amd64 or arm64 when RN is upgraded
run-ios: export TARGET := ios run-ios: export TARGET := ios
run-ios: export IOS_STATUS_GO_TARGETS := ios/arm64;iossimulator/amd64 run-ios: export IOS_STATUS_GO_TARGETS := ios/arm64;iossimulator/amd64
run-ios: export XCBeautify=$(shell which xcbeautify) # for react-native-cli to pick this up and to auto format output
run-ios: ##@run Build iOS app and start it in a simulator/device run-ios: ##@run Build iOS app and start it in a simulator/device
ifneq ("$(SIMULATOR)", "") ifneq ("$(SIMULATOR)", "")
npx react-native run-ios --simulator="$(SIMULATOR)" | xcbeautify npx react-native run-ios --simulator="$(SIMULATOR)"
else else
npx react-native run-ios | xcbeautify npx react-native run-ios
endif endif
show-ios-devices: ##@other shows connected ios device and its name show-ios-devices: ##@other shows connected ios device and its name
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@@ -51,3 +51,9 @@
(visibility-status-updates/<-rpc-settings) (visibility-status-updates/<-rpc-settings)
(set/rename-keys {:compressedKey :compressed-key (set/rename-keys {:compressedKey :compressed-key
:emojiHash :emoji-hash}))) :emojiHash :emoji-hash})))
(defn rpc->setting-value
[{:keys [name] :as setting}]
(condp = name
:currency (update setting :value keyword)
setting))
+1 -1
View File
@@ -231,7 +231,7 @@
[db] [db]
(into #{} (into #{}
(remove #(= (:type %) :watch) (remove #(= (:type %) :watch)
(map #(eip55/address->checksum (:address %)) (get db :profile/wallet-accounts))))) (map #(eip55/address->checksum (:address %)) (vals (get-in db [:wallet :accounts]))))))
;;NOTE we want to handle only last resolve ;;NOTE we want to handle only last resolve
(def resolve-last-id (atom nil)) (def resolve-last-id (atom nil))
@@ -79,10 +79,15 @@
"recent-history-ready" (recent-history-fetching-ended cofx event) "recent-history-ready" (recent-history-fetching-ended cofx event)
"fetching-history-error" (fetching-error cofx event) "fetching-history-error" (fetching-error cofx event)
"non-archival-node-detected" (non-archival-node-detected cofx event) "non-archival-node-detected" (non-archival-node-detected cofx event)
"pending-transaction-status-changed" {:fx
[[:dispatch
[:wallet/pending-transaction-status-changed-received
event]]]}
"wallet-owned-collectibles-filtering-done" {:fx [[:dispatch "wallet-owned-collectibles-filtering-done" {:fx [[:dispatch
[:wallet/owned-collectibles-filtering-done [:wallet/owned-collectibles-filtering-done
event]]]} event]]]}
"wallet-get-collectibles-details-done" {:fx [[:dispatch "wallet-get-collectibles-details-done" {:fx [[:dispatch
[:wallet/get-collectible-details-done [:wallet/get-collectible-details-done
event]]]} event]]]}
"wallet-tick-reload" {:fx [[:dispatch [:wallet/reload]]]}
(log/debug ::unknown-wallet-event :type type :event event))) (log/debug ::unknown-wallet-event :type type :event event)))
+1
View File
@@ -43,6 +43,7 @@
[react-native.permissions :as permissions] [react-native.permissions :as permissions]
[react-native.platform :as platform] [react-native.platform :as platform]
[status-im.common.biometric.events :as biometric] [status-im.common.biometric.events :as biometric]
status-im.common.serialization
status-im.common.standard-authentication.events status-im.common.standard-authentication.events
[status-im.common.theme.core :as theme] [status-im.common.theme.core :as theme]
[status-im.common.universal-links :as universal-links] [status-im.common.universal-links :as universal-links]
@@ -246,7 +246,7 @@
[rn/touchable-opacity [rn/touchable-opacity
{:on-press #(do {:on-press #(do
(rf/dispatch [:pop-to-root :shell-stack]) (rf/dispatch [:pop-to-root :shell-stack])
(rf/dispatch [:navigate-to :community-overview (:id community)]) (rf/dispatch [:communities/navigate-to-community-overview (:id community)])
(rf/dispatch [:chat/close]))} (rf/dispatch [:chat/close]))}
[rn/text [rn/text
{:style {:text-align :center {:style {:text-align :center
+11 -11
View File
@@ -11,17 +11,17 @@
(defn token-requirement-list-row (defn token-requirement-list-row
[tokens padding?] [tokens padding?]
[rn/view {:style (style/token-row padding?)} [rn/view {:style (style/token-row padding?)}
(map-indexed (fn [token-index token] (map-indexed (fn [token-index {:keys [img-src amount sufficient? purchasable?] :as token}]
(let [{:keys [amount sufficient? purchasable?]} token] ^{:key token-index}
^{:key token-index} [rn/view {:style style/token-tag-spacing}
[rn/view {:style style/token-tag-spacing} [token-tag/view
[token-tag/view {:token-symbol (:symbol token)
{:token-symbol (:symbol token) :token-img-src img-src
:token-value amount :token-value amount
:size :size-24 :size :size-24
:options (cond :options (cond
sufficient? :hold sufficient? :hold
purchasable? :add)}]])) purchasable? :add)}]])
tokens)]) tokens)])
(defn- internal-view (defn- internal-view
+33 -20
View File
@@ -76,15 +76,19 @@
(str description " · " (i18n/label :t/on-device))]) (str description " · " (i18n/label :t/on-device))])
(defn- context-tag-subtitle (defn- context-tag-subtitle
[{:keys [community-logo community-name]}] [{:keys [context-tag-type community-logo community-name account-name emoji customization-color]}]
[rn/view (let [tag-type (or context-tag-type :account)]
{:accessibility-label :context-tag-wrapper [rn/view
:style {:flex-wrap :wrap}} {:accessibility-label :context-tag-wrapper
[context-tag/view :style {:flex-wrap :wrap}}
{:type :community [context-tag/view
:community-name community-name {:type tag-type
:community-logo community-logo :account-name account-name
:size 24}]]) :emoji emoji
:community-name community-name
:community-logo community-logo
:size 24
:customization-color customization-color}]]))
(defn- description-subtitle (defn- description-subtitle
[{:keys [theme blur? description]}] [{:keys [theme blur? description]}]
@@ -95,7 +99,8 @@
description]) description])
(defn- subtitle (defn- subtitle
[{:keys [type theme blur? keycard? networks description community-name community-logo]}] [{:keys [type theme blur? keycard? networks description community-name community-logo
context-tag-type account-name emoji customization-color]}]
(cond (cond
(= :keypair type) (= :keypair type)
[keypair-subtitle [keypair-subtitle
@@ -118,8 +123,12 @@
(= :context-tag type) (= :context-tag type)
[context-tag-subtitle [context-tag-subtitle
{:community-logo community-logo {:context-tag-type context-tag-type
:community-name community-name}] :community-logo community-logo
:community-name community-name
:account-name account-name
:emoji emoji
:customization-color customization-color}]
(and (not= :label type) description) (and (not= :label type) description)
[description-subtitle [description-subtitle
@@ -173,6 +182,7 @@
(defn- view-internal (defn- view-internal
[{:keys [title title-icon type theme description blur? community-name community-logo button-icon [{:keys [title title-icon type theme description blur? community-name community-logo button-icon
account-name emoji
on-button-press on-button-press
on-button-long-press on-button-long-press
button-disabled? account-avatar-emoji account-avatar-type customization-color icon-avatar button-disabled? account-avatar-emoji account-avatar-type customization-color icon-avatar
@@ -196,14 +206,17 @@
:theme theme :theme theme
:blur? blur?}] :blur? blur?}]
[subtitle [subtitle
{:type type {:type type
:theme theme :theme theme
:blur? blur? :blur? blur?
:keycard? keycard? :keycard? keycard?
:networks networks :networks networks
:description description :description description
:community-name community-name :community-name community-name
:community-logo community-logo}]] :community-logo community-logo
:customization-color customization-color
:account-name account-name
:emoji emoji}]]
[right-icon [right-icon
{:theme theme {:theme theme
:type type :type type
@@ -1,6 +1,6 @@
(ns quo.components.gradient.gradient-cover.style) (ns quo.components.gradient.gradient-cover.style)
(defn root-container (defn root-container
[opacity] [opacity height]
{:height 252 {:height (or height 252)
:opacity opacity}) :opacity opacity})
@@ -6,7 +6,7 @@
[react-native.linear-gradient :as linear-gradient])) [react-native.linear-gradient :as linear-gradient]))
(defn- view-internal (defn- view-internal
[{:keys [customization-color opacity container-style] :or {customization-color :blue}}] [{:keys [customization-color opacity container-style height] :or {customization-color :blue}}]
(let [color-top (colors/custom-color customization-color 50 20) (let [color-top (colors/custom-color customization-color 50 20)
color-bottom (colors/custom-color customization-color 50 0)] color-bottom (colors/custom-color customization-color 50 0)]
[linear-gradient/linear-gradient [linear-gradient/linear-gradient
@@ -14,6 +14,6 @@
:colors [color-top color-bottom] :colors [color-top color-bottom]
:start {:x 0 :y 0} :start {:x 0 :y 0}
:end {:x 0 :y 1} :end {:x 0 :y 1}
:style (merge (style/root-container opacity) container-style)}])) :style (merge (style/root-container opacity height) container-style)}]))
(def view (quo.theme/with-theme view-internal)) (def view (quo.theme/with-theme view-internal))
@@ -0,0 +1,40 @@
(ns quo.components.list-items.network-list.component-spec
(:require [quo.components.list-items.network-list.view :as network-list]
[quo.foundations.colors :as colors]
[test-helpers.component :as h]))
(defn- render
[component]
(h/render-with-theme-provider component :light))
(def props
{:theme :light
:state :default
:label "Mainnet"
:network-image 873
:customization-color :blue
:token-value "100.00 ETH"
:fiat-value "€100.00"})
(h/describe "List items: Network List"
(h/test "default state explicit"
(render [network-list/view props])
(h/is-truthy (h/get-by-text "Mainnet")))
(h/test "Pressed state"
(render [network-list/view props])
(h/fire-event :on-press-in (h/get-by-label-text ::network-list))
(h/wait-for #(h/has-style (h/query-by-label-text ::network-list)
{:backgroundColor (colors/resolve-color :blue :light 5)})))
(h/test "Active state"
(render [network-list/view (assoc props :state :active)])
(h/has-style (h/query-by-label-text ::network-list)
{:backgroundColor (colors/resolve-color :blue :light 10)}))
(h/test "Call on-press"
(let [on-press (h/mock-fn)]
(render [network-list/view (assoc props :on-press on-press)])
(h/fire-event :on-press (h/get-by-label-text ::network-list))
(h/was-called on-press))))
@@ -0,0 +1,41 @@
(ns quo.components.list-items.network-list.style
(:require [quo.foundations.colors :as colors]))
(defn- background-color
[state customization-color theme]
(case state
:pressed (colors/resolve-color customization-color theme 5)
:active (colors/resolve-color customization-color theme 10)
:transparent))
(defn container
[state customization-color theme]
{:flex-direction :row
:justify-content :space-between
:align-items :center
:padding-horizontal 12
:padding-vertical 8
:border-radius 12
:height 56
:background-color (background-color state customization-color theme)})
(def info
{:flex-direction :row
:align-items :center
:gap 2})
(def network-image
{:border-width 1
:border-radius 16
:border-color colors/neutral-80-opa-5
:margin-right 8
:background-color colors/neutral-80-opa-5
:height 32
:width 32})
(def values-container
{:align-items :flex-end})
(defn fiat-value
[theme]
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
@@ -0,0 +1,76 @@
(ns quo.components.list-items.network-list.view
(:require
[clojure.string :as string]
[quo.components.list-items.network-list.style :as style]
[quo.components.markdown.text :as text]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[reagent.core :as reagent]
[schema.core :as schema]))
(defn- info
[{:keys [network-image label]}]
[rn/view {:style style/info}
[rn/image
{:source network-image
:style style/network-image}]
[rn/view
[text/text
{:weight :semi-bold
:style {:text-transform :capitalize}
:number-of-lines 1}
(if (string/blank? label) "-" label)]]])
(defn- values
[{:keys [token-value fiat-value theme]}]
[rn/view {:style style/values-container}
[text/text
{:weight :medium
:size :paragraph-2
:number-of-lines 1}
token-value]
[text/text
{:style (style/fiat-value theme)
:size :paragraph-2
:number-of-lines 1}
fiat-value]])
(def ?schema
[:=>
[:catn
[:props
[:map {:closed true}
[:network-image :int]
[:label :string]
[:fiat-value :string]
[:token-value :string]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
[:state [:enum :pressed :active :default]]
[:on-press {:optional true} [:maybe fn?]]
[:theme :schema.common/theme]]]]
:any])
(defn- view-internal
[]
(let [pressed? (reagent/atom false)
on-press-in #(reset! pressed? true)
on-press-out #(reset! pressed? false)]
(fn [{:keys [on-press state customization-color theme]
:as props
:or {customization-color :blue}}]
(let [internal-state (if @pressed?
:pressed
state)]
[rn/pressable
{:style (style/container internal-state customization-color theme)
:on-press-in on-press-in
:on-press-out on-press-out
:on-press on-press
:accessibility-label :network-list}
[info props]
[values props]]))))
(def view
(quo.theme/with-theme
(schema/instrument #'view-internal ?schema)))
@@ -1,4 +1,4 @@
(ns quo.components.list-items.user-list (ns quo.components.list-items.user
(:require (:require
[quo.components.avatars.user-avatar.view :as user-avatar] [quo.components.avatars.user-avatar.view :as user-avatar]
[quo.components.icon :as icons] [quo.components.icon :as icons]
@@ -18,14 +18,14 @@
:align-items :center}) :align-items :center})
(defn action-icon (defn action-icon
[{:keys [type on-press on-check disabled? checked?]}] [{:keys [type on-press on-check disabled? checked?]} theme]
[rn/touchable-opacity [rn/touchable-opacity
{:on-press (when on-press on-press)} {:on-press (when on-press on-press)}
(case type (case type
:options :options
[icons/icon :i/options [icons/icon :i/options
{:size 20 {:size 20
:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}] :color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}]
:checkbox :checkbox
[selectors/view [selectors/view
{:type :checkbox {:type :checkbox
@@ -37,30 +37,33 @@
[text/text "not implemented"] [text/text "not implemented"]
[rn/view])]) [rn/view])])
(defn user-list (defn user
[{:keys [short-chat-key primary-name secondary-name photo-path online? contact? verified? [{:keys [short-chat-key primary-name secondary-name photo-path online? contact? verified?
untrustworthy? on-press on-long-press accessory]}] untrustworthy? on-press on-long-press accessory customization-color theme]}]
[rn/touchable-opacity [rn/touchable-highlight
{:style container-style {:style container-style
:underlay-color (colors/resolve-color customization-color theme 5)
:accessibility-label :user-list :accessibility-label :user-list
:on-press (when on-press on-press) :on-press (when on-press on-press)
:on-long-press (when on-long-press on-long-press)} :on-long-press (when on-long-press on-long-press)}
[user-avatar/user-avatar [:<>
{:full-name primary-name [user-avatar/user-avatar
:profile-picture photo-path {:full-name primary-name
:online? online? :profile-picture photo-path
:size :small}] :online? online?
[rn/view {:style {:margin-horizontal 8 :flex 1}} :size :small}]
[author/view [rn/view {:style {:margin-horizontal 8 :flex 1}}
{:primary-name primary-name [author/view
:secondary-name secondary-name {:primary-name primary-name
:contact? contact? :secondary-name secondary-name
:verified? verified? :contact? contact?
:untrustworthy? untrustworthy?}] :verified? verified?
(when short-chat-key :untrustworthy? untrustworthy?
[text/text :size 15}]
{:size :paragraph-1 (when short-chat-key
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}} [text/text
short-chat-key])] {:size :paragraph-2
(when accessory :style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
[action-icon accessory])]) short-chat-key])]
(when accessory
[action-icon accessory theme])]])
@@ -38,7 +38,7 @@
(defn icon-container (defn icon-container
[is-first?] [is-first?]
{:margin-left (if is-first? 4 2) {:margin-left (if is-first? 4 2)
:margin-bottom 2}) :margin-bottom 4})
(defn time-text (defn time-text
[theme] [theme]
+1 -2
View File
@@ -51,8 +51,7 @@
[icons/icon :main-icons2/untrustworthy [icons/icon :main-icons2/untrustworthy
{:size 12 {:size 12
:no-color true :no-color true
:container-style (style/icon-container contact?)}]) :container-style (style/icon-container contact?)}])]
]
(when (and (not verified?) short-chat-key) (when (and (not verified?) short-chat-key)
[text/text [text/text
{:weight :monospace {:weight :monospace
@@ -34,10 +34,9 @@
(= :pinned use-case) (= :pinned use-case)
theme) theme)
container-style)} container-style)}
[rn/image [rn/text
{:style {:width 15 :height 15} {:accessibility-label :emoji}
:accessibility-label :emoji (reaction.resource/system-emojis emoji)]
:source (reaction.resource/get-reaction emoji)}]
[text/text [text/text
{:size :paragraph-2 {:size :paragraph-2
:weight :semi-bold :weight :semi-bold
@@ -4,6 +4,14 @@
(def ^:private reactions (def ^:private reactions
(resolve-all-reactions)) (resolve-all-reactions))
(def system-emojis
{:reaction/thumbs-up "👍"
:reaction/thumbs-down "👎"
:reaction/love "❤"
:reaction/laugh "😂"
:reaction/sad "😢"
:reaction/angry "😡"})
(defn get-reaction (defn get-reaction
[reaction] [reaction]
(assert (keyword? reaction) "Reaction should be a keyword") (assert (keyword? reaction) "Reaction should be a keyword")
@@ -19,6 +19,5 @@
(swap! pressed? not) (swap! pressed? not)
(when on-press (when on-press
(on-press e)))} (on-press e)))}
[rn/image [rn/text
{:source (reactions.resource/get-reaction emoji) (reactions.resource/system-emojis emoji)]])))
:style {:width 20 :height 20}}]])))
@@ -8,19 +8,20 @@
(defn- category-internal (defn- category-internal
[{:keys [label data container-style] :as props}] [{:keys [label data container-style] :as props}]
[rn/view {:style (merge (style/container label) container-style)} (let [settings-item (filter identity data)]
(when label [rn/view {:style (merge (style/container label) container-style)}
[text/text (when label
{:weight :medium [text/text
:size :paragraph-2 {:weight :medium
:style (style/label props)} :size :paragraph-2
label]) :style (style/label props)}
[rn/view {:style (style/settings-items props)} label])
(for [item data] [rn/view {:style (style/settings-items props)}
^{:key item} (for [item settings-item]
[:<> ^{:key item}
[settings-item/view item] [:<>
(when-not (= item (last data)) [settings-item/view item]
[rn/view {:style (style/settings-separator props)}])])]]) (when-not (= item (last settings-item))
[rn/view {:style (style/settings-separator props)}])])]]))
(def settings-category (quo.theme/with-theme category-internal)) (def settings-category (quo.theme/with-theme category-internal))
@@ -20,7 +20,7 @@
network-image] network-image]
:or {subtitle-type :default}}] :or {subtitle-type :default}}]
[rn/view {:style style/subtitle-container} [rn/view {:style style/subtitle-container}
(when (not= :small size) (when (and subtitle-type (not= :small size))
[rn/view {:style (style/subtitle-icon-container subtitle-type)} [rn/view {:style (style/subtitle-icon-container subtitle-type)}
(case subtitle-type (case subtitle-type
:icon [icons/icon icon :icon [icons/icon icon
@@ -16,6 +16,12 @@
:padding-top 12 :padding-top 12
:padding-bottom 8}) :padding-bottom 8})
(def gradient-bg
{:position :absolute
:top 0
:left 0
:right 0})
;;; Header ;;; Header
(def header-container (def header-container
{:flex-direction :row {:flex-direction :row
@@ -4,14 +4,13 @@
[oops.core :as oops] [oops.core :as oops]
[quo.components.avatars.account-avatar.view :as account-avatar] [quo.components.avatars.account-avatar.view :as account-avatar]
[quo.components.buttons.button.view :as button] [quo.components.buttons.button.view :as button]
[quo.components.gradient.gradient-cover.view :as gradient-cover]
[quo.components.markdown.text :as text] [quo.components.markdown.text :as text]
[quo.components.share.qr-code.view :as qr-code] [quo.components.share.qr-code.view :as qr-code]
[quo.components.share.share-qr-code.style :as style] [quo.components.share.share-qr-code.style :as style]
[quo.components.tabs.tab.view :as tab] [quo.components.tabs.tab.view :as tab]
[quo.theme] [quo.theme]
[react-native.blur :as blur]
[react-native.core :as rn] [react-native.core :as rn]
[react-native.platform :as platform]
[reagent.core :as reagent] [reagent.core :as reagent]
[utils.i18n :as i18n])) [utils.i18n :as i18n]))
@@ -126,41 +125,44 @@
[{:keys [share-qr-type qr-image-uri component-width customization-color full-name [{:keys [share-qr-type qr-image-uri component-width customization-color full-name
profile-picture emoji on-share-press] profile-picture emoji on-share-press]
:as props}] :as props}]
[rn/view {:style style/content-container} [:<>
[rn/view [rn/view {:style style/gradient-bg}
{:style style/share-qr-container} [gradient-cover/view {:customization-color customization-color :height 463}]]
[rn/view {:style style/content-container}
[rn/view [rn/view
{:style style/share-qr-inner-container} {:style style/share-qr-container}
[account-avatar/view [rn/view
{:customization-color customization-color {:style style/share-qr-inner-container}
:emoji emoji [account-avatar/view
:size 32}] {:customization-color customization-color
[text/text :emoji emoji
{:size :heading-2 :size 32}]
:weight :semi-bold [text/text
:style {:margin-left 8}} full-name]] {:size :heading-2
[share-button {:on-press on-share-press}]] :weight :semi-bold
(when (#{:wallet-legacy :wallet-multichain} share-qr-type) :style {:margin-left 8}} full-name]]
[header props]) [share-button {:on-press on-share-press}]]
[quo.theme/provider {:theme :light} (when (#{:wallet-legacy :wallet-multichain} share-qr-type)
[qr-code/view [header props])
{:qr-image-uri qr-image-uri [quo.theme/provider {:theme :light}
:size (style/qr-code-size component-width) [qr-code/view
:avatar (if (= share-qr-type :profile) {:qr-image-uri qr-image-uri
:profile :size (style/qr-code-size component-width)
:wallet-account) :avatar (if (= share-qr-type :profile)
:customization-color customization-color :profile
:full-name full-name :wallet-account)
:profile-picture profile-picture :customization-color customization-color
:emoji emoji}]] :full-name full-name
[rn/view {:style style/bottom-container} :profile-picture profile-picture
(case share-qr-type :emoji emoji}]]
:profile [profile-bottom props] [rn/view {:style style/bottom-container}
:wallet-legacy [wallet-legacy-bottom props] (case share-qr-type
:wallet-multichain [wallet-multichain-bottom props] :profile [profile-bottom props]
nil)]]) :wallet-legacy [wallet-legacy-bottom props]
:wallet-multichain [wallet-multichain-bottom props]
nil)]]])
(defn view (defn- view-internal
"Receives the following properties: "Receives the following properties:
- type: :profile | :wallet-legacy | :wallet-multichain - type: :profile | :wallet-legacy | :wallet-multichain
- qr-image-uri: Image source value. - qr-image-uri: Image source value.
@@ -190,16 +192,9 @@
Sometimes while using a blur layer on top of another on Android, this component looks Sometimes while using a blur layer on top of another on Android, this component looks
bad because of the `blur/view`, so we can set `unblur-on-android? true` to fix it. bad because of the `blur/view`, so we can set `unblur-on-android? true` to fix it.
" "
[{:keys [unblur-on-android?] :as props}] [props]
(reagent/with-let [component-width (reagent/atom nil) (reagent/with-let [component-width (reagent/atom nil)
container-component (if (and platform/android? unblur-on-android?) container-component [rn/view {:background-color style/overlay-color}]]
[rn/view {:background-color style/overlay-color}]
[blur/view
{:blur-radius 20
:blur-amount 20
:blur-type :transparent
:overlay-color style/overlay-color
:background-color style/overlay-color}])]
[quo.theme/provider {:theme :dark} [quo.theme/provider {:theme :dark}
[rn/view [rn/view
{:accessibility-label :share-qr-code {:accessibility-label :share-qr-code
@@ -211,3 +206,6 @@
(-> props (-> props
(assoc :component-width @component-width) (assoc :component-width @component-width)
(clojure.set/rename-keys {:type :share-qr-type}))]))]])) (clojure.set/rename-keys {:type :share-qr-type}))]))]]))
(def view (quo.theme/with-theme view-internal))
+7 -6
View File
@@ -20,7 +20,7 @@
- :token-symbol - string" - :token-symbol - string"
[] []
(let [container-width (reagent/atom 0)] (let [container-width (reagent/atom 0)]
(fn [{:keys [options size blur? theme token-value token-symbol] (fn [{:keys [options size blur? theme token-value token-img-src token-symbol]
:or {size :size-24}}] :or {size :size-24}}]
[rn/view [rn/view
{:on-layout #(reset! container-width {:on-layout #(reset! container-width
@@ -42,11 +42,12 @@
[])} [])}
[rn/view {:style (style/container size options blur? theme)} [rn/view {:style (style/container size options blur? theme)}
[token/view [token/view
{:style (style/token-img size) {:style (style/token-img size)
:token token-symbol :token token-symbol
:size (case size :size (case size
:size-24 :size-20 :size-24 :size-20
:size-32 :size-28)}] :size-32 :size-28)
:image-source token-img-src}]
[text/text [text/text
{:size :paragraph-2 {:size :paragraph-2
:weight :medium :weight :medium
+20 -18
View File
@@ -15,9 +15,7 @@
[:token {:optional true} [:or keyword? string?]] [:token {:optional true} [:or keyword? string?]]
[:style {:optional true} map?] [:style {:optional true} map?]
;; Ignores `token` and uses this as parameter to `rn/image`'s source. ;; Ignores `token` and uses this as parameter to `rn/image`'s source.
[:image-source {:optional true} [:or :schema.common/image-source :string]] [:image-source {:optional true} [:or :schema.common/image-source :string]]]]
;; If true, adds `data:image/png;base64,` as prefix to the string passed as `image-source`
[:add-b64-prefix? {:optional true} boolean?]]]
:any]) :any])
(defn- size->number (defn- size->number
@@ -52,28 +50,32 @@
first first
string/capitalize)]]) string/capitalize)]])
(defn- normalize-b64-string
[b64-image]
(if (string/starts-with? b64-image "data:image/")
b64-image
(str b64-png-image-prefix b64-image)))
(defn view-internal (defn view-internal
"Render a token image. "Render a token image.
Props: Props:
- style: extra styles to apply to the `rn/image` component. - style: extra styles to apply to the `rn/image` component.
- size: `:size-nn` or just `nn`, being `nn` any number. Defaults to 32. - size: `:size-nn` or just `nn`, being `nn` any number. Defaults to 32.
- token: string or keyword, it can contain upper case letters or not. - token: string or keyword, it can contain upper case letters or not.
E.g. all of these are valid and resolve to the same: E.g. all of these are valid and resolve to the same:
:token/snt | :snt | :SNT | \"SNT\" | \"snt\". :token/snt | :snt | :SNT | \"SNT\" | \"snt\".
- image-source: Ignores `token` and uses this as parameter to `rn/image`'s source. - image-source: Ignores `token` and uses this as parameter to `rn/image`'s source, it
- add-b64-prefix?: If true, adds `data:image/png;base64,` as prefix to the string can be a b64 string representing an image.
passed as `image-source`.
" "
[{:keys [token size style image-source add-b64-prefix?] [{:keys [token size style image-source]
:or {size 32}}] :or {size 32}}]
(let [b64-string (if (and image-source add-b64-prefix?) (let [img-src (if (string? image-source)
(str b64-png-image-prefix image-source) (normalize-b64-string image-source)
image-source) image-source)]
source (or b64-string (token-loader/get-token-image token))] (if-let [existing-source (or img-src (token-loader/get-token-image token))]
(if source
[rn/image [rn/image
{:style (token-style style size) {:style (token-style style size)
:source source}] :source existing-source}]
[temp-empty-symbol token size style]))) [temp-empty-symbol token size style])))
(def view (schema/instrument #'view-internal ?schema)) (def view (schema/instrument #'view-internal ?schema))
@@ -1,8 +1,7 @@
(ns quo.components.wallet.token-input.style (ns quo.components.wallet.token-input.style
(:require (:require
[quo.foundations.colors :as colors] [quo.foundations.colors :as colors]
[quo.foundations.typography :as typography] [quo.foundations.typography :as typography]))
[react-native.platform :as platform]))
(defn main-container (defn main-container
[width] [width]
@@ -16,23 +15,55 @@
:flex-direction :row :flex-direction :row
:justify-content :space-between}) :justify-content :space-between})
(defn text-input (defn token-name
[theme] [theme]
(merge typography/heading-1 {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
{:font-weight "600" :margin-right 8
:margin-left 8 :padding-bottom 2})
:margin-right (if platform/ios? 6 4)
:color (colors/theme-colors colors/neutral-100 colors/white theme) (def token-label-container
:padding 0 {:position :absolute
:text-align :center :left 40 ; token image size + margin
:height "100%"})) :right 0
:bottom 0
:top 0
:flex-direction :row
:align-items :flex-end})
(def text-input-container
{:position :absolute
:top 0
:bottom 0
:left 40 ; token image size + margin
:right 0})
(def text-input-dimensions
(-> typography/heading-1
(dissoc :letter-spacing)
(assoc :font-weight "600"
:margin-right 5
:padding-left 0
:padding-right 0
:padding-top 0
:padding-bottom 0
:height "100%")))
(defn text-input
[theme error?]
(assoc text-input-dimensions
:color
(if error?
(colors/resolve-color :danger theme)
(colors/theme-colors colors/neutral-100 colors/white theme))))
(defn placeholder-text
[theme]
(colors/theme-colors colors/neutral-40 colors/neutral-50 theme))
(defn divider (defn divider
[width theme] [theme]
{:height 1 {:margin-vertical 8
:width width :background-color (colors/theme-colors colors/neutral-10 colors/neutral-90 theme)})
:background-color (colors/theme-colors colors/neutral-10 colors/neutral-90 theme)
:margin-vertical 8})
(def data-container (def data-container
{:padding-top 4 {:padding-top 4
@@ -40,3 +71,7 @@
:flex-direction :row :flex-direction :row
:justify-content :space-between :justify-content :space-between
:align-items :center}) :align-items :center})
(defn fiat-amount
[theme]
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)})
+115 -63
View File
@@ -7,85 +7,137 @@
[quo.components.tags.network-tags.view :as network-tag] [quo.components.tags.network-tags.view :as network-tag]
[quo.components.utilities.token.view :as token] [quo.components.utilities.token.view :as token]
[quo.components.wallet.token-input.style :as style] [quo.components.wallet.token-input.style :as style]
[quo.foundations.colors :as colors]
[quo.foundations.common :as common] [quo.foundations.common :as common]
[quo.theme :as quo.theme] [quo.theme :as quo.theme]
[react-native.core :as rn] [react-native.core :as rn]
[reagent.core :as reagent])) [reagent.core :as reagent]))
(defn fiat-format
[currency num-value conversion]
(str (get common/currency-label currency) (.toFixed (* num-value conversion) 2)))
(defn crypto-format
[num-value conversion crypto-decimals token]
(str (.toFixed (/ num-value conversion) (or crypto-decimals 2))
" "
(string/upper-case (or (clj->js token) ""))))
(defn calc-value (defn calc-value
[crypto? currency token value conversion] [{:keys [crypto? currency token value conversion crypto-decimals]}]
(let [num-value (if (string? value) (parse-double (or value "0")) value)] (let [num-value (if (string? value)
(or (parse-double value) 0)
value)]
(if crypto? (if crypto?
(str (get common/currency-label currency) (.toFixed (* num-value conversion) 2)) (fiat-format currency num-value conversion)
(str (.toFixed (/ num-value conversion) 2) " " (string/upper-case (or (clj->js token) "")))))) (crypto-format num-value conversion crypto-decimals token))))
(defn- data-info
[{:keys [theme token crypto-decimals conversion networks title crypto? currency amount error?]}]
[rn/view {:style style/data-container}
[network-tag/view
{:networks networks
:title title
:status (when error? :error)}]
[text/text
{:size :paragraph-2
:weight :medium
:style (style/fiat-amount theme)}
(calc-value {:crypto? crypto?
:currency currency
:token token
:value amount
:conversion conversion
:crypto-decimals crypto-decimals})]])
(defn- token-name-text
[theme text]
[text/text
{:style (style/token-name theme)
:size :paragraph-2
:weight :semi-bold}
(string/upper-case (or (clj->js text) ""))])
(defn- token-label
[{:keys [theme value text]}]
[rn/view
{:style style/token-label-container
:pointer-events :none}
[rn/text-input
{:max-length 12
:style style/text-input-dimensions
:editable false
:placeholder "0"
:opacity 0
:value value}]
[token-name-text theme text]])
(defn input-section
[{:keys [on-change-text value value-atom]}]
(let [input-ref (atom nil)
set-ref #(reset! input-ref %)
focus-input #(when-let [ref ^js @input-ref]
(.focus ref))
controlled-input? (some? value)
handle-on-change-text (fn [v]
(when-not controlled-input?
(reset! value-atom v))
(when on-change-text
(on-change-text v)))]
(fn [{:keys [theme token customization-color show-keyboard? crypto? currency value error?]
:or {show-keyboard? true}}]
[rn/pressable
{:on-press focus-input
:style {:flex 1}}
[token/view
{:token token
:size :size-32}]
[rn/view {:style style/text-input-container}
[rn/text-input
(cond-> {:style (style/text-input theme error?)
:placeholder-text-color (style/placeholder-text theme)
:auto-focus true
:ref set-ref
:placeholder "0"
:keyboard-type :numeric
:max-length 12
:on-change-text handle-on-change-text
:selection-color customization-color
:show-soft-input-on-focus show-keyboard?}
controlled-input? (assoc :value value)
(not controlled-input?) (assoc :default-value @value-atom))]]
[token-label
{:theme theme
:text (if crypto? token currency)
:value (if controlled-input? value @value-atom)}]])))
(defn- view-internal (defn- view-internal
[{external-value :value}] [{:keys [on-swap]}]
(let [width (:width (rn/get-window)) (let [width (:width (rn/get-window))
value (reagent/atom nil) value-atom (reagent/atom nil)
crypto? (reagent/atom true) crypto? (reagent/atom true)
input-ref (atom nil) handle-on-swap (fn []
controlled-input? (some? external-value)] (swap! crypto? not)
(fn [{:keys [theme token currency conversion networks title customization-color (when on-swap
on-change-text on-swap container-style show-keyboard?] (on-swap @crypto?)))]
:or {show-keyboard? true} (fn [{:keys [theme container-style value] :as props}]
external-value :value}] [rn/view {:style (merge (style/main-container width) container-style)}
[rn/view
{:style (merge
(style/main-container width)
container-style)}
[rn/view {:style style/amount-container} [rn/view {:style style/amount-container}
[rn/pressable [input-section
{:on-press #(when @input-ref (.focus ^js @input-ref)) (assoc props
:style {:flex-direction :row :value-atom value-atom
:flex-grow 1 :crypto? @crypto?)]
:align-items :flex-end}}
[token/view {:token token :size :size-32}]
[rn/text-input
(cond-> {:auto-focus true
:ref #(reset! input-ref %)
:placeholder "0"
:placeholder-text-color (colors/theme-colors colors/neutral-40
colors/neutral-50
theme)
:keyboard-type :numeric
:max-length 12
:on-change-text (fn [v]
(when-not controlled-input?
(reset! value v))
(when on-change-text
(on-change-text v)))
:style (style/text-input theme)
:selection-color customization-color
:show-soft-input-on-focus show-keyboard?}
controlled-input? (assoc :value external-value)
(not controlled-input?) (assoc :default-value @value))]
[text/text
{:size :paragraph-2
:weight :semi-bold
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
:margin-right 8
:padding-bottom 2}}
(string/upper-case (or (clj->js (if @crypto? token currency)) ""))]]
[button/button [button/button
{:icon true {:icon true
:icon-only? true :icon-only? true
:size 32 :size 32
:on-press (fn [] :on-press handle-on-swap
(swap! crypto? not)
(when on-swap
(on-swap @crypto?)))
:type :outline :type :outline
:accessibility-label :reorder} :accessibility-label :reorder}
:i/reorder]] :i/reorder]]
[divider-line/view {:container-style {:margin-vertical 8}}] [divider-line/view {:container-style (style/divider theme)}]
[rn/view {:style style/data-container} [data-info
[network-tag/view {:networks networks :title title}] (assoc props
[text/text :crypto? @crypto?
{:size :paragraph-2 :amount (or value @value-atom))]])))
:weight :medium
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
(calc-value @crypto? currency token (or external-value @value) conversion)]]])))
(def view (quo.theme/with-theme view-internal)) (def view (quo.theme/with-theme view-internal))
+5 -3
View File
@@ -80,13 +80,14 @@
quo.components.list-items.community.view quo.components.list-items.community.view
quo.components.list-items.dapp.view quo.components.list-items.dapp.view
quo.components.list-items.menu-item quo.components.list-items.menu-item
quo.components.list-items.network-list.view
quo.components.list-items.preview-list.view quo.components.list-items.preview-list.view
quo.components.list-items.quiz-item.view quo.components.list-items.quiz-item.view
quo.components.list-items.saved-address.view quo.components.list-items.saved-address.view
quo.components.list-items.saved-contact-address.view quo.components.list-items.saved-contact-address.view
quo.components.list-items.token-network.view quo.components.list-items.token-network.view
quo.components.list-items.token-value.view quo.components.list-items.token-value.view
quo.components.list-items.user-list quo.components.list-items.user
quo.components.loaders.skeleton-list.view quo.components.loaders.skeleton-list.view
quo.components.markdown.list.view quo.components.markdown.list.view
quo.components.markdown.text quo.components.markdown.text
@@ -299,16 +300,17 @@
(def account-list-card quo.components.list-items.account-list-card.view/view) (def account-list-card quo.components.list-items.account-list-card.view/view)
(def address quo.components.list-items.address.view/view) (def address quo.components.list-items.address.view/view)
(def channel quo.components.list-items.channel.view/view) (def channel quo.components.list-items.channel.view/view)
(def community-list-item quo.components.list-items.community.view/view) (def community-list quo.components.list-items.community.view/view)
(def dapp quo.components.list-items.dapp.view/view) (def dapp quo.components.list-items.dapp.view/view)
(def menu-item quo.components.list-items.menu-item/menu-item) (def menu-item quo.components.list-items.menu-item/menu-item)
(def network-list quo.components.list-items.network-list.view/view)
(def preview-list quo.components.list-items.preview-list.view/view) (def preview-list quo.components.list-items.preview-list.view/view)
(def quiz-item quo.components.list-items.quiz-item.view/view) (def quiz-item quo.components.list-items.quiz-item.view/view)
(def saved-address quo.components.list-items.saved-address.view/view) (def saved-address quo.components.list-items.saved-address.view/view)
(def saved-contact-address quo.components.list-items.saved-contact-address.view/view) (def saved-contact-address quo.components.list-items.saved-contact-address.view/view)
(def token-network quo.components.list-items.token-network.view/view) (def token-network quo.components.list-items.token-network.view/view)
(def token-value quo.components.list-items.token-value.view/view) (def token-value quo.components.list-items.token-value.view/view)
(def user-list quo.components.list-items.user-list/user-list) (def user quo.components.list-items.user/user)
;;;; Loaders ;;;; Loaders
(def skeleton-list quo.components.loaders.skeleton-list.view/view) (def skeleton-list quo.components.loaders.skeleton-list.view/view)
+1
View File
@@ -48,6 +48,7 @@
quo.components.list-items.channel.component-spec quo.components.list-items.channel.component-spec
quo.components.list-items.community.component-spec quo.components.list-items.community.component-spec
quo.components.list-items.dapp.component-spec quo.components.list-items.dapp.component-spec
quo.components.list-items.network-list.component-spec
quo.components.list-items.quiz-item.component-spec quo.components.list-items.quiz-item.component-spec
quo.components.list-items.saved-address.component-spec quo.components.list-items.saved-address.component-spec
quo.components.list-items.saved-contact-address.component-spec quo.components.list-items.saved-contact-address.component-spec
+13 -11
View File
@@ -17,19 +17,19 @@
(fn [^js data] (fn [^js data]
(let [^js section (.-section data)] (let [^js section (.-section data)]
(reagent/as-element [f (reagent/as-element [f
{:title (.-title section) {:index (.-index section)
:title (.-title section)
:data (.-data section)}])))) :data (.-data section)}]))))
(defn- wrap-per-section-render-fn (defn- wrap-per-section-render-fn
[props] [index props]
(update (-> (if-let [f (:render-fn props)]
(if-let [f (:render-fn props)] (assoc (dissoc props :render-fn :render-data)
(assoc (dissoc props :render-fn :render-data) :renderItem
:renderItem (memo-wrap-render-fn f (:render-data props)))
(memo-wrap-render-fn f (:render-data props))) props)
props) (update :data to-array)
:data (assoc :index index)))
to-array))
(defn section-list (defn section-list
"A wrapper for SectionList. "A wrapper for SectionList.
@@ -42,6 +42,8 @@
props props
(when render-section-footer-fn (when render-section-footer-fn
{:renderSectionFooter (wrap-render-section-header-fn render-section-footer-fn)}) {:renderSectionFooter (wrap-render-section-header-fn render-section-footer-fn)})
{:sections (clj->js (map wrap-per-section-render-fn sections)) {:sections (->> sections
(map-indexed wrap-per-section-render-fn)
(clj->js))
:renderSectionHeader (wrap-render-section-header-fn render-section-header-fn) :renderSectionHeader (wrap-render-section-header-fn render-section-header-fn)
:style style})]) :style style})])
@@ -0,0 +1,5 @@
(ns status-im.common.contact-list.style)
(defn contacts-section-header
[first-item?]
{:padding-top (if first-item? 0 8)})
+6 -3
View File
@@ -1,7 +1,10 @@
(ns status-im.common.contact-list.view (ns status-im.common.contact-list.view
(:require (:require
[quo.core :as quo])) [quo.core :as quo]
[react-native.core :as rn]
[status-im.common.contact-list.style :as style]))
(defn contacts-section-header (defn contacts-section-header
[{:keys [title]}] [{:keys [title index]}]
[quo/divider-label title]) [rn/view (style/contacts-section-header (= index 0))
[quo/divider-label title]])
@@ -6,17 +6,21 @@
(defn contact-list-item (defn contact-list-item
[{:keys [on-press on-long-press accessory]} [{:keys [on-press on-long-press accessory]}
{:keys [primary-name secondary-name public-key compressed-key ens-verified added?]}] {:keys [primary-name secondary-name public-key compressed-key ens-verified added?]}
(let [photo-path (rf/sub [:chats/photo-path public-key]) theme]
online? (rf/sub [:visibility-status-updates/online? public-key])] (let [photo-path (rf/sub [:chats/photo-path public-key])
[quo/user-list online? (rf/sub [:visibility-status-updates/online? public-key])
{:short-chat-key (address/get-shortened-compressed-key (or compressed-key public-key)) customization-color (rf/sub [:profile/customization-color])]
:primary-name primary-name [quo/user
:secondary-name secondary-name {:customization-color customization-color
:photo-path photo-path :theme theme
:online? online? :short-chat-key (address/get-shortened-compressed-key (or compressed-key public-key))
:verified? ens-verified :primary-name primary-name
:contact? added? :secondary-name secondary-name
:on-press on-press :photo-path photo-path
:on-long-press on-long-press :online? online?
:accessory accessory}])) :verified? ens-verified
:contact? added?
:on-press on-press
:on-long-press on-long-press
:accessory accessory}]))
@@ -52,7 +52,8 @@
:remove-listeners remove-listeners})) :remove-listeners remove-listeners}))
(defn view (defn view
[{:keys [header footer customization-color gradient-cover?]} & [{:keys [header footer customization-color footer-container-padding gradient-cover?]
:or {footer-container-padding (safe-area/get-top)}} &
children] children]
(reagent/with-let [window-height (:height (rn/get-window)) (reagent/with-let [window-height (:height (rn/get-window))
footer-container-height (reagent/atom 0) footer-container-height (reagent/atom 0)
@@ -94,7 +95,7 @@
children)] children)]
[rn/keyboard-avoiding-view [rn/keyboard-avoiding-view
{:style style/keyboard-avoiding-view {:style style/keyboard-avoiding-view
:keyboard-vertical-offset (if platform/ios? (safe-area/get-top) 0) :keyboard-vertical-offset (if platform/ios? footer-container-padding 0)
:pointer-events :box-none} :pointer-events :box-none}
[floating-container/view [floating-container/view
{:on-layout set-footer-container-height {:on-layout set-footer-container-height
+3
View File
@@ -38,6 +38,9 @@
:no-contacts :no-contacts
{:light (js/require "../resources/images/ui2/no-contacts-light.png") {:light (js/require "../resources/images/ui2/no-contacts-light.png")
:dark (js/require "../resources/images/ui2/no-contacts-dark.png")} :dark (js/require "../resources/images/ui2/no-contacts-dark.png")}
:no-contacts-to-chat
{:light (js/require "../resources/images/ui2/no-contacts-to-chat-light.png")
:dark (js/require "../resources/images/ui2/no-contacts-to-chat-dark.png")}
:keycard-chip :keycard-chip
{:light (js/require "../resources/images/ui2/keycard-chip-light.png") {:light (js/require "../resources/images/ui2/keycard-chip-light.png")
:dark (js/require "../resources/images/ui2/keycard-chip-dark.png")} :dark (js/require "../resources/images/ui2/keycard-chip-dark.png")}
+2 -8
View File
@@ -259,12 +259,6 @@
{:type :wallet-account {:type :wallet-account
:account (when account (string/lower-case account))}) :account (when account (string/lower-case account))})
(defn community-route-type
[route-params]
(if (string/starts-with? (:community-id route-params) "z")
:desktop-community
:community))
(defn handle-uri (defn handle-uri
[chain chats uri cb] [chain chats uri cb]
(let [{:keys [handler route-params query-params]} (match-uri uri)] (let [{:keys [handler route-params query-params]} (match-uri uri)]
@@ -297,14 +291,14 @@
(cb {:type handler :community-id (:community-id route-params)}) (cb {:type handler :community-id (:community-id route-params)})
(and (= handler :community) (:community-id route-params)) (and (= handler :community) (:community-id route-params))
(cb {:type (community-route-type route-params) (cb {:type :community
:community-id (:community-id route-params)}) :community-id (:community-id route-params)})
(and (= handler :community-chat) (:community-channel-id route-params) (:community-id route-params)) (and (= handler :community-chat) (:community-channel-id route-params) (:community-id route-params))
(match-community-channel-async route-params cb) (match-community-channel-async route-params cb)
(and (= handler :community-chat) (:community-id route-params)) (and (= handler :community-chat) (:community-id route-params))
(cb {:type (community-route-type route-params) (cb {:type :community
:community-id (:community-id route-params)}) :community-id (:community-id route-params)})
;; NOTE: removed in `match-uri`, might need this in the future ;; NOTE: removed in `match-uri`, might need this in the future
+27
View File
@@ -0,0 +1,27 @@
(ns status-im.common.serialization
(:require
[native-module.core :as native-module]
[status-im.constants :as constants]
[utils.re-frame :as rf]
[utils.transforms :as transforms]))
(rf/reg-fx :serialization/deserialize-and-compress-key
(fn [{:keys [serialized-key on-success on-error]}]
(native-module/deserialize-and-compress-key
serialized-key
(fn [resp]
(let [{:keys [error]} (transforms/json->clj resp)]
(if error
(on-error error)
(on-success resp)))))))
(rf/reg-fx :serialization/decompress-public-key
(fn [{:keys [compressed-key on-success on-error]}]
(native-module/compressed-key->public-key
compressed-key
constants/deserialization-key
(fn [resp]
(let [{:keys [error]} (transforms/json->clj resp)]
(if error
(on-error error)
(on-success (str "0x" (subs resp 5)))))))))
+4 -31
View File
@@ -2,12 +2,12 @@
(:require (:require
[clojure.string :as string] [clojure.string :as string]
[goog.string :as gstring] [goog.string :as gstring]
[native-module.core :as native-module]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[react-native.async-storage :as async-storage] [react-native.async-storage :as async-storage]
[react-native.core :as rn] [react-native.core :as rn]
[schema.core :as schema] [schema.core :as schema]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.contexts.communities.events :as communities.events]
[status-im.navigation.events :as navigation] [status-im.navigation.events :as navigation]
[taoensso.timbre :as log] [taoensso.timbre :as log]
[utils.ethereum.chain :as chain] [utils.ethereum.chain :as chain]
@@ -68,32 +68,6 @@
(log/info "universal-links: handling community request " community-id) (log/info "universal-links: handling community request " community-id)
(navigation/navigate-to cofx :community-requests-to-join {:community-id community-id})) (navigation/navigate-to cofx :community-requests-to-join {:community-id community-id}))
(rf/defn handle-community
[cofx {:keys [community-id]}]
(log/info "universal-links: handling community" community-id)
(navigation/navigate-to cofx :community {:community-id community-id}))
(rf/defn handle-navigation-to-desktop-community-from-mobile
{:events [:handle-navigation-to-desktop-community-from-mobile]}
[cofx deserialized-key]
(rf/merge
cofx
{:dispatch [:navigate-to :community-overview deserialized-key]}
(navigation/pop-to-root :shell-stack)))
(rf/defn handle-desktop-community
[_ {:keys [community-id]}]
(native-module/deserialize-and-compress-key
community-id
(fn [deserialized-key]
(rf/dispatch [:chat.ui/fetch-community (str deserialized-key)])
(rf/dispatch [:handle-navigation-to-desktop-community-from-mobile (str deserialized-key)]))))
(rf/defn handle-community-chat
[cofx {:keys [chat-id]}]
(log/info "universal-links: handling community chat" chat-id)
{:dispatch [:chat/pop-to-root-and-navigate-to-chat chat-id]})
(rf/defn handle-view-profile (rf/defn handle-view-profile
[{:keys [db] :as cofx} {:keys [public-key ens-name]}] [{:keys [db] :as cofx} {:keys [public-key ens-name]}]
(log/info "universal-links: handling view profile" public-key) (log/info "universal-links: handling view profile" public-key)
@@ -143,14 +117,13 @@
(rf/defn on-handle (rf/defn on-handle
{:events [::match-value]} {:events [::match-value]}
[cofx url {:keys [type] :as data}] [cofx url {:keys [type chat-id] :as data}]
(case type (case type
:group-chat (handle-group-chat cofx data) :group-chat (handle-group-chat cofx data)
:private-chat (handle-private-chat cofx data) :private-chat (handle-private-chat cofx data)
:community-requests (handle-community-requests cofx data) :community-requests (handle-community-requests cofx data)
:community (handle-community cofx data) :community (communities.events/navigate-to-serialized-community cofx data)
:desktop-community (handle-desktop-community cofx data) :community-chat {:dispatch [:communities/navigate-to-community-chat chat-id :pop-to-root]}
:community-chat (handle-community-chat cofx data)
:contact (handle-view-profile cofx data) :contact (handle-view-profile cofx data)
:browser (handle-browse cofx data) :browser (handle-browse cofx data)
:eip681 (handle-eip681 cofx data) :eip681 (handle-eip681 cofx data)
+7
View File
@@ -338,6 +338,13 @@
(def ^:const local-pairing-action-sync-device 3) (def ^:const local-pairing-action-sync-device 3)
(def ^:const local-pairing-action-pairing-installation 4) (def ^:const local-pairing-action-pairing-installation 4)
(def ^:const serialization-key
"We pass this serialization key as a parameter to MultiformatSerializePublicKey
function at status-go, This key determines the output base of the serialization.
according to https://specs.status.im/spec/2#public-key-serialization we serialize
keys with base58btc encoding"
"z")
(def ^:const deserialization-key (def ^:const deserialization-key
"We pass this deserialization key as a parameter to MultiformatDeserializePublicKey "We pass this deserialization key as a parameter to MultiformatDeserializePublicKey
function at status-go, This key determines the output base of the deserialization. function at status-go, This key determines the output base of the deserialization.
@@ -29,7 +29,7 @@
{:icon :i/add-user {:icon :i/add-user
:accessibility-label :add-a-contact :accessibility-label :add-a-contact
:label (i18n/label :t/add-a-contact) :label (i18n/label :t/add-a-contact)
:sub-label (i18n/label :t/enter-a-chat-key) :sub-label (i18n/label :t/enter-chat-key)
:add-divider? true :add-divider? true
:on-press #(debounce/dispatch-and-chill :on-press #(debounce/dispatch-and-chill
[:open-modal :new-contact] [:open-modal :new-contact]
@@ -1,21 +1,7 @@
(ns status-im.contexts.chat.home.add-new-contact.effects (ns status-im.contexts.chat.home.add-new-contact.effects
(:require (:require
[legacy.status-im.ethereum.ens :as ens] [legacy.status-im.ethereum.ens :as ens]
[native-module.core :as native-module] [utils.re-frame :as rf]))
[status-im.constants :as constants]
[utils.re-frame :as rf]
[utils.transforms :as transforms]))
(rf/reg-fx :effects.contacts/decompress-public-key
(fn [{:keys [compressed-key on-success on-error]}]
(native-module/compressed-key->public-key
compressed-key
constants/deserialization-key
(fn [resp]
(let [{:keys [error]} (transforms/json->clj resp)]
(if error
(on-error error)
(on-success (str "0x" (subs resp 5)))))))))
(rf/reg-fx :effects.contacts/resolve-public-key-from-ens (rf/reg-fx :effects.contacts/resolve-public-key-from-ens
(fn [{:keys [chain-id ens on-success on-error]}] (fn [{:keys [chain-id ens on-success on-error]}]
@@ -104,7 +104,7 @@
:empty {:db (dissoc db :contacts/new-identity)} :empty {:db (dissoc db :contacts/new-identity)}
(:valid :invalid) {:db (assoc db :contacts/new-identity contact)} (:valid :invalid) {:db (assoc db :contacts/new-identity contact)}
:decompress-key {:db (assoc db :contacts/new-identity contact) :decompress-key {:db (assoc db :contacts/new-identity contact)
:effects.contacts/decompress-public-key :serialization/decompress-public-key
{:compressed-key id {:compressed-key id
:on-success :on-success
(dispatcher :contacts/set-new-identity-success input) (dispatcher :contacts/set-new-identity-success input)
@@ -132,7 +132,7 @@
:type :compressed-key :type :compressed-key
:public-key nil ; not yet... :public-key nil ; not yet...
:state :decompress-key})) :state :decompress-key}))
:effects.contacts/decompress-public-key :serialization/decompress-public-key
{:compressed-key user-ckey {:compressed-key user-ckey
:on-success [:contacts/set-new-identity-success user-ckey] :on-success [:contacts/set-new-identity-success user-ckey]
:on-error [:contacts/set-new-identity-error user-ckey]}}))) :on-error [:contacts/set-new-identity-error user-ckey]}})))
@@ -21,7 +21,7 @@
[] []
{:size :heading-1 {:size :heading-1
:weight :semi-bold :weight :semi-bold
:style {:margin-top 32 :style {:margin-top 28
:margin-bottom 6 :margin-bottom 6
:color (colors/theme-colors colors/neutral-100 colors/white)}}) :color (colors/theme-colors colors/neutral-100 colors/white)}})
@@ -16,33 +16,38 @@
(defn- no-contacts-view (defn- no-contacts-view
[{:keys [theme]}] [{:keys [theme]}]
[rn/view (let [customization-color (rf/sub [:profile/customization-color])]
{:style (style/no-contacts)} [rn/view
[rn/image {:source (resources/get-themed-image :no-contacts theme)}] {:style (style/no-contacts)}
[quo/text [rn/image {:source (resources/get-themed-image :no-contacts-to-chat theme)}]
{:weight :semi-bold [quo/text
:size :paragraph-1 {:weight :semi-bold
:style {:margin-bottom 2 :size :paragraph-1
:margin-top 12}} :style {:margin-bottom 2
(i18n/label :t/you-have-no-contacts)] :margin-top 12}}
[quo/text (i18n/label :t/you-have-no-contacts)]
{:weight :regular [quo/text
:size :label} {:weight :regular
(i18n/label :t/dont-yell-at-me)] :size :paragraph-2}
[quo/button (i18n/label :t/dont-yell-at-me)]
{:type :primary [quo/button
:size 32 {:customization-color customization-color
:container-style {:margin-top 20 :theme theme
:margin-bottom 12} :type :primary
:on-press #(rf/dispatch [:invite.events/share-link])} :size 32
(i18n/label :t/invite-friends)] :container-style {:margin-top 20
[quo/button :margin-bottom 12}
{:type :grey :on-press #(rf/dispatch [:invite.events/share-link])}
:size 32 (i18n/label :t/invite-friends)]
:on-press #(do [quo/button
(rf/dispatch [:navigate-back]) {:customization-color customization-color
(rf/dispatch [:open-modal :new-contact]))} :theme theme
(i18n/label :t/add-a-contact)]]) :type :grey
:size 32
:on-press #(do
(rf/dispatch [:navigate-back])
(rf/dispatch [:open-modal :new-contact]))}
(i18n/label :t/add-a-contact)]]))
(defn contact-item-render (defn contact-item-render
[_] [_]
+5 -3
View File
@@ -73,7 +73,7 @@
:shared-value scroll-shared-value})}]))) :shared-value scroll-shared-value})}])))
(defn contact-item-render (defn contact-item-render
[{:keys [public-key] :as item}] [{:keys [public-key] :as item} theme]
(let [current-pk (rf/sub [:multiaccount/public-key]) (let [current-pk (rf/sub [:multiaccount/public-key])
show-profile-actions #(rf/dispatch [:show-bottom-sheet show-profile-actions #(rf/dispatch [:show-bottom-sheet
{:content (fn [] [actions/contact-actions item])}])] {:content (fn [] [actions/contact-actions item])}])]
@@ -83,7 +83,8 @@
:on-long-press show-profile-actions :on-long-press show-profile-actions
:accessory {:type :options :accessory {:type :options
:on-press show-profile-actions}}) :on-press show-profile-actions}})
item])) item
theme]))
(defn contacts (defn contacts
[{:keys [theme pending-contact-requests set-scroll-ref scroll-shared-value]}] [{:keys [theme pending-contact-requests set-scroll-ref scroll-shared-value]}]
@@ -105,7 +106,8 @@
:sections items :sections items
:sticky-section-headers-enabled false :sticky-section-headers-enabled false
:render-section-header-fn contact-list/contacts-section-header :render-section-header-fn contact-list/contacts-section-header
:render-fn contact-item-render :render-fn (fn [data]
(contact-item-render data theme))
:scroll-event-throttle 8 :scroll-event-throttle 8
:on-scroll #(common.banner/set-scroll-shared-value :on-scroll #(common.banner/set-scroll-shared-value
{:scroll-input (oops/oget % "nativeEvent.contentOffset.y") {:scroll-input (oops/oget % "nativeEvent.contentOffset.y")
@@ -30,7 +30,7 @@
(js/setTimeout #(reanimated/set-shared-value background-y (js/setTimeout #(reanimated/set-shared-value background-y
(- window-height)) (- window-height))
300) 300)
(rf/dispatch [:chat.ui/replace-mentions-and-send-current-message]) (rf/dispatch [:chat.ui/send-current-message])
(rf/dispatch [:chat.ui/set-input-maximized false]) (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-input-content-height comp-constants/input-height])
(rf/dispatch [:chat.ui/set-chat-input-text nil]) (rf/dispatch [:chat.ui/set-chat-input-text nil])
@@ -114,9 +114,8 @@
[{:keys [input-ref]} [{:keys [input-ref]}
{:keys [text-value saved-cursor-position cursor-position]} {:keys [text-value saved-cursor-position cursor-position]}
{:keys [edit input-with-mentions]} {:keys [edit input-with-mentions]}
messages-list-on-layout-finished?] chat-screen-layout-calculations-complete?]
(let [mention? (some #(= :mention (first %)) (seq input-with-mentions)) (let [mention? (some #(= :mention (first %)) (seq input-with-mentions))]
composer-just-opened? (not @messages-list-on-layout-finished?)]
(rn/use-effect (rn/use-effect
(fn [] (fn []
(let [mention-text (reduce (fn [acc item] (let [mention-text (reduce (fn [acc item]
@@ -128,7 +127,9 @@
;; NOTE: using text-value for cases when the user ;; NOTE: using text-value for cases when the user
;; leaves the app with an unfinished edit and re-opens ;; leaves the app with an unfinished edit and re-opens
;; the chat. ;; the chat.
(and (seq @text-value) composer-just-opened?) (and (seq @text-value)
(not (reanimated/get-shared-value
chat-screen-layout-calculations-complete?)))
@text-value @text-value
:else (get-in edit [:content :text])) :else (get-in edit [:content :text]))
selection-pos (count edit-text) selection-pos (count edit-text)
@@ -150,7 +151,9 @@
;; UI. This way, `on-focus` will trigger first without changing the height, after which ;; UI. This way, `on-focus` will trigger first without changing the height, after which
;; `on-content-size-change` will animate the height of the input based on the injected ;; `on-content-size-change` will animate the height of the input based on the injected
;; text. ;; text.
(js/setTimeout #(do (when @messages-list-on-layout-finished? (.focus ^js @input-ref)) (js/setTimeout #(do (when (reanimated/get-shared-value
chat-screen-layout-calculations-complete?)
(.focus ^js @input-ref))
(reagent/next-tick inject-edit-text)) (reagent/next-tick inject-edit-text))
600)))) 600))))
[(:message-id edit)]))) [(:message-id edit)])))
@@ -159,12 +162,12 @@
[{:keys [input-ref]} [{:keys [input-ref]}
{:keys [container-opacity]} {:keys [container-opacity]}
{:keys [reply]} {:keys [reply]}
messages-list-on-layout-finished?] chat-screen-layout-calculations-complete?]
(rn/use-effect (rn/use-effect
(fn [] (fn []
(when reply (when reply
(reanimated/animate container-opacity 1)) (reanimated/animate container-opacity 1))
(when (and reply @input-ref @messages-list-on-layout-finished?) (when (and reply @input-ref (reanimated/get-shared-value chat-screen-layout-calculations-complete?))
(js/setTimeout #(.focus ^js @input-ref) 600))) (js/setTimeout #(.focus ^js @input-ref) 600)))
[(:message-id reply)])) [(:message-id reply)]))
@@ -207,24 +207,12 @@
(link-preview/reset-unfurled) (link-preview/reset-unfurled)
(cancel-message-edit))) (cancel-message-edit)))
(rf/defn replace-mentions-and-send-current-message (rf/defn send-current-message
"Sends message from current chat input" "Sends message from current chat input"
{:events [:chat.ui/replace-mentions-and-send-current-message]} {:events [:chat.ui/send-current-message]}
[{{:keys [current-chat-id] :as db} :db}] [{{:keys [current-chat-id] :as db} :db :as cofx}]
(let [{:keys [input-text metadata]} (get-in db [:chat/inputs current-chat-id])] (let [{:keys [input-text metadata]} (get-in db [:chat/inputs current-chat-id])
{:json-rpc/call [{:method "wakuext_chatMentionReplaceWithPublicKey" editing-message (:editing-message metadata)]
:params [current-chat-id input-text] (if editing-message
:on-error #(log/error "[wakuext_chatMentionReplaceWithPublicKey] on-error" %) (send-edited-message cofx input-text editing-message)
:on-success #(rf/dispatch [:chat.ui/send-current-message-with-mentions (send-messages cofx input-text current-chat-id))))
current-chat-id
(:editing-message metadata)
input-text
%])}]}))
(rf/defn send-current-message-with-mentions
{:events [:chat.ui/send-current-message-with-mentions]}
[{:keys [db] :as cofx} current-chat-id editing-message input-text new-text]
(rf/merge cofx
(if editing-message
(send-edited-message new-text editing-message)
(send-messages new-text current-chat-id))))
@@ -127,8 +127,9 @@
(defn change-text (defn change-text
"Update `text-value`, update cursor selection, find links, find mentions" "Update `text-value`, update cursor selection, find links, find mentions"
[text [text
{:keys [input-ref record-reset-fn]} {:keys [input-ref record-reset-fn] :as props}
{:keys [text-value cursor-position recording?]}] {:keys [text-value cursor-position recording?]}
scroll-to-end]
(reset! text-value text) (reset! text-value text)
(reagent/next-tick #(when @input-ref (reagent/next-tick #(when @input-ref
(.setNativeProps ^js @input-ref (.setNativeProps ^js @input-ref
@@ -140,6 +141,8 @@
(rf/dispatch [:chat.ui/set-chat-input-text text]) (rf/dispatch [:chat.ui/set-chat-input-text text])
(debounce/debounce-and-dispatch [:link-preview/unfurl-urls text] (debounce/debounce-and-dispatch [:link-preview/unfurl-urls text]
constants/unfurl-debounce-ms) constants/unfurl-debounce-ms)
(when (string/ends-with? text (with-out-str (newline)))
(scroll-to-end props))
(if (string/ends-with? text "@") (if (string/ends-with? text "@")
(rf/dispatch [:mention/on-change-text text]) (rf/dispatch [:mention/on-change-text text])
(debounce/debounce-and-dispatch [:mention/on-change-text text] 300))) (debounce/debounce-and-dispatch [:mention/on-change-text text] 300)))
@@ -69,17 +69,11 @@
:min-height constants/input-height}) :min-height constants/input-height})
(defn input-text (defn input-text
[{:keys [saved-emoji-kb-extra-height]} [{:keys [maximized?]}
{:keys [focused? maximized?]} {:keys [theme]}]
{:keys [max-height theme]}]
(assoc typography/paragraph-1 (assoc typography/paragraph-1
:color (colors/theme-colors :black :white theme) :color (colors/theme-colors :black :white theme)
:text-align-vertical :top :text-align-vertical :top
:position (if @saved-emoji-kb-extra-height :relative :absolute)
:top 0
:left 0
:right (when (or focused? platform/ios?) 0)
:max-height max-height
:padding-bottom (when @maximized? 0))) :padding-bottom (when @maximized? 0)))
(defn background (defn background
@@ -175,7 +175,8 @@
:record-reset-fn (atom nil) :record-reset-fn (atom nil)
:scroll-y (atom 0) :scroll-y (atom 0)
:selection-event (atom nil) :selection-event (atom nil)
:selection-manager (rn/selectable-text-input-manager)}) :selection-manager (rn/selectable-text-input-manager)
:composer-scrollview-ref (atom nil)})
(defn init-reactive-state (defn init-reactive-state
[] []
@@ -31,12 +31,12 @@
(defn sheet-component (defn sheet-component
[{:keys [insets [{:keys [insets
chat-list-scroll-y chat-list-scroll-y
chat-screen-layout-calculations-complete?
window-height window-height
blur-height blur-height
opacity opacity
background-y background-y
theme theme]} props state]
messages-list-on-layout-finished?]} props state]
(let [subscriptions (utils/init-subs) (let [subscriptions (utils/init-subs)
content-height (reagent/atom (or (:input-content-height ; Actual text height content-height (reagent/atom (or (:input-content-height ; Actual text height
subscriptions) subscriptions)
@@ -68,15 +68,22 @@
;; Cursor position, needed to determine where to display the mentions view ;; Cursor position, needed to determine where to display the mentions view
cursor-pos (utils/cursor-y-position-relative-to-container cursor-pos (utils/cursor-y-position-relative-to-container
props props
state)] state)
scroll-to-end (fn []
;; Needs to be queued, Otherwise might not be called on the right
;; time.
(js/setTimeout #(when @(:composer-scrollview-ref props)
(.scrollToEnd @(:composer-scrollview-ref props)))
50))
chat-screen-loaded? (rf/sub [:shell/chat-screen-loaded?])]
(effects/did-mount props) (effects/did-mount props)
(effects/initialize props (effects/initialize props
state state
animations animations
dimensions dimensions
subscriptions) subscriptions)
(effects/use-edit props state subscriptions messages-list-on-layout-finished?) (effects/use-edit props state subscriptions chat-screen-layout-calculations-complete?)
(effects/use-reply props animations subscriptions messages-list-on-layout-finished?) (effects/use-reply props animations subscriptions chat-screen-layout-calculations-complete?)
(effects/update-input-mention props state subscriptions) (effects/update-input-mention props state subscriptions)
(effects/link-previews props state animations subscriptions) (effects/link-previews props state animations subscriptions)
(effects/use-images props state animations subscriptions) (effects/use-images props state animations subscriptions)
@@ -90,8 +97,7 @@
{:style style/composer-sheet-and-jump-to-container} {:style style/composer-sheet-and-jump-to-container}
[sub-view/shell-button state chat-list-scroll-y window-height] [sub-view/shell-button state chat-list-scroll-y window-height]
[gesture/gesture-detector [gesture/gesture-detector
{:gesture {:gesture (drag-gesture/drag-gesture props state animations dimensions keyboard-shown)}
(drag-gesture/drag-gesture props state animations dimensions keyboard-shown)}
[reanimated/view [reanimated/view
{:style (style/sheet-container insets state animations theme) {:style (style/sheet-container insets state animations theme)
:on-layout #(handler/layout % state blur-height)} :on-layout #(handler/layout % state blur-height)}
@@ -112,55 +118,60 @@
{:ref #(reset! (:selectable-input-ref props) %) {:ref #(reset! (:selectable-input-ref props) %)
:menu-items @(:menu-items state) :menu-items @(:menu-items state)
:style (style/input-view state)} :style (style/input-view state)}
[rn/text-input ;; https://github.com/facebook/react-native/issues/39660
{:ref #(reset! (:input-ref props) %) [rn/scroll-view
:default-value @(:text-value state) {:on-scroll #(handler/scroll % props state animations dimensions)
:on-focus #(handler/focus props state animations dimensions) :keyboard-should-persist-taps :handled
:on-blur #(handler/blur state animations dimensions subscriptions) :scroll-event-throttle 64
:on-content-size-change #(handler/content-size-change % :ref #(reset! (:composer-scrollview-ref props) %)
state :shows-vertical-scroll-indicator false}
animations [rn/text-input
dimensions {:ref #(reset! (:input-ref props) %)
(or keyboard-shown :default-value @(:text-value state)
(:edit subscriptions))) :on-focus #(handler/focus props state animations dimensions)
:on-scroll #(handler/scroll % props state animations dimensions) :on-blur #(handler/blur state animations dimensions subscriptions)
:on-change-text #(handler/change-text % props state) :on-change-text #(handler/change-text % props state scroll-to-end)
:on-selection-change #(handler/selection-change % props state) :on-selection-change #(handler/selection-change % props state)
:on-selection #(selection/on-selection % props state) :on-content-size-change #(handler/content-size-change %1
:keyboard-appearance (quo.theme/theme-value :light :dark) state
:max-font-size-multiplier 1 animations
:multiline true dimensions
:placeholder (i18n/label :t/type-something) (or keyboard-shown
:placeholder-text-color (colors/theme-colors colors/neutral-40 colors/neutral-50) (:edit subscriptions)))
:style (style/input-text props :on-selection #(selection/on-selection % props state)
state :keyboard-appearance (quo.theme/theme-value :light :dark)
{:max-height max-height :max-font-size-multiplier 1
:theme theme}) :multiline true
:max-length constants/max-text-size :scroll-enabled false
:accessibility-label :chat-message-input}]]] :placeholder (i18n/label :t/type-something)
[:<> :placeholder-text-color (colors/theme-colors colors/neutral-40 colors/neutral-50)
[gradients/view props state animations show-bottom-gradient?] :style (style/input-text state
[link-preview/view] {:max-height max-height
[images/images-list]] :theme theme})
:max-length constants/max-text-size
:accessibility-label :chat-message-input}]]]]
(when chat-screen-loaded?
[:<>
[gradients/view props state animations show-bottom-gradient?]
[link-preview/view]
[images/images-list]])
[:f> actions/view props state animations window-height insets subscriptions]]]]])) [:f> actions/view props state animations window-height insets subscriptions]]]]]))
(defn f-composer (defn f-composer
[{:keys [insets chat-list-scroll-y messages-list-on-layout-finished?]}] [props]
(let [window-height (:height (rn/get-window)) (let [window-height (:height (rn/get-window))
theme (quo.theme/use-theme-value) theme (quo.theme/use-theme-value)
opacity (reanimated/use-shared-value 0) opacity (reanimated/use-shared-value 0)
background-y (reanimated/use-shared-value (- window-height)) ; Y position of background background-y (reanimated/use-shared-value (- window-height)) ; Y position of background
; overlay ; overlay
blur-height (reanimated/use-shared-value (+ constants/composer-default-height blur-height (reanimated/use-shared-value (+ constants/composer-default-height
(:bottom insets))) (:bottom (:insets props))))
extra-params {:insets insets extra-params (assoc props
:window-height window-height :window-height window-height
:chat-list-scroll-y chat-list-scroll-y :blur-height blur-height
:blur-height blur-height :opacity opacity
:opacity opacity :background-y background-y
:background-y background-y :theme theme)
:theme theme
:messages-list-on-layout-finished? messages-list-on-layout-finished?}
props (utils/init-non-reactive-state) props (utils/init-non-reactive-state)
state (utils/init-reactive-state)] state (utils/init-reactive-state)]
[rn/view (when platform/ios? {:style {:z-index 1}}) [rn/view (when platform/ios? {:style {:z-index 1}})
@@ -52,7 +52,7 @@
(get constants/reactions (:emoji-id reaction)))) (get constants/reactions (:emoji-id reaction))))
(defn- view-internal (defn- view-internal
[{:keys [message-id chat-id pinned-by theme]} user-message-content] [{:keys [message-id chat-id pinned-by preview? theme]} user-message-content]
(let [reactions (rf/sub [:chats/message-reactions message-id chat-id])] (let [reactions (rf/sub [:chats/message-reactions message-id chat-id])]
[:<> [:<>
(when (seq reactions) (when (seq reactions)
@@ -60,7 +60,7 @@
{:container-style {:margin-left 44 {:container-style {:margin-left 44
:margin-top 8} :margin-top 8}
:reactions (map add-emoji-key reactions) :reactions (map add-emoji-key reactions)
:add-reaction? true :add-reaction? (not preview?)
:use-case (when pinned-by :pinned) :use-case (when pinned-by :pinned)
:on-press #(on-press (assoc % :message-id message-id)) :on-press #(on-press (assoc % :message-id message-id))
:on-long-press #(on-long-press (assoc % :on-long-press #(on-long-press (assoc %
@@ -2,6 +2,8 @@
(:require (:require
[quo.foundations.colors :as colors])) [quo.foundations.colors :as colors]))
(def ^:private message-padding-scaling-ratio 4.5)
(defn message-container (defn message-container
([] ([]
(message-container false nil nil false)) (message-container false nil nil false))
@@ -16,10 +18,16 @@
(assoc :margin-top 4)))) (assoc :margin-top 4))))
(defn user-message-content (defn user-message-content
[{:keys [outgoing outgoing-status]}] [{:keys [outgoing outgoing-status six-reactions? window-scale small-screen?]}]
{:border-radius 16 {:border-radius 16
:padding-horizontal 8 :padding-horizontal 8
:padding-vertical 4 :padding-top 4
:padding-bottom (if (or small-screen?
(and
(> 3 window-scale)
six-reactions?))
(* message-padding-scaling-ratio window-scale)
4)
:opacity (if (and outgoing (= outgoing-status :sending)) :opacity (if (and outgoing (= outgoing-status :sending))
0.5 0.5
1)}) 1)})
@@ -119,31 +119,38 @@
[] []
(let [show-delivery-state? (reagent/atom false)] (let [show-delivery-state? (reagent/atom false)]
(fn [{:keys [message-data context keyboard-shown? show-reactions? in-reaction-and-action-menu? (fn [{:keys [message-data context keyboard-shown? show-reactions? in-reaction-and-action-menu?
show-user-info? theme]}] show-user-info? preview? theme]}]
(let [{:keys [content-type quoted-message content (let [{:keys [content-type quoted-message content
outgoing outgoing-status pinned-by]} message-data outgoing outgoing-status pinned-by
first-image (first (:album message-data)) message-id chat-id]} message-data
outgoing-status (if (= content-type first-image (first (:album message-data))
constants/content-type-album) outgoing-status (if (= content-type
(:outgoing-status first-image) constants/content-type-album)
outgoing-status) (:outgoing-status first-image)
outgoing (if (= content-type outgoing-status)
constants/content-type-album) outgoing (if (= content-type
(:outgoing first-image) constants/content-type-album)
outgoing) (:outgoing first-image)
context (assoc context outgoing)
:on-long-press context (assoc context
#(on-long-press message-data :on-long-press
context #(on-long-press message-data
keyboard-shown?)) context
response-to (:response-to content) keyboard-shown?))
height (rf/sub [:dimensions/window-height]) response-to (:response-to content)
{window-width :width} (rn/get-window) height (rf/sub [:dimensions/window-height])
message-container-data {:window-width window-width {window-width :width
:padding-right 20 window-scale :scale} (rn/get-window)
:padding-left 20 message-container-data {:window-width window-width
:avatar-container-width 32 :padding-right 20
:message-margin-left 8}] :padding-left 20
:avatar-container-width 32
:message-margin-left 8}
reactions (rf/sub [:chats/message-reactions message-id
chat-id])
six-reactions? (-> reactions
count
(= 6))]
[rn/touchable-highlight [rn/touchable-highlight
{:accessibility-label (if (and outgoing (= outgoing-status :sending)) {:accessibility-label (if (and outgoing (= outgoing-status :sending))
:message-sending :message-sending
@@ -152,7 +159,10 @@
:style (style/user-message-content :style (style/user-message-content
{:first-in-group? (:first-in-group? message-data) {:first-in-group? (:first-in-group? message-data)
:outgoing outgoing :outgoing outgoing
:outgoing-status outgoing-status}) :outgoing-status outgoing-status
:small-screen? rn/small-screen?
:window-scale window-scale
:six-reactions? six-reactions?})
:on-press (fn [] :on-press (fn []
(if (and platform/ios? keyboard-shown?) (if (and platform/ios? keyboard-shown?)
(do (do
@@ -212,7 +222,7 @@
(when @show-delivery-state? (when @show-delivery-state?
[status/status outgoing-status])])] [status/status outgoing-status])])]
(when show-reactions? (when show-reactions?
[reactions/message-reactions-row message-data [reactions/message-reactions-row (assoc message-data :preview? preview?)
[rn/view {:pointer-events :none} [rn/view {:pointer-events :none}
[user-message-content-internal [user-message-content-internal
{:theme theme {:theme theme
@@ -226,22 +236,24 @@
(defn on-long-press (defn on-long-press
[{:keys [deleted? deleted-for-me?] :as message-data} context keyboard-shown?] [{:keys [deleted? deleted-for-me?] :as message-data} context keyboard-shown?]
(rf/dispatch [:dismiss-keyboard]) (rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:show-bottom-sheet (rf/dispatch
{:content (drawers/reactions-and-actions message-data context) [:show-bottom-sheet
:border-radius 16 {:content (drawers/reactions-and-actions message-data context)
:selected-item :border-radius 16
(if (or deleted? deleted-for-me?) :selected-item
(fn [] [content.deleted/deleted-message message-data]) (if (or deleted? deleted-for-me?)
(fn [] (fn [] [content.deleted/deleted-message message-data])
[rn/view (fn []
{:pointer-events :none [rn/view
:padding-top 4} {:pointer-events :none
[user-message-content :padding-top 4}
{:message-data message-data [user-message-content
:context context {:message-data message-data
:keyboard-shown? keyboard-shown? :context context
:show-reactions? true :keyboard-shown? keyboard-shown?
:show-user-info? true}]]))}])) :show-reactions? true
:show-user-info? true
:preview? true}]]))}]))
(defn system-message? (defn system-message?
[content-type] [content-type]
@@ -8,9 +8,7 @@
:justify-content :center}) :justify-content :center})
(def tab-icon (def tab-icon
{:margin-right 4 {:margin-right 4})
:width 20
:height 20})
(defn tab-count (defn tab-count
[active? theme] [active? theme]
@@ -34,10 +34,10 @@
{:id reaction-type-int {:id reaction-type-int
:accessibility-label (keyword (str "authors-for-reaction-" reaction-type-int)) :accessibility-label (keyword (str "authors-for-reaction-" reaction-type-int))
:label [rn/view {:style style/tab} :label [rn/view {:style style/tab}
[rn/image [rn/text
{:source (reactions.resource/get-reaction {:style style/tab-icon}
(get constants/reactions reaction-type-int)) (reactions.resource/system-emojis
:style style/tab-icon}] (get constants/reactions reaction-type-int))]
[quo/text [quo/text
{:weight :medium {:weight :medium
:size :paragraph-1 :size :paragraph-1
@@ -1,8 +1,6 @@
(ns status-im.contexts.chat.messenger.messages.link-preview.events (ns status-im.contexts.chat.messenger.messages.link-preview.events
(:require (:require
[camel-snake-kebab.core :as csk] [camel-snake-kebab.core :as csk]
[legacy.status-im.mailserver.core :as mailserver]
[schema.core :as schema]
[status-im.contexts.profile.settings.events :as profile.settings.events] [status-im.contexts.profile.settings.events :as profile.settings.events]
[taoensso.timbre :as log] [taoensso.timbre :as log]
[utils.collection] [utils.collection]
@@ -42,96 +40,6 @@
(boolean enabled?) (boolean enabled?)
{})) {}))
(defn community-resolved
[{:keys [db]} [community-id community]]
(when community
{:db (update db :communities/resolve-community-info dissoc community-id)
:fx [[:dispatch [:communities/handle-community community]]
[:dispatch
[:chat.ui/cache-link-preview-data (community-link community-id) community]]]}))
(rf/reg-event-fx :chat.ui/community-resolved community-resolved)
(defn community-failed-to-resolve
[{:keys [db]} [community-id]]
{:db (update db :communities/resolve-community-info dissoc community-id)})
(rf/reg-event-fx :chat.ui/community-failed-to-resolve community-failed-to-resolve)
(defn fetch-community
[{:keys [db]} [community-id]]
(when community-id
{:db (assoc-in db [:communities/resolve-community-info community-id] true)
:json-rpc/call [{:method "wakuext_fetchCommunity"
:params [{:CommunityKey community-id
:TryDatabase true
:WaitForResponse true}]
:on-success (fn [community]
(rf/dispatch [:chat.ui/community-resolved community-id community]))
:on-error (fn [err]
(rf/dispatch [:chat.ui/community-failed-to-resolve community-id])
(log/error {:message
"Failed to request community info from mailserver"
:error err}))}]}))
(schema/=> fetch-community
[:=>
[:catn
[:cofx :schema.re-frame/cofx]
[:args
[:schema [:catn [:community-id [:? :string]]]]]]
[:maybe
[:map
[:db map?]
[:json-rpc/call :schema.common/rpc-call]]]])
(rf/reg-event-fx :chat.ui/fetch-community fetch-community)
(defn spectate-community-success
[{:keys [db]} [{:keys [communities]}]]
(when-let [community (first communities)]
{:db (-> db
(assoc-in [:communities (:id community) :spectated] true)
(assoc-in [:communities (:id community) :spectating] false))
:fx [[:dispatch [:communities/handle-community community]]
[:dispatch [::mailserver/request-messages]]]}))
(rf/reg-event-fx :chat.ui/spectate-community-success spectate-community-success)
(defn spectate-community-failed
[{:keys [db]} [community-id]]
{:db (assoc-in db [:communities community-id :spectating] false)})
(rf/reg-event-fx :chat.ui/spectate-community-failed spectate-community-failed)
(defn spectate-community
[{:keys [db]} [community-id]]
(let [{:keys [spectated spectating joined]} (get-in db [:communities community-id])]
(when (and (not joined) (not spectated) (not spectating))
{:db (assoc-in db [:communities community-id :spectating] true)
:json-rpc/call [{:method "wakuext_spectateCommunity"
:params [community-id]
:on-success [:chat.ui/spectate-community-success]
:on-error (fn [err]
(log/error {:message
"Failed to spectate community"
:error err})
(rf/dispatch [:chat.ui/spectate-community-failed
community-id]))}]})))
(schema/=> spectate-community
[:=>
[:catn
[:cofx :schema.re-frame/cofx]
[:args
[:schema [:catn [:community-id [:? :string]]]]]]
[:maybe
[:map
[:db map?]
[:json-rpc/call :schema.common/rpc-call]]]])
(rf/reg-event-fx :chat.ui/spectate-community spectate-community)
(rf/defn save-link-preview-whitelist (rf/defn save-link-preview-whitelist
{:events [:chat.ui/link-preview-whitelist-received]} {:events [:chat.ui/link-preview-whitelist-received]}
[{:keys [db]} whitelist] [{:keys [db]} whitelist]
@@ -1,139 +0,0 @@
(ns status-im.contexts.chat.messenger.messages.link-preview.events-test
(:require [cljs.test :as t]
[legacy.status-im.mailserver.core :as mailserver]
matcher-combinators.test
[status-im.contexts.chat.messenger.messages.link-preview.events :as sut]))
(t/deftest fetch-community
(t/testing "with community id"
(t/testing "update resolving indicator in db"
(t/is (match?
{:db {:communities/resolve-community-info {"community-id" true}}}
(sut/fetch-community {} ["community-id"]))))
(t/testing "call the fetch community rpc method with correct community id"
(t/is (match?
{:json-rpc/call [{:method "wakuext_fetchCommunity"
:params [{:CommunityKey "community-id"
:TryDatabase true
:WaitForResponse true}]}]}
(sut/fetch-community {} ["community-id"])))))
(t/testing "with no community id"
(t/testing "do nothing"
(t/is (match?
nil
(sut/fetch-community {} []))))))
(t/deftest community-failed-to-resolve
(t/testing "given a community id"
(t/testing "remove community id from resolving indicator in db"
(t/is (match?
nil
(get-in (sut/community-failed-to-resolve {:db {:communities/resolve-community-info
{"community-id" true}}}
["community-id"])
[:db :communities/resolve-community-info "community-id"]))))))
(t/deftest community-resolved
(with-redefs [sut/community-link (fn [id] (str "community-link+" id))]
(t/testing "given a community"
(let [cofx {:db {:communities/resolve-community-info {"community-id" true}}}
arg ["community-id" {:id "community-id"}]]
(t/testing "remove community id from resolving indicator in db"
(t/is (match?
nil
(get-in (sut/community-resolved cofx arg)
[:db :communities/resolve-community-info "community-id"]))))
(t/testing "dispatch fxs"
(t/is (match?
{:fx [[:dispatch [:communities/handle-community {:id "community-id"}]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id "community-id"}]]]}
(sut/community-resolved cofx arg))))))
(t/testing "given a joined community"
(let [cofx {:db {:communities/resolve-community-info {"community-id" true}}}
arg ["community-id" {:id "community-id" :joined true}]]
(t/testing "dispatch fxs, do not spectate community"
(t/is (match?
{:fx [[:dispatch [:communities/handle-community {:id "community-id"}]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id "community-id"}]]]}
(sut/community-resolved cofx arg))))))
(t/testing "given a token-gated community"
(let [cofx {:db {:communities/resolve-community-info {"community-id" true}}}
arg ["community-id" {:id "community-id" :tokenPermissions [1]}]]
(t/testing "dispatch fxs, do not spectate community"
(t/is (match?
{:fx [[:dispatch [:communities/handle-community {:id "community-id"}]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id "community-id"}]]]}
(sut/community-resolved cofx arg))))))
(t/testing "given nil community"
(t/testing "do nothing"
(t/is (match?
nil
(sut/community-resolved {} ["community-id" nil])))))))
(t/deftest spectate-community
(t/testing "given a joined community"
(t/testing "do nothing"
(t/is (match?
nil
(sut/spectate-community {:db {:communities {"community-id" {:joined true}}}}
["community-id"])))))
(t/testing "given a spectated community"
(t/testing "do nothing"
(t/is (match?
nil
(sut/spectate-community {:db {:communities {"community-id" {:spectated true}}}}
["community-id"])))))
(t/testing "given a spectating community"
(t/testing "do nothing"
(t/is (match?
nil
(sut/spectate-community {:db {:communities {"community-id" {:spectating true}}}}
["community-id"])))))
(t/testing "given a community"
(t/testing "mark community spectating"
(t/is (match?
{:db {:communities {"community-id" {:spectating true}}}}
(sut/spectate-community {:db {:communities {"community-id" {}}}} ["community-id"]))))
(t/testing "call spectate community rpc with correct community id"
(t/is (match?
{:json-rpc/call [{:method "wakuext_spectateCommunity"
:params ["community-id"]}]}
(sut/spectate-community {:db {:communities {"community-id" {}}}} ["community-id"]))))))
(t/deftest spectate-community-failed
(t/testing "mark community spectating false"
(t/is (match?
{:db {:communities {"community-id" {:spectating false}}}}
(sut/spectate-community-failed {} ["community-id"])))))
(t/deftest spectate-community-success
(t/testing "given communities"
(t/testing "mark first community spectating false"
(t/is (match?
{:db {:communities {"community-id" {:spectating false}}}}
(sut/spectate-community-success {} [{:communities [{:id "community-id"}]}]))))
(t/testing "mark first community spectated true"
(t/is (match?
{:db {:communities {"community-id" {:spectated true}}}}
(sut/spectate-community-success {} [{:communities [{:id "community-id"}]}]))))
(t/testing "dispatch fxs for first community"
(t/is (match?
{:fx [[:dispatch [:communities/handle-community {:id "community-id"}]]
[:dispatch [::mailserver/request-messages]]]}
(sut/spectate-community-success {} [{:communities [{:id "community-id"}]}])))))
(t/testing "given empty community"
(t/testing "do nothing"
(t/is (match?
nil
(sut/spectate-community-success {} [{:communities []}])))))
(t/testing "given nil community"
(t/testing "do nothing"
(t/is (match?
nil
(sut/spectate-community-success {} []))))))
@@ -81,7 +81,7 @@
(fn [] (fn []
(when-not cached-preview-data (when-not cached-preview-data
(let [community-id (community-id-from-link community-link)] (let [community-id (community-id-from-link community-link)]
(rf/dispatch [:chat.ui/fetch-community community-id])))) (rf/dispatch [:communities/fetch-community community-id]))))
:reagent-render :reagent-render
(fn [] (fn []
(when cached-preview-data (when cached-preview-data
@@ -159,7 +159,7 @@
unmute-chat-label unmute-chat-label
mute-chat-label)) mute-chat-label))
:color cover-bg-color :color cover-bg-color
:icon (if muted? :i/muted :i/activity-center) :icon (if muted? :i/activity-center :i/muted)
:on-press (fn [] :on-press (fn []
(if muted? (if muted?
(home.actions/unmute-chat-action chat-id) (home.actions/unmute-chat-action chat-id)
@@ -267,7 +267,7 @@
(defn on-layout (defn on-layout
[{:keys [event layout-height distance-atom distance-from-list-top [{:keys [event layout-height distance-atom distance-from-list-top
calculations-complete? messages-list-on-layout-finished?]}] chat-screen-layout-calculations-complete?]}]
(let [layout-height-new (oops/oget event "nativeEvent.layout.height") (let [layout-height-new (oops/oget event "nativeEvent.layout.height")
change (- layout-height-new @layout-height) change (- layout-height-new @layout-height)
new-distance (- @distance-atom change)] new-distance (- @distance-atom change)]
@@ -275,9 +275,8 @@
(reanimated/set-shared-value distance-from-list-top new-distance) (reanimated/set-shared-value distance-from-list-top new-distance)
(reset! distance-atom new-distance) (reset! distance-atom new-distance)
(reset! layout-height layout-height-new)) (reset! layout-height layout-height-new))
(when-not (reanimated/get-shared-value calculations-complete?) (when-not (reanimated/get-shared-value chat-screen-layout-calculations-complete?)
(reanimated/set-shared-value calculations-complete? true)) (reanimated/set-shared-value chat-screen-layout-calculations-complete? true))))
(js/setTimeout #(reset! messages-list-on-layout-finished? true) 1000)))
(defn on-scroll-fn (defn on-scroll-fn
[distance-atom layout-height-atom] [distance-atom layout-height-atom]
@@ -288,7 +287,7 @@
(defn f-messages-list-content (defn f-messages-list-content
[{:keys [insets distance-from-list-top content-height layout-height cover-bg-color distance-atom [{:keys [insets distance-from-list-top content-height layout-height cover-bg-color distance-atom
calculations-complete? messages-list-on-layout-finished? chat-list-scroll-y]}] chat-screen-layout-calculations-complete? chat-list-scroll-y]}]
(let [theme (quo.theme/use-theme-value) (let [theme (quo.theme/use-theme-value)
chat (rf/sub [:chats/current-chat-chat-view]) chat (rf/sub [:chats/current-chat-chat-view])
{:keys [keyboard-shown]} (hooks/use-keyboard) {:keys [keyboard-shown]} (hooks/use-keyboard)
@@ -351,8 +350,7 @@
:layout-height layout-height :layout-height layout-height
:distance-atom distance-atom :distance-atom distance-atom
:distance-from-list-top distance-from-list-top :distance-from-list-top distance-from-list-top
:calculations-complete? calculations-complete? :chat-screen-layout-calculations-complete?
:messages-list-on-layout-finished? chat-screen-layout-calculations-complete?})
messages-list-on-layout-finished?})
:scroll-enabled (not recording?) :scroll-enabled (not recording?)
:content-inset-adjustment-behavior :never}]]])) :content-inset-adjustment-behavior :never}]]]))
@@ -18,7 +18,7 @@
[utils.worklets.chat.messenger.navigation :as worklets])) [utils.worklets.chat.messenger.navigation :as worklets]))
(defn f-header-content-container (defn f-header-content-container
[{:keys [chat distance-from-list-top all-loaded? calculations-complete?]}] [{:keys [chat distance-from-list-top all-loaded? chat-screen-layout-calculations-complete?]}]
(let [{:keys [chat-id group-chat chat-type chat-name (let [{:keys [chat-id group-chat chat-type chat-name
emoji]} chat emoji]} chat
display-name (cond display-name (cond
@@ -34,7 +34,7 @@
header-opacity (worklets/navigation-header-opacity header-opacity (worklets/navigation-header-opacity
distance-from-list-top distance-from-list-top
all-loaded? all-loaded?
calculations-complete? chat-screen-layout-calculations-complete?
(if platform/ios? (if platform/ios?
messages.constants/content-animation-start-position-ios messages.constants/content-animation-start-position-ios
messages.constants/content-animation-start-position-android)) messages.constants/content-animation-start-position-android))
@@ -104,7 +104,7 @@
:top-offset navigation-view-height}]])) :top-offset navigation-view-height}]]))
(defn f-view (defn f-view
[{:keys [distance-from-list-top calculations-complete?]}] [{:keys [distance-from-list-top chat-screen-layout-calculations-complete?]}]
(let [{:keys [chat-id chat-type] :as chat} (rf/sub [:chats/current-chat-chat-view]) (let [{:keys [chat-id chat-type] :as chat} (rf/sub [:chats/current-chat-chat-view])
all-loaded? (reanimated/use-shared-value false) all-loaded? (reanimated/use-shared-value false)
all-loaded-sub (rf/sub [:chats/all-loaded? chat-id]) all-loaded-sub (rf/sub [:chats/all-loaded? chat-id])
@@ -129,10 +129,10 @@
:on-press #(rf/dispatch [:navigate-back])} :on-press #(rf/dispatch [:navigate-back])}
(if (= chat-type constants/community-chat-type) :i/arrow-left :i/close)] (if (= chat-type constants/community-chat-type) :i/arrow-left :i/close)]
[:f> f-header-content-container [:f> f-header-content-container
{:chat chat {:chat chat
:distance-from-list-top distance-from-list-top :distance-from-list-top distance-from-list-top
:all-loaded? all-loaded? :all-loaded? all-loaded?
:calculations-complete? calculations-complete?}] :chat-screen-layout-calculations-complete? chat-screen-layout-calculations-complete?}]
[quo/button [quo/button
{:icon-only? true {:icon-only? true
:type :grey :type :grey
@@ -3,7 +3,6 @@
[react-native.core :as rn] [react-native.core :as rn]
[react-native.reanimated :as reanimated] [react-native.reanimated :as reanimated]
[react-native.safe-area :as safe-area] [react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im.contexts.chat.messenger.composer.view :as composer.view] [status-im.contexts.chat.messenger.composer.view :as composer.view]
[status-im.contexts.chat.messenger.messages.list.style :as style] [status-im.contexts.chat.messenger.messages.list.style :as style]
[status-im.contexts.chat.messenger.messages.list.view :as list.view] [status-im.contexts.chat.messenger.messages.list.view :as list.view]
@@ -15,49 +14,47 @@
;; improvement. Please avoid refactoring these files. Also if you are not already working on bug ;; improvement. Please avoid refactoring these files. Also if you are not already working on bug
;; fixes related to the composer, please skip them. And ping me, so I can address them while refactoring ;; fixes related to the composer, please skip them. And ping me, so I can address them while refactoring
(defn- f-chat-screen (defn- f-chat-screen
[calculations-complete?] [chat-screen-layout-calculations-complete?]
(let [insets (safe-area/get-insets) (let [insets (safe-area/get-insets)
content-height (atom 0) content-height (atom 0)
layout-height (atom 0) layout-height (atom 0)
distance-atom (atom 0) distance-atom (atom 0)
messages-list-on-layout-finished? (reagent/atom false) distance-from-list-top (reanimated/use-shared-value 0)
distance-from-list-top (reanimated/use-shared-value 0) chat-list-scroll-y (reanimated/use-shared-value 0)]
chat-list-scroll-y (reanimated/use-shared-value 0)]
[rn/keyboard-avoiding-view [rn/keyboard-avoiding-view
{:style style/keyboard-avoiding-container {:style style/keyboard-avoiding-container
:keyboard-vertical-offset (- (:bottom insets))} :keyboard-vertical-offset (- (:bottom insets))}
[:f> messages.navigation/f-view [:f> messages.navigation/f-view
{:distance-from-list-top distance-from-list-top {:distance-from-list-top distance-from-list-top
:calculations-complete? calculations-complete?}] :chat-screen-layout-calculations-complete? chat-screen-layout-calculations-complete?}]
[:f> list.view/f-messages-list-content [:f> list.view/f-messages-list-content
{:insets insets {:insets insets
:layout-height layout-height :layout-height layout-height
:content-height content-height :content-height content-height
:distance-atom distance-atom :distance-atom distance-atom
:calculations-complete? calculations-complete? :chat-screen-layout-calculations-complete? chat-screen-layout-calculations-complete?
:distance-from-list-top distance-from-list-top :distance-from-list-top distance-from-list-top
:chat-list-scroll-y chat-list-scroll-y :chat-list-scroll-y chat-list-scroll-y
:messages-list-on-layout-finished? messages-list-on-layout-finished? :cover-bg-color :turquoise}]
:cover-bg-color :turquoise}]
[composer.view/composer [composer.view/composer
{:insets insets {:insets insets
:chat-list-scroll-y chat-list-scroll-y :chat-screen-layout-calculations-complete? chat-screen-layout-calculations-complete?
:messages-list-on-layout-finished? messages-list-on-layout-finished?}]])) :chat-list-scroll-y chat-list-scroll-y}]]))
(defn lazy-chat-screen (defn lazy-chat-screen
[calculations-complete?] [chat-screen-layout-calculations-complete?]
(let [screen-loaded? (rf/sub [:shell/chat-screen-loaded?])] (let [screen-loaded? (rf/sub [:shell/chat-screen-loaded?])]
(when-not screen-loaded? (when-not screen-loaded?
(reanimated/set-shared-value calculations-complete? false)) (reanimated/set-shared-value chat-screen-layout-calculations-complete? false))
(when screen-loaded? (when screen-loaded?
[:f> f-chat-screen calculations-complete?]))) [:f> f-chat-screen chat-screen-layout-calculations-complete?])))
(defn- f-chat (defn- f-chat
[] []
(let [calculations-complete? (reanimated/use-shared-value false)] (let [chat-screen-layout-calculations-complete? (reanimated/use-shared-value false)]
[:<> [:<>
[lazy-chat-screen calculations-complete?] [lazy-chat-screen chat-screen-layout-calculations-complete?]
[:f> placeholder.view/f-view calculations-complete?]])) [:f> placeholder.view/f-view chat-screen-layout-calculations-complete?]]))
(defn chat (defn chat
[] []
@@ -15,9 +15,9 @@
:animated? false}]) :animated? false}])
(defn f-view (defn f-view
[calculations-complete?] [chat-screen-layout-calculations-complete?]
(let [top (safe-area/get-top) (let [top (safe-area/get-top)
opacity (worklets/placeholder-opacity calculations-complete?) opacity (worklets/placeholder-opacity chat-screen-layout-calculations-complete?)
z-index (worklets/placeholder-z-index calculations-complete?)] z-index (worklets/placeholder-z-index chat-screen-layout-calculations-complete?)]
[reanimated/view {:style (style/container top opacity z-index)} [reanimated/view {:style (style/container top opacity z-index)}
[loading-skeleton]])) [loading-skeleton]]))
@@ -23,11 +23,8 @@
[] []
(let [{id :community-id} (rf/sub [:get-screen-params]) (let [{id :community-id} (rf/sub [:get-screen-params])
{:keys [name color images]} (rf/sub [:communities/community id]) {:keys [name color images]} (rf/sub [:communities/community id])
airdrop-account (rf/sub [:communities/airdrop-account]) airdrop-account (rf/sub [:communities/airdrop-account id])
selected-accounts (rf/sub [:communities/selected-permission-accounts])] selected-accounts (rf/sub [:communities/selected-permission-accounts id])]
(rn/use-effect (fn []
(rf/dispatch [:communities/initialize-permission-addresses]))
[])
[rn/view {:style style/container} [rn/view {:style style/container}
[quo/page-nav [quo/page-nav
{:text-align :left {:text-align :left
@@ -8,7 +8,7 @@
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
(defn- account-item (defn- account-item
[item _ _ selected-addresses] [item _ _ [selected-addresses community-id]]
[quo/account-permissions [quo/account-permissions
{:account {:name (:name item) {:account {:name (:name item)
:address (:address item) :address (:address item)
@@ -17,7 +17,7 @@
:token-details [] :token-details []
:checked? (contains? selected-addresses (:address item)) :checked? (contains? selected-addresses (:address item))
:on-change #(rf/dispatch [:communities/toggle-selected-permission-address :on-change #(rf/dispatch [:communities/toggle-selected-permission-address
(:address item)]) (:address item) community-id])
:container-style {:margin-bottom 8}}]) :container-style {:margin-bottom 8}}])
(defn view (defn view
@@ -25,7 +25,7 @@
(let [{id :community-id} (rf/sub [:get-screen-params]) (let [{id :community-id} (rf/sub [:get-screen-params])
{:keys [name color images]} (rf/sub [:communities/community id]) {:keys [name color images]} (rf/sub [:communities/community id])
accounts (rf/sub [:wallet/accounts-with-customization-color]) accounts (rf/sub [:wallet/accounts-with-customization-color])
selected-addresses (rf/sub [:communities/selected-permission-addresses])] selected-addresses (rf/sub [:communities/selected-permission-addresses id])]
[rn/safe-area-view {:style style/container} [rn/safe-area-view {:style style/container}
[quo/drawer-top [quo/drawer-top
{:type :context-tag {:type :context-tag
@@ -38,7 +38,7 @@
[rn/flat-list [rn/flat-list
{:render-fn account-item {:render-fn account-item
:render-data selected-addresses :render-data [selected-addresses id]
:content-container-style {:padding 20} :content-container-style {:padding 20}
:key-fn :address :key-fn :address
:data accounts}] :data accounts}]
@@ -60,7 +60,7 @@
{:type :grey {:type :grey
:container-style {:flex 1} :container-style {:flex 1}
:on-press (fn [] :on-press (fn []
(rf/dispatch [:communities/reset-selected-permission-addresses]) (rf/dispatch [:communities/reset-selected-permission-addresses id])
(rf/dispatch [:navigate-back]))} (rf/dispatch [:navigate-back]))}
(i18n/label :t/cancel)] (i18n/label :t/cancel)]
[quo/button [quo/button
@@ -68,6 +68,6 @@
:customization-color color :customization-color color
:disabled? (empty? selected-addresses) :disabled? (empty? selected-addresses)
:on-press (fn [] :on-press (fn []
(rf/dispatch [:communities/update-previous-permission-addresses]) (rf/dispatch [:communities/update-previous-permission-addresses id])
(rf/dispatch [:navigate-back]))} (rf/dispatch [:navigate-back]))}
(i18n/label :t/confirm-changes)]]])) (i18n/label :t/confirm-changes)]]]))
@@ -8,12 +8,12 @@
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
(defn- render-item (defn- render-item
[item _ _ airdrop-address] [item _ _ [airdrop-address community-id]]
[quo/account-item [quo/account-item
{:account-props item {:account-props item
:state (when (= airdrop-address (:address item)) :selected) :state (when (= airdrop-address (:address item)) :selected)
:on-press (fn [] :on-press (fn []
(rf/dispatch [:communities/set-airdrop-address (:address item)]) (rf/dispatch [:communities/set-airdrop-address (:address item) community-id])
(rf/dispatch [:navigate-back])) (rf/dispatch [:navigate-back]))
:emoji (:emoji item)}]) :emoji (:emoji item)}])
@@ -21,8 +21,8 @@
[] []
(let [{id :community-id} (rf/sub [:get-screen-params]) (let [{id :community-id} (rf/sub [:get-screen-params])
{:keys [name images color]} (rf/sub [:communities/community id]) {:keys [name images color]} (rf/sub [:communities/community id])
selected-accounts (rf/sub [:communities/selected-permission-accounts]) selected-accounts (rf/sub [:communities/selected-permission-accounts id])
airdrop-address (rf/sub [:communities/airdrop-address])] airdrop-address (rf/sub [:communities/airdrop-address id])]
[:<> [:<>
[quo/drawer-top [quo/drawer-top
{:type :context-tag {:type :context-tag
@@ -35,6 +35,6 @@
[rn/flat-list [rn/flat-list
{:data selected-accounts {:data selected-accounts
:render-fn render-item :render-fn render-item
:render-data airdrop-address :render-data [airdrop-address id]
:content-container-style style/account-list-container :content-container-style style/account-list-container
:key-fn :address}]])) :key-fn :address}]]))
@@ -6,9 +6,8 @@
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
(defn token-requirements (defn token-requirements
[id] []
(rf/dispatch [:communities/check-permissions-to-join-community id]) (fn [id]
(fn []
(let [{:keys [can-request-access? (let [{:keys [can-request-access?
number-of-hold-tokens tokens]} (rf/sub [:community/token-gated-overview id])] number-of-hold-tokens tokens]} (rf/sub [:community/token-gated-overview id])]
[rn/view {:style {:padding-horizontal 12}} [rn/view {:style {:padding-horizontal 12}}
@@ -20,11 +20,11 @@
[quo/community-card-view-item [quo/community-card-view-item
{:community (assoc item :cover cover) {:community (assoc item :cover cover)
:width width :width width
:on-press #(rf/dispatch [:navigate-to :community-overview (:id item)])}] :on-press #(rf/dispatch [:communities/navigate-to-community-overview (:id item)])}]
[quo/community-list-item [quo/community-list
{:on-press (fn [] {:on-press (fn []
(rf/dispatch [:dismiss-keyboard]) (rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:navigate-to :community-overview (:id item)])) (rf/dispatch [:communities/navigate-to-community-overview (:id item)]))
:on-long-press #(rf/dispatch :on-long-press #(rf/dispatch
[:show-bottom-sheet [:show-bottom-sheet
{:content (fn [] {:content (fn []
@@ -142,12 +142,13 @@
(if (= view-type :card-view) (if (= view-type :card-view)
[quo/community-card-view-item [quo/community-card-view-item
{:community (assoc community :cover cover) {:community (assoc community :cover cover)
:on-press #(rf/dispatch [:navigate-to :community-overview (:id community)])}] :on-press #(rf/dispatch [:communities/navigate-to-community-overview (:id community)])}]
[quo/community-list-item [quo/community-list
{:on-press (fn [] {:on-press (fn []
(rf/dispatch [:dismiss-keyboard]) (rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:navigate-to :community-overview (:id community)])) (rf/dispatch [:communities/navigate-to-community-overview
(:id community)]))
:on-long-press #(js/alert "TODO: to be implemented")} :on-long-press #(js/alert "TODO: to be implemented")}
community])])) community])]))
(if communities communities communities-ids)) (if communities communities communities-ids))
+178 -40
View File
@@ -1,12 +1,17 @@
(ns status-im.contexts.communities.events (ns status-im.contexts.communities.events
(:require [clojure.set :as set] (:require [clojure.set :as set]
[clojure.string :as string]
[clojure.walk :as walk] [clojure.walk :as walk]
[legacy.status-im.data-store.chats :as data-store.chats] [legacy.status-im.data-store.chats :as data-store.chats]
[legacy.status-im.mailserver.core :as mailserver]
[react-native.platform :as platform] [react-native.platform :as platform]
[react-native.share :as share] [react-native.share :as share]
[schema.core :as schema]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.contexts.chat.messenger.messages.link-preview.events :as link-preview.events]
status-im.contexts.communities.actions.community-options.events status-im.contexts.communities.actions.community-options.events
status-im.contexts.communities.actions.leave.events status-im.contexts.communities.actions.leave.events
[status-im.navigation.events :as navigation]
[taoensso.timbre :as log] [taoensso.timbre :as log]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
@@ -71,14 +76,20 @@
(when community-js (when community-js
(let [{:keys [token-permissions (let [{:keys [token-permissions
token-permissions-check joined id] token-permissions-check joined id]
:as community} (<-rpc community-js) :as community} (<-rpc community-js)
has-token-permissions? (not (seq token-permissions))] has-channel-perm? (fn [id-perm-tuple]
(let [{:keys [type]} (second id-perm-tuple)]
(or (= type constants/community-token-permission-can-view-channel)
(=
type
constants/community-token-permission-can-view-and-post-channel))))]
{:db (assoc-in db [:communities id] community) {:db (assoc-in db [:communities id] community)
:fx [(when (and has-token-permissions? (not joined)) :fx [[:dispatch [:communities/initialize-permission-addresses id]]
(when (not joined)
[:dispatch [:chat.ui/spectate-community id]]) [:dispatch [:chat.ui/spectate-community id]])
(when (and has-token-permissions? (nil? token-permissions-check)) (when (nil? token-permissions-check)
[:dispatch [:communities/check-permissions-to-join-community id]]) [:dispatch [:communities/check-permissions-to-join-community id]])
(when (and has-token-permissions? (not (get-in db [:community-channels-permissions id]))) (when (some has-channel-perm? token-permissions)
[:dispatch [:communities/check-all-community-channels-permissions id]])]})))) [:dispatch [:communities/check-all-community-channels-permissions id]])]}))))
(rf/defn handle-removed-chats (rf/defn handle-removed-chats
@@ -189,54 +200,62 @@
:on-error #(log/error "failed to fetch collapsed community categories" %)}]})) :on-error #(log/error "failed to fetch collapsed community categories" %)}]}))
(defn initialize-permission-addresses (defn initialize-permission-addresses
[{:keys [db]}] [{:keys [db]} [community-id]]
(let [accounts (get-in db [:wallet :accounts]) (when community-id
sorted-accounts (sort-by :position (vals accounts)) (let [accounts (get-in db [:wallet :accounts])
addresses (set (map :address sorted-accounts))] sorted-accounts (sort-by :position (vals accounts))
{:db (assoc db addresses (set (map :address sorted-accounts))]
:communities/previous-permission-addresses addresses {:db (update-in db
:communities/selected-permission-addresses addresses [:communities community-id]
:communities/airdrop-address (:address (first sorted-accounts)))})) assoc
:previous-permission-addresses addresses
:selected-permission-addresses addresses
:airdrop-address (:address (first sorted-accounts)))})))
(rf/reg-event-fx :communities/initialize-permission-addresses (rf/reg-event-fx :communities/initialize-permission-addresses
initialize-permission-addresses) initialize-permission-addresses)
(defn update-previous-permission-addresses (defn update-previous-permission-addresses
[{:keys [db]}] [{:keys [db]} [community-id]]
(let [accounts (get-in db [:wallet :accounts]) (when community-id
sorted-accounts (sort-by :position (vals accounts)) (let [accounts (get-in db [:wallet :accounts])
selected-permission-addresses (get-in db [:communities/selected-permission-addresses]) sorted-accounts (sort-by :position (vals accounts))
selected-accounts (filter #(contains? selected-permission-addresses selected-permission-addresses (get-in db
(:address %)) [:communities community-id
sorted-accounts) :selected-permission-addresses])
current-airdrop-address (get-in db [:communities/airdrop-address])] selected-accounts (filter #(contains? selected-permission-addresses (:address %))
{:db (assoc db sorted-accounts)
:communities/previous-permission-addresses selected-permission-addresses current-airdrop-address (get-in db [:communities community-id :airdrop-address])]
:communities/airdrop-address (if (contains? selected-permission-addresses {:db (update-in db
current-airdrop-address) [:communities community-id]
current-airdrop-address assoc
(:address (first selected-accounts))))})) :previous-permission-addresses selected-permission-addresses
:airdrop-address (if (contains? selected-permission-addresses
current-airdrop-address)
current-airdrop-address
(:address (first selected-accounts))))})))
(rf/reg-event-fx :communities/update-previous-permission-addresses (rf/reg-event-fx :communities/update-previous-permission-addresses
update-previous-permission-addresses) update-previous-permission-addresses)
(defn toggle-selected-permission-address (defn toggle-selected-permission-address
[{:keys [db]} [address]] [{:keys [db]} [address community-id]]
{:db (update db {:db (update-in db
:communities/selected-permission-addresses [:communities community-id :selected-permission-addresses]
(fn [selected-addresses] (fn [selected-addresses]
(if (contains? selected-addresses address) (if (contains? selected-addresses address)
(disj selected-addresses address) (disj selected-addresses address)
(conj selected-addresses address))))}) (conj selected-addresses address))))})
(rf/reg-event-fx :communities/toggle-selected-permission-address (rf/reg-event-fx :communities/toggle-selected-permission-address
toggle-selected-permission-address) toggle-selected-permission-address)
(rf/reg-event-fx :communities/reset-selected-permission-addresses (rf/reg-event-fx :communities/reset-selected-permission-addresses
(fn [{:keys [db]}] (fn [{:keys [db]} [community-id]]
{:db (assoc db (when community-id
:communities/selected-permission-addresses {:db (assoc-in db
(get-in db [:communities/previous-permission-addresses]))})) [:communities community-id :selected-permission-addresses]
(get-in db [:communities community-id :previous-permission-addresses]))})))
(rf/reg-event-fx :communities/share-community-channel-url-with-data (rf/reg-event-fx :communities/share-community-channel-url-with-data
(fn [_ [chat-id]] (fn [_ [chat-id]]
@@ -265,5 +284,124 @@
:event "share-community-channel-url-with-data"}))}]}))) :event "share-community-channel-url-with-data"}))}]})))
(rf/reg-event-fx :communities/set-airdrop-address (rf/reg-event-fx :communities/set-airdrop-address
(fn [{:keys [db]} [address]] (fn [{:keys [db]} [address community-id]]
{:db (assoc db :communities/airdrop-address address)})) {:db (assoc-in db [:communities community-id :airdrop-address] address)}))
(defn community-fetched
[{:keys [db]} [community-id community]]
(when community
{:db (update db :communities/fetching-community dissoc community-id)
:fx [[:dispatch [:communities/handle-community community]]
[:dispatch
[:chat.ui/cache-link-preview-data (link-preview.events/community-link community-id)
community]]]}))
(rf/reg-event-fx :chat.ui/community-fetched community-fetched)
(defn community-failed-to-fetch
[{:keys [db]} [community-id]]
{:db (update db :communities/fetching-community dissoc community-id)})
(rf/reg-event-fx :chat.ui/community-failed-to-fetch community-failed-to-fetch)
(defn fetch-community
[{:keys [db]} [community-id]]
(when (and community-id (not (get-in db [:communities/fetching-community community-id])))
{:db (assoc-in db [:communities/fetching-community community-id] true)
:json-rpc/call [{:method "wakuext_fetchCommunity"
:params [{:CommunityKey community-id
:TryDatabase true
:WaitForResponse true}]
:on-success (fn [community]
(rf/dispatch [:chat.ui/community-fetched community-id community]))
:on-error (fn [err]
(rf/dispatch [:chat.ui/community-failed-to-fetch community-id])
(log/error {:message
"Failed to request community info from mailserver"
:error err}))}]}))
(schema/=> fetch-community
[:=>
[:catn
[:cofx :schema.re-frame/cofx]
[:args
[:schema [:catn [:community-id [:? :string]]]]]]
[:maybe
[:map
[:db map?]
[:json-rpc/call :schema.common/rpc-call]]]])
(rf/reg-event-fx :communities/fetch-community fetch-community)
(defn spectate-community-success
[{:keys [db]} [{:keys [communities]}]]
(when-let [community (first communities)]
{:db (-> db
(assoc-in [:communities (:id community) :spectated] true)
(assoc-in [:communities (:id community) :spectating] false))
:fx [[:dispatch [:communities/handle-community community]]
[:dispatch [::mailserver/request-messages]]]}))
(rf/reg-event-fx :chat.ui/spectate-community-success spectate-community-success)
(defn spectate-community-failed
[{:keys [db]} [community-id]]
{:db (assoc-in db [:communities community-id :spectating] false)})
(rf/reg-event-fx :chat.ui/spectate-community-failed spectate-community-failed)
(defn spectate-community
[{:keys [db]} [community-id]]
(let [{:keys [spectated spectating joined]} (get-in db [:communities community-id])]
(when (and (not joined) (not spectated) (not spectating))
{:db (assoc-in db [:communities community-id :spectating] true)
:json-rpc/call [{:method "wakuext_spectateCommunity"
:params [community-id]
:on-success [:chat.ui/spectate-community-success]
:on-error (fn [err]
(log/error {:message
"Failed to spectate community"
:error err})
(rf/dispatch [:chat.ui/spectate-community-failed
community-id]))}]})))
(schema/=> spectate-community
[:=>
[:catn
[:cofx :schema.re-frame/cofx]
[:args
[:schema [:catn [:community-id [:? :string]]]]]]
[:maybe
[:map
[:db map?]
[:json-rpc/call :schema.common/rpc-call]]]])
(rf/reg-event-fx :chat.ui/spectate-community spectate-community)
(rf/defn navigate-to-serialized-community
[_ {:keys [community-id]}]
{:serialization/deserialize-and-compress-key
{:serialized-key community-id
:on-success #(rf/dispatch [:communities/navigate-to-community-overview %])
:on-error #(log/error {:message "Failed to decompress community-id"
:error %
:community-id community-id})}})
(rf/reg-event-fx :communities/navigate-to-community-overview
(fn [cofx [deserialized-key]]
(if (string/starts-with? deserialized-key constants/serialization-key)
(navigate-to-serialized-community cofx deserialized-key)
(rf/merge
cofx
{:fx [[:dispatch [:communities/fetch-community deserialized-key]]
[:dispatch [:navigate-to :community-overview deserialized-key]]]}
(navigation/pop-to-root :shell-stack)))))
(rf/reg-event-fx :communities/navigate-to-community-chat
(fn [{:keys [db]} [chat-id pop-to-root?]]
(let [{:keys [community-id]} (get-in db [:chats chat-id])]
{:fx [(when community-id
[:dispatch [:communities/fetch-community community-id]])
(if pop-to-root?
[:dispatch [:chat/pop-to-root-and-navigate-to-chat chat-id]]
[:dispatch [:chat/navigate-to-chat chat-id]])]})))
@@ -1,25 +1,31 @@
(ns status-im.contexts.communities.events-test (ns status-im.contexts.communities.events-test
(:require [cljs.test :refer [deftest is]] (:require [cljs.test :refer [deftest is testing]]
[legacy.status-im.mailserver.core :as mailserver]
matcher-combinators.test matcher-combinators.test
[status-im.contexts.chat.messenger.messages.link-preview.events :as link-preview.events]
[status-im.contexts.communities.events :as events])) [status-im.contexts.communities.events :as events]))
(def community-id "community-id")
(deftest initialize-permission-addresses-test (deftest initialize-permission-addresses-test
(let [initial-db {:db {:wallet {:accounts {"0x1" {:address "0x1" (let [initial-db {:db {:wallet {:accounts {"0x1" {:address "0x1"
:position 0} :position 0}
"0x2" {:address "0x2" "0x2" {:address "0x2"
:position 1}}}}} :position 1}}}}}
expected-db {:db (assoc (:db initial-db) expected-db {:db (update-in (:db initial-db)
:communities/previous-permission-addresses #{"0x1" "0x2"} [:communities community-id]
:communities/selected-permission-addresses #{"0x1" "0x2"} assoc
:communities/airdrop-address "0x1")}] :previous-permission-addresses #{"0x1" "0x2"}
(is (match? expected-db (events/initialize-permission-addresses initial-db))))) :selected-permission-addresses #{"0x1" "0x2"}
:airdrop-address "0x1")}]
(is (match? expected-db (events/initialize-permission-addresses initial-db [community-id])))))
(deftest toggle-selected-permission-address-test (deftest toggle-selected-permission-address-test
(let [initial-db {:db {:communities/selected-permission-addresses #{"0x1" "0x2"}}}] (let [initial-db {:db {:communities {community-id {:selected-permission-addresses #{"0x1" "0x2"}}}}}]
(is (match? {:db {:communities/selected-permission-addresses #{"0x1"}}} (is (match? {:db {:communities {community-id {:selected-permission-addresses #{"0x1"}}}}}
(events/toggle-selected-permission-address initial-db ["0x2"]))) (events/toggle-selected-permission-address initial-db ["0x2" community-id])))
(is (match? {:db {:communities/selected-permission-addresses #{"0x1" "0x2" "0x3"}}} (is (match? {:db {:communities {community-id {:selected-permission-addresses #{"0x1" "0x2" "0x3"}}}}}
(events/toggle-selected-permission-address initial-db ["0x3"]))))) (events/toggle-selected-permission-address initial-db ["0x3" community-id])))))
(deftest update-previous-permission-addresses-test (deftest update-previous-permission-addresses-test
(let [wallet {:accounts {"0x1" {:address "0x1" (let [wallet {:accounts {"0x1" {:address "0x1"
@@ -28,25 +34,162 @@
:position 1} :position 1}
"0x3" {:address "0x3" "0x3" {:address "0x3"
:position 2}}}] :position 2}}}]
(let [initial-db {:db {:wallet wallet (let [initial-db {:db {:wallet wallet
:communities/previous-permission-addresses #{"0x1" "0x2"} :communities {community-id {:previous-permission-addresses #{"0x1" "0x2"}
:communities/selected-permission-addresses #{"0x1" "0x2" "0x3"} :selected-permission-addresses #{"0x1" "0x2"
:communities/airdrop-address "0x1"}} "0x3"}
expected-db {:db {:wallet wallet :airdrop-address "0x1"}}}}
:communities/previous-permission-addresses #{"0x1" "0x2" "0x3"} expected-db {:db {:wallet wallet
:communities/selected-permission-addresses #{"0x1" "0x2" "0x3"} :communities {community-id {:previous-permission-addresses #{"0x1" "0x2"
:communities/airdrop-address "0x1"}}] "0x3"}
:selected-permission-addresses #{"0x1" "0x2"
"0x3"}
:airdrop-address "0x1"}}}}]
(is (is
(match? expected-db (match? expected-db
(events/update-previous-permission-addresses initial-db)))) (events/update-previous-permission-addresses initial-db [community-id]))))
(let [initial-db {:db {:wallet wallet (let [initial-db {:db {:wallet wallet
:communities/previous-permission-addresses #{"0x1" "0x2"} :communities {community-id {:previous-permission-addresses #{"0x1" "0x2"}
:communities/selected-permission-addresses #{"0x2" "0x3"} :selected-permission-addresses #{"0x2" "0x3"}
:communities/airdrop-address "0x1"}} :airdrop-address "0x1"}}}}
expected-db {:db {:wallet wallet expected-db {:db {:wallet wallet
:communities/previous-permission-addresses #{"0x2" "0x3"} :communities {community-id {:previous-permission-addresses #{"0x2" "0x3"}
:communities/selected-permission-addresses #{"0x2" "0x3"} :selected-permission-addresses #{"0x2" "0x3"}
:communities/airdrop-address "0x2"}}] :airdrop-address "0x2"}}}}]
(is (is
(match? expected-db (match? expected-db
(events/update-previous-permission-addresses initial-db)))))) (events/update-previous-permission-addresses initial-db [community-id]))))))
(deftest fetch-community
(testing "with community id"
(testing "update fetching indicator in db"
(is (match?
{:db {:communities/fetching-community {community-id true}}}
(events/fetch-community {} [community-id]))))
(testing "call the fetch community rpc method with correct community id"
(is (match?
{:json-rpc/call [{:method "wakuext_fetchCommunity"
:params [{:CommunityKey community-id
:TryDatabase true
:WaitForResponse true}]}]}
(events/fetch-community {} [community-id])))))
(testing "with no community id"
(testing "do nothing"
(is (match?
nil
(events/fetch-community {} []))))))
(deftest community-failed-to-fetch
(testing "given a community id"
(testing "remove community id from fetching indicator in db"
(is (match?
nil
(get-in (events/community-failed-to-fetch {:db {:communities/fetching-community
{community-id true}}}
[community-id])
[:db :communities/fetching-community community-id]))))))
(deftest community-fetched
(with-redefs [link-preview.events/community-link (fn [id] (str "community-link+" id))]
(testing "given a community"
(let [cofx {:db {:communities/fetching-community {community-id true}}}
arg [community-id {:id community-id}]]
(testing "remove community id from fetching indicator in db"
(is (match?
nil
(get-in (events/community-fetched cofx arg)
[:db :communities/fetching-community community-id]))))
(testing "dispatch fxs"
(is (match?
{:fx [[:dispatch [:communities/handle-community {:id community-id}]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id community-id}]]]}
(events/community-fetched cofx arg))))))
(testing "given a joined community"
(let [cofx {:db {:communities/fetching-community {community-id true}}}
arg [community-id {:id community-id :joined true}]]
(testing "dispatch fxs, do not spectate community"
(is (match?
{:fx [[:dispatch [:communities/handle-community {:id community-id}]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id community-id}]]]}
(events/community-fetched cofx arg))))))
(testing "given a token-gated community"
(let [cofx {:db {:communities/fetching-community {community-id true}}}
arg [community-id {:id community-id :tokenPermissions [1]}]]
(testing "dispatch fxs, do not spectate community"
(is (match?
{:fx [[:dispatch [:communities/handle-community {:id community-id}]]
[:dispatch
[:chat.ui/cache-link-preview-data "community-link+community-id"
{:id community-id}]]]}
(events/community-fetched cofx arg))))))
(testing "given nil community"
(testing "do nothing"
(is (match?
nil
(events/community-fetched {} [community-id nil])))))))
(deftest spectate-community
(testing "given a joined community"
(testing "do nothing"
(is (match?
nil
(events/spectate-community {:db {:communities {community-id {:joined true}}}}
[community-id])))))
(testing "given a spectated community"
(testing "do nothing"
(is (match?
nil
(events/spectate-community {:db {:communities {community-id {:spectated true}}}}
[community-id])))))
(testing "given a spectating community"
(testing "do nothing"
(is (match?
nil
(events/spectate-community {:db {:communities {community-id {:spectating true}}}}
[community-id])))))
(testing "given a community"
(testing "mark community spectating"
(is (match?
{:db {:communities {community-id {:spectating true}}}}
(events/spectate-community {:db {:communities {community-id {}}}} [community-id]))))
(testing "call spectate community rpc with correct community id"
(is (match?
{:json-rpc/call [{:method "wakuext_spectateCommunity"
:params [community-id]}]}
(events/spectate-community {:db {:communities {community-id {}}}} [community-id]))))))
(deftest spectate-community-failed
(testing "mark community spectating false"
(is (match?
{:db {:communities {community-id {:spectating false}}}}
(events/spectate-community-failed {} [community-id])))))
(deftest spectate-community-success
(testing "given communities"
(testing "mark first community spectating false"
(is (match?
{:db {:communities {community-id {:spectating false}}}}
(events/spectate-community-success {} [{:communities [{:id community-id}]}]))))
(testing "mark first community spectated true"
(is (match?
{:db {:communities {community-id {:spectated true}}}}
(events/spectate-community-success {} [{:communities [{:id community-id}]}]))))
(testing "dispatch fxs for first community"
(is (match?
{:fx [[:dispatch [:communities/handle-community {:id community-id}]]
[:dispatch [::mailserver/request-messages]]]}
(events/spectate-community-success {} [{:communities [{:id community-id}]}])))))
(testing "given empty community"
(testing "do nothing"
(is (match?
nil
(events/spectate-community-success {} [{:communities []}])))))
(testing "given nil community"
(testing "do nothing"
(is (match?
nil
(events/spectate-community-success {} []))))))
@@ -26,7 +26,8 @@
[quo/communities-membership-list-item [quo/communities-membership-list-item
{:customization-color customization-color {:customization-color customization-color
:style {:padding-horizontal 20} :style {:padding-horizontal 20}
:on-press #(debounce/dispatch-and-chill [:navigate-to :community-overview id] 500) :on-press #(debounce/dispatch-and-chill [:communities/navigate-to-community-overview id]
500)
:on-long-press #(rf/dispatch :on-long-press #(rf/dispatch
[:show-bottom-sheet [:show-bottom-sheet
{:content (fn [] {:content (fn []
@@ -144,13 +144,12 @@
(defn request-to-join-with-signatures-and-addresses (defn request-to-join-with-signatures-and-addresses
[{:keys [db]} [community-id signatures]] [{:keys [db]} [community-id signatures]]
(let [airdrop-address (get-in db [:communities/airdrop-address]) (let [{:keys [airdrop-address selected-permission-addresses]} (get-in db [:communities community-id])]
addresses-to-reveal (get-in db [:communities/selected-permission-addresses])]
{:fx [[:json-rpc/call {:fx [[:json-rpc/call
[{:method "wakuext_requestToJoinCommunity" [{:method "wakuext_requestToJoinCommunity"
:params [{:communityId community-id :params [{:communityId community-id
:signatures signatures :signatures signatures
:addressesToReveal addresses-to-reveal :addressesToReveal selected-permission-addresses
:airdropAddress airdrop-address}] :airdropAddress airdrop-address}]
:js-response true :js-response true
:on-success [:communities/requested-to-join] :on-success [:communities/requested-to-join]
@@ -173,7 +172,7 @@
[{:keys [db]} [{:keys [db]}
[{:keys [community-id password]}]] [{:keys [community-id password]}]]
(let [pub-key (get-in db [:profile/profile :public-key]) (let [pub-key (get-in db [:profile/profile :public-key])
addresses-to-reveal (get-in db [:communities/selected-permission-addresses])] addresses-to-reveal (get-in db [:communities community-id :selected-permission-addresses])]
{:fx [[:json-rpc/call {:fx [[:json-rpc/call
[{:method "wakuext_generateJoiningCommunityRequestsForSigning" [{:method "wakuext_generateJoiningCommunityRequestsForSigning"
:params [pub-key community-id addresses-to-reveal] :params [pub-key community-id addresses-to-reveal]
@@ -137,8 +137,7 @@
[quo/icon :i/info {:no-color true}]]]) [quo/icon :i/info {:no-color true}]]])
(defn token-gates (defn token-gates
[{:keys [id]}] []
(rf/dispatch [:communities/check-permissions-to-join-community id])
(fn [{:keys [id color]}] (fn [{:keys [id color]}]
(let [{:keys [can-request-access? (let [{:keys [can-request-access?
number-of-hold-tokens tokens]} (rf/sub [:community/token-gated-overview id])] number-of-hold-tokens tokens]} (rf/sub [:community/token-gated-overview id])]
@@ -222,8 +221,9 @@
{:on-press (when joined-or-spectated {:on-press (when joined-or-spectated
(fn [] (fn []
(rf/dispatch [:dismiss-keyboard]) (rf/dispatch [:dismiss-keyboard])
(debounce/dispatch-and-chill [:chat/navigate-to-chat (str community-id id)] (debounce/dispatch-and-chill
1000))) [:communities/navigate-to-community-chat (str community-id id)]
1000)))
:on-long-press #(rf/dispatch :on-long-press #(rf/dispatch
[:show-bottom-sheet [:show-bottom-sheet
{:content (fn [] {:content (fn []
@@ -370,9 +370,10 @@
(let [{:keys [id joined] (let [{:keys [id joined]
:as community} (rf/sub [:communities/community id]) :as community} (rf/sub [:communities/community id])
pending? (rf/sub [:communities/my-pending-request-to-join id])] pending? (rf/sub [:communities/my-pending-request-to-join id])]
(when joined (when community
(rf/dispatch [:activity-center.notifications/dismiss-community-overview id])) (when joined
[community-scroll-page community pending?])) (rf/dispatch [:activity-center.notifications/dismiss-community-overview id]))
[community-scroll-page community pending?])))
(defn overview (defn overview
[id] [id]
@@ -30,7 +30,7 @@
:status-indicator? false :status-indicator? false
:customization-color customization-color}]] :customization-color customization-color}]]
[rn/view [rn/view
{:style style/card-view} {:pointer-events :none :style style/card-view}
[reanimated/view [reanimated/view
{:style (style/card-container container-background)} {:style (style/card-container container-background)}
[rn/view {:style style/card-header} [rn/view {:style style/card-header}
@@ -15,3 +15,8 @@
{:justify-self :flex-end {:justify-self :flex-end
:margin-bottom 46 :margin-bottom 46
:margin-horizontal 20}) :margin-horizontal 20})
(defn carousel-background
[height width]
{:height height
:width width})
@@ -26,6 +26,8 @@
paused? (atom nil) paused? (atom nil)
is-dragging? (atom nil) is-dragging? (atom nil)
drag-amount (atom nil) drag-amount (atom nil)
window-width (rf/sub [:dimensions/window-width])
window-height (rf/sub [:dimensions/window-height])
{:keys [emoji-hash display-name compressed-key {:keys [emoji-hash display-name compressed-key
public-key]} (rf/sub [:profile/profile]) public-key]} (rf/sub [:profile/profile])
{:keys [color]} (rf/sub [:onboarding/profile]) {:keys [color]} (rf/sub [:onboarding/profile])
@@ -42,11 +44,16 @@
{:animate? true {:animate? true
:progress progress :progress progress
:paused? paused? :paused? paused?
:gesture :tappable :gesture :swipeable
:is-dragging? is-dragging? :is-dragging? is-dragging?
:drag-amount drag-amount :drag-amount drag-amount
:header-text header-text}] :header-text header-text
[rn/view {:style style/content-container} :background [rn/view
{:style (style/carousel-background window-height
(* (count header-text) window-width))}]}]
[rn/view
{:style style/content-container
:pointer-events :box-none}
[profile-card/profile-card [profile-card/profile-card
{:profile-picture photo-path {:profile-picture photo-path
:name display-name :name display-name
@@ -1,4 +1,4 @@
(ns status-im.contexts.preview.quo.list-items.community-list (ns status-im.contexts.preview.quo.community.list-item
(:require (:require
[quo.core :as quo] [quo.core :as quo]
[quo.theme :as quo.theme] [quo.theme :as quo.theme]
@@ -95,7 +95,7 @@
:unread-count 5})] :unread-count 5})]
(fn [] (fn []
[preview/preview-container {:state state :descriptor (descriptors @state)} [preview/preview-container {:state state :descriptor (descriptors @state)}
[quo/community-list-item [quo/community-list
(merge @state (merge @state
{:container-style {:width 335} {:container-style {:width 335}
:logo (resources/get-mock-image :status-logo) :logo (resources/get-mock-image :status-logo)
@@ -0,0 +1,46 @@
(ns status-im.contexts.preview.quo.list-items.network-list
(:require
[quo.core :as quo]
[quo.foundations.resources :as quo.resources]
[reagent.core :as reagent]
[status-im.contexts.preview.quo.preview :as preview]))
(def descriptor
[{:key :state
:type :select
:options [{:key :default}
{:key :active}
{:key :pressed}]}
{:key :network-image
:type :select
:options [{:key (quo.resources/get-network :ethereum)
:value :ethereum}
{:key (quo.resources/get-network :arbitrum)
:value :arbitrum}
{:key (quo.resources/get-network :optimism)
:value :optimism}]}
{:key :label
:type :text}
{:key :token-value
:type :text}
{:key :fiat-value
:type :text}
{:key :show-alert-on-press?
:type :boolean}])
(defn view
[]
(let [state (reagent/atom {:network-image (quo.resources/get-network :ethereum)
:label "Mainnet"
:token-value "0.00 ETH"
:fiat-value "€0.00"
:state :default
:customization-color :blue})]
(fn []
[preview/preview-container
{:state state
:descriptor descriptor}
[quo/network-list
(merge @state
(when (:show-alert-on-press? @state)
{:on-press #(js/alert "Pressed!")}))]])))
@@ -41,4 +41,4 @@
:descriptor descriptor :descriptor descriptor
:component-container-style {:padding-vertical 30 :component-container-style {:padding-vertical 30
:padding-horizontal 15}} :padding-horizontal 15}}
[quo/user-list @state]]))) [quo/user @state]])))
+5 -3
View File
@@ -41,6 +41,7 @@
:as community-membership-list-view] :as community-membership-list-view]
[status-im.contexts.preview.quo.community.community-stat :as community-stat] [status-im.contexts.preview.quo.community.community-stat :as community-stat]
[status-im.contexts.preview.quo.community.discover-card :as discover-card] [status-im.contexts.preview.quo.community.discover-card :as discover-card]
[status-im.contexts.preview.quo.community.list-item :as community-list-item]
[status-im.contexts.preview.quo.community.token-gating :as token-gating] [status-im.contexts.preview.quo.community.token-gating :as token-gating]
[status-im.contexts.preview.quo.counter.counter :as counter] [status-im.contexts.preview.quo.counter.counter :as counter]
[status-im.contexts.preview.quo.counter.step :as step] [status-im.contexts.preview.quo.counter.step :as step]
@@ -92,9 +93,8 @@
account-list-card] account-list-card]
[status-im.contexts.preview.quo.list-items.address :as address] [status-im.contexts.preview.quo.list-items.address :as address]
[status-im.contexts.preview.quo.list-items.channel :as channel] [status-im.contexts.preview.quo.list-items.channel :as channel]
[status-im.contexts.preview.quo.list-items.community-list :as
community-list]
[status-im.contexts.preview.quo.list-items.dapp :as dapp] [status-im.contexts.preview.quo.list-items.dapp :as dapp]
[status-im.contexts.preview.quo.list-items.network-list :as network-list]
[status-im.contexts.preview.quo.list-items.preview-lists :as preview-lists] [status-im.contexts.preview.quo.list-items.preview-lists :as preview-lists]
[status-im.contexts.preview.quo.list-items.quiz-item :as quiz-item] [status-im.contexts.preview.quo.list-items.quiz-item :as quiz-item]
[status-im.contexts.preview.quo.list-items.saved-address :as saved-address] [status-im.contexts.preview.quo.list-items.saved-address :as saved-address]
@@ -349,9 +349,11 @@
:component channel/view} :component channel/view}
{:name :community-list {:name :community-list
:options {:insets {:top? true}} :options {:insets {:top? true}}
:component community-list/view} :component community-list-item/view}
{:name :dapp {:name :dapp
:component dapp/preview} :component dapp/preview}
{:name :network-list
:component network-list/view}
{:name :preview-lists {:name :preview-lists
:component preview-lists/view} :component preview-lists/view}
{:name :quiz-item {:name :quiz-item
@@ -320,7 +320,7 @@
(defn- f-preview-container (defn- f-preview-container
[{:keys [title state descriptor blur? blur-dark-only? [{:keys [title state descriptor blur? blur-dark-only?
component-container-style component-container-style
blur-container-style blur-view-props blur-height show-blur-background?] blur-container-style blur-view-props blur-height show-blur-background? full-screen?]
:or {blur-height 200}} :or {blur-height 200}}
& children] & children]
(let [theme (quo.theme/use-theme-value) (let [theme (quo.theme/use-theme-value)
@@ -337,8 +337,11 @@
[common/navigation-bar {:title title}] [common/navigation-bar {:title title}]
[rn/scroll-view [rn/scroll-view
{:style (style/panel-basic) {:style (style/panel-basic)
:shows-vertical-scroll-indicator false} :shows-vertical-scroll-indicator false
[rn/pressable {:on-press rn/dismiss-keyboard!} :content-container-style (when full-screen? {:flex 1})}
[rn/pressable
{:style (when full-screen? {:flex 1})
:on-press rn/dismiss-keyboard!}
(when descriptor (when descriptor
[rn/view {:style style/customizer-container} [rn/view {:style style/customizer-container}
[customizer state descriptor]]) [customizer state descriptor]])
@@ -2,6 +2,7 @@
(:require (:require
[quo.core :as quo] [quo.core :as quo]
[quo.foundations.resources :as resources] [quo.foundations.resources :as resources]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im.contexts.preview.quo.preview :as preview])) [status-im.contexts.preview.quo.preview :as preview]))
@@ -20,21 +21,35 @@
{:key :currency {:key :currency
:type :select :type :select
:options [{:key :usd} :options [{:key :usd}
{:key :eur}]}]) {:key :eur}]}
{:key :error?
:type :boolean}])
(defn view (defn view
[] []
(let [state (reagent/atom {:token :eth (let [state (reagent/atom {:token :eth
:currency :usd :currency :usd
:conversion 0.02 :conversion 0.02
:networks networks :networks networks
:title title :title title
:customization-color :blue})] :customization-color :blue
:show-keyboard? false})
value (reagent/atom "")
set-value (fn [v]
(swap! value str v))
delete (fn [_]
(swap! value #(subs % 0 (dec (count %)))))]
(fn [] (fn []
[preview/preview-container [preview/preview-container
{:state state {:state state
:descriptor descriptor :descriptor descriptor
:component-container-style {:padding-horizontal 20 :full-screen? true
:margin-top 50 :component-container-style {:flex 1
:align-items :center}} :justify-content :space-between}}
[quo/token-input @state]]))) [quo/token-input (assoc @state :value @value)]
[quo/numbered-keyboard
{:container-style {:padding-bottom (safe-area/get-top)}
:left-action :dot
:delete-key? true
:on-press set-value
:on-delete delete}]])))
+5 -2
View File
@@ -1,5 +1,6 @@
(ns status-im.contexts.profile.events (ns status-im.contexts.profile.events
(:require (:require
[legacy.status-im.data-store.settings :as data-store.settings]
[native-module.core :as native-module] [native-module.core :as native-module]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[status-im.contexts.profile.edit.name.events] [status-im.contexts.profile.edit.name.events]
@@ -52,8 +53,10 @@
(rf/defn update-setting-from-backup (rf/defn update-setting-from-backup
{:events [:profile/update-setting-from-backup]} {:events [:profile/update-setting-from-backup]}
[{:keys [db]} {{:keys [name value]} :backedUpSettings}] [{:keys [db]} {:keys [backedUpSettings]}]
{:db (assoc-in db [:profile/profile (keyword name)] value)}) (let [setting (update backedUpSettings :name keyword)
{:keys [name value]} (data-store.settings/rpc->setting-value setting)]
{:db (assoc-in db [:profile/profile name] value)}))
(rf/defn update-profile-from-backup (rf/defn update-profile-from-backup
{:events [:profile/update-profile-from-backup]} {:events [:profile/update-profile-from-backup]}
@@ -1,5 +1,6 @@
(ns status-im.contexts.profile.settings.list-items (ns status-im.contexts.profile.settings.list-items
(:require [status-im.common.not-implemented :as not-implemented] (:require [status-im.common.not-implemented :as not-implemented]
[status-im.config :as config]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf])) [utils.re-frame :as rf]))
@@ -89,12 +90,13 @@
:image :icon :image :icon
:blur? true :blur? true
:image-props :i/toggle} :image-props :i/toggle}
{:title "Quo preview" (when config/quo-preview-enabled?
:on-press #(rf/dispatch [:navigate-to :quo-preview]) {:title "Quo preview"
:action :arrow :on-press #(rf/dispatch [:navigate-to :quo-preview])
:image :icon :action :arrow
:blur? true :image :icon
:image-props :i/light}] :blur? true
:image-props :i/light})]
[{:title (i18n/label :t/about) [{:title (i18n/label :t/about)
:on-press not-implemented/alert :on-press not-implemented/alert
:action :arrow} :action :arrow}
@@ -71,7 +71,7 @@
[gesture/touchable-without-feedback [gesture/touchable-without-feedback
{:on-press (fn [] {:on-press (fn []
(rf/dispatch [:navigate-back]) (rf/dispatch [:navigate-back])
(rf/dispatch [:navigate-to :community-overview community-id]))} (rf/dispatch [:communities/navigate-to-community-overview community-id]))}
[quo/activity-log [quo/activity-log
{:title header-text {:title header-text
:customization-color customization-color :customization-color customization-color
@@ -197,10 +197,10 @@
(rf/dispatch [:chat/navigate-to-chat id]) (rf/dispatch [:chat/navigate-to-chat id])
(= card-type shell.constants/community-channel-card) (= card-type shell.constants/community-channel-card)
(rf/dispatch [:chat/navigate-to-chat channel-id]) (rf/dispatch [:communities/navigate-to-community-chat channel-id])
(= card-type shell.constants/community-card) (= card-type shell.constants/community-card)
(rf/dispatch [:navigate-to :community-overview id]))) (rf/dispatch [:communities/navigate-to-community-overview id])))
(defn calculate-card-position-and-open-screen (defn calculate-card-position-and-open-screen
[card-ref card-type id channel-id] [card-ref card-type id channel-id]
@@ -21,11 +21,11 @@
abbreviated-url (address/get-abbreviated-profile-url abbreviated-url (address/get-abbreviated-profile-url
universal-profile-url) universal-profile-url)
emoji-hash-string (string/join emoji-hash)] emoji-hash-string (string/join emoji-hash)]
[:<> [rn/scroll-view
{:content-container-style {:padding-bottom 16}}
[rn/view {:style style/qr-code-container} [rn/view {:style style/qr-code-container}
[qr-codes/share-qr-code [qr-codes/share-qr-code
{:type :profile {:type :profile
:unblur-on-android? true
:qr-data universal-profile-url :qr-data universal-profile-url
:qr-data-label-shown abbreviated-url :qr-data-label-shown abbreviated-url
:on-share-press #(list-selection/open-share {:message universal-profile-url}) :on-share-press #(list-selection/open-share {:message universal-profile-url})
@@ -5,13 +5,6 @@
(def screen-padding 20) (def screen-padding 20)
(def blur
{:position :absolute
:top 0
:left 0
:right 0
:bottom 0
:overlay-color colors/neutral-80-opa-80-blur})
(def header-row (def header-row
{:flex-direction :row {:flex-direction :row
+5 -9
View File
@@ -1,9 +1,7 @@
(ns status-im.contexts.shell.share.view (ns status-im.contexts.shell.share.view
(:require (:require
[quo.core :as quo] [quo.core :as quo]
[react-native.blur :as blur]
[react-native.core :as rn] [react-native.core :as rn]
[react-native.platform :as platform]
[react-native.safe-area :as safe-area] [react-native.safe-area :as safe-area]
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im.contexts.shell.share.profile.view :as profile-view] [status-im.contexts.shell.share.profile.view :as profile-view]
@@ -43,7 +41,7 @@
[] []
(let [selected-tab (reagent/atom :profile)] (let [selected-tab (reagent/atom :profile)]
(fn [] (fn []
[:<> [rn/view {:style {:padding-top (safe-area/get-top)}}
[header] [header]
[rn/view {:style style/tabs-container} [rn/view {:style style/tabs-container}
[quo/segmented-control [quo/segmented-control
@@ -61,9 +59,7 @@
(defn view (defn view
[] []
[rn/view {:flex 1 :padding-top (safe-area/get-top)} [quo/overlay {:type :shell}
[blur/view [rn/view
{:style style/blur {:key :share}
:blur-amount 20 [tab-content]]])
:blur-radius (if platform/android? 25 10)}]
[tab-content]])
@@ -66,7 +66,6 @@
:networks @selected-networks :networks @selected-networks
:on-share-press #(share-action qr-url share-title) :on-share-press #(share-action qr-url share-title)
:profile-picture nil :profile-picture nil
:unblur-on-android? true
:full-name (:name account) :full-name (:name account)
:customization-color (:color account) :customization-color (:color account)
:emoji (:emoji account) :emoji (:emoji account)
@@ -67,7 +67,7 @@
[] []
(let [{:keys [customization-color] :as profile} (rf/sub [:profile/profile-with-image]) (let [{:keys [customization-color] :as profile} (rf/sub [:profile/profile-with-image])
{:keys [address path watch-only?]} (rf/sub [:wallet/current-viewing-account]) {:keys [address path watch-only?]} (rf/sub [:wallet/current-viewing-account])
networks (rf/sub [:wallet/network-details])] networks (rf/sub [:wallet/network-preference-details])]
[rn/scroll-view [rn/scroll-view
{:style style/about-tab {:style style/about-tab
:content-container-style {:padding-bottom 20}} :content-container-style {:padding-bottom 20}}
@@ -18,7 +18,7 @@
:assets [assets/view] :assets [assets/view]
:collectibles [collectibles/view :collectibles [collectibles/view
{:collectibles collectible-list {:collectibles collectible-list
:on-collectible-press (fn [id] :on-collectible-press (fn [{:keys [id]}]
(rf/dispatch [:wallet/get-collectible-details id]) (rf/dispatch [:wallet/get-collectible-details id])
(rf/dispatch [:navigate-to :wallet-collectible]))}] (rf/dispatch [:navigate-to :wallet-collectible]))}]
:activity [activity/view] :activity [activity/view]
@@ -46,7 +46,9 @@
[quo/wallet-graph {:time-frame :empty}] [quo/wallet-graph {:time-frame :empty}]
(when (not watch-only?) (when (not watch-only?)
[quo/wallet-ctas [quo/wallet-ctas
{:send-action #(rf/dispatch [:open-modal :wallet-select-address]) {:send-action (fn []
(rf/dispatch [:wallet/clean-send-data])
(rf/dispatch [:open-modal :wallet-select-address]))
:receive-action #(rf/dispatch [:open-modal :wallet-share-address {:status :receive}]) :receive-action #(rf/dispatch [:open-modal :wallet-share-address {:status :receive}])
:buy-action #(rf/dispatch [:show-bottom-sheet :buy-action #(rf/dispatch [:show-bottom-sheet
{:content buy-drawer}]) {:content buy-drawer}])
@@ -122,17 +122,17 @@
(rf/dispatch [:wallet/clean-scanned-address]) (rf/dispatch [:wallet/clean-scanned-address])
(rf/dispatch [:wallet/clear-address-activity-check]) (rf/dispatch [:wallet/clear-address-activity-check])
(rf/dispatch [:navigate-back]))}] (rf/dispatch [:navigate-back]))}]
:footer :footer [quo/button
[quo/button {:customization-color customization-color
{:customization-color customization-color :disabled? (or (string/blank? @input-value)
:disabled? (or (string/blank? @input-value) (some? (validate @input-value))) (some? (validate @input-value)))
:on-press (fn [] :on-press (fn []
(rf/dispatch [:navigate-to (rf/dispatch [:navigate-to
:confirm-address-to-watch :confirm-address-to-watch
{:address @input-value}]) {:address @input-value}])
(clear-input)) (clear-input))
:container-style {:z-index 2}} :container-style {:z-index 2}}
(i18n/label :t/continue)]} (i18n/label :t/continue)]}
[quo/text-combinations [quo/text-combinations
{:container-style style/header-container {:container-style style/header-container
:title (i18n/label :t/add-address) :title (i18n/label :t/add-address)

Some files were not shown because too many files have changed in this diff Show More