Compare commits

...
Author SHA1 Message Date
Ulises M 127903f077 Remove deprecated custom-color usage 2024-01-26 21:18:57 -06:00
Ulises M a468b62384 Fix linear gradient breaking while deleting an account 2024-01-26 21:17:08 -06:00
Rende11 07258a653a Clean up code issues 2024-01-27 01:51:19 +03:00
Rende11 e81961b3cb Connect remove account rpc request
Remove account

Don't remove default account

Fix account path
2024-01-26 18:48:42 +03:00
yqrashawnandAjay Sivan 1acf8f0d07 feat: show highest permission role when join community (#18497)
* feat: get revealed accounts for joined community

Signed-off-by: yqrashawn <namy.19@gmail.com>

* Show token requirements only when membership permissions are present.

- Add membership-permissions? to community state.

* feat: show highest permission role in overview and req to join

Signed-off-by: yqrashawn <namy.19@gmail.com>

* feat: get highest perm role in addr for perms

Signed-off-by: yqrashawn <namy.19@gmail.com>

* feat: ui for address for perm drawer

* test: unit test and spec for handle-community

Signed-off-by: yqrashawn <namy.19@gmail.com>

* fix: for #18581

* refactor: based on PR feedback

- move <-rpc to data store
- `role->translation-key`
- highest-permission-role-text -> highest-role-text
- filter out nils for handle community test

Signed-off-by: yqrashawn <namy.19@gmail.com>

---------

Signed-off-by: yqrashawn <namy.19@gmail.com>
Co-authored-by: Ajay Sivan <ajayesivan@gmail.com>
2024-01-26 15:38:10 +08:00
Parvesh Monu d82bf3365d fix bottom tabs blur overlay color (#18621) 2024-01-26 11:44:58 +05:30
Jamie Caprani d8e0d1c36b chore: remove mock data from wallet and feature flag incomplete features (#18569) 2024-01-25 13:13:33 -08:00
Yevheniia Berdnyk ad7a95ed3d e2e: updated deep/universal links tests 2024-01-25 22:20:21 +02:00
Paul Fitzgerald cc24794b74 chore (shell): add indicators to share wallet qrs (#18523) 2024-01-25 19:00:18 +00:00
Omar Basem 1fb6c60f72 Wallet: network receiver preferences (#18583)
* wallet: network receiver preferences
2024-01-25 15:45:45 +04:00
40 changed files with 889 additions and 493 deletions
@@ -1,5 +1,8 @@
(ns legacy.status-im.data-store.communities
(:require [clojure.set :as set]))
(:require
[clojure.set :as set]
[clojure.walk :as walk]
[status-im.constants :as constants]))
(defn rpc->channel-permissions
[rpc-channels-permissions]
@@ -7,3 +10,66 @@
(fn [{:keys [viewAndPostPermissions viewOnlyPermissions]}]
{:view-only (set/rename-keys viewOnlyPermissions {:satisfied :satisfied?})
:view-and-post (set/rename-keys viewAndPostPermissions {:satisfied :satisfied?})})))
(defn <-revealed-accounts-rpc
[accounts]
(mapv
#(set/rename-keys % {:isAirdropAddress :airdrop-address?})
(js->clj accounts :keywordize-keys true)))
(defn <-request-to-join-community-rpc
[r]
(set/rename-keys r
{:communityId :community-id
:publicKey :public-key
:chatId :chat-id}))
(defn <-requests-to-join-community-rpc
[requests key-fn]
(reduce #(assoc %1 (key-fn %2) (<-request-to-join-community-rpc %2)) {} requests))
(defn <-chats-rpc
[chats]
(reduce-kv (fn [acc k v]
(assoc acc
(name k)
(-> v
(assoc :can-post? (:canPost v))
(dissoc :canPost)
(update :members walk/stringify-keys))))
{}
chats))
(defn <-categories-rpc
[categ]
(reduce-kv #(assoc %1 (name %2) %3) {} categ))
(defn <-rpc
[c]
(-> c
(set/rename-keys {:canRequestAccess :can-request-access?
:canManageUsers :can-manage-users?
:canDeleteMessageForEveryone :can-delete-message-for-everyone?
:canJoin :can-join?
:requestedToJoinAt :requested-to-join-at
:isMember :is-member?
:adminSettings :admin-settings
:tokenPermissions :token-permissions
:communityTokensMetadata :tokens-metadata
:introMessage :intro-message
:muteTill :muted-till})
(update :admin-settings
set/rename-keys
{:pinMessageAllMembersEnabled :pin-message-all-members-enabled?})
(update :members walk/stringify-keys)
(update :chats <-chats-rpc)
(update :token-permissions seq)
(update :categories <-categories-rpc)
(assoc :membership-permissions?
(some #(= (:type %) constants/community-token-permission-become-member)
(vals (:tokenPermissions c))))
(assoc :token-images
(reduce (fn [acc {sym :symbol image :image}]
(assoc acc sym image))
{}
(:communityTokensMetadata c)))))
@@ -6,14 +6,21 @@
[react-native.linear-gradient :as linear-gradient]))
(defn- view-internal
[{:keys [customization-color opacity container-style height] :or {customization-color :blue}}]
(let [color-top (colors/custom-color customization-color 50 20)
color-bottom (colors/custom-color customization-color 50 0)]
[linear-gradient/linear-gradient
{:accessibility-label :gradient-cover
:colors [color-top color-bottom]
:start {:x 0 :y 0}
:end {:x 0 :y 1}
:style (merge (style/root-container opacity height) container-style)}]))
[{:keys [customization-color opacity container-style height]
:or {customization-color :blue}}]
;; `when` added for safety, `linear-gradient` will break if `nil` is passed,
;; the `:or` destructuring won't work because it's only applied when the
;; `:customization-color` key is non-existent. While deleting an account the key exists
;; and has a `nil` value.
(when customization-color
(let [color-top (colors/resolve-color customization-color 50 20)
color-bottom (colors/resolve-color customization-color 50 0)]
[linear-gradient/linear-gradient
{:accessibility-label :gradient-cover
:colors [color-top color-bottom]
:start {:x 0 :y 0}
:end {:x 0 :y 1}
:style (merge (style/root-container opacity height)
container-style)}])))
(def view (quo.theme/with-theme view-internal))
+1 -1
View File
@@ -15,7 +15,7 @@
[:token {:optional true} [:or keyword? string?]]
[:style {:optional true} map?]
;; Ignores `token` and uses this as parameter to `rn/image`'s source.
[:image-source {:optional true} [:or :schema.common/image-source :string]]]]
[:image-source {:optional true} [:maybe [:or :schema.common/image-source :string]]]]]
:any])
(defn- size->number
@@ -4,7 +4,7 @@
(defn container
[network state theme]
{:flex 1
{:width 136
:height 44
:border-width 1
:border-radius 12
@@ -10,8 +10,12 @@
[react-native.core :as rn]))
(defn network-bridge-add
[{:keys [network state theme]}]
[rn/view {:style (merge (style/container network state theme) (style/add-container theme))}
[{:keys [network state theme container-style on-press]}]
[rn/pressable
{:style (merge (style/container network state theme)
(style/add-container theme)
container-style)
:on-press on-press}
[icon/icon :i/add-circle {:size 12 :no-color true}]])
(defn- network->text
@@ -21,13 +25,14 @@
:else (string/capitalize (name network))))
(defn view-internal
[{:keys [theme network status amount container-style] :as args}]
[{:keys [theme network status amount container-style on-press] :as args}]
(if (= status :add)
[network-bridge-add args]
[rn/view
[rn/pressable
{:style (merge (style/container network status theme) container-style)
:accessible true
:accessibility-label :container}
:accessibility-label :container
:on-press on-press}
(if (= status :loading)
[rn/view
{:style (style/loading-skeleton theme)
+4
View File
@@ -162,3 +162,7 @@
(def community-accounts-selection-enabled? false)
(def fetch-messages-enabled? (enabled? (get-config :FETCH_MESSAGES_ENABLED "1")))
(def wallet-feature-flags
{:edit-default-keypair false
:bridge-token false})
@@ -6,6 +6,7 @@
[legacy.status-im.chat.models.message :as models.message]
[legacy.status-im.data-store.activities :as data-store.activities]
[legacy.status-im.data-store.chats :as data-store.chats]
[legacy.status-im.data-store.communities :as data-store.communities]
[legacy.status-im.data-store.invitations :as data-store.invitations]
[legacy.status-im.group-chats.core :as models.group]
[legacy.status-im.multiaccounts.update.core :as update.core]
@@ -127,7 +128,7 @@
(seq requests-to-join-community)
(let [requests (->> requests-to-join-community
types/js->clj
(map communities/<-request-to-join-community-rpc))]
(map data-store.communities/<-request-to-join-community-rpc))]
(js-delete response-js "requestsToJoinCommunity")
(rf/merge cofx
(process-next response-js sync-handler)
@@ -6,25 +6,28 @@
[status-im.common.password-authentication.view :as password-authentication]
[status-im.contexts.communities.actions.accounts-selection.style :as style]
[status-im.contexts.communities.actions.community-rules.view :as community-rules]
[status-im.contexts.communities.utils :as communities.utils]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- join-community-and-navigate-back
[id]
(rf/dispatch [:password-authentication/show
{:content (fn [] [password-authentication/view])}
(rf/dispatch [:password-authentication/show {:content (fn [] [password-authentication/view])}
{:label (i18n/label :t/join-open-community)
:on-press #(rf/dispatch [:communities/request-to-join-with-addresses
{:community-id id
:password %}])}])
{:community-id id :password %}])}])
(rf/dispatch [:navigate-back]))
(defn f-view-internal
[]
(let [{id :community-id} (rf/sub [:get-screen-params])
{:keys [name color images]} (rf/sub [:communities/community id])
airdrop-account (rf/sub [:communities/airdrop-account id])
selected-accounts (rf/sub [:communities/selected-permission-accounts id])]
(let [{id :community-id} (rf/sub [:get-screen-params])
{:keys [name color images]} (rf/sub [:communities/community id])
airdrop-account (rf/sub [:communities/airdrop-account id])
selected-accounts (rf/sub [:communities/selected-permission-accounts id])
{:keys [highest-permission-role]} (rf/sub [:community/token-gated-overview id])
highest-role-text (i18n/label (communities.utils/role->translation-key
highest-permission-role
:t/member))]
[rn/view {:style style/container}
[quo/page-nav
{:text-align :left
@@ -48,7 +51,7 @@
(i18n/label :t/address-to-share)]
[quo/category
{:list-type :settings
:data [{:title (i18n/label :t/join-as-a-member)
:data [{:title (i18n/label :t/join-as-a {:role highest-role-text})
:on-press #(rf/dispatch [:open-modal :addresses-for-permissions
{:community-id id}])
:description :text
@@ -13,3 +13,10 @@
:gap 4
:justify-content :center
:margin-bottom 8})
(def highest-role
{:flex-direction :row
:gap 4
:justify-content :center
:align-items :center
:margin-bottom 8})
@@ -4,6 +4,7 @@
[react-native.core :as rn]
[status-im.common.not-implemented :as not-implemented]
[status-im.contexts.communities.actions.addresses-for-permissions.style :as style]
[status-im.contexts.communities.utils :as communities.utils]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -22,10 +23,14 @@
(defn view
[]
(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])
accounts (rf/sub [:wallet/accounts-with-customization-color])
selected-addresses (rf/sub [:communities/selected-permission-addresses id])]
{:keys [highest-permission-role]} (rf/sub [:community/token-gated-overview id])
accounts (rf/sub [:wallet/accounts-with-customization-color])
selected-addresses (rf/sub [:communities/selected-permission-addresses id])
highest-role-text
(i18n/label
(communities.utils/role->translation-key highest-permission-role))]
[rn/safe-area-view {:style style/container}
[quo/drawer-top
{:type :context-tag
@@ -43,6 +48,19 @@
:key-fn :address
:data accounts}]
(when (and highest-permission-role (seq selected-addresses))
[rn/view
{:style style/highest-role}
[quo/text
{:size :paragraph-2
:style {:color colors/neutral-50}}
(i18n/label :t/eligible-to-join-as {:role ""})]
[quo/context-tag
{:type :icon
:icon :i/members
:size 24
:context highest-role-text}]])
(when (empty? selected-addresses)
[rn/view
{:style style/error-message}
+116 -97
View File
@@ -1,96 +1,56 @@
(ns status-im.contexts.communities.events
(:require [clojure.set :as set]
[clojure.string :as string]
[clojure.walk :as walk]
[legacy.status-im.data-store.chats :as data-store.chats]
[legacy.status-im.mailserver.core :as mailserver]
[react-native.platform :as platform]
[react-native.share :as share]
[schema.core :as schema]
[status-im.constants :as constants]
[status-im.contexts.chat.messenger.messages.link-preview.events :as link-preview.events]
status-im.contexts.communities.actions.community-options.events
status-im.contexts.communities.actions.leave.events
[status-im.navigation.events :as navigation]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(:require
[clojure.string :as string]
[legacy.status-im.data-store.chats :as data-store.chats]
[legacy.status-im.data-store.communities :as data-store.communities]
[legacy.status-im.mailserver.core :as mailserver]
[react-native.platform :as platform]
[react-native.share :as share]
[schema.core :as schema]
[status-im.constants :as constants]
[status-im.contexts.chat.messenger.messages.link-preview.events :as link-preview.events]
status-im.contexts.communities.actions.community-options.events
status-im.contexts.communities.actions.leave.events
[status-im.navigation.events :as navigation]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn <-request-to-join-community-rpc
[r]
(set/rename-keys r
{:communityId :community-id
:publicKey :public-key
:chatId :chat-id}))
(defn handle-community
[{:keys [db]} [community-js]]
(when community-js
(let [{:keys [token-permissions
token-permissions-check joined id]
:as community} (data-store.communities/<-rpc community-js)
has-channel-perm? (fn [id-perm-tuple]
(let [{:keys [type]} (second id-perm-tuple)]
(or (= type constants/community-token-permission-can-view-channel)
(=
type
constants/community-token-permission-can-view-and-post-channel))))]
{:db (assoc-in db [:communities id] community)
:fx [[:dispatch [:communities/initialize-permission-addresses id]]
(when (not joined)
[:dispatch [:chat.ui/spectate-community id]])
(when (nil? token-permissions-check)
[:dispatch [:communities/check-permissions-to-join-community id]])
(when (some has-channel-perm? token-permissions)
[:dispatch [:communities/check-all-community-channels-permissions id]])
(when joined
[:dispatch [:communities/get-revealed-accounts id]])]})))
(defn <-requests-to-join-community-rpc
[requests key-fn]
(reduce #(assoc %1 (key-fn %2) (<-request-to-join-community-rpc %2)) {} requests))
(rf/reg-event-fx :communities/handle-community handle-community)
(defn <-chats-rpc
[chats]
(reduce-kv (fn [acc k v]
(assoc acc
(name k)
(-> v
(assoc :can-post? (:canPost v))
(dissoc :canPost)
(update :members walk/stringify-keys))))
{}
chats))
(defn <-categories-rpc
[categ]
(reduce-kv #(assoc %1 (name %2) %3) {} categ))
(defn <-rpc
[c]
(-> c
(set/rename-keys {:canRequestAccess :can-request-access?
:canManageUsers :can-manage-users?
:canDeleteMessageForEveryone :can-delete-message-for-everyone?
:canJoin :can-join?
:requestedToJoinAt :requested-to-join-at
:isMember :is-member?
:adminSettings :admin-settings
:tokenPermissions :token-permissions
:communityTokensMetadata :tokens-metadata
:introMessage :intro-message
:muteTill :muted-till})
(update :admin-settings
set/rename-keys
{:pinMessageAllMembersEnabled :pin-message-all-members-enabled?})
(update :members walk/stringify-keys)
(update :chats <-chats-rpc)
(update :token-permissions seq)
(update :categories <-categories-rpc)
(assoc :token-images
(reduce (fn [acc {sym :symbol image :image}]
(assoc acc sym image))
{}
(:communityTokensMetadata c)))))
(rf/reg-event-fx :communities/handle-community
(fn [{:keys [db]}
[community-js]]
(when community-js
(let [{:keys [token-permissions
token-permissions-check joined id]
:as community} (<-rpc community-js)
has-channel-perm? (fn [id-perm-tuple]
(let [{:keys [type]} (second id-perm-tuple)]
(or (= type constants/community-token-permission-can-view-channel)
(=
type
constants/community-token-permission-can-view-and-post-channel))))]
{:db (assoc-in db [:communities id] community)
:fx [[:dispatch [:communities/initialize-permission-addresses id]]
(when (not joined)
[:dispatch [:chat.ui/spectate-community id]])
(when (nil? token-permissions-check)
[:dispatch [:communities/check-permissions-to-join-community id]])
(when (some has-channel-perm? token-permissions)
[:dispatch [:communities/check-all-community-channels-permissions id]])]}))))
(schema/=> handle-community
[:=>
[:catn
[:cofx :schema.re-frame/cofx]
[:args
[:schema [:catn [:community-js map?]]]]]
[:maybe
[:map
[:db [:map [:communities map?]]]
[:fx vector?]]]])
(rf/defn handle-removed-chats
[{:keys [db]} chat-ids]
@@ -164,7 +124,7 @@
(fn [{:keys [db]} [requests]]
{:db (assoc db
:communities/my-pending-requests-to-join
(<-requests-to-join-community-rpc requests :communityId))}))
(data-store.communities/<-requests-to-join-community-rpc requests :communityId))}))
(rf/reg-event-fx :communities/get-user-requests-to-join
(fn [_]
@@ -240,12 +200,19 @@
(defn toggle-selected-permission-address
[{:keys [db]} [address community-id]]
{:db (update-in db
[:communities community-id :selected-permission-addresses]
(fn [selected-addresses]
(if (contains? selected-addresses address)
(disj selected-addresses address)
(conj selected-addresses address))))})
(let [selected-permission-addresses
(get-in db [:communities community-id :selected-permission-addresses])
updated-selected-permission-addresses
(if (contains? selected-permission-addresses address)
(disj selected-permission-addresses address)
(conj selected-permission-addresses address))]
{:db (assoc-in db
[:communities community-id :selected-permission-addresses]
updated-selected-permission-addresses)
:fx [(when community-id
[:dispatch
[:communities/check-permissions-to-join-community community-id
updated-selected-permission-addresses :based-on-client-selection]])]}))
(rf/reg-event-fx :communities/toggle-selected-permission-address
toggle-selected-permission-address)
@@ -255,7 +222,8 @@
(when community-id
{:db (assoc-in db
[:communities community-id :selected-permission-addresses]
(get-in db [:communities community-id :previous-permission-addresses]))})))
(get-in db [:communities community-id :previous-permission-addresses]))
:fx [[:dispatch [:communities/check-permissions-to-join-community community-id]]]})))
(rf/reg-event-fx :communities/share-community-channel-url-with-data
(fn [_ [chat-id]]
@@ -405,3 +373,54 @@
(if pop-to-root?
[:dispatch [:chat/pop-to-root-and-navigate-to-chat chat-id]]
[:dispatch [:chat/navigate-to-chat chat-id]])]})))
(defn get-revealed-accounts
[{:keys [db]} [community-id]]
(let [{:keys [joined fetching-revealed-accounts]
:as community} (get-in db [:communities community-id])]
(when (and community joined (not fetching-revealed-accounts))
{:db (assoc-in db [:communities community-id :fetching-revealed-accounts] true)
:json-rpc/call
[{:method "wakuext_getRevealedAccounts"
:params [community-id (get-in db [:profile/profile :public-key])]
:js-response true
:on-success [:communities/get-revealed-accounts-success community-id]
:on-error (fn [err]
(log/error {:message "failed to fetch revealed accounts"
:community-id community-id
:err err})
(rf/dispatch [:communities/get-revealed-accounts-failed community-id]))}]})))
(rf/reg-event-fx :communities/get-revealed-accounts get-revealed-accounts)
(schema/=> get-revealed-accounts
[:=>
[: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/get-revealed-accounts-success
(fn [{:keys [db]} [community-id revealed-accounts-js]]
(when-let [community (get-in db [:communities community-id])]
(let [revealed-accounts
(reduce
(fn [acc {:keys [address] :as revealed-account}]
(assoc acc address (dissoc revealed-account :address)))
{}
(data-store.communities/<-revealed-accounts-rpc revealed-accounts-js))
community-with-revealed-accounts
(-> community
(assoc :revealed-accounts revealed-accounts)
(dissoc :fetching-revealed-accounts))]
{:db (assoc-in db [:communities community-id] community-with-revealed-accounts)}))))
(rf/reg-event-fx :communities/get-revealed-accounts-failed
(fn [{:keys [db]} [community-id]]
(when (get-in db [:communities community-id])
{:db (update-in db [:communities community-id] dissoc :fetching-revealed-accounts)})))
@@ -2,6 +2,7 @@
(:require [cljs.test :refer [deftest is testing]]
[legacy.status-im.mailserver.core :as mailserver]
matcher-combinators.test
[status-im.constants :as constants]
[status-im.contexts.chat.messenger.messages.link-preview.events :as link-preview.events]
[status-im.contexts.communities.events :as events]))
@@ -193,3 +194,79 @@
(is (match?
nil
(events/spectate-community-success {} []))))))
(deftest get-revealed-accounts
(let [community {:id community-id}]
(testing "given a unjoined community"
(is (match?
nil
(events/get-revealed-accounts {:db {:communities {community-id community}}} [community-id]))))
(testing "given a already :fetching-revealed-accounts community"
(is (match?
nil
(events/get-revealed-accounts
{:db {:communities {community-id (assoc community :fetching-revealed-accounts true)}}}
[community-id]))))
(testing "given joined community"
(let [community (assoc community :joined true)
db {:communities {community-id community}
:profile/profile {:public-key "profile-public-key"}}
effects (events/get-revealed-accounts {:db db} [community-id])]
(is (match? (assoc-in db [:communities community-id :fetching-revealed-accounts] true)
(:db effects)))
(is (match? {:method "wakuext_getRevealedAccounts"
:params [community-id "profile-public-key"]}
(-> effects :json-rpc/call first (select-keys [:method :params]))))))))
(deftest handle-community
(let [community {:id community-id}]
(testing "given a unjoined community"
(let [effects (events/handle-community {} [community])]
(is (match? community-id
(-> effects :db :communities (get community-id) :id)))
(is (match?
[[:dispatch [:communities/initialize-permission-addresses community-id]]
[:dispatch [:chat.ui/spectate-community community-id]]
[:dispatch [:communities/check-permissions-to-join-community community-id]]]
(filter some? (:fx effects))))))
(testing "given a joined community"
(let [community (assoc community :joined true)
effects (events/handle-community {} [community])]
(is (match?
[[:dispatch [:communities/initialize-permission-addresses community-id]]
[:dispatch [:communities/check-permissions-to-join-community community-id]]
[:dispatch [:communities/get-revealed-accounts community-id]]]
(filter some? (:fx effects))))))
(testing "given a community with token-permissions-check"
(let [community (assoc community :token-permissions-check :fake-token-permissions-check)
effects (events/handle-community {} [community])]
(is (match?
[[:dispatch [:communities/initialize-permission-addresses community-id]]
[:dispatch [:chat.ui/spectate-community community-id]]]
(filter some? (:fx effects))))))
(testing "given a community with view channel permission"
(let [community (assoc community
:token-permissions
[["perm-id" {:type constants/community-token-permission-can-view-channel}]])
effects (events/handle-community {} [community])]
(is (match?
[[:dispatch [:communities/initialize-permission-addresses community-id]]
[:dispatch [:chat.ui/spectate-community community-id]]
[:dispatch [:communities/check-permissions-to-join-community community-id]]
[:dispatch
[:communities/check-all-community-channels-permissions community-id]]]
(filter some? (:fx effects))))))
(testing "given a community with post in channel permission"
(let [community (assoc community
:token-permissions
[["perm-id"
{:type constants/community-token-permission-can-view-and-post-channel}]])
effects (events/handle-community {} [community])]
(is (match?
[[:dispatch [:communities/initialize-permission-addresses community-id]]
[:dispatch [:chat.ui/spectate-community community-id]]
[:dispatch [:communities/check-permissions-to-join-community community-id]]
[:dispatch
[:communities/check-all-community-channels-permissions community-id]]]
(filter some? (:fx effects))))))))
@@ -34,26 +34,31 @@
:communities/check-all-community-channels-permissions}))}]]]})))
(rf/reg-event-fx :communities/check-permissions-to-join-community-success
(fn [{:keys [db]} [community-id result]]
{:db (-> db
(assoc-in [:communities community-id :checking-permissions?] false)
(assoc-in [:communities community-id :token-permissions-check] result))}))
(fn [{:keys [db]} [community-id based-on-client-selection? result]]
(let [token-permissions-check (cond-> result
based-on-client-selection? (assoc :based-on-client-selection? true))]
{:db (-> db
(assoc-in [:communities community-id :checking-permissions?] false)
(assoc-in [:communities community-id :token-permissions-check]
token-permissions-check))})))
(rf/reg-event-fx :communities/check-permissions-to-join-community-failed
(fn [{:keys [db]} [community-id]]
{:db (assoc-in db [:communities community-id :checking-permissions?] false)}))
(rf/reg-event-fx :communities/check-permissions-to-join-community
(fn [{:keys [db]} [community-id]]
(fn [{:keys [db]} [community-id addresses based-on-client-selection?]]
(when-let [community (get-in db [:communities community-id])]
(when-not (:checking-permissions? community)
{:db (-> db
(assoc-in [:communities community-id :checking-permissions?] true)
(assoc-in [:communities community-id :can-request-access?] false))
:json-rpc/call [{:method "wakuext_checkPermissionsToJoinCommunity"
:params [{:communityId community-id}]
:params [(cond-> {:communityId community-id}
addresses
(assoc :addresses addresses))]
:on-success [:communities/check-permissions-to-join-community-success
community-id]
community-id based-on-client-selection?]
:on-error (fn [err]
(rf/dispatch
[:communities/check-permissions-to-join-community-failed
@@ -16,6 +16,7 @@
[status-im.contexts.communities.actions.community-options.view :as options]
[status-im.contexts.communities.overview.style :as style]
[status-im.contexts.communities.overview.utils :as utils]
[status-im.contexts.communities.utils :as communities.utils]
[utils.debounce :as debounce]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -140,7 +141,11 @@
[]
(fn [{:keys [id color]}]
(let [{:keys [can-request-access?
number-of-hold-tokens tokens]} (rf/sub [:community/token-gated-overview id])]
number-of-hold-tokens tokens
highest-permission-role]} (rf/sub [:community/token-gated-overview id])
highest-role-text
(i18n/label
(communities.utils/role->translation-key highest-permission-role :t/member))]
[rn/view {:style (style/token-gated-container)}
[rn/view
{:style {:padding-horizontal 12
@@ -150,7 +155,7 @@
:flex 1}}
[quo/text {:weight :medium}
(if can-request-access?
(i18n/label :t/you-eligible-to-join)
(i18n/label :t/you-eligible-to-join-as {:role highest-role-text})
(i18n/label :t/you-not-eligible-to-join))]
[info-button]]
(when (pos? number-of-hold-tokens)
@@ -163,23 +168,26 @@
{:tokens tokens
:padding? true}]
[quo/button
{:on-press #(join-gated-community id)
{:on-press
(if config/community-accounts-selection-enabled?
#(rf/dispatch [:open-modal :community-account-selection {:community-id id}])
#(join-gated-community id))
:accessibility-label :join-community-button
:customization-color color
:container-style {:margin-horizontal 12 :margin-top 12 :margin-bottom 12}
:disabled? (not can-request-access?)
:icon-left (if can-request-access? :i/unlocked :i/locked)}
:container-style {:margin-horizontal 12 :margin-top 12 :margin-bottom 12}
:disabled? (not can-request-access?)
:icon-left (if can-request-access? :i/unlocked :i/locked)}
(i18n/label :t/join-open-community)]])))
(defn join-community
[{:keys [joined color permissions token-permissions id] :as community}
[{:keys [joined color permissions token-permissions membership-permissions? id] :as community}
pending?]
(let [access-type (get-access-type (:access permissions))
unknown-access? (= access-type :unknown-access)
invite-only? (= access-type :invite-only)]
[:<>
(when-not (or joined pending? invite-only? unknown-access?)
(if (seq token-permissions)
(if membership-permissions?
[token-gates community]
[quo/button
{:on-press
@@ -190,7 +198,7 @@
:accessibility-label :show-request-to-join-screen-button
:customization-color color
:icon-left :i/communities}
(i18n/label :t/request-to-join-community)]))
(i18n/label :t/request-to-join)]))
(when (not (or joined pending? token-permissions))
[quo/text
@@ -0,0 +1,13 @@
(ns status-im.contexts.communities.utils
(:require
[status-im.constants :as constants]))
(defn role->translation-key
([role] (role->translation-key role nil))
([role fallback-to]
(condp = role
constants/community-token-permission-become-token-owner :t/token-owner
constants/community-token-permission-become-token-master :t/token-master
constants/community-token-permission-become-admin :t/admin
constants/community-token-permission-become-member :t/member
fallback-to)))
@@ -2,6 +2,7 @@
(:require
[quo.foundations.colors :as colors]
[react-native.platform :as platform]
[react-native.reanimated :as reanimated]
[status-im.contexts.shell.jump-to.utils :as utils]))
(defn bottom-tabs-container
@@ -28,10 +29,11 @@
(defn bottom-tabs-blur-overlay
[height]
[{:height height}
(reanimated/apply-animations-to-style
{:height height}
{:position :absolute
:left 0
:right 0
:bottom 0
:height (utils/bottom-tabs-container-height)
:background-color colors/neutral-100-opa-70-blur}])
:background-color colors/neutral-100-opa-70-blur}))
@@ -0,0 +1,18 @@
(ns status-im.contexts.shell.share.wallet.style
(:require
[quo.foundations.colors :as colors]))
(defn indicator-wrapper-style
[active?]
{:width 8
:height 8
:border-radius 4
:background-color colors/white
:opacity (if active? 1.0 0.5)})
(def indicator-list-style
{:display :flex
:flex-direction :row
:align-items :center
:justify-content :center
:gap 8})
@@ -6,6 +6,7 @@
[react-native.share :as share]
[reagent.core :as reagent]
[status-im.contexts.shell.share.style :as style]
[status-im.contexts.shell.share.wallet.style :as wallet-style]
[status-im.contexts.wallet.common.sheets.network-preferences.view :as network-preferences]
[status-im.contexts.wallet.common.utils :as utils]
[utils.i18n :as i18n]
@@ -43,10 +44,11 @@
(rf/dispatch [:hide-bottom-sheet])
(reset! selected-networks (map #(get utils/id->network %)
chain-ids)))}])}]))
(defn wallet-qr-code-item
[account width index]
(let [selected-networks (reagent/atom [:ethereum :optimism :arbitrum])
wallet-type (reagent/atom :wallet-legacy)]
(defn- wallet-qr-code-item-internal
[props]
(let [{:keys [account width index]} props
selected-networks (reagent/atom [:ethereum :optimism :arbitrum])
wallet-type (reagent/atom :wallet-legacy)]
(fn []
(let [share-title (str (:name account) " " (i18n/label :t/address))
qr-url (utils/get-wallet-qr {:wallet-type @wallet-type
@@ -57,7 +59,7 @@
:port (rf/sub [:mediaserver/port])
:qr-size qr-size
:error-level :highest})]
[rn/view {:style {:width width :margin-left (if (zero? index) 0 -30)}}
[rn/view {:style {:height qr-size :width width :margin-left (if (zero? index) 0 -30)}}
[rn/view {:style style/qr-code-container}
[quo/share-qr-code
{:type @wallet-type
@@ -73,18 +75,54 @@
:on-legacy-press #(reset! wallet-type :wallet-legacy)
:on-settings-press #(open-preferences @selected-networks)}]]]))))
(def wallet-qr-code-item (memoize wallet-qr-code-item-internal))
(defn- indicator
[active?]
[rn/view
{:style (wallet-style/indicator-wrapper-style active?)}])
(defn- indicator-list
[indicator-count current-index]
[rn/view
{:style wallet-style/indicator-list-style}
(for [i (range indicator-count)]
(let [current-index (cond (<= current-index 0) 0
(>= current-index (dec indicator-count)) (dec indicator-count)
:else current-index)]
^{:key i} [indicator (= current-index i)]))])
(defn render-item
[item]
(let [width (rf/sub [:dimensions/window-width])]
[wallet-qr-code-item
{:account item
:index (:position item)
:width width}]))
(defn wallet-tab
[]
(let [accounts (rf/sub [:wallet/accounts])
width (rf/sub [:dimensions/window-width])]
[rn/flat-list
{:horizontal true
:deceleration-rate 0.9
:snap-to-alignment "start"
:snap-to-interval (- width 30)
:disable-interval-momentum true
:scroll-event-throttle 64
:data accounts
:directional-lock-enabled true
:render-fn (fn [account index]
(wallet-qr-code-item account width index))}]))
(let [accounts (rf/sub [:wallet/accounts])
width (rf/sub [:dimensions/window-width])
current-index (reagent/atom 0)]
(fn []
[rn/view
[rn/flat-list
{:horizontal true
:deceleration-rate 0.9
:snap-to-alignment :start
:snap-to-interval (- width 30)
:disable-interval-momentum true
:scroll-event-throttle 64
:data accounts
:directional-lock-enabled true
:shows-horizontal-scroll-indicator false
:on-scroll (fn [e]
(reset! current-index (js/Math.ceil
(/ e.nativeEvent.contentOffset.x
width))))
:render-fn render-item}]
(when (> (count accounts) 1)
[rn/view
{:style {:margin-top 20}}
(indicator-list (count accounts) @current-index)])])))
@@ -3,6 +3,7 @@
[quo.core :as quo]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im.config :as config]
[status-im.contexts.wallet.account.style :as style]
[status-im.contexts.wallet.account.tabs.view :as tabs]
[status-im.contexts.wallet.common.account-switcher.view :as account-switcher]
@@ -52,7 +53,9 @@
:receive-action #(rf/dispatch [:open-modal :wallet-share-address {:status :receive}])
:buy-action #(rf/dispatch [:show-bottom-sheet
{:content buy-drawer}])
:bridge-action #(rf/dispatch [:open-modal :wallet-bridge])}])
:bridge-action (if (:bridge-token config/wallet-feature-flags)
#(rf/dispatch [:open-modal :wallet-bridge])
#(js/alert "feature disabled in config file"))}])
[quo/tabs
{:style style/tabs
:size 32
@@ -3,7 +3,6 @@
[quo.theme]
[react-native.core :as rn]
[status-im.contexts.wallet.collectible.tabs.about.style :as style]
[status-im.contexts.wallet.temp :as temp]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -14,7 +13,8 @@
(let [window-width (rf/sub [:dimensions/window-width])
item-width (- (/ window-width 2) link-card-space)
{:keys [collectible-data]} (rf/sub [:wallet/last-collectible-details])
link-card-container-style (style/link-card item-width)]
link-card-container-style (style/link-card item-width)
collectible-about {:cards []}]
[:<>
[rn/view {:style style/title}
[quo/text
@@ -25,12 +25,13 @@
[quo/text
{:size :paragraph-2}
(:description collectible-data)]]
[quo/section-label
{:container-style style/section-label
:section (i18n/label :t/on-the-web)}]
[rn/view {:style style/link-cards-container}
(for [item (:cards temp/collectible-about)]
^{:key (:title item)}
[quo/link-card (assoc item :container-style link-card-container-style)])]]))
(when (count collectible-about)
[quo/section-label
{:container-style style/section-label
:section (i18n/label :t/on-the-web)}]
[rn/view {:style style/link-cards-container}
(for [item (:cards collectible-about)]
^{:key (:title item)}
[quo/link-card (assoc item :container-style link-card-container-style)])])]))
(def view (quo.theme/with-theme view-internal))
@@ -1,7 +1,6 @@
(ns status-im.contexts.wallet.collectible.tabs.activity.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.contexts.wallet.temp :as temp]))
[react-native.core :as rn]))
(defn activity-item
[item]
@@ -12,6 +11,6 @@
(defn view
[]
[rn/flat-list
{:data temp/collectible-activities
{:data nil
:style {:flex 1}
:render-fn activity-item}])
@@ -32,12 +32,13 @@
(defn- options
[{:keys [theme show-account-selector? options-height]}]
(let [{:keys [name color emoji address watch-only?]} (rf/sub [:wallet/current-viewing-account])
network-preference-details (rf/sub [:wallet/network-preference-details])
multichain-address (utils/get-multichain-address
network-preference-details
address)
share-title (str name " " (i18n/label :t/address))]
(let [{:keys [name color emoji address watch-only?
default-account?]} (rf/sub [:wallet/current-viewing-account])
network-preference-details (rf/sub [:wallet/network-preference-details])
multichain-address (utils/get-multichain-address
network-preference-details
address)
share-title (i18n/label :t/share-address-title {:address name})]
[rn/view
{:on-layout #(reset! options-height (oops/oget % "nativeEvent.layout.height"))
:style (when show-account-selector? style/options-container)}
@@ -92,15 +93,16 @@
#(rf/dispatch [:wallet/share-account
{:title share-title :content multichain-address}])
600))}
{:add-divider? (not show-account-selector?)
:icon :i/delete
:accessibility-label :remove-account
:label (i18n/label :t/remove-account)
:danger? true
:on-press #(rf/dispatch [:show-bottom-sheet
{:content
(fn []
[remove-account/view])}])}]]]
(when-not default-account?
{:add-divider? (not show-account-selector?)
:icon :i/delete
:accessibility-label :remove-account
:label (i18n/label :t/remove-account)
:danger? true
:on-press #(rf/dispatch [:show-bottom-sheet
{:content
(fn []
[remove-account/view])}])})]]]
(when show-account-selector?
[:<>
[quo/divider-line {:container-style style/divider-label}]
@@ -11,13 +11,17 @@
[utils.re-frame :as rf]))
(defn- footer
[{:keys [submit-disabled?]}]
[{:keys [address submit-disabled? toast-message]}]
[quo/bottom-actions
{:actions :2-actions
:customization-color :danger
:button-one-label (i18n/label :t/remove)
:button-one-props {:on-press #(js/alert "Will be implemented")
:type :danger
:button-one-props {:on-press
(fn []
(rf/dispatch [:wallet/remove-account
{:address address
:toast-message toast-message}]))
:type :danger
:disabled? submit-disabled?}
:button-two-label (i18n/label :t/cancel)
:button-two-props {:on-press #(rf/dispatch [:hide-bottom-sheet])
@@ -26,7 +30,7 @@
(defn- recovery-phase-flow
[]
(let [confirmed? (reagent/atom false)]
(fn [{:keys [name emoji path color] :as _account}]
(fn [{:keys [address name emoji path color] :as _account}]
(let [formatted-path (utils/format-derivation-path path)]
[:<>
[quo/drawer-top
@@ -64,10 +68,13 @@
:checked? @confirmed?
:on-change #(swap! confirmed? not)}]
[quo/text (i18n/label :t/remove-account-confirmation)]]
[footer {:submit-disabled? (not @confirmed?)}]]))))
[footer
{:submit-disabled? (not @confirmed?)
:address address
:toast-message (i18n/label :t/account-removed)}]]))))
(defn- watched-address-flow
[{:keys [name emoji color] :as _account}]
[{:keys [address name emoji color] :as _account}]
[:<>
[quo/drawer-top
{:title (i18n/label :t/remove-watched-address-title)
@@ -79,13 +86,17 @@
[rn/view {:style style/desc-container}
[quo/text {:weight :medium}
(i18n/label :t/remove-watched-address-desc)]]
[footer {:submit-disabled? false}]])
[footer
{:submit-disabled? false
:address address
:toast-message (i18n/label :t/watched-account-removed)}]])
(defn- view-internal
[]
(let [{:keys [type] :as account} (rf/sub [:wallet/current-viewing-account])]
(case type
:generated [recovery-phase-flow account]
:watch [watched-address-flow account])))
:watch [watched-address-flow account]
nil)))
(def view (quo.theme/with-theme view-internal))
@@ -185,6 +185,11 @@
constants/arbitrum-chain-id :arbitrum
constants/arbitrum-test-chain-id :arbitrum})
(def short-name->id
{:eth constants/mainnet-chain-id
:opt constants/optimism-chain-id
:arb1 constants/arbitrum-chain-id})
(defn get-standard-fiat-format
[crypto-value currency-symbol fiat-value]
(if (string/includes? crypto-value "<")
@@ -9,6 +9,7 @@
[reagent.core :as reagent]
[status-im.common.emoji-picker.utils :as emoji-picker.utils]
[status-im.common.standard-authentication.core :as standard-auth]
[status-im.config :as config]
[status-im.constants :as constants]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.create-account.style :as style]
@@ -31,7 +32,9 @@
:size :xxs
:customization-color account-color}
:action :button
:action-props {:on-press #(rf/dispatch [:navigate-to :wallet-select-keypair])
:action-props {:on-press (if (:edit-default-keypair config/wallet-feature-flags)
#(rf/dispatch [:navigate-to :wallet-select-keypair])
#(js/alert "feature disabled in config file"))
:button-text (i18n/label :t/edit)
:alignment :flex-start}
:description :text
@@ -40,7 +43,7 @@
:image :icon
:image-props :i/derivated-path
:action :button
:action-props {:on-press #(js/alert "Button pressed!")
:action-props {:on-press #(js/alert "Coming soon!")
:button-text (i18n/label :t/edit)
:icon-left :i/placeholder
:alignment :flex-start}
@@ -33,6 +33,7 @@
(update :test-preferred-chain-ids chain-ids-string->set)
(update :type keyword)
(update :color #(if (seq %) (keyword %) constants/account-default-customization-color))
(assoc :default-account? (:wallet account))
add-keys-to-account))
(defn rpc->accounts
@@ -49,7 +50,8 @@
:color :colorId})
(update :prodPreferredChainIds chain-ids-set->string)
(update :testPreferredChainIds chain-ids-set->string)
(dissoc :watch-only?)))
(dissoc :watch-only?)
(dissoc :default-account?)))
(defn- rpc->balances-per-chain
[token]
@@ -51,7 +51,7 @@
:updated-key :name
:new-value @edited-account-name}))]
(fn []
(let [{:keys [name emoji address color watch-only?]
(let [{:keys [name emoji address color watch-only? default-account?]
:as account} (rf/sub [:wallet/current-viewing-account])
network-details (rf/sub [:wallet/network-preference-details])
test-networks-enabled? (rf/sub [:profile/test-networks-enabled?])
@@ -62,13 +62,14 @@
button-disabled? (or (nil? @edited-account-name)
(= name @edited-account-name))]
[create-or-edit-account/view
{:page-nav-right-side [{:icon-name :i/delete
:on-press
(fn []
(rf/dispatch [:show-bottom-sheet
{:content
(fn []
[remove-account/view])}]))}]
{:page-nav-right-side [(when-not default-account?
{:icon-name :i/delete
:on-press
(fn []
(rf/dispatch [:show-bottom-sheet
{:content
(fn []
[remove-account/view])}]))})]
:account-name account-name
:account-emoji emoji
:account-color color
+35 -27
View File
@@ -6,8 +6,8 @@
[status-im.contexts.wallet.data-store :as data-store]
[status-im.contexts.wallet.events.collectibles]
[status-im.contexts.wallet.item-types :as item-types]
[status-im.contexts.wallet.temp :as temp]
[taoensso.timbre :as log]
[utils.collection]
[utils.ethereum.chain :as chain]
[utils.ethereum.eip.eip55 :as eip55]
[utils.i18n :as i18n]
@@ -52,10 +52,9 @@
wallet-db (get db :wallet)
new-account? (:new-account? wallet-db)
navigate-to-account (:navigate-to-account wallet-db)]
{:db (reduce (fn [db {:keys [address] :as account}]
(assoc-in db [:wallet :accounts address] account))
db
(data-store/rpc->accounts wallet-accounts))
{:db (assoc-in db
[:wallet :accounts]
(utils.collection/index-by :address (data-store/rpc->accounts wallet-accounts)))
:fx [[:dispatch [:wallet/get-wallet-token]]
[:dispatch [:wallet/request-collectibles {:start-at-index 0 :new-request? true}]]
(when new-account?
@@ -85,6 +84,30 @@
{:error %
:event :wallet/save-account})}]]]}))
(rf/reg-event-fx
:wallet/show-account-deleted-toast
(fn [_ [toast-message]]
{:fx [[:dispatch [:toasts/upsert {:type :positive :text toast-message}]]]}))
(rf/reg-event-fx
:wallet/remove-account-success
(fn [_ [toast-message _]]
{:fx [[:dispatch [:hide-bottom-sheet]]
[:dispatch [:pop-to-root :shell-stack]]
[:dispatch [:wallet/get-accounts]]
[:dispatch [:wallet/show-account-deleted-toast toast-message]]]}))
(rf/reg-event-fx
:wallet/remove-account
(fn [_ [{:keys [address toast-message]}]]
{:fx [[:json-rpc/call
[{:method "accounts_deleteAccount"
:params [address]
:on-success [:wallet/remove-account-success toast-message]
:on-error #(log/info "failed to remove account "
{:error %
:event :wallet/remove-account})}]]]}))
(rf/reg-event-fx
:wallet/get-wallet-token
(fn [{:keys [db]}]
@@ -134,10 +157,10 @@
(rf/reg-event-fx :wallet/create-derived-addresses
(fn [{:keys [db]} [{:keys [sha3-pwd path]} on-success]]
(let [{:keys [wallet-root-address]} (:profile/profile db)]
(let [{:keys [address]} (:profile/profile db)]
{:fx [[:json-rpc/call
[{:method "wallet_getDerivedAddresses"
:params [sha3-pwd wallet-root-address [path]]
:params [sha3-pwd address [path]]
:on-success on-success
:on-error #(log/info "failed to derive address " %)}]]]})))
@@ -242,30 +265,15 @@
(rf/reg-event-fx :wallet/fetch-address-suggestions
(fn [{:keys [db]} [address]]
(fn [{:keys [db]} [_address]]
{:db (assoc db
:wallet/local-suggestions
(cond
(= address
(get-in
temp/address-local-suggestion-saved-contact-address-mock
[:accounts 0 :address]))
[temp/address-local-suggestion-saved-contact-address-mock]
(= address
(get temp/address-local-suggestion-saved-address-mock
:address))
[temp/address-local-suggestion-saved-address-mock]
:else (temp/find-matching-addresses address))
:wallet/valid-ens-or-address?
false)}))
:wallet/local-suggestions nil
:wallet/valid-ens-or-address? false)}))
(rf/reg-event-fx :wallet/ens-validation-success
(fn [{:keys [db]} [ens]]
(fn [{:keys [db]} [_ens]]
{:db (assoc db
:wallet/local-suggestions (if (= ens
(:ens temp/ens-local-suggestion-saved-address-mock))
[temp/ens-local-suggestion-saved-address-mock]
[temp/ens-local-suggestion-mock])
:wallet/local-suggestions nil
:wallet/valid-ens-or-address? true)}))
(rf/reg-event-fx :wallet/address-validation-success
+12 -3
View File
@@ -2,6 +2,7 @@
(:require
[camel-snake-kebab.core :as csk]
[camel-snake-kebab.extras :as cske]
[clojure.string :as string]
[status-im.constants :as constants]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.send.utils :as send-utils]
@@ -57,16 +58,23 @@
(rf/reg-event-fx :wallet/select-send-address
(fn [{:keys [db]} [{:keys [address token recipient stack-id]}]]
(let [[prefix to-address] (utils/split-prefix-and-address address)]
(let [[prefix to-address] (utils/split-prefix-and-address address)
prefix-seq (string/split prefix #":")
selected-networks (mapv #(utils/short-name->id (keyword %)) prefix-seq)]
{:db (-> db
(assoc-in [:wallet :ui :send :recipient] (or recipient address))
(assoc-in [:wallet :ui :send :to-address] to-address)
(assoc-in [:wallet :ui :send :address-prefix] prefix))
(assoc-in [:wallet :ui :send :address-prefix] prefix)
(assoc-in [:wallet :ui :send :selected-networks] selected-networks))
:fx [[:navigate-to-within-stack
(if token
[:wallet-send-input-amount stack-id]
[:wallet-select-asset stack-id])]]})))
(rf/reg-event-fx :wallet/update-receiver-networks
(fn [{:keys [db]} [selected-networks]]
{:db (assoc-in db [:wallet :ui :send :selected-networks] selected-networks)}))
(rf/reg-event-fx :wallet/send-select-token
(fn [{:keys [db]} [{:keys [token stack-id]}]]
{:db (assoc-in db [:wallet :ui :send :token] token)
@@ -92,10 +100,11 @@
(let [wallet-address (get-in db [:wallet :current-viewing-account-address])
token (get-in db [:wallet :ui :send :token])
account-address (get-in db [:wallet :ui :send :send-account-address])
selected-networks (get-in db [:wallet :ui :send :selected-networks])
to-address (or account-address (get-in db [:wallet :ui :send :to-address]))
token-decimal (:decimals token)
token-id (:symbol token)
network-preferences []
network-preferences selected-networks
gas-rates constants/gas-rate-medium
amount-in (send-utils/amount-in-hex amount token-decimal)
from-address wallet-address
@@ -44,7 +44,8 @@
:market-values-per-currency {:usd {:price 10}}}
:wallet/wallet-send-loading-suggested-routes? false
:wallet/wallet-send-route {:route []}
:wallet/wallet-send-suggested-routes {:candidates []}})
:wallet/wallet-send-suggested-routes {:candidates []}
:wallet/wallet-send-selected-networks []})
(h/describe "Send > input amount screen"
(h/setup-restorable-re-frame)
@@ -54,13 +54,6 @@
(normalize-input current v)
current))
(defn- find-affordable-networks
[{:keys [balances-per-chain]} input-value]
(->> balances-per-chain
(filter (fn [[_ {:keys [balance]}]]
(>= (js/parseFloat balance) input-value)))
(map first)))
(defn- reset-input-error
[new-value prev-value input-error]
(reset! input-error
@@ -129,21 +122,22 @@
(<= input-num-value 0)
(> input-num-value (:amount @current-limit)))
amount (str @input-value " " token-symbol)
{:keys [color]} (rf/sub [:wallet/current-viewing-account])]
{:keys [color]} (rf/sub [:wallet/current-viewing-account])
fetch-routes (fn []
(rf/dispatch [:wallet/clean-suggested-routes])
(when-not (or
(empty? @input-value)
(<= input-num-value 0)
(> input-num-value (:amount @current-limit)))
(debounce/debounce-and-dispatch [:wallet/get-suggested-routes
@input-value]
100)))]
(rn/use-effect
(fn []
(let [dismiss-keyboard-fn #(when (= % "active") (rn/dismiss-keyboard!))
app-keyboard-listener (.addEventListener rn/app-state "change" dismiss-keyboard-fn)]
#(.remove app-keyboard-listener))))
(rn/use-effect (fn []
(rf/dispatch [:wallet/clean-suggested-routes])
(when-not (or
(empty? @input-value)
(<= input-num-value 0)
(> input-num-value (:amount @current-limit)))
(debounce/debounce-and-dispatch [:wallet/get-suggested-routes @input-value]
100)))
[@input-value])
(rn/use-effect #(fetch-routes) [@input-value])
[rn/view
{:style style/screen
:accessibility-label (str "container" (when @input-error "-error"))}
@@ -166,10 +160,11 @@
:on-change-text (fn [text]
(handle-on-change text))}]
[routes/view
{:amount amount
:routes suggested-routes
:loading-networks (find-affordable-networks token @input-value)
:networks (:networks token)}]
{:amount amount
:routes suggested-routes
:token token
:input-value @input-value
:fetch-routes fetch-routes}]
[quo/bottom-actions
{:actions :1-action
:button-one-label (i18n/label :t/confirm)
@@ -1,4 +1,5 @@
(ns status-im.contexts.wallet.send.routes.style)
(ns status-im.contexts.wallet.send.routes.style
(:require [quo.foundations.colors :as colors]))
(def routes-container
{:padding-horizontal 20
@@ -30,3 +31,26 @@
{:flex-grow 1
:align-items :center
:justify-content :center})
(def add-network
{:margin-top 8
:align-self :flex-end
:left 12})
(defn warning-container
[color theme]
{:flex-direction :row
:border-width 1
:border-color (colors/resolve-color color theme 10)
:background-color (colors/resolve-color color theme 5)
:margin-horizontal 20
:margin-top 4
:margin-bottom 8
:padding-left 12
:padding-vertical 11
:border-radius 12})
(def warning-text
{:margin-left 8
:margin-right 12
:padding-right 12})
@@ -1,39 +1,134 @@
(ns status-im.contexts.wallet.send.routes.view
(:require
[clojure.string :as string]
[quo.core :as quo]
[quo.foundations.colors :as colors]
[quo.foundations.resources :as resources]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.send.routes.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn route-item
[{:keys [amount from-network to-network status]}]
[rn/view {:style style/routes-inner-container}
[quo/network-bridge
{:amount amount
:network from-network
:status status}]
(if (= status :default)
[quo/network-link
{:shape :linear
:source from-network
:destination to-network
:container-style style/network-link}]
[rn/view {:style {:width 73}}])
[quo/network-bridge
{:amount amount
:network to-network
:status status
:container-style {:right 12}}]])
(defn- find-affordable-networks
[{:keys [balances-per-chain]} input-value selected-networks]
(->> balances-per-chain
(filter (fn [[_ {:keys [balance chain-id]}]]
(and
(>= (js/parseFloat balance) input-value)
(some #(= % chain-id) selected-networks))))
(map first)))
(defn view
[{:keys [amount routes loading-networks]}]
(let [loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
candidates (:candidates routes)]
(if (or (and (not-empty loading-networks) loading-suggested-routes?) (not-empty candidates))
(defn- make-network-item
[{:keys [network-name chain-id] :as _network}
{:keys [title color on-change network-preferences] :as _options}]
{:title (or title (string/capitalize (name network-name)))
:image :icon-avatar
:image-props {:icon (resources/get-network network-name)
:size :size-20}
:action :selector
:action-props {:type :checkbox
:customization-color color
:checked? (some #(= % chain-id) @network-preferences)
:on-change on-change}})
(defn networks-drawer
[{:keys [fetch-routes theme]}]
(let [network-details (rf/sub [:wallet/network-details])
{:keys [color]} (rf/sub [:wallet/current-viewing-account])
selected-networks (rf/sub [:wallet/wallet-send-selected-networks])
prefix (rf/sub [:wallet/wallet-send-address-prefix])
prefix-seq (string/split prefix #":")
grouped-details (group-by #(contains? (set prefix-seq) (:short-name %)) network-details)
preferred (get grouped-details true [])
not-preferred (get grouped-details false [])
network-preferences (reagent/atom selected-networks)
toggle-network (fn [{:keys [chain-id]}]
(swap! network-preferences
(fn [preferences]
(if (some #(= % chain-id) preferences)
(vec (remove #(= % chain-id) preferences))
(conj preferences chain-id)))))]
(fn []
[rn/view
[quo/drawer-top {:title (i18n/label :t/edit-receiver-networks)}]
[quo/category
{:list-type :settings
:label (i18n/label :t/preferred-by-receiver)
:data (mapv (fn [network]
(make-network-item network
{:color color
:network-preferences network-preferences
:on-change #(toggle-network network)}))
preferred)}]
(when (pos? (count not-preferred))
[quo/category
{:list-type :settings
:label (i18n/label :t/not-preferred-by-receiver)
:data (mapv (fn [network]
(make-network-item network
{:color color
:network-preferences network-preferences
:on-change #(toggle-network network)}))
not-preferred)}])
(when (not= selected-networks @network-preferences)
[rn/view {:style (style/warning-container color theme)}
[quo/icon :i/info {:color (colors/resolve-color color theme)}]
[quo/text
{:size :paragraph-2
:style style/warning-text} (i18n/label :t/receiver-networks-warning)]])
[quo/bottom-actions
{:button-one-label (i18n/label :t/apply-changes)
:button-one-props {:disabled? (= selected-networks @network-preferences)
:on-press (fn []
(rf/dispatch [:wallet/update-receiver-networks
@network-preferences])
(rf/dispatch [:hide-bottom-sheet])
(fetch-routes))
:customization-color color}}]])))
(defn route-item
[{:keys [amount from-network to-network status theme fetch-routes]}]
(if (= status :add)
[quo/network-bridge
{:status :add
:container-style style/add-network
:on-press #(rf/dispatch [:show-bottom-sheet
{:content (fn [] [networks-drawer
{:theme theme
:fetch-routes fetch-routes}])}])}]
[rn/view {:style style/routes-inner-container}
[quo/network-bridge
{:amount amount
:network from-network
:status status}]
(if (= status :default)
[quo/network-link
{:shape :linear
:source from-network
:destination to-network
:container-style style/network-link}]
[rn/view {:style {:width 73}}])
[quo/network-bridge
{:amount amount
:network to-network
:status status
:container-style {:right 12}}]]))
(defn- view-internal
[{:keys [amount routes token input-value theme fetch-routes]}]
(let [selected-networks (rf/sub [:wallet/wallet-send-selected-networks])
loading-networks (find-affordable-networks token input-value selected-networks)
loading-suggested-routes? (rf/sub [:wallet/wallet-send-loading-suggested-routes?])
best-routes (:best routes)
data (if loading-suggested-routes? loading-networks best-routes)]
(if (or (and (not-empty loading-networks) loading-suggested-routes?) (not-empty best-routes))
[rn/flat-list
{:data (if loading-suggested-routes? loading-networks candidates)
{:data (if (and (< (count data) 3) (pos? (count data)))
(concat data [{:status :add}])
data)
:content-container-style style/routes-container
:header [rn/view {:style style/routes-header-container}
[quo/section-label
@@ -45,7 +140,12 @@
:render-fn (fn [item]
[route-item
{:amount amount
:status (if loading-suggested-routes? :loading :default)
:theme theme
:fetch-routes fetch-routes
:status (cond
(= (:status item) :add) :add
loading-suggested-routes? :loading
:else :default)
:from-network (if loading-suggested-routes?
(utils/id->network item)
(utils/id->network (get-in item [:from :chain-id])))
@@ -54,5 +154,7 @@
(utils/id->network (get-in item
[:to :chain-id])))}])}]
[rn/view {:style style/empty-container}
(when (and (not (nil? candidates)) (not loading-suggested-routes?))
(when (and (not (nil? best-routes)) (not loading-suggested-routes?))
[quo/text (i18n/label :t/no-routes-found)])])))
(def view (quo.theme/with-theme view-internal))
-124
View File
@@ -1,124 +0,0 @@
(ns status-im.contexts.wallet.temp
(:require [clojure.string :as string]
[quo.foundations.resources :as quo.resources]
[status-im.common.resources :as resources]
[status-im.contexts.wallet.item-types :as types]))
(def ens-local-suggestion-saved-address-mock
{:type types/saved-address
:name "Pedro"
:ens "pedro.eth"
:address "0x4732894732894738294783294723894723984"
:customization-color :purple
:networks [{:network-name :ethereum
:short-name "eth"}
{:network-name :optimism
:short-name "opt"}]})
(def ens-local-suggestion-mock
{:type types/address
:ens "pedro.eth"
:address "0x4732894732894738294783294723894723984"
:networks [{:network-name :ethereum
:short-name "eth"}
{:network-name :optimism
:short-name "opt"}]})
(def address-local-suggestion-saved-contact-address-mock
{:type types/saved-contact-address
:customization-color :blue
:accounts [{:name "New House"
:address "0x62cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2"
:emoji "🍔"
:customization-color :blue}]
:contact-props {:full-name "Mark Libot"
:profile-picture (resources/get-mock-image :user-picture-male4)
:customization-color :purple}})
(def address-local-suggestion-saved-address-mock
{:type types/saved-address
:name "Peter Lamborginski"
:address "0x12FaBc34De56Ef78A9B0Cd12Ef3456AbC7D8E9F0"
:customization-color :magenta
:networks [{:network-name :ethereum
:short-name "eth"}
{:network-name :optimism
:short-name "opt"}]})
(def address-local-suggestion-mock
{:type types/address
:address "0x1233cD34De56Ef78A9B0Cd12Ef3456AbC7123dee"
:networks [{:network-name :ethereum
:short-name "eth"}
{:network-name :optimism
:short-name "opt"}]})
(defn find-matching-addresses
[substring]
(let [all-addresses [address-local-suggestion-saved-address-mock
address-local-suggestion-mock]]
(vec (filter #(string/starts-with? (:address %) substring) all-addresses))))
(def collectible-activities
[{:transaction :receive
:timestamp "Today 22:20"
:status :finalised
:counter 1
:first-tag {:size 24
:type :collectible
:collectible (resources/mock-images :collectible)
:collectible-name "Collectible"
:collectible-number "123"}
:second-tag-prefix :t/from
:second-tag {:size 24
:type :default
:full-name "Aretha Gosling"
:profile-picture (resources/mock-images :user-picture-female2)}
:third-tag-prefix :t/to
:third-tag {:size 24
:type :account
:account-name "Piggy bank"
:emoji "🐷"}
:fourth-tag-prefix :t/via
:fourth-tag {:size 24
:type :network
:network-logo (quo.resources/get-network :ethereum)
:network-name "Mainnet"}}
{:transaction :mint
:timestamp "Yesterday"
:status :finalised
:counter 1
:first-tag {:size 24
:type :collectible
:collectible (resources/mock-images :collectible)
:collectible-name "Collectible"
:collectible-number "123"}
:second-tag-prefix :t/at
:second-tag
{:size 24
:type :address
:address
"0x04fcf40c526b09ff9fb22f4a5dbd08490ef9b64af700870f8a0ba2133f4251d5607ed83cd9047b8c2796576bc83fa0de23a13a4dced07654b8ff137fe744047917"}
:third-tag-prefix :t/on
:third-tag {:size 24
:type :network
:network-logo (quo.resources/get-network :ethereum)
:network-name "Mainnet"}}])
(def collectible-about
{:cards [{:title "BAYC"
:icon :social/link
:address "boredapeyachtclub"
:customization-color :social/link
:on-press #(js/alert "pressed")}
{:title "Twitter"
:icon :social/twitter
:address "@BoredApeYC"
:customization-color :social/twitter
:on-press #(js/alert "pressed")}
{:title "Opensea"
:icon :social/opensea
:address "Bored Ape Yacht Club"
:customization-color :social/opensea
:on-press #(js/alert "pressed")}]})
+51 -21
View File
@@ -297,32 +297,62 @@
(fn [collapsed-categories [_ community-id]]
(get collapsed-categories community-id)))
(defn- permission-id->permission-value
[token-permissions permission-id]
(get (into {} token-permissions) permission-id))
(re-frame/reg-sub
:community/token-gated-overview
(fn [[_ community-id]]
[(re-frame/subscribe [:communities/community community-id])])
(fn [[{:keys [token-permissions-check token-permissions checking-permissions? token-images]}] _]
{:can-request-access? (:satisfied token-permissions-check)
:number-of-hold-tokens (reduce
(fn [acc [_ {:keys [criteria]}]]
(reduce #(+ %1 (if %2 1 0)) acc criteria))
0
(:permissions token-permissions-check))
:tokens (->> token-permissions
(filter (fn [[_ {:keys [type]}]]
(= type constants/community-token-permission-become-member)))
(map (fn [[perm-key {:keys [token_criteria]}]]
(let [check-criteria (get-in token-permissions-check
[:permissions perm-key :criteria])]
(map
(fn [{sym :symbol amount :amount} sufficient?]
{:symbol sym
:sufficient? (when (seq check-criteria) sufficient?)
:loading? checking-permissions?
:amount amount
:img-src (get token-images sym)})
token_criteria
(or check-criteria token_criteria))))))}))
(let [can-request-access? (:satisfied token-permissions-check)
role-permissions #{constants/community-token-permission-become-admin
constants/community-token-permission-become-member
constants/community-token-permission-become-token-master
constants/community-token-permission-become-token-owner}
highest-permission-role
(when can-request-access?
(->> token-permissions-check
:permissions
(reduce-kv
(fn [highest-permission-role permission-id {:keys [criteria]}]
(if-let [permission-type
(and (first criteria)
(some #{(:type (permission-id->permission-value token-permissions
permission-id))}
role-permissions))]
(if highest-permission-role
(min highest-permission-role permission-type)
permission-type)
highest-permission-role))
nil)))
highest-permission-role (if (and can-request-access? (nil? highest-permission-role))
constants/community-token-permission-become-member
highest-permission-role)]
{:can-request-access? can-request-access?
:highest-permission-role highest-permission-role
:number-of-hold-tokens (reduce
(fn [acc [_ {:keys [criteria]}]]
(reduce #(+ %1 (if %2 1 0)) acc criteria))
0
(:permissions token-permissions-check))
:tokens (->>
token-permissions
(filter (fn [[_ {:keys [type]}]]
(= type constants/community-token-permission-become-member)))
(map (fn [[perm-key {:keys [token_criteria]}]]
(let [check-criteria (get-in token-permissions-check
[:permissions perm-key :criteria])]
(map
(fn [{sym :symbol amount :amount} sufficient?]
{:symbol sym
:sufficient? (when (seq check-criteria) sufficient?)
:loading? checking-permissions?
:amount amount
:img-src (get token-images sym)})
token_criteria
(or check-criteria token_criteria))))))})))
(re-frame/reg-sub
:community/images
+37 -35
View File
@@ -1,6 +1,7 @@
(ns status-im.subs.communities-test
(:require
[cljs.test :refer [is testing]]
matcher-combinators.test
[re-frame.db :as rf-db]
[status-im.constants :as constants]
status-im.subs.communities
@@ -17,7 +18,7 @@
(swap! rf-db/app-db assoc
:communities
raw-communities)
(is (= raw-communities (rf/sub [sub-name]))))))
(is (match? raw-communities (rf/sub [sub-name]))))))
(h/deftest-sub :communities/section-list
[sub-name]
@@ -26,29 +27,29 @@
:communities
{"0x1" {:name "civilized monkeys"}
"0x2" {:name "Civilized rats"}})
(is (= [{:title "C"
:data [{:name "civilized monkeys"}
{:name "Civilized rats"}]}]
(rf/sub [sub-name]))))
(is (match? [{:title "C"
:data [{:name "civilized monkeys"}
{:name "Civilized rats"}]}]
(rf/sub [sub-name]))))
(testing "sorts by section ascending"
(swap! rf-db/app-db assoc
:communities
{"0x3" {:name "Memorable"}
"0x1" {:name "Civilized monkeys"}})
(is (= [{:title "C" :data [{:name "Civilized monkeys"}]}
{:title "M" :data [{:name "Memorable"}]}]
(rf/sub [sub-name]))))
(is (match? [{:title "C" :data [{:name "Civilized monkeys"}]}
{:title "M" :data [{:name "Memorable"}]}]
(rf/sub [sub-name]))))
(testing "builds default section for communities without a name"
(swap! rf-db/app-db assoc
:communities
{"0x2" {:id "0x2"}
"0x1" {:id "0x1"}})
(is (= [{:title ""
:data [{:id "0x2"}
{:id "0x1"}]}]
(rf/sub [sub-name])))))
(is (match? [{:title ""
:data [{:id "0x2"}
{:id "0x1"}]}]
(rf/sub [sub-name])))))
(h/deftest-sub :communities/unviewed-counts
[sub-name]
@@ -64,17 +65,17 @@
"0x102" {:community-id community-id
:unviewed-mentions-count 5
:unviewed-messages-count 1}})
(is (= {:unviewed-messages-count 3
:unviewed-mentions-count 8}
(rf/sub [sub-name community-id]))))
(is (match? {:unviewed-messages-count 3
:unviewed-mentions-count 8}
(rf/sub [sub-name community-id]))))
(testing "defaults to zero when count keys are not present"
(swap! rf-db/app-db assoc
:chats
{"0x100" {:community-id community-id}})
(is (= {:unviewed-messages-count 0
:unviewed-mentions-count 0}
(rf/sub [sub-name community-id])))))
(is (match? {:unviewed-messages-count 0
:unviewed-mentions-count 0}
(rf/sub [sub-name community-id])))))
(h/deftest-sub :communities/categorized-channels
[sub-name]
@@ -350,16 +351,16 @@
(swap! rf-db/app-db assoc
:communities/my-pending-requests-to-join
{})
(is (= {}
(rf/sub [sub-name]))))
(is (match? {}
(rf/sub [sub-name]))))
(testing "users requests to join different communities"
(swap! rf-db/app-db assoc
:communities/my-pending-requests-to-join
{:community-id-1 {:id :request-id-1}
:community-id-2 {:id :request-id-2}})
(is (= {:community-id-1 {:id :request-id-1}
:community-id-2 {:id :request-id-2}}
(rf/sub [sub-name])))))
(is (match? {:community-id-1 {:id :request-id-1}
:community-id-2 {:id :request-id-2}}
(rf/sub [sub-name])))))
(h/deftest-sub :communities/my-pending-request-to-join
[sub-name]
@@ -367,15 +368,15 @@
(swap! rf-db/app-db assoc
:communities/my-pending-requests-to-join
{})
(is (= nil
(rf/sub [sub-name :community-id-1]))))
(is (match? nil
(rf/sub [sub-name :community-id-1]))))
(testing "users request to join a specific communities"
(swap! rf-db/app-db assoc
:communities/my-pending-requests-to-join
{:community-id-1 {:id :request-id-1}
:community-id-2 {:id :request-id-2}})
(is (= :request-id-1
(rf/sub [sub-name :community-id-1])))))
(is (match? :request-id-1
(rf/sub [sub-name :community-id-1])))))
(h/deftest-sub :community/token-gated-overview
[sub-name]
@@ -385,6 +386,7 @@
community {:id community-id
:checking-permissions? checking-permissions?
:permissions {:access 3}
:highest-permission-role constants/community-token-permission-become-admin
:token-images {"ETH" token-image-eth}
:token-permissions [[:permission-id-01
{:id "permission-id-01"
@@ -451,14 +453,14 @@
:outroMessage "bla"
:verified false}]
(swap! rf-db/app-db assoc-in [:communities community-id] community)
(is (= {:can-request-access? true
:number-of-hold-tokens 2
:tokens [[{:symbol "ETH"
:amount "0.001"
:sufficient? nil
:loading? checking-permissions?
:img-src token-image-eth}]]}
(rf/sub [sub-name community-id])))))
(is (match? {:can-request-access? true
:number-of-hold-tokens 2
:tokens [[{:symbol "ETH"
:amount "0.001"
:sufficient? nil
:loading? checking-permissions?
:img-src token-image-eth}]]}
(rf/sub [sub-name community-id])))))
(h/deftest-sub :communities/airdrop-account
[sub-name]
+5
View File
@@ -48,6 +48,11 @@
:<- [:wallet/wallet-send]
:-> :address-prefix)
(rf/reg-sub
:wallet/wallet-send-selected-networks
:<- [:wallet/wallet-send]
:-> :selected-networks)
(rf/reg-sub
:wallet/wallet-send-route
:<- [:wallet/wallet-send]
@@ -45,20 +45,27 @@ class TestDeepLinksOneDevice(MultipleSharedDeviceTestCase):
self.errors.append("Profile was not opened by the profile url %s" % url)
self.home.navigate_back_to_chat_view()
closed_community_urls = [
"https://status.app/c/G8EAAGTiXKuwNbVVAu0GNLD-XzX4oz_E8oC1-7qSLikaTnCuG9Ag13ZgQKrMd8En9Qcpuaj3Qx3mfZ1atZzH8Zw-x_sFJ_MDv0P_7YfqoV-pNr3V4dsza-jVk41GaCGWasJb92Oer8qggaoNWf0tYCgSH19VonXciKPUz3ITdgke#zQ3shbmfT3hvh4mKa1v6uAjjyztQEroh8Mfn6Ckegjd7LT3XK",
"https://status.app/c/Ow==#zQ3shbmfT3hvh4mKa1v6uAjjyztQEroh8Mfn6Ckegjd7LT3XK",
"https://status.app/c#zQ3shbmfT3hvh4mKa1v6uAjjyztQEroh8Mfn6Ckegjd7LT3XK",
"https://status.app/c/ixiACjAKCHRlc3RDb21tEhZkemZ4Z2Nodmpra2xra2xrbCAgbGxsGAYiByM4OEIwRkYqARQD#zQ3shuK3RAMBGtNWJ5QAKtuGeyEhiwko5gXhyGg6T89Q2xrHq"
]
for url in closed_community_urls:
closed_community_urls = {
"https://status.app/c/G8EAAMR_fz8tsCQ-aR2QrCS5sVAvvzc_N3mAA-En_Zxy4JA3j7Dl1A50Pd4DbooQOMbWf7E1_4wipgDyGe8XZEappDn-Qomf9l_xyXhSYBuSQic8InCEUBSRGR0oixSTh3iw5ZCxzkGSI95Iyu1EBpcIlFOEMPHpKUBIdkkoKBJglMDKko8O8dBvBtIYncOA8mwztwLpx3C0rK_u59PldFuXe4cx#zQ3shwQnEfMtcXpHXF4qJPyCGgw2F18N3nbGzYbzsVHnMq4yK":
"Status mobile QA community max",
"https://status.app/c/GyoAAORtA48geFrtWr2mu-G5DnFaI0sgqUIIaBFX_DJ_mRbXmzoMnCJnqwI=#zQ3shQhL414wEjDJMEpgTjd14aHCiBDnk6Bq5YTWoi4b7wvnu":
"test_comm_enc",
"https://status.app/c/G00AAGS9TbI9mSR-ZNmFrhRjNuEeXAAbcAIUaLLJyjMOG3ACJQ12oIHD78QhzO9s_T5bUeU7rnATWJg3mGgTUemrAg==#zQ3shspPKCZ1VPVQ9dLXGufUGvGphjxVwrcZ6rkZc7S39T4b3":
"closed community",
"https://status.app/c/GyAAAOQbK4dMy1OMI8s2nGvJR3QRqBQqbExff0-cgmN0T-4C#zQ3shqQ4voo845RAkip2JkYTjL4dpiGnRhaNHjVDxPdEZ1xvP":
"e2e_open",
"https://status.app/c/G0UAAMTyNsn2QZDEG0EXftOl8pOEfwEBOOSA_YTfIk85xmADDgINGmxpUHAXzK36bN0fK42Xf4YD2yjPk1z2pbFwFw==#zQ3shgkDFQEnwxji7CvMTokMrShmC2UgxiJ549X5Aw746zQrK":
"open community"
}
for url, text in closed_community_urls.items():
self.channel.chat_message_input.clear()
self.channel.send_message(url)
self.channel.chat_element_by_text(url).click_on_link_inside_message_body()
if not self.channel.element_by_translation_id(
"community-admins-will-review-your-request").is_element_displayed(10):
if not self.community_view.join_button.is_element_displayed(
10) or self.community_view.community_title.text != text:
self.errors.append("Closed community was not requested to join by the url %s" % url)
self.home.jump_to_card_by_text(self.community_name)
if text != "open community": # the last one
self.home.jump_to_card_by_text(self.community_name)
self.errors.verify_no_errors()
@@ -84,16 +91,22 @@ class TestDeepLinksOneDevice(MultipleSharedDeviceTestCase):
self.errors.append("Profile was not opened by the profile deep link %s" % link)
self.browser_view.click_system_back_button()
community_links = [
"status-app://c/G8EAAGTiXKuwNbVVAu0GNLD-XzX4oz_E8oC1-7qSLikaTnCuG9Ag13ZgQKrMd8En9Qcpuaj3Qx3mfZ1atZzH8Zw-x_sFJ_MDv0P_7YfqoV-pNr3V4dsza-jVk41GaCGWasJb92Oer8qggaoNWf0tYCgSH19VonXciKPUz3ITdgke#zQ3shbmfT3hvh4mKa1v6uAjjyztQEroh8Mfn6Ckegjd7LT3XK",
"status-app://c/Ow==#zQ3shbmfT3hvh4mKa1v6uAjjyztQEroh8Mfn6Ckegjd7LT3XK",
"status-app://c#zQ3shbmfT3hvh4mKa1v6uAjjyztQEroh8Mfn6Ckegjd7LT3XK",
"status-app://c/ixiACjAKCHRlc3RDb21tEhZkemZ4Z2Nodmpra2xra2xrbCAgbGxsGAYiByM4OEIwRkYqARQD#zQ3shuK3RAMBGtNWJ5QAKtuGeyEhiwko5gXhyGg6T89Q2xrHq"
]
for link in community_links:
community_links = {
"status.app://c/G8EAAMR_fz8tsCQ-aR2QrCS5sVAvvzc_N3mAA-En_Zxy4JA3j7Dl1A50Pd4DbooQOMbWf7E1_4wipgDyGe8XZEappDn-Qomf9l_xyXhSYBuSQic8InCEUBSRGR0oixSTh3iw5ZCxzkGSI95Iyu1EBpcIlFOEMPHpKUBIdkkoKBJglMDKko8O8dBvBtIYncOA8mwztwLpx3C0rK_u59PldFuXe4cx#zQ3shwQnEfMtcXpHXF4qJPyCGgw2F18N3nbGzYbzsVHnMq4yK":
"Status mobile QA community max",
"status.app://c/GyoAAORtA48geFrtWr2mu-G5DnFaI0sgqUIIaBFX_DJ_mRbXmzoMnCJnqwI=#zQ3shQhL414wEjDJMEpgTjd14aHCiBDnk6Bq5YTWoi4b7wvnu":
"test_comm_enc",
"status.app://c/G00AAGS9TbI9mSR-ZNmFrhRjNuEeXAAbcAIUaLLJyjMOG3ACJQ12oIHD78QhzO9s_T5bUeU7rnATWJg3mGgTUemrAg==#zQ3shspPKCZ1VPVQ9dLXGufUGvGphjxVwrcZ6rkZc7S39T4b3":
"closed community",
"status.app://c/G0UAAMTyNsn2QZDEG0EXftOl8pOEfwEBOOSA_YTfIk85xmADDgINGmxpUHAXzK36bN0fK42Xf4YD2yjPk1z2pbFwFw==#zQ3shgkDFQEnwxji7CvMTokMrShmC2UgxiJ549X5Aw746zQrK":
"open community",
"status.app://c/GyAAAOQbK4dMy1OMI8s2nGvJR3QRqBQqbExff0-cgmN0T-4C#zQ3shqQ4voo845RAkip2JkYTjL4dpiGnRhaNHjVDxPdEZ1xvP":
"e2e_open"
}
for link, text in community_links.items():
self.browser_view.open_url(link)
if not self.channel.element_by_translation_id(
"community-admins-will-review-your-request").is_element_displayed(10):
if not self.community_view.join_button.is_element_displayed(
10) or self.community_view.community_title.text != text:
self.errors.append("Closed community was not requested to join by the deep link %s" % link)
self.home.navigate_back_to_home_view()
self.home.browser_tab.click()
+1
View File
@@ -425,6 +425,7 @@ class CommunityView(HomeView):
self.close_community_view_button = Button(
self.driver,
xpath="//*[@content-desc='community-options-for-community']/../*[1]//android.widget.ImageView")
self.community_title = Text(self.driver, accessibility_id="community-title")
self.community_description_text = Text(self.driver, accessibility_id="community-description-text")
self.community_status_joined = Text(self.driver, accessibility_id="status-tag-positive")
self.community_status_pending = Text(self.driver, accessibility_id="status-tag-pending")
+16 -4
View File
@@ -184,7 +184,7 @@
"no-addresses-selected": "At least 1 address must be shared with community",
"confirm-changes": "Confirm changes",
"airdrop-addresses": "Address for airdrops",
"join-as-a-member": "Join as a Member",
"join-as-a": "Join as a {{role}}",
"all-addresses": "All addresses",
"for-airdrops": "For airdrops",
"members-label": "Members",
@@ -2016,6 +2016,9 @@
"mentions": "Mentions",
"mention": "Mention",
"admin": "Admin",
"member": "Member",
"token-master": "Token Master",
"token-owner": "Token Owner",
"replies": "Replies",
"replied": "Replied",
"identity-verification": "Identity verification",
@@ -2252,7 +2255,9 @@
"sync-devices-complete-title": "Device sync complete!",
"sync-devices-complete-sub-title": "Your devices are now in sync",
"synced-with": "Synced with",
"eligible-to-join-as": "Eligible to join as {{role}}",
"you-eligible-to-join": "Youre eligible to join",
"you-eligible-to-join-as": "Youre eligible to join as {{role}}",
"you-not-eligible-to-join": "Youre not eligible to join",
"you-hold-number-of-hold-tokens-of-these": "You hold {{number-of-hold-tokens}} of these:",
"token-gated-communities": "Token gated communities",
@@ -2453,11 +2458,10 @@
"share-details": "Share details",
"what-are-you-waiting-for": "What are you waiting for?",
"no-relevant-tokens": "No relevant tokens",
"on-the-web": "On the web",
"sending-with-ellipsis": "Sending...",
"sending-with-elipsis": "Sending...",
"transaction-confirmed": "Transaction confirmed!",
"transacation-finalised": "Transaction finalised!",
"no-relevant-tokens": "No relevant tokens",
"from-label": "From",
"to-label": "To",
"oops-wrong-word": "Oops! Wrong word",
@@ -2469,5 +2473,13 @@
"remove-account-title": "Remove account",
"remove-account-desc": "The account will be removed from all of your synced devices. Make sure you have a backup of your keypair or recovery phrase and derivation path (if its not default).",
"derivation-path-copied": "Derivation path copied",
"remove-account-confirmation": "I have taken note of the derivation path"
"remove-account-confirmation": "I have taken note of the derivation path",
"edit-receiver-networks": "Edit receiver networks",
"preferred-by-receiver": "Preferred by receiver",
"not-preferred-by-receiver": "Not preferred by receiver",
"apply-changes": "Apply changes",
"receiver-networks-warning": "Changing these settings may result in sending tokens to networks the recipient doesn't use",
"watched-account-removed": "Watched address has been removed",
"account-removed": "Account has been removed",
"share-address-title": "{{address}} address"
}