Account selection: Implement features related to editing shared addresses (#19177)
* Fix schema error
* Implement feature to edit shared addresses
* fix: show tokens when sharing all future addresses toggled
* fix: eligibility not checked when toggling all addresses
* Revert "fix: show tokens when sharing all future addresses toggled"
This reverts commit 8443a3432e
.
* fix: don't fetch balances on mount if toggled share all
---------
Co-authored-by: Cristian Lungu <lungucristian95@gmail.com>
This commit is contained in:
parent
6c5242b3e0
commit
7948582e46
|
@ -59,4 +59,15 @@
|
|||
:button-one-label "Request to join"}])
|
||||
(h/is-truthy (h/get-by-text "Eligible to join as"))
|
||||
(h/is-truthy (h/get-by-text "Admin"))
|
||||
(h/is-truthy (h/get-by-text "Request to join")))
|
||||
|
||||
(h/test "render with top description with custom text & 1 action"
|
||||
(render [bottom-actions/view
|
||||
{:description :top
|
||||
:role :admin
|
||||
:actions :one-action
|
||||
:description-top-text "You'll be an"
|
||||
:button-one-label "Request to join"}])
|
||||
(h/is-truthy (h/get-by-text "You'll be an"))
|
||||
(h/is-truthy (h/get-by-text "Admin"))
|
||||
(h/is-truthy (h/get-by-text "Request to join"))))
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
[:actions [:maybe [:enum :one-action :two-actions]]]
|
||||
[:description {:optional true} [:maybe [:enum :top :bottom :top-error]]]
|
||||
[:description-text {:optional true} [:maybe :string]]
|
||||
[:description-top-text {:optional true} [:maybe :string]]
|
||||
[:error-message {:optional true} [:maybe :string]]
|
||||
[:role {:optional true} [:maybe [:enum :admin :member :token-master :owner]]]
|
||||
[:button-one-label {:optional true} [:maybe :string]]
|
||||
|
@ -38,8 +39,8 @@
|
|||
:owner :i/crown})
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [actions description description-text error-message role button-one-label button-two-label
|
||||
blur? button-one-props button-two-props theme scroll? container-style]}]
|
||||
[{:keys [actions description description-text description-top-text error-message role button-one-label
|
||||
button-two-label blur? button-one-props button-two-props theme scroll? container-style]}]
|
||||
[rn/view
|
||||
{:style (merge (style/container scroll? blur? theme) container-style)}
|
||||
(when (= description :top-error)
|
||||
|
@ -54,12 +55,11 @@
|
|||
error-message]])
|
||||
|
||||
(when (and (= description :top) role)
|
||||
[rn/view
|
||||
{:style style/description-top}
|
||||
[rn/view {:style style/description-top}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style (style/description-top-text scroll? blur? theme)}
|
||||
(i18n/label :t/eligible-to-join-as)]
|
||||
(or description-top-text (i18n/label :t/eligible-to-join-as))]
|
||||
[context-tag/view
|
||||
{:type :icon
|
||||
:size 24
|
||||
|
|
|
@ -5,6 +5,14 @@
|
|||
(def ^:private ?cofx
|
||||
[:map])
|
||||
|
||||
(def ^:private ?event
|
||||
[:and
|
||||
[:vector {:min 1} :any]
|
||||
[:catn
|
||||
[:event-id keyword?]
|
||||
[:event-args [:* :any]]]])
|
||||
|
||||
(defn register-schemas
|
||||
[]
|
||||
(registry/register ::cofx ?cofx))
|
||||
(registry/register ::cofx ?cofx)
|
||||
(registry/register ::event ?event))
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
(ns status-im.contexts.communities.actions.accounts-selection.effects
|
||||
(:require
|
||||
[promesa.core :as p]
|
||||
[schema.core :as schema]
|
||||
[status-im.common.json-rpc.events :as rpc]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- generate-requests-for-signing
|
||||
[pub-key community-id addresses-to-reveal]
|
||||
(p/create
|
||||
(fn [p-resolve p-reject]
|
||||
(rpc/call
|
||||
{:method :wakuext_generateJoiningCommunityRequestsForSigning
|
||||
:params [pub-key community-id addresses-to-reveal]
|
||||
:on-success p-resolve
|
||||
:on-error #(p-reject (str "failed to generate requests for signing\n" %))}))))
|
||||
|
||||
(defn- sign-data
|
||||
[sign-params password]
|
||||
(p/create
|
||||
(fn [p-resolve p-reject]
|
||||
(rpc/call
|
||||
{:method :wakuext_signData
|
||||
:params [(map #(assoc % :password password) sign-params)]
|
||||
:on-success p-resolve
|
||||
:on-error #(p-reject (str "failed to sign data\n" %))}))))
|
||||
|
||||
(defn- edit-shared-addresses-for-community
|
||||
[community-id signatures addresses-to-reveal airdrop-address]
|
||||
(p/create
|
||||
(fn [p-resolve p-reject]
|
||||
(rpc/call
|
||||
{:method :wakuext_editSharedAddressesForCommunity
|
||||
:params [{:communityId community-id
|
||||
:signatures signatures
|
||||
:addressesToReveal addresses-to-reveal
|
||||
:airdropAddress airdrop-address}]
|
||||
:js-response true
|
||||
:on-success p-resolve
|
||||
:on-error p-reject}))))
|
||||
|
||||
(defn- request-to-join
|
||||
[community-id signatures addresses-to-reveal airdrop-address]
|
||||
(p/create
|
||||
(fn [p-resolve p-reject]
|
||||
(rpc/call
|
||||
{:method :wakuext_requestToJoinCommunity
|
||||
:params [{:communityId community-id
|
||||
:signatures signatures
|
||||
:addressesToReveal addresses-to-reveal
|
||||
:airdropAddress airdrop-address}]
|
||||
:js-response true
|
||||
:on-success p-resolve
|
||||
:on-error p-reject}))))
|
||||
|
||||
(defn- run-callback-or-event
|
||||
[callback-or-event result]
|
||||
(cond (fn? callback-or-event)
|
||||
(callback-or-event result)
|
||||
|
||||
(vector? callback-or-event)
|
||||
(rf/dispatch (conj callback-or-event result))))
|
||||
|
||||
(defn- sign-and-call-endpoint
|
||||
[{:keys [community-id password pub-key
|
||||
addresses-to-reveal airdrop-address
|
||||
on-success on-error
|
||||
callback]}]
|
||||
(-> (p/let [sign-params (generate-requests-for-signing pub-key community-id addresses-to-reveal)
|
||||
signatures (sign-data sign-params password)
|
||||
result (callback community-id
|
||||
signatures
|
||||
addresses-to-reveal
|
||||
airdrop-address)]
|
||||
(run-callback-or-event on-success result))
|
||||
(p/catch #(run-callback-or-event on-error %))))
|
||||
|
||||
(schema/=> sign-and-call-endpoint
|
||||
[:=>
|
||||
[:cat
|
||||
[:map {:closed true}
|
||||
[:community-id string?]
|
||||
[:password string?]
|
||||
[:pub-key string?]
|
||||
[:addresses-to-reveal
|
||||
[:or [:set string?]
|
||||
[:sequential string?]]]
|
||||
[:airdrop-address string?]
|
||||
[:on-success [:or fn? :schema.re-frame/event]]
|
||||
[:on-error [:or fn? :schema.re-frame/event]]
|
||||
[:callback fn?]]]
|
||||
:any])
|
||||
|
||||
(rf/reg-fx :effects.community/edit-shared-addresses
|
||||
(fn [opts]
|
||||
(sign-and-call-endpoint
|
||||
(assoc opts :callback edit-shared-addresses-for-community))))
|
||||
|
||||
(rf/reg-fx :effects.community/request-to-join
|
||||
(fn [opts]
|
||||
(sign-and-call-endpoint
|
||||
(assoc opts :callback request-to-join))))
|
|
@ -0,0 +1,103 @@
|
|||
(ns status-im.contexts.communities.actions.accounts-selection.events
|
||||
(:require
|
||||
status-im.contexts.communities.actions.accounts-selection.effects
|
||||
[status-im.contexts.communities.utils :as utils]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn initialize-permission-addresses
|
||||
[{:keys [db]} [community-id]]
|
||||
(let [{:keys [joined]} (get-in db [:communities community-id])
|
||||
pending-requests (get-in db [:communities/my-pending-requests-to-join community-id])
|
||||
init-using-revealed-accounts? (or joined (seq pending-requests))]
|
||||
{:fx [(if init-using-revealed-accounts?
|
||||
[:dispatch
|
||||
[:communities/get-revealed-accounts community-id
|
||||
[:communities/do-init-permission-addresses community-id]]]
|
||||
[:dispatch [:communities/do-init-permission-addresses community-id]])]}))
|
||||
|
||||
(rf/reg-event-fx :communities/initialize-permission-addresses initialize-permission-addresses)
|
||||
|
||||
(defn do-init-permission-addresses
|
||||
[{:keys [db]} [community-id revealed-accounts]]
|
||||
(let [wallet-accounts (utils/sorted-non-watch-only-accounts db)
|
||||
addresses-to-reveal (if (seq revealed-accounts)
|
||||
(set (keys revealed-accounts))
|
||||
;; Reveal all addresses as fallback.
|
||||
(set (map :address wallet-accounts)))
|
||||
|
||||
;; When there are no revealed addresses, such as when joining a
|
||||
;; community, use first address for airdrops.
|
||||
airdrop-address (or (->> revealed-accounts
|
||||
vals
|
||||
(filter :airdrop-address?)
|
||||
first
|
||||
:address)
|
||||
(->> wallet-accounts
|
||||
first
|
||||
:address))]
|
||||
{:db (-> db
|
||||
;; Set to false by default while we don't persist the user's choice
|
||||
;; in status-go, otherwise whenever the view is mounted, the choice
|
||||
;; of selected addresses won't be respected.
|
||||
(assoc-in [:communities/selected-share-all-addresses community-id] false)
|
||||
(assoc-in [:communities/all-addresses-to-reveal community-id] addresses-to-reveal)
|
||||
(assoc-in [:communities/all-airdrop-addresses community-id] airdrop-address))
|
||||
:fx [[:dispatch
|
||||
[:communities/check-permissions-to-join-community
|
||||
community-id addresses-to-reveal :based-on-client-selection]]
|
||||
;; Pre-fetch permissions check so that when first opening the
|
||||
;; Addresses for Permissions screen the highest permission role is
|
||||
;; already available and no incorrect information flashes on screen.
|
||||
[:dispatch
|
||||
[:communities/check-permissions-to-join-during-selection community-id
|
||||
addresses-to-reveal]]]}))
|
||||
|
||||
(rf/reg-event-fx :communities/do-init-permission-addresses do-init-permission-addresses)
|
||||
|
||||
(defn edit-shared-addresses
|
||||
"This event will effectively persist the choice of addresses and airdrop address
|
||||
in status-go. It can either take addresses to share AND an airdrop address, or
|
||||
just addresses to share OR an airdrop address. This is because when the user
|
||||
is selecting an airdrop address, we must submit to status-go the current
|
||||
choice of addresses to share, and vice-versa. If we omit addresses to share,
|
||||
status-go will default to all available."
|
||||
[{:keys [db]} [{:keys [community-id password on-success addresses airdrop-address]}]]
|
||||
(let [pub-key (get-in db [:profile/profile :public-key])
|
||||
wallet-accounts (utils/sorted-non-watch-only-accounts db)
|
||||
addresses-to-reveal (if (seq addresses)
|
||||
(set addresses)
|
||||
(get-in db [:communities/all-addresses-to-reveal community-id]))
|
||||
new-airdrop-address (if (contains? addresses-to-reveal airdrop-address)
|
||||
airdrop-address
|
||||
(->> wallet-accounts
|
||||
(filter #(contains? addresses-to-reveal (:address %)))
|
||||
first
|
||||
:address))]
|
||||
{:fx [[:effects.community/edit-shared-addresses
|
||||
{:community-id community-id
|
||||
:password password
|
||||
:pub-key pub-key
|
||||
:addresses-to-reveal addresses-to-reveal
|
||||
:airdrop-address new-airdrop-address
|
||||
:on-success (fn []
|
||||
(when (fn? on-success)
|
||||
(on-success addresses-to-reveal new-airdrop-address))
|
||||
(rf/dispatch [:communities/edit-shared-addresses-success
|
||||
community-id addresses-to-reveal airdrop-address]))
|
||||
:on-error [:communities/edit-shared-addresses-failure community-id]}]]}))
|
||||
|
||||
(rf/reg-event-fx :communities/edit-shared-addresses edit-shared-addresses)
|
||||
|
||||
(rf/reg-event-fx :communities/edit-shared-addresses-success
|
||||
(fn [_ [community-id addresses-to-reveal airdrop-address]]
|
||||
{:fx [[:dispatch [:communities/set-airdrop-address community-id airdrop-address]]
|
||||
[:dispatch [:communities/set-addresses-to-reveal community-id addresses-to-reveal]]]}))
|
||||
|
||||
(rf/reg-event-fx :communities/edit-shared-addresses-failure
|
||||
(fn [{:keys [db]} [community-id error]]
|
||||
(log/error "failed to edit shared addresses"
|
||||
{:event :communities/edit-shared-addresses
|
||||
:community-id community-id
|
||||
:error error})
|
||||
{:db (assoc-in db [:password-authentication :error] error)}))
|
|
@ -0,0 +1,169 @@
|
|||
(ns status-im.contexts.communities.actions.accounts-selection.events-test
|
||||
(:require [cljs.test :refer [deftest is testing]]
|
||||
matcher-combinators.test
|
||||
[status-im.contexts.communities.actions.accounts-selection.events :as sut]))
|
||||
|
||||
(def community-id "0x99")
|
||||
(def password "password")
|
||||
|
||||
(def wallet-accounts
|
||||
{"0xA" {:address "0xA"
|
||||
:watch-only? true
|
||||
:position 2
|
||||
:color :red
|
||||
:emoji "🦇"}
|
||||
"0xB" {:address "0xB"
|
||||
:position 0
|
||||
:color :blue
|
||||
:emoji "🐈"}
|
||||
"0xC" {:address "0xC"
|
||||
:position 1
|
||||
:color :orange
|
||||
:emoji "🛏️"}})
|
||||
|
||||
(def permissioned-accounts
|
||||
[{:address "0xB"
|
||||
:position 0
|
||||
:color :blue
|
||||
:emoji "🐈"
|
||||
:airdrop-address? true
|
||||
:reveal? true}
|
||||
{:address "0xC"
|
||||
:position 1
|
||||
:color :orange
|
||||
:emoji "🛏️"
|
||||
:airdrop-address? false
|
||||
:reveal? false}])
|
||||
|
||||
(deftest initialize-permission-addresses-test
|
||||
(testing "fetches revealed accounts when pending and not joined"
|
||||
(let [cofx {:db {:communities {community-id {:joined false}}
|
||||
:communities/my-pending-requests-to-join {community-id [:anything]}}}]
|
||||
(is (match?
|
||||
{:fx [[:dispatch
|
||||
[:communities/get-revealed-accounts community-id
|
||||
[:communities/do-init-permission-addresses community-id]]]]}
|
||||
(sut/initialize-permission-addresses cofx [community-id])))))
|
||||
|
||||
(testing "fetches revealed accounts when not pending and joined"
|
||||
(let [cofx {:db {:communities {community-id {:joined true}}
|
||||
:communities/my-pending-requests-to-join {}}}]
|
||||
(is (match?
|
||||
{:fx [[:dispatch
|
||||
[:communities/get-revealed-accounts community-id
|
||||
[:communities/do-init-permission-addresses community-id]]]]}
|
||||
(sut/initialize-permission-addresses cofx [community-id])))))
|
||||
|
||||
(testing "does not fetch revealed accounts when not pending and not joined"
|
||||
(let [cofx {:db {:communities {community-id {:joined false}}
|
||||
:communities/my-pending-requests-to-join {}}}]
|
||||
(is (match?
|
||||
{:fx [[:dispatch [:communities/do-init-permission-addresses community-id]]]}
|
||||
(sut/initialize-permission-addresses cofx [community-id]))))))
|
||||
|
||||
(deftest do-init-permission-addresses-test
|
||||
(testing "uses already revealed accounts to initialize shareable accounts"
|
||||
(let [cofx {:db {:wallet {:accounts wallet-accounts}}}
|
||||
revealed-accounts {"0xC" {:address "0xC"
|
||||
:airdrop-address? true
|
||||
:position 1}}
|
||||
airdrop-address "0xC"
|
||||
addresses-to-reveal #{"0xC"}]
|
||||
(is
|
||||
(match?
|
||||
{:db (-> (:db cofx)
|
||||
(assoc-in [:communities/selected-share-all-addresses community-id] false)
|
||||
(assoc-in [:communities/all-addresses-to-reveal community-id] addresses-to-reveal)
|
||||
(assoc-in [:communities/all-airdrop-addresses community-id] airdrop-address))
|
||||
:fx [[:dispatch
|
||||
[:communities/check-permissions-to-join-community
|
||||
community-id addresses-to-reveal :based-on-client-selection]]
|
||||
;; Pre-fetch permissions check so that when first opening the
|
||||
;; Addresses for Permissions screen the highest permission role is
|
||||
;; already available and no incorrect information flashes on screen.
|
||||
[:dispatch
|
||||
[:communities/check-permissions-to-join-during-selection community-id
|
||||
addresses-to-reveal]]]}
|
||||
(sut/do-init-permission-addresses cofx [community-id revealed-accounts])))))
|
||||
|
||||
;; Expect to mark all addresses to be revealed and first one to receive
|
||||
;; airdrops when no addresses were previously revealed.
|
||||
(testing "handles case where there are no previously revealed addresses"
|
||||
(let [cofx {:db {:wallet {:accounts wallet-accounts}}}
|
||||
addresses-to-reveal #{"0xB" "0xC"}
|
||||
revealed-accounts []]
|
||||
(is
|
||||
(match?
|
||||
{:db (-> (:db cofx)
|
||||
(assoc-in [:communities/selected-share-all-addresses community-id] false)
|
||||
(assoc-in [:communities/all-addresses-to-reveal community-id] addresses-to-reveal))
|
||||
:fx [[:dispatch
|
||||
[:communities/check-permissions-to-join-community
|
||||
community-id addresses-to-reveal :based-on-client-selection]]
|
||||
[:dispatch
|
||||
[:communities/check-permissions-to-join-during-selection community-id
|
||||
addresses-to-reveal]]]}
|
||||
(sut/do-init-permission-addresses cofx [community-id revealed-accounts]))))))
|
||||
|
||||
(deftest edit-shared-addresses-test
|
||||
(testing
|
||||
"when airdrop address is passed, but addresses to reveal is not, then
|
||||
fallback to all wallet addresses"
|
||||
(let [pub-key "abcdef"
|
||||
revealed-addresses #{"0xB" "0xC"}
|
||||
cofx {:db {:profile/profile {:public-key pub-key}
|
||||
:communities/all-addresses-to-reveal {community-id revealed-addresses}}}
|
||||
airdrop-address "0xB"
|
||||
|
||||
actual
|
||||
(sut/edit-shared-addresses
|
||||
cofx
|
||||
[{:community-id community-id
|
||||
:password password
|
||||
:airdrop-address airdrop-address
|
||||
:on-success (fn [new-addresses-to-reveal]
|
||||
(is (match? revealed-addresses new-addresses-to-reveal)))}])
|
||||
|
||||
on-success-wrapper (-> actual :fx first second :on-success)]
|
||||
(is (match?
|
||||
{:fx [[:effects.community/edit-shared-addresses
|
||||
{:community-id community-id
|
||||
:password password
|
||||
:pub-key pub-key
|
||||
:addresses-to-reveal revealed-addresses
|
||||
:airdrop-address airdrop-address
|
||||
:on-success fn?
|
||||
:on-error [:communities/edit-shared-addresses-failure community-id]}]]}
|
||||
actual))
|
||||
|
||||
(on-success-wrapper)))
|
||||
|
||||
(testing "when addresses to reveal are passed, but airdrop address is not"
|
||||
(let [pub-key "abcdef"
|
||||
cofx {:db {:profile/profile {:public-key pub-key}
|
||||
:wallet {:accounts wallet-accounts}
|
||||
:communities/all-addresses-to-reveal {community-id #{"0xB" "0xC"}}}}
|
||||
|
||||
actual (sut/edit-shared-addresses
|
||||
cofx
|
||||
[{:community-id community-id
|
||||
:password password
|
||||
:addresses ["0xC"]
|
||||
:on-success (fn [new-addresses-to-reveal new-airdrop-address]
|
||||
(is (= #{"0xC"} new-addresses-to-reveal))
|
||||
(is (= "0xC" new-airdrop-address)))}])
|
||||
|
||||
on-success-wrapper
|
||||
(-> actual :fx first second :on-success)]
|
||||
(is (match?
|
||||
{:fx [[:effects.community/edit-shared-addresses
|
||||
{:community-id community-id
|
||||
:password password
|
||||
:pub-key pub-key
|
||||
:addresses-to-reveal #{"0xC"}
|
||||
:airdrop-address "0xC"
|
||||
:on-success fn?
|
||||
:on-error [:communities/edit-shared-addresses-failure community-id]}]]}
|
||||
actual))
|
||||
|
||||
(on-success-wrapper))))
|
|
@ -14,83 +14,110 @@
|
|||
|
||||
(defn view
|
||||
[]
|
||||
(let [{id :community-id} (rf/sub [:get-screen-params])
|
||||
show-addresses-for-permissions (fn []
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:community-id id
|
||||
:content addresses-for-permissions/view}]))
|
||||
show-airdrop-addresses (fn []
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:community-id id
|
||||
:content airdrop-addresses/view}]))
|
||||
navigate-back #(rf/dispatch [:navigate-back])
|
||||
join-and-go-back (fn []
|
||||
(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 %}])}])
|
||||
(navigate-back))]
|
||||
(fn []
|
||||
(let [{: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/safe-area-view {:style style/container}
|
||||
[quo/page-nav
|
||||
{:text-align :left
|
||||
:icon-name :i/close
|
||||
:on-press navigate-back
|
||||
:accessibility-label :back-button}]
|
||||
[quo/page-top
|
||||
{:title (i18n/label :t/request-to-join)
|
||||
:description :context-tag
|
||||
:context-tag {:type :community
|
||||
:size 24
|
||||
:community-logo (get-in images [:thumbnail :uri])
|
||||
:community-name name}}]
|
||||
[gesture/scroll-view
|
||||
[:<>
|
||||
[quo/text
|
||||
{:style style/section-title
|
||||
:accessibility-label :community-rules-title
|
||||
:weight :semi-bold
|
||||
:size :paragraph-1}
|
||||
(i18n/label :t/address-to-share)]
|
||||
[quo/category
|
||||
{:list-type :settings
|
||||
:data [{:title (i18n/label :t/join-as-a {:role highest-role-text})
|
||||
:on-press show-addresses-for-permissions
|
||||
:description :text
|
||||
:action :arrow
|
||||
:label :preview
|
||||
:label-props {:type :accounts
|
||||
:data selected-accounts}
|
||||
:description-props {:text (i18n/label :t/all-addresses)}}
|
||||
{:title (i18n/label :t/for-airdrops)
|
||||
:on-press show-airdrop-addresses
|
||||
:description :text
|
||||
:action :arrow
|
||||
:label :preview
|
||||
:label-props {:type :accounts
|
||||
:data [airdrop-account]}
|
||||
:description-props {:text (:name airdrop-account)}}]}]
|
||||
[quo/text
|
||||
{:style style/section-title
|
||||
:accessibility-label :community-rules-title
|
||||
:weight :semi-bold
|
||||
:size :paragraph-1}
|
||||
(i18n/label :t/community-rules)]
|
||||
[community-rules/view id]]]
|
||||
[rn/view {:style (style/bottom-actions)}
|
||||
[quo/slide-button
|
||||
{:size :size-48
|
||||
:track-text (i18n/label :t/slide-to-request-to-join)
|
||||
:track-icon :i/face-id
|
||||
:customization-color color
|
||||
:on-complete join-and-go-back}]]]))))
|
||||
(let [{id :community-id} (rf/sub [:get-screen-params])
|
||||
{:keys [name color images joined]} (rf/sub [:communities/community id])
|
||||
airdrop-account (rf/sub [:communities/airdrop-account id])
|
||||
revealed-accounts (rf/sub [:communities/accounts-to-reveal 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))
|
||||
can-edit-addresses? (rf/sub [:communities/can-edit-shared-addresses? id])
|
||||
navigate-back (rn/use-callback #(rf/dispatch [:navigate-back]))
|
||||
|
||||
show-addresses-for-permissions
|
||||
(rn/use-callback
|
||||
(fn []
|
||||
(if can-edit-addresses?
|
||||
(rf/dispatch [:open-modal :addresses-for-permissions {:community-id id}])
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:community-id id
|
||||
:content (fn [] [addresses-for-permissions/view])}])))
|
||||
[can-edit-addresses?])
|
||||
|
||||
show-airdrop-addresses
|
||||
(rn/use-callback
|
||||
(fn []
|
||||
(if can-edit-addresses?
|
||||
(rf/dispatch [:open-modal :address-for-airdrop {:community-id id}])
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:community-id id
|
||||
:content (fn [] [airdrop-addresses/view])}])))
|
||||
[can-edit-addresses?])
|
||||
|
||||
confirm-choices
|
||||
(rn/use-callback
|
||||
(fn []
|
||||
(rf/dispatch
|
||||
[:password-authentication/show
|
||||
{:content (fn [] [password-authentication/view])}
|
||||
{:label (i18n/label :t/join-open-community)
|
||||
:on-press (fn [password]
|
||||
(rf/dispatch [:communities/request-to-join-with-addresses
|
||||
{:community-id id :password password}]))}])
|
||||
(navigate-back)))]
|
||||
(rn/use-mount
|
||||
(fn []
|
||||
(rf/dispatch [:communities/initialize-permission-addresses id])))
|
||||
|
||||
[rn/safe-area-view {:style style/container}
|
||||
[quo/page-nav
|
||||
{:text-align :left
|
||||
:icon-name :i/close
|
||||
:on-press navigate-back
|
||||
:accessibility-label :back-button}]
|
||||
[quo/page-top
|
||||
{:title (if can-edit-addresses?
|
||||
(i18n/label :t/edit-shared-addresses)
|
||||
(i18n/label :t/request-to-join))
|
||||
:description :context-tag
|
||||
:context-tag {:type :community
|
||||
:size 24
|
||||
:community-logo (get-in images [:thumbnail :uri])
|
||||
:community-name name}}]
|
||||
[gesture/scroll-view
|
||||
[:<>
|
||||
(when-not can-edit-addresses?
|
||||
[quo/text
|
||||
{:style style/section-title
|
||||
:accessibility-label :community-rules-title
|
||||
:weight :semi-bold
|
||||
:size :paragraph-1}
|
||||
(i18n/label :t/address-to-share)])
|
||||
[quo/category
|
||||
{:list-type :settings
|
||||
:data [{:title (if joined
|
||||
(i18n/label :t/you-are-a-role {:role highest-role-text})
|
||||
(i18n/label :t/join-as-a {:role highest-role-text}))
|
||||
:on-press show-addresses-for-permissions
|
||||
:description :text
|
||||
:action :arrow
|
||||
:label :preview
|
||||
:label-props {:type :accounts
|
||||
:data revealed-accounts}
|
||||
:description-props {:text (i18n/label :t/all-addresses)}}
|
||||
{:title (i18n/label :t/for-airdrops)
|
||||
:on-press show-airdrop-addresses
|
||||
:description :text
|
||||
:action :arrow
|
||||
:label :preview
|
||||
:label-props {:type :accounts
|
||||
:data [airdrop-account]}
|
||||
:description-props {:text (:name airdrop-account)}}]}]
|
||||
(when-not can-edit-addresses?
|
||||
[quo/text
|
||||
{:style style/section-title
|
||||
:accessibility-label :community-rules-title
|
||||
:weight :semi-bold
|
||||
:size :paragraph-1}
|
||||
(i18n/label :t/community-rules)])
|
||||
(when-not can-edit-addresses?
|
||||
[community-rules/view id])]]
|
||||
(when-not can-edit-addresses?
|
||||
[rn/view {:style (style/bottom-actions)}
|
||||
[quo/slide-button
|
||||
{:size :size-48
|
||||
:track-text (i18n/label :t/slide-to-request-to-join)
|
||||
:track-icon :i/face-id
|
||||
:customization-color color
|
||||
:on-complete confirm-choices}]])]))
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
(ns status-im.contexts.communities.actions.addresses-for-permissions.events
|
||||
(:require
|
||||
[schema.core :as schema]
|
||||
[status-im.contexts.communities.utils :as utils]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
|
@ -56,3 +57,97 @@
|
|||
map?])
|
||||
|
||||
(rf/reg-event-fx :communities/get-permissioned-balances-success get-permissioned-balances-success)
|
||||
|
||||
(rf/reg-event-fx :communities/addresses-for-permissions-cancel-request
|
||||
(fn [_ [request-id]]
|
||||
{:fx [[:dispatch [:communities/cancel-request-to-join request-id]]
|
||||
[:dispatch [:pop-to-root :shell-stack]]
|
||||
[:dispatch [:hide-bottom-sheet]]]}))
|
||||
|
||||
(rf/reg-event-fx :communities/addresses-for-permissions-leave
|
||||
(fn [_ [community-id]]
|
||||
{:fx [[:dispatch [:communities/leave community-id]]
|
||||
[:dispatch [:hide-bottom-sheet]]
|
||||
[:dispatch [:dismiss-modal :addresses-for-permissions]]
|
||||
[:dispatch [:pop-to-root :shell-stack]]]}))
|
||||
|
||||
(defn check-permissions-to-join-for-selection
|
||||
[{:keys [db]} [community-id addresses]]
|
||||
(if (empty? addresses)
|
||||
;; When there are no addresses we can't just check permissions, otherwise
|
||||
;; status-go will consider all possible addresses and the user will see the
|
||||
;; incorrect highest permission role.
|
||||
{:db (update db :communities/permissions-checks-for-selection dissoc community-id)}
|
||||
(let [{:keys [checking?]} (get-in db [:communities/permissions-checks-for-selection community-id])]
|
||||
(when-not checking?
|
||||
{:db (assoc-in db [:communities/permissions-checks-for-selection community-id :checking?] true)
|
||||
:fx [[:json-rpc/call
|
||||
[{:method :wakuext_checkPermissionsToJoinCommunity
|
||||
:params [{:communityId community-id :addresses addresses}]
|
||||
:on-success [:communities/check-permissions-to-join-during-selection-success
|
||||
community-id]
|
||||
:on-error [:communities/check-permissions-to-join-during-selection-failure
|
||||
community-id addresses]}]]]}))))
|
||||
|
||||
;; This event should be used to check permissions temporarily because it won't
|
||||
;; mutate the state `:communities/permissions-check` (used by many other
|
||||
;; screens).
|
||||
(rf/reg-event-fx :communities/check-permissions-to-join-during-selection
|
||||
check-permissions-to-join-for-selection)
|
||||
|
||||
(rf/reg-event-fx :communities/check-permissions-to-join-during-selection-success
|
||||
(fn [{:keys [db]} [community-id result]]
|
||||
{:db (assoc-in db
|
||||
[:communities/permissions-checks-for-selection community-id]
|
||||
{:checking? false
|
||||
:based-on-client-selection? true
|
||||
:check result})}))
|
||||
|
||||
(rf/reg-event-fx :communities/check-permissions-to-join-during-selection-failure
|
||||
(fn [_ [community-id addresses error]]
|
||||
(log/error "failed to check permissions for currently selected addresses"
|
||||
{:event :communities/check-permissions-to-join-during-selection
|
||||
:community-id community-id
|
||||
:addresses addresses
|
||||
:error error})))
|
||||
|
||||
(defn set-permissioned-accounts
|
||||
[{:keys [db]} [community-id addresses-to-reveal]]
|
||||
(let [addresses-to-reveal (set addresses-to-reveal)
|
||||
wallet-accounts (utils/sorted-non-watch-only-accounts db)
|
||||
current-airdrop-address (get-in db [:communities/all-airdrop-addresses community-id])
|
||||
new-airdrop-address (if (contains? addresses-to-reveal current-airdrop-address)
|
||||
current-airdrop-address
|
||||
(->> wallet-accounts
|
||||
(filter #(contains? addresses-to-reveal (:address %)))
|
||||
first
|
||||
:address))]
|
||||
{:db (-> db
|
||||
(assoc-in [:communities/all-addresses-to-reveal community-id] addresses-to-reveal)
|
||||
(assoc-in [:communities/all-airdrop-addresses community-id] new-airdrop-address))
|
||||
:fx [[:dispatch
|
||||
[:communities/check-permissions-to-join-community
|
||||
community-id addresses-to-reveal :based-on-client-selection]]
|
||||
[:dispatch [:hide-bottom-sheet]]]}))
|
||||
|
||||
(rf/reg-event-fx :communities/set-addresses-to-reveal set-permissioned-accounts)
|
||||
|
||||
(defn set-share-all-addresses
|
||||
[{:keys [db]} [community-id new-value]]
|
||||
(let [current-addresses (get-in db [:communities/all-addresses-to-reveal community-id])
|
||||
addresses-to-reveal (if new-value
|
||||
(->> (utils/sorted-non-watch-only-accounts db)
|
||||
(map :address)
|
||||
set)
|
||||
current-addresses)]
|
||||
{:db (-> db
|
||||
(assoc-in [:communities/selected-share-all-addresses community-id] new-value)
|
||||
(assoc-in [:communities/all-addresses-to-reveal community-id] addresses-to-reveal))
|
||||
;; We should check permissions again because the flag is being enabled and
|
||||
;; different addresses will be revealed.
|
||||
:fx [(when new-value
|
||||
[:dispatch
|
||||
[:communities/check-permissions-to-join-during-selection
|
||||
community-id addresses-to-reveal]])]}))
|
||||
|
||||
(rf/reg-event-fx :communities/set-share-all-addresses set-share-all-addresses)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
(ns status-im.contexts.communities.actions.addresses-for-permissions.events-test
|
||||
(:require
|
||||
[cljs.test :refer [deftest is]]
|
||||
[cljs.test :refer [deftest is testing]]
|
||||
[status-im.contexts.communities.actions.addresses-for-permissions.events :as sut]))
|
||||
|
||||
(def community-id "0x1")
|
||||
|
@ -13,3 +13,101 @@
|
|||
:on-success [:communities/get-permissioned-balances-success community-id]
|
||||
:on-error fn?}]]]}
|
||||
(sut/get-permissioned-balances cofx [community-id])))))
|
||||
|
||||
(deftest set-permissioned-accounts-test
|
||||
(testing "new accounts contain the current airdrop address"
|
||||
(let [cofx {:db {:communities/all-addresses-to-reveal
|
||||
{community-id #{"0xA" "0xB"}}}}
|
||||
addresses-to-reveal ["0xA"]
|
||||
expected-addresses-to-reveal (set addresses-to-reveal)]
|
||||
(is (match?
|
||||
{:db {:communities/all-addresses-to-reveal
|
||||
{community-id expected-addresses-to-reveal}}
|
||||
:fx [[:dispatch
|
||||
[:communities/check-permissions-to-join-community
|
||||
community-id expected-addresses-to-reveal :based-on-client-selection]]
|
||||
[:dispatch [:hide-bottom-sheet]]]}
|
||||
(sut/set-permissioned-accounts cofx [community-id addresses-to-reveal])))))
|
||||
|
||||
(testing "new accounts do not contain the current airdrop address"
|
||||
(let [cofx
|
||||
{:db {:communities/all-addresses-to-reveal {community-id #{"0xA" "0xB" "0xC"}}
|
||||
:communities/all-airdrop-addresses {community-id "0xB"}
|
||||
:wallet {:accounts {"0xB" {:address "0xB" :position 0}
|
||||
"0xA" {:address "0xA" :position 1}
|
||||
"0xC" {:address "0xC" :position 2}}}}}
|
||||
addresses-to-reveal ["0xA" "0xC"]]
|
||||
(is (match?
|
||||
{:db {:communities/all-addresses-to-reveal
|
||||
{community-id (set addresses-to-reveal)}
|
||||
:communities/all-airdrop-addresses
|
||||
{community-id "0xA"}}
|
||||
:fx [[:dispatch
|
||||
[:communities/check-permissions-to-join-community
|
||||
community-id (set addresses-to-reveal) :based-on-client-selection]]
|
||||
[:dispatch [:hide-bottom-sheet]]]}
|
||||
(sut/set-permissioned-accounts cofx [community-id addresses-to-reveal]))))))
|
||||
|
||||
(deftest set-share-all-addresses-test
|
||||
(testing "sets flag from false -> true will mark all addresses to be revealed"
|
||||
(let [cofx {:db
|
||||
{:wallet
|
||||
{:accounts {"0xB" {:address "0xB" :position 0}
|
||||
"0xA" {:address "0xA" :position 1}
|
||||
"0xC" {:address "0xC" :position 2}}}
|
||||
:communities/all-addresses-to-reveal {community-id #{"0xA"}}
|
||||
:communities/selected-share-all-addresses {community-id false}}}
|
||||
addresses-to-reveal #{"0xA" "0xB" "0xC"}]
|
||||
(is (match?
|
||||
{:db {:communities/selected-share-all-addresses {community-id true}
|
||||
:communities/all-addresses-to-reveal
|
||||
{community-id addresses-to-reveal}}
|
||||
:fx [[:dispatch
|
||||
[:communities/check-permissions-to-join-during-selection
|
||||
community-id addresses-to-reveal]]]}
|
||||
(sut/set-share-all-addresses cofx [community-id true])))))
|
||||
|
||||
(testing "sets flag from true -> false will not change addresses to be revealed"
|
||||
(let [cofx {:db {:communities/all-addresses-to-reveal {community-id #{"0xA"}}}}]
|
||||
(is (match?
|
||||
{:db {:communities/selected-share-all-addresses {community-id false}
|
||||
:communities/all-addresses-to-reveal {community-id #{"0xA"}}}
|
||||
:fx [nil]}
|
||||
(sut/set-share-all-addresses cofx [community-id false]))))))
|
||||
|
||||
(deftest check-permissions-to-join-for-selection-test
|
||||
(testing "when no addresses are passed don't check permissions"
|
||||
(let [addresses []
|
||||
cofx {:db {:foo :bar
|
||||
:communities/permissions-checks-for-selection
|
||||
{"0xC" :another-check
|
||||
community-id :some-check}}}]
|
||||
(is (match?
|
||||
{:db {:foo :bar
|
||||
:communities/permissions-checks-for-selection {"0xC" :another-check}}}
|
||||
(sut/check-permissions-to-join-for-selection cofx [community-id addresses])))))
|
||||
|
||||
(testing "when there are addresses to check permissions and not currently checking"
|
||||
(let [addresses ["0xA"]
|
||||
cofx {:db {:communities/permissions-checks-for-selection
|
||||
{"other-comm-id" {}
|
||||
community-id {:checking? false}}}}]
|
||||
(is (match?
|
||||
{:db {:communities/permissions-checks-for-selection
|
||||
{"other-comm-id" {}
|
||||
community-id {:checking? true}}}
|
||||
:fx [[:json-rpc/call
|
||||
[{:method :wakuext_checkPermissionsToJoinCommunity
|
||||
:params [{:communityId community-id :addresses addresses}]
|
||||
:on-success [:communities/check-permissions-to-join-during-selection-success
|
||||
community-id]
|
||||
:on-error [:communities/check-permissions-to-join-during-selection-failure
|
||||
community-id addresses]}]]]}
|
||||
(sut/check-permissions-to-join-for-selection cofx [community-id addresses])))))
|
||||
|
||||
(testing "when there are addresses to check permissions, but currently checking, then skip the check"
|
||||
(let [addresses ["0xA"]
|
||||
cofx {:db {:communities/permissions-checks-for-selection
|
||||
{"other-comm-id" {}
|
||||
community-id {:checking? true}}}}]
|
||||
(is (nil? (sut/check-permissions-to-join-for-selection cofx [community-id addresses]))))))
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
(ns status-im.contexts.communities.actions.addresses-for-permissions.style)
|
||||
|
||||
(def drawer-body
|
||||
{:padding-top 4
|
||||
:padding-horizontal 20
|
||||
:padding-bottom 12})
|
|
@ -1,11 +1,16 @@
|
|||
(ns status-im.contexts.communities.actions.addresses-for-permissions.view
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.gesture :as gesture]
|
||||
[status-im.common.not-implemented :as not-implemented]
|
||||
[status-im.constants :as constants]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.money :as money]
|
||||
[utils.re-frame :as rf]))
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[react-native.gesture :as gesture]
|
||||
[status-im.common.not-implemented :as not-implemented]
|
||||
[status-im.common.password-authentication.view :as password-authentication]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.communities.actions.addresses-for-permissions.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.money :as money]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- role-keyword
|
||||
[role]
|
||||
|
@ -36,96 +41,316 @@
|
|||
:token (:symbol balance)
|
||||
:token-img-src (images-by-symbol sym)))))
|
||||
|
||||
(defn- cancel-join-request-drawer
|
||||
[community-id]
|
||||
(let [{:keys [name logo color]} (rf/sub [:communities/for-context-tag community-id])
|
||||
request-id (rf/sub [:communities/my-pending-request-to-join community-id])]
|
||||
[:<>
|
||||
[quo/drawer-top
|
||||
{:type :context-tag
|
||||
:context-tag-type :community
|
||||
:title (i18n/label :t/cancel-request?)
|
||||
:community-name name
|
||||
:community-logo logo
|
||||
:customization-color color}]
|
||||
[rn/view {:style style/drawer-body}
|
||||
[quo/text (i18n/label :t/pending-join-request-farewell)]]
|
||||
[quo/bottom-actions
|
||||
{:actions :two-actions
|
||||
|
||||
:button-one-label (i18n/label :t/confirm-and-cancel)
|
||||
:button-one-props {:customization-color color
|
||||
:on-press
|
||||
(fn []
|
||||
(rf/dispatch [:communities/addresses-for-permissions-cancel-request
|
||||
request-id]))}
|
||||
|
||||
:button-two-label (i18n/label :t/cancel)
|
||||
:button-two-props {:type :grey
|
||||
:on-press #(rf/dispatch [:hide-bottom-sheet])}}]]))
|
||||
|
||||
(defn- confirm-discard-drawer
|
||||
[community-id]
|
||||
(let [{:keys [name logo color]} (rf/sub [:communities/for-context-tag community-id])]
|
||||
[:<>
|
||||
[quo/drawer-top
|
||||
{:type :context-tag
|
||||
:context-tag-type :community
|
||||
:title (i18n/label :t/discard-changes?)
|
||||
:community-name name
|
||||
:community-logo logo
|
||||
:customization-color color}]
|
||||
[rn/view {:style style/drawer-body}
|
||||
[quo/text (i18n/label :t/all-changes-will-be-discarded)]]
|
||||
[quo/bottom-actions
|
||||
{:actions :two-actions
|
||||
|
||||
:button-one-label (i18n/label :t/discard)
|
||||
:button-one-props {:customization-color color
|
||||
:on-press
|
||||
(fn []
|
||||
(rf/dispatch [:dismiss-modal :addresses-for-permissions])
|
||||
(rf/dispatch [:hide-bottom-sheet]))}
|
||||
|
||||
:button-two-label (i18n/label :t/cancel)
|
||||
:button-two-props {:type :grey
|
||||
:on-press #(rf/dispatch [:hide-bottom-sheet])}}]]))
|
||||
|
||||
(defn- leave-community-drawer
|
||||
[community-id outro-message]
|
||||
(let [{:keys [name logo color]} (rf/sub [:communities/for-context-tag community-id])]
|
||||
[:<>
|
||||
[quo/drawer-top
|
||||
{:type :context-tag
|
||||
:context-tag-type :community
|
||||
:title (i18n/label :t/leave-community?)
|
||||
:community-name name
|
||||
:community-logo logo
|
||||
:customization-color color}]
|
||||
[rn/view {:style style/drawer-body}
|
||||
[quo/text
|
||||
(if (string/blank? outro-message)
|
||||
(i18n/label :t/leave-community-farewell)
|
||||
outro-message)]]
|
||||
[quo/bottom-actions
|
||||
{:actions :two-actions
|
||||
|
||||
:button-one-label (i18n/label :t/confirm-and-leave)
|
||||
:button-one-props {:customization-color color
|
||||
:on-press
|
||||
#(rf/dispatch [:communities/addresses-for-permissions-leave community-id])}
|
||||
|
||||
:button-two-label (i18n/label :t/cancel)
|
||||
:button-two-props {:type :grey
|
||||
:on-press #(rf/dispatch [:hide-bottom-sheet])}}]]))
|
||||
|
||||
(defn- account-item
|
||||
[{:keys [color address name emoji]} _ _
|
||||
{:keys [selected-addresses community-id share-all-addresses? community-color]}]
|
||||
[{:keys [customization-color address name emoji]} _ _
|
||||
[addresses-to-reveal set-addresses-to-reveal community-id community-color share-all-addresses?]]
|
||||
(let [balances (rf/sub [:communities/permissioned-balances-by-address community-id address])
|
||||
images-by-symbol (rf/sub [:communities/token-images-by-symbol community-id])]
|
||||
images-by-symbol (rf/sub [:communities/token-images-by-symbol community-id])
|
||||
checked? (contains? addresses-to-reveal address)
|
||||
toggle-address (fn []
|
||||
(let [new-addresses (if checked?
|
||||
(disj addresses-to-reveal address)
|
||||
(conj addresses-to-reveal address))]
|
||||
(set-addresses-to-reveal new-addresses)))]
|
||||
[quo/account-permissions
|
||||
{:account {:name name
|
||||
:address address
|
||||
:emoji emoji
|
||||
:customization-color color}
|
||||
:token-details (balances->components-props balances images-by-symbol)
|
||||
:checked? (contains? selected-addresses address)
|
||||
:customization-color customization-color}
|
||||
:token-details (when-not share-all-addresses?
|
||||
(balances->components-props balances images-by-symbol))
|
||||
:checked? checked?
|
||||
:disabled? share-all-addresses?
|
||||
:on-change #(rf/dispatch [:communities/toggle-selected-permission-address
|
||||
address community-id])
|
||||
:on-change toggle-address
|
||||
:container-style {:margin-bottom 8}
|
||||
:customization-color community-color}]))
|
||||
|
||||
(defn- page-top
|
||||
[{:keys [community-id identical-choices? can-edit-addresses?]}]
|
||||
(let [{:keys [name logo color]} (rf/sub [:communities/for-context-tag community-id])
|
||||
confirm-discard-changes (rn/use-callback
|
||||
(fn []
|
||||
(if identical-choices?
|
||||
(rf/dispatch [:dismiss-modal :addresses-for-permissions])
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:content (fn [] [confirm-discard-drawer
|
||||
community-id])}])))
|
||||
[identical-choices?])]
|
||||
[:<>
|
||||
(when can-edit-addresses?
|
||||
[quo/page-nav
|
||||
{:type :no-title
|
||||
:icon-name :i/arrow-left
|
||||
:on-press confirm-discard-changes}])
|
||||
|
||||
(if can-edit-addresses?
|
||||
[quo/page-top
|
||||
{:title (i18n/label :t/addresses-for-permissions)
|
||||
:title-accessibility-label :title-label
|
||||
:description :context-tag
|
||||
:context-tag {:type :community
|
||||
:community-logo logo
|
||||
:community-name name}}]
|
||||
[quo/drawer-top
|
||||
{:type :context-tag
|
||||
:title (i18n/label :t/addresses-for-permissions)
|
||||
:context-tag-type :community
|
||||
:community-name name
|
||||
:button-icon :i/info
|
||||
:button-type :grey
|
||||
:on-button-press not-implemented/alert
|
||||
:community-logo logo
|
||||
:customization-color color}])]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [{id :community-id} (rf/sub [:get-screen-params])
|
||||
toggle-share-all-addresses #(rf/dispatch [:communities/toggle-share-all-addresses id])
|
||||
update-previous-addresses (fn []
|
||||
(rf/dispatch [:communities/update-previous-permission-addresses id])
|
||||
(rf/dispatch [:hide-bottom-sheet]))
|
||||
reset-selected-addresses (fn []
|
||||
(rf/dispatch [:communities/reset-selected-permission-addresses id])
|
||||
(rf/dispatch [:hide-bottom-sheet]))]
|
||||
(rf/dispatch [:communities/get-permissioned-balances id])
|
||||
(fn []
|
||||
(let [{:keys [name color images]} (rf/sub [:communities/community id])
|
||||
{:keys [checking?
|
||||
highest-permission-role]} (rf/sub [:community/token-gated-overview id])
|
||||
accounts (rf/sub [:wallet/accounts-without-watched-accounts])
|
||||
selected-addresses (rf/sub [:communities/selected-permission-addresses id])
|
||||
share-all-addresses? (rf/sub [:communities/share-all-addresses? id])
|
||||
unsaved-address-changes? (rf/sub [:communities/unsaved-address-changes? id])]
|
||||
[:<>
|
||||
[quo/drawer-top
|
||||
{:type :context-tag
|
||||
:title (i18n/label :t/addresses-for-permissions)
|
||||
:context-tag-type :community
|
||||
:community-name name
|
||||
:button-icon :i/info
|
||||
:button-type :grey
|
||||
:on-button-press not-implemented/alert
|
||||
:community-logo (get-in images [:thumbnail :uri])
|
||||
:customization-color color}]
|
||||
(let [{id :community-id} (rf/sub [:get-screen-params])
|
||||
{:keys [color joined] outro-message :outroMessage} (rf/sub [:communities/community id])
|
||||
|
||||
[gesture/flat-list
|
||||
{:render-fn account-item
|
||||
:render-data {:selected-addresses selected-addresses
|
||||
:community-id id
|
||||
:share-all-addresses? share-all-addresses?
|
||||
:community-color color}
|
||||
:header [quo/category
|
||||
{:list-type :settings
|
||||
:data [{:title
|
||||
(i18n/label
|
||||
:t/share-all-current-and-future-addresses)
|
||||
:action :selector
|
||||
:action-props
|
||||
{:on-change toggle-share-all-addresses
|
||||
:customization-color color
|
||||
:checked? share-all-addresses?}}]
|
||||
:container-style {:padding-bottom 16 :padding-horizontal 0}}]
|
||||
:content-container-style {:padding-horizontal 20}
|
||||
:key-fn :address
|
||||
:data accounts}]
|
||||
highest-role (rf/sub [:communities/highest-role-for-selection id])
|
||||
[unmodified-role _] (rn/use-state highest-role)
|
||||
|
||||
[quo/bottom-actions
|
||||
{:actions :two-actions
|
||||
:button-one-label (i18n/label :t/confirm-changes)
|
||||
:button-one-props {:customization-color color
|
||||
:disabled? (or checking?
|
||||
(empty? selected-addresses)
|
||||
(not highest-permission-role)
|
||||
(not unsaved-address-changes?))
|
||||
:on-press update-previous-addresses}
|
||||
:button-two-label (i18n/label :t/cancel)
|
||||
:button-two-props {:type :grey
|
||||
:on-press reset-selected-addresses}
|
||||
:description (if (or (empty? selected-addresses)
|
||||
(not highest-permission-role))
|
||||
:top-error
|
||||
:top)
|
||||
:role (when-not checking? (role-keyword highest-permission-role))
|
||||
:error-message (cond
|
||||
(empty? selected-addresses)
|
||||
(i18n/label :t/no-addresses-selected)
|
||||
can-edit-addresses? (rf/sub [:communities/can-edit-shared-addresses? id])
|
||||
pending? (boolean (rf/sub [:communities/my-pending-request-to-join id]))
|
||||
|
||||
(not highest-permission-role)
|
||||
(i18n/label :t/addresses-dont-contain-tokens-needed))}]]))))
|
||||
wallet-accounts (rf/sub [:wallet/accounts-without-watched-accounts])
|
||||
unmodified-addresses-to-reveal (rf/sub [:communities/addresses-to-reveal id])
|
||||
[addresses-to-reveal set-addresses-to-reveal] (rn/use-state unmodified-addresses-to-reveal)
|
||||
|
||||
unmodified-flag-share-all-addresses (rf/sub [:communities/share-all-addresses? id])
|
||||
[flag-share-all-addresses
|
||||
set-flag-share-all-addresses] (rn/use-state unmodified-flag-share-all-addresses)
|
||||
|
||||
identical-choices? (and (= unmodified-addresses-to-reveal addresses-to-reveal)
|
||||
(= unmodified-flag-share-all-addresses flag-share-all-addresses))
|
||||
|
||||
toggle-flag-share-all-addresses
|
||||
(fn []
|
||||
(let [new-value (not flag-share-all-addresses)]
|
||||
(set-flag-share-all-addresses new-value)
|
||||
(when new-value
|
||||
(set-addresses-to-reveal (set (map :address wallet-accounts))))))
|
||||
|
||||
cancel-join-request
|
||||
(rn/use-callback
|
||||
(fn []
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:content (fn [] [cancel-join-request-drawer id])}])))
|
||||
|
||||
leave-community
|
||||
(rn/use-callback
|
||||
(fn []
|
||||
(rf/dispatch [:show-bottom-sheet
|
||||
{:content (fn [] [leave-community-drawer id outro-message])}]))
|
||||
[outro-message])
|
||||
|
||||
cancel-selection
|
||||
(fn []
|
||||
(rf/dispatch [:communities/check-permissions-to-join-community
|
||||
id
|
||||
unmodified-addresses-to-reveal
|
||||
:based-on-client-selection])
|
||||
(rf/dispatch [:hide-bottom-sheet]))
|
||||
|
||||
confirm-changes
|
||||
(fn []
|
||||
(if can-edit-addresses?
|
||||
(rf/dispatch
|
||||
[:password-authentication/show
|
||||
{:content (fn [] [password-authentication/view])}
|
||||
{:label (i18n/label :t/enter-password)
|
||||
:on-press (fn [password]
|
||||
(rf/dispatch
|
||||
[:communities/edit-shared-addresses
|
||||
{:community-id id
|
||||
:password password
|
||||
:addresses addresses-to-reveal
|
||||
:on-success (fn []
|
||||
(rf/dispatch [:dismiss-modal :addresses-for-permissions])
|
||||
(rf/dispatch [:hide-bottom-sheet]))}]))}])
|
||||
(do
|
||||
(rf/dispatch [:communities/set-share-all-addresses id flag-share-all-addresses])
|
||||
(rf/dispatch [:communities/set-addresses-to-reveal id addresses-to-reveal]))))]
|
||||
|
||||
(rn/use-mount
|
||||
(fn []
|
||||
(when-not flag-share-all-addresses
|
||||
(rf/dispatch [:communities/get-permissioned-balances id]))))
|
||||
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(rf/dispatch [:communities/check-permissions-to-join-during-selection id addresses-to-reveal]))
|
||||
[id addresses-to-reveal])
|
||||
|
||||
[:<>
|
||||
[page-top
|
||||
{:community-id id
|
||||
:identical-choices? identical-choices?
|
||||
:can-edit-addresses? can-edit-addresses?}]
|
||||
|
||||
[gesture/flat-list
|
||||
{:render-fn account-item
|
||||
:render-data [addresses-to-reveal
|
||||
set-addresses-to-reveal
|
||||
id
|
||||
color
|
||||
flag-share-all-addresses]
|
||||
:header [quo/category
|
||||
{:list-type :settings
|
||||
:data [{:title
|
||||
(i18n/label
|
||||
:t/share-all-current-and-future-addresses)
|
||||
:action :selector
|
||||
:action-props
|
||||
{:on-change toggle-flag-share-all-addresses
|
||||
:customization-color color
|
||||
:checked? flag-share-all-addresses}}]
|
||||
:container-style {:padding-bottom 16 :padding-horizontal 0}}]
|
||||
:content-container-style {:padding-horizontal 20}
|
||||
:key-fn :address
|
||||
:data wallet-accounts}]
|
||||
|
||||
[quo/bottom-actions
|
||||
(cond-> {:role (role-keyword highest-role)
|
||||
:description (if highest-role
|
||||
:top
|
||||
:top-error)
|
||||
:button-one-props {:customization-color color
|
||||
:on-press confirm-changes
|
||||
:disabled? (or (empty? addresses-to-reveal)
|
||||
(not highest-role)
|
||||
identical-choices?)}}
|
||||
can-edit-addresses?
|
||||
(->
|
||||
(assoc :actions :one-action
|
||||
:button-one-label (cond
|
||||
(and pending? (not highest-role))
|
||||
(i18n/label :t/cancel-request)
|
||||
|
||||
(and joined (not highest-role))
|
||||
(i18n/label :t/leave-community)
|
||||
|
||||
:else
|
||||
(i18n/label :t/confirm-changes))
|
||||
:description-top-text (cond
|
||||
(and pending? highest-role)
|
||||
(i18n/label :t/eligible-to-join-as)
|
||||
|
||||
(and joined (= highest-role unmodified-role))
|
||||
(i18n/label :t/you-are-a)
|
||||
|
||||
(and joined (not= highest-role unmodified-role))
|
||||
(i18n/label :t/you-will-be-a))
|
||||
:error-message (cond
|
||||
(and pending? (not highest-role))
|
||||
(i18n/label :t/community-join-requirements-not-met)
|
||||
|
||||
(and joined (not highest-role))
|
||||
(i18n/label :t/membership-requirements-not-met)))
|
||||
(update :button-one-props
|
||||
merge
|
||||
(cond (and pending? (not highest-role))
|
||||
{:type :danger
|
||||
:disabled? false
|
||||
:on-press cancel-join-request}
|
||||
|
||||
(and joined (not highest-role))
|
||||
{:type :danger
|
||||
:disabled? false
|
||||
:on-press leave-community})))
|
||||
|
||||
(not can-edit-addresses?)
|
||||
(assoc :actions :two-actions
|
||||
:button-one-label (i18n/label :t/confirm-changes)
|
||||
:button-two-label (i18n/label :t/cancel)
|
||||
:button-two-props {:type :grey
|
||||
:on-press cancel-selection}
|
||||
:error-message (cond
|
||||
(empty? addresses-to-reveal)
|
||||
(i18n/label :t/no-addresses-selected)
|
||||
|
||||
(not highest-role)
|
||||
(i18n/label :t/addresses-dont-contain-tokens-needed))))]]))
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
(ns status-im.contexts.communities.actions.airdrop-addresses.events
|
||||
(:require
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn set-airdrop-address
|
||||
[{:keys [db]} [community-id airdrop-address]]
|
||||
{:db (assoc-in db [:communities/all-airdrop-addresses community-id] airdrop-address)})
|
||||
|
||||
(rf/reg-event-fx :communities/set-airdrop-address set-airdrop-address)
|
|
@ -0,0 +1,18 @@
|
|||
(ns status-im.contexts.communities.actions.airdrop-addresses.events-test
|
||||
(:require
|
||||
[cljs.test :refer [deftest is testing]]
|
||||
[status-im.contexts.communities.actions.airdrop-addresses.events :as sut]))
|
||||
|
||||
(def community-id "community-id")
|
||||
|
||||
(deftest set-airdrop-address-test
|
||||
(testing "updates all reveal? flags"
|
||||
(let [new-airdrop-address "0xA"
|
||||
cofx {:db {:communities/all-airdrop-addresses
|
||||
{"another-community" "0xF"
|
||||
community-id "0xB"}}}]
|
||||
(is (match?
|
||||
(assoc-in cofx
|
||||
[:db :communities/all-airdrop-addresses community-id]
|
||||
new-airdrop-address)
|
||||
(sut/set-airdrop-address cofx [community-id new-airdrop-address]))))))
|
|
@ -1,41 +1,81 @@
|
|||
(ns status-im.contexts.communities.actions.airdrop-addresses.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[react-native.gesture :as gesture]
|
||||
[status-im.common.not-implemented :as not-implemented]
|
||||
[status-im.common.password-authentication.view :as password-authentication]
|
||||
[status-im.contexts.communities.actions.airdrop-addresses.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- render-item
|
||||
[item _ _ [airdrop-address community-id]]
|
||||
[quo/account-item
|
||||
{:account-props item
|
||||
:state (when (= airdrop-address (:address item)) :selected)
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:communities/set-airdrop-address (:address item) community-id])
|
||||
(rf/dispatch [:hide-bottom-sheet]))
|
||||
:emoji (:emoji item)}])
|
||||
(defn- account-item
|
||||
[{:keys [address emoji] :as account}
|
||||
_ _
|
||||
[community-id airdrop-address can-edit-addresses?]]
|
||||
(let [airdrop-address? (= address airdrop-address)
|
||||
on-press
|
||||
(when-not airdrop-address?
|
||||
(fn []
|
||||
(if can-edit-addresses?
|
||||
(rf/dispatch
|
||||
[:password-authentication/show
|
||||
{:content (fn [] [password-authentication/view])}
|
||||
{:label (i18n/label :t/enter-password)
|
||||
:on-press (fn [password]
|
||||
(rf/dispatch
|
||||
[:communities/edit-shared-addresses
|
||||
{:community-id community-id
|
||||
:password password
|
||||
:airdrop-address address
|
||||
:on-success (fn []
|
||||
(rf/dispatch [:dismiss-modal :address-for-airdrop])
|
||||
(rf/dispatch [:hide-bottom-sheet]))}]))}])
|
||||
(do
|
||||
(rf/dispatch [:communities/set-airdrop-address community-id address])
|
||||
(rf/dispatch [:hide-bottom-sheet])))))]
|
||||
[quo/account-item
|
||||
{:account-props account
|
||||
:emoji emoji
|
||||
:state (if airdrop-address? :selected :default)
|
||||
:on-press on-press}]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [{id :community-id} (rf/sub [:get-screen-params])
|
||||
{:keys [name images color]} (rf/sub [:communities/community id])
|
||||
selected-accounts (rf/sub [:communities/selected-permission-accounts id])
|
||||
airdrop-address (rf/sub [:communities/airdrop-address id])]
|
||||
(let [{id :community-id} (rf/sub [:get-screen-params])
|
||||
{:keys [name logo color]} (rf/sub [:communities/for-context-tag id])
|
||||
accounts (rf/sub [:communities/accounts-to-reveal id])
|
||||
airdrop-address (rf/sub [:communities/airdrop-address id])
|
||||
can-edit-addresses? (rf/sub [:communities/can-edit-shared-addresses? id])
|
||||
go-back (rn/use-callback #(rf/dispatch [:dismiss-modal :address-for-airdrop]))]
|
||||
[:<>
|
||||
[quo/drawer-top
|
||||
{:type :context-tag
|
||||
:context-tag-type :community
|
||||
:title (i18n/label :t/airdrop-addresses)
|
||||
:community-name name
|
||||
:button-icon :i/info
|
||||
:on-button-press not-implemented/alert
|
||||
:community-logo (get-in images [:thumbnail :uri])
|
||||
:customization-color color}]
|
||||
(when can-edit-addresses?
|
||||
[quo/page-nav
|
||||
{:type :no-title
|
||||
:icon-name :i/arrow-left
|
||||
:on-press go-back}])
|
||||
|
||||
(if can-edit-addresses?
|
||||
[quo/page-top
|
||||
{:title (i18n/label :t/airdrop-addresses)
|
||||
:title-accessibility-label :title-label
|
||||
:description :context-tag
|
||||
:context-tag {:type :community
|
||||
:community-logo logo
|
||||
:community-name name}}]
|
||||
[quo/drawer-top
|
||||
{:type :context-tag
|
||||
:context-tag-type :community
|
||||
:title (i18n/label :t/airdrop-addresses)
|
||||
:community-name name
|
||||
:button-icon :i/info
|
||||
:on-button-press not-implemented/alert
|
||||
:community-logo logo
|
||||
:customization-color color}])
|
||||
|
||||
[gesture/flat-list
|
||||
{:data selected-accounts
|
||||
:render-fn render-item
|
||||
:render-data [airdrop-address id]
|
||||
{:data accounts
|
||||
:render-fn account-item
|
||||
:render-data [id airdrop-address can-edit-addresses?]
|
||||
:content-container-style style/account-list-container
|
||||
:key-fn :address}]]))
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
[status-im.contexts.communities.actions.leave.view :as leave-menu]
|
||||
[status-im.contexts.communities.actions.see-rules.view :as see-rules]
|
||||
[status-im.contexts.communities.actions.token-gating.view :as token-gating]
|
||||
[status-im.feature-flags :as ff]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
|
@ -41,6 +42,15 @@
|
|||
{:content (fn [] [token-gating/token-requirements id])}])
|
||||
:label (i18n/label :t/view-token-gating)})
|
||||
|
||||
(defn edit-shared-addresses
|
||||
[id]
|
||||
{:icon :i/wallet
|
||||
:right-icon :i/chevron-right
|
||||
:accessibility-label :edit-shared-addresses
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:open-modal :community-account-selection {:community-id id}]))
|
||||
:label (i18n/label :t/edit-shared-addresses)})
|
||||
|
||||
(defn mark-as-read
|
||||
[id]
|
||||
{:icon :i/up-to-date
|
||||
|
@ -119,28 +129,33 @@
|
|||
request-id])}])})
|
||||
|
||||
(defn not-joined-options
|
||||
[id token-gated?]
|
||||
[id token-gated? pending?]
|
||||
[[(when-not token-gated? (view-members id))
|
||||
(when-not token-gated? (view-rules id))
|
||||
(invite-contacts id)
|
||||
(when token-gated? (view-token-gating id))
|
||||
(when (and pending? (ff/enabled? ::ff/community.edit-account-selection))
|
||||
(edit-shared-addresses id))
|
||||
(show-qr id)
|
||||
(share-community id)]])
|
||||
|
||||
(defn join-request-sent-options
|
||||
[id token-gated? request-id]
|
||||
[(conj (first (not-joined-options id token-gated?))
|
||||
[(conj (first (not-joined-options id token-gated? request-id))
|
||||
(assoc (cancel-request-to-join id request-id) :add-divider? true))])
|
||||
|
||||
(defn banned-options
|
||||
[id token-gated?]
|
||||
(not-joined-options id token-gated?))
|
||||
(let [pending? false]
|
||||
(not-joined-options id token-gated? pending?)))
|
||||
|
||||
(defn joined-options
|
||||
[id token-gated? muted? muted-till]
|
||||
[[(view-members id)
|
||||
(view-rules id)
|
||||
(when token-gated? (view-token-gating id))
|
||||
(when (ff/enabled? ::ff/community.edit-account-selection)
|
||||
(edit-shared-addresses id))
|
||||
(mark-as-read id)
|
||||
(mute-community id muted? muted-till)
|
||||
(community-notification-settings id)
|
||||
|
@ -171,7 +186,7 @@
|
|||
joined (joined-options id token-permissions muted muted-till)
|
||||
request-id (join-request-sent-options id token-permissions request-id)
|
||||
banList (banned-options id token-permissions)
|
||||
:else (not-joined-options id token-permissions))))
|
||||
:else (not-joined-options id token-permissions request-id))))
|
||||
|
||||
(defn community-options-bottom-sheet
|
||||
[id]
|
||||
|
|
|
@ -29,10 +29,11 @@
|
|||
{:type :positive
|
||||
:text (i18n/label :t/left-community {:community community-name})}]]
|
||||
[:dispatch [:activity-center.notifications/fetch-unread-count]]
|
||||
[:dispatch [:hide-bottom-sheet]]
|
||||
[:dispatch [:navigate-back]]]})))
|
||||
|
||||
(rf/reg-event-fx :communities/leave
|
||||
(fn [{:keys [db]} [community-id]]
|
||||
(fn [{:keys [db]} [community-id on-success]]
|
||||
(let [community-chat-ids (map #(str community-id %)
|
||||
(keys (get-in db [:communities community-id :chats])))]
|
||||
{:effects/push-notifications-clear-message-notifications community-chat-ids
|
||||
|
@ -41,5 +42,8 @@
|
|||
[{:method "wakuext_leaveCommunity"
|
||||
:params [community-id]
|
||||
:js-response true
|
||||
:on-success #(rf/dispatch [:communities/left %])
|
||||
:on-success (fn [^js response]
|
||||
(when (fn? on-success)
|
||||
(on-success))
|
||||
(rf/dispatch [:communities/left response]))
|
||||
:on-error #(log/error "failed to leave community" community-id %)}]})))
|
||||
|
|
|
@ -9,10 +9,11 @@
|
|||
[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.accounts-selection.events
|
||||
status-im.contexts.communities.actions.addresses-for-permissions.events
|
||||
status-im.contexts.communities.actions.airdrop-addresses.events
|
||||
status-im.contexts.communities.actions.community-options.events
|
||||
status-im.contexts.communities.actions.leave.events
|
||||
[status-im.contexts.communities.utils :as utils]
|
||||
[status-im.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.i18n :as i18n]
|
||||
|
@ -29,13 +30,10 @@
|
|||
{:db (assoc-in db
|
||||
[:communities id]
|
||||
(assoc community :last-opened-at (max last-opened-at previous-last-opened-at)))
|
||||
:fx [[:dispatch [:communities/initialize-permission-addresses id]]
|
||||
(when (not joined)
|
||||
:fx [(when (not joined)
|
||||
[:dispatch [:chat.ui/spectate-community id]])
|
||||
(when (nil? token-permissions-check)
|
||||
[:dispatch [:communities/check-permissions-to-join-community id]])
|
||||
(when joined
|
||||
[:dispatch [:communities/get-revealed-accounts id]])]}))))
|
||||
[:dispatch [:communities/check-permissions-to-join-community id]])]}))))
|
||||
|
||||
(rf/reg-event-fx :communities/handle-community handle-community)
|
||||
|
||||
|
@ -157,97 +155,6 @@
|
|||
:on-success #(rf/dispatch [:communities/fetched-collapsed-categories-success %])
|
||||
:on-error #(log/error "failed to fetch collapsed community categories" %)}]}))
|
||||
|
||||
(defn initialize-permission-addresses
|
||||
[{:keys [db]} [community-id]]
|
||||
(when community-id
|
||||
(let [accounts (utils/sorted-non-watch-only-accounts db)
|
||||
addresses (set (map :address accounts))]
|
||||
{:db (update-in db
|
||||
[:communities community-id]
|
||||
assoc
|
||||
:previous-share-all-addresses? true
|
||||
:share-all-addresses? true
|
||||
:previous-permission-addresses addresses
|
||||
:selected-permission-addresses addresses
|
||||
:airdrop-address (:address (first accounts)))})))
|
||||
|
||||
(rf/reg-event-fx :communities/initialize-permission-addresses
|
||||
initialize-permission-addresses)
|
||||
|
||||
(defn update-previous-permission-addresses
|
||||
[{:keys [db]} [community-id]]
|
||||
(when community-id
|
||||
(let [accounts (utils/sorted-non-watch-only-accounts db)
|
||||
selected-permission-addresses (get-in db
|
||||
[:communities community-id
|
||||
:selected-permission-addresses])
|
||||
selected-accounts (filter #(contains? selected-permission-addresses (:address %))
|
||||
accounts)
|
||||
current-airdrop-address (get-in db [:communities community-id :airdrop-address])
|
||||
share-all-addresses? (get-in db [:communities community-id :share-all-addresses?])]
|
||||
{:db (update-in db
|
||||
[:communities community-id]
|
||||
assoc
|
||||
:previous-share-all-addresses? share-all-addresses?
|
||||
: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
|
||||
update-previous-permission-addresses)
|
||||
|
||||
(defn toggle-selected-permission-address
|
||||
[{:keys [db]} [address community-id]]
|
||||
(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)
|
||||
|
||||
(defn toggle-share-all-addresses
|
||||
[{:keys [db]} [community-id]]
|
||||
(let [share-all-addresses? (get-in db [:communities community-id :share-all-addresses?])
|
||||
next-share-all-addresses? (not share-all-addresses?)
|
||||
accounts (utils/sorted-non-watch-only-accounts db)
|
||||
addresses (set (map :address accounts))]
|
||||
{:db (update-in db
|
||||
[:communities community-id]
|
||||
assoc
|
||||
:share-all-addresses? next-share-all-addresses?
|
||||
:selected-permission-addresses addresses)
|
||||
:fx [(when (and community-id next-share-all-addresses?)
|
||||
[:dispatch
|
||||
[:communities/check-permissions-to-join-community community-id
|
||||
addresses :based-on-client-selection]])]}))
|
||||
|
||||
(rf/reg-event-fx :communities/toggle-share-all-addresses
|
||||
toggle-share-all-addresses)
|
||||
|
||||
(rf/reg-event-fx :communities/reset-selected-permission-addresses
|
||||
(fn [{:keys [db]} [community-id]]
|
||||
(when community-id
|
||||
{:db (update-in db
|
||||
[:communities community-id]
|
||||
assoc
|
||||
:selected-permission-addresses
|
||||
(get-in db [:communities community-id :previous-permission-addresses])
|
||||
:share-all-addresses?
|
||||
(get-in db [:communities community-id :previous-share-all-addresses?]))
|
||||
:fx [[:dispatch [:communities/check-permissions-to-join-community community-id]]]})))
|
||||
|
||||
(rf/reg-event-fx :communities/get-community-channel-share-data
|
||||
(fn [_ [chat-id on-success]]
|
||||
(let [{:keys [community-id channel-id]} (data-store.chats/decode-chat-id chat-id)]
|
||||
|
@ -286,10 +193,6 @@
|
|||
:url %}])]
|
||||
{:fx [[:dispatch [:communities/get-community-channel-share-data chat-id on-success]]]})))
|
||||
|
||||
(rf/reg-event-fx :communities/set-airdrop-address
|
||||
(fn [{:keys [db]} [address community-id]]
|
||||
{:db (assoc-in db [:communities community-id :airdrop-address] address)}))
|
||||
|
||||
(defn community-fetched
|
||||
[{:keys [db]} [community-id community]]
|
||||
(when community
|
||||
|
@ -425,16 +328,17 @@
|
|||
[:dispatch [:chat/navigate-to-chat chat-id]])]})))
|
||||
|
||||
(defn get-revealed-accounts
|
||||
[{:keys [db]} [community-id]]
|
||||
[{:keys [db]} [community-id on-success]]
|
||||
(let [{:keys [joined fetching-revealed-accounts]
|
||||
:as community} (get-in db [:communities community-id])]
|
||||
(when (and community joined (not fetching-revealed-accounts))
|
||||
:as community} (get-in db [:communities community-id])
|
||||
pending? (get-in db [:communities/my-pending-requests-to-join community-id])]
|
||||
(when (and community (or pending? 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-success [:communities/get-revealed-accounts-success community-id on-success]
|
||||
:on-error (fn [err]
|
||||
(log/error {:message "failed to fetch revealed accounts"
|
||||
:community-id community-id
|
||||
|
@ -448,19 +352,22 @@
|
|||
[:catn
|
||||
[:cofx :schema.re-frame/cofx]
|
||||
[:args
|
||||
[:schema [:catn [:community-id [:? :string]]]]]]
|
||||
[:schema
|
||||
[:catn
|
||||
[:community-id [:? :string]]
|
||||
[:on-success [:? :schema.re-frame/event]]]]]]
|
||||
[: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]]
|
||||
(fn [{:keys [db]} [community-id on-success 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)))
|
||||
(assoc acc address revealed-account))
|
||||
{}
|
||||
(data-store.communities/<-revealed-accounts-rpc revealed-accounts-js))
|
||||
|
||||
|
@ -468,7 +375,9 @@
|
|||
(-> community
|
||||
(assoc :revealed-accounts revealed-accounts)
|
||||
(dissoc :fetching-revealed-accounts))]
|
||||
{:db (assoc-in db [:communities community-id] community-with-revealed-accounts)}))))
|
||||
{:db (assoc-in db [:communities community-id] community-with-revealed-accounts)
|
||||
:fx [(when (vector? on-success)
|
||||
[:dispatch (conj on-success revealed-accounts)])]}))))
|
||||
|
||||
(rf/reg-event-fx :communities/get-revealed-accounts-failed
|
||||
(fn [{:keys [db]} [community-id]]
|
||||
|
|
|
@ -7,99 +7,6 @@
|
|||
|
||||
(def community-id "community-id")
|
||||
|
||||
(deftest initialize-permission-addresses-test
|
||||
(let [initial-db {:db {:wallet {:accounts {"0x1" {:address "0x1"
|
||||
:position 0}
|
||||
"0x2" {:address "0x2"
|
||||
:position 1}}}}}
|
||||
expected-db {:db (update-in (:db initial-db)
|
||||
[:communities community-id]
|
||||
assoc
|
||||
:share-all-addresses? true
|
||||
:previous-share-all-addresses? true
|
||||
:previous-permission-addresses #{"0x1" "0x2"}
|
||||
:selected-permission-addresses #{"0x1" "0x2"}
|
||||
:airdrop-address "0x1")}]
|
||||
(is (match? expected-db (events/initialize-permission-addresses initial-db [community-id])))))
|
||||
|
||||
(deftest toggle-selected-permission-address-test
|
||||
(let [initial-db {:db {:communities {community-id {:selected-permission-addresses #{"0x1" "0x2"}}}}}]
|
||||
(is (match? {:db {:communities {community-id {:selected-permission-addresses #{"0x1"}}}}}
|
||||
(events/toggle-selected-permission-address initial-db ["0x2" community-id])))
|
||||
(is (match? {:db {:communities {community-id {:selected-permission-addresses #{"0x1" "0x2" "0x3"}}}}}
|
||||
(events/toggle-selected-permission-address initial-db ["0x3" community-id])))))
|
||||
|
||||
(deftest update-previous-permission-addresses-test
|
||||
(let [wallet {:accounts {"0x1" {:address "0x1"
|
||||
:position 0}
|
||||
"0x2" {:address "0x2"
|
||||
:position 1}
|
||||
"0x3" {:address "0x3"
|
||||
:position 2}}}]
|
||||
(let [initial-db {:db {:wallet wallet
|
||||
:communities {community-id {:previous-permission-addresses #{"0x1" "0x2"}
|
||||
:selected-permission-addresses #{"0x1" "0x2"
|
||||
"0x3"}
|
||||
:share-all-addresses? true
|
||||
:previous-share-all-addresses? false
|
||||
:airdrop-address "0x1"}}}}
|
||||
expected-db {:db {:wallet wallet
|
||||
:communities {community-id {:previous-permission-addresses #{"0x1" "0x2"
|
||||
"0x3"}
|
||||
:selected-permission-addresses #{"0x1" "0x2"
|
||||
"0x3"}
|
||||
:share-all-addresses? true
|
||||
:previous-share-all-addresses? true
|
||||
:airdrop-address "0x1"}}}}]
|
||||
(is
|
||||
(match? expected-db
|
||||
(events/update-previous-permission-addresses initial-db [community-id]))))
|
||||
(let [initial-db {:db {:wallet wallet
|
||||
:communities {community-id {:previous-permission-addresses #{"0x1" "0x2"}
|
||||
:selected-permission-addresses #{"0x2" "0x3"}
|
||||
:airdrop-address "0x1"}}}}
|
||||
expected-db {:db {:wallet wallet
|
||||
:communities {community-id {:previous-permission-addresses #{"0x2" "0x3"}
|
||||
:selected-permission-addresses #{"0x2" "0x3"}
|
||||
:airdrop-address "0x2"}}}}]
|
||||
(is
|
||||
(match? expected-db
|
||||
(events/update-previous-permission-addresses initial-db [community-id]))))))
|
||||
|
||||
(deftest toggle-share-all-addresses-test
|
||||
(let [initial-db {:db {:wallet {:accounts {"0x1" {:address "0x1"
|
||||
:position 0}
|
||||
"0x2" {:address "0x2"
|
||||
:position 1}}}
|
||||
:communities {community-id {:share-all-addresses? true
|
||||
:previous-share-all-addresses? true
|
||||
:previous-permission-addresses #{"0x1" "0x2"}
|
||||
:selected-permission-addresses #{"0x1" "0x2"}
|
||||
:airdrop-address "0x1"}}}}
|
||||
expected-db (update-in initial-db
|
||||
[:db :communities community-id]
|
||||
assoc
|
||||
:previous-share-all-addresses? true
|
||||
:share-all-addresses?
|
||||
false)]
|
||||
(is (match? expected-db (events/toggle-share-all-addresses initial-db [community-id]))))
|
||||
(let [initial-db {:db {:wallet {:accounts {"0x1" {:address "0x1"
|
||||
:position 0}
|
||||
"0x2" {:address "0x2"
|
||||
:position 1}}}
|
||||
:communities {community-id {:share-all-addresses? false
|
||||
:previous-share-all-addresses? false
|
||||
:previous-permission-addresses #{"0x1"}
|
||||
:selected-permission-addresses #{"0x1"}
|
||||
:airdrop-address "0x1"}}}}
|
||||
expected-db (update-in initial-db
|
||||
[:db :communities community-id]
|
||||
assoc
|
||||
:selected-permission-addresses #{"0x1" "0x2"}
|
||||
:previous-share-all-addresses? false
|
||||
:share-all-addresses? true)]
|
||||
(is (match? expected-db (events/toggle-share-all-addresses initial-db [community-id])))))
|
||||
|
||||
(deftest fetch-community
|
||||
(testing "with community id"
|
||||
(testing "update fetching indicator in db"
|
||||
|
@ -243,12 +150,14 @@
|
|||
(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}
|
||||
|
@ -258,7 +167,26 @@
|
|||
(:db effects)))
|
||||
(is (match? {:method "wakuext_getRevealedAccounts"
|
||||
:params [community-id "profile-public-key"]}
|
||||
(-> effects :json-rpc/call first (select-keys [:method :params]))))))))
|
||||
(-> effects :json-rpc/call first (select-keys [:method :params]))))))
|
||||
|
||||
(testing "given there is a pending request"
|
||||
(let [pub-key "profile-public-key"
|
||||
community (assoc community :joined false)
|
||||
db {:communities {community-id community}
|
||||
:profile/profile {:public-key pub-key}
|
||||
:communities/my-pending-requests-to-join {community-id [:anything]}}
|
||||
on-success [:some-event-id]
|
||||
actual (events/get-revealed-accounts {:db db} [community-id on-success])
|
||||
expected {:db (assoc-in db
|
||||
[:communities community-id :fetching-revealed-accounts]
|
||||
true)
|
||||
:json-rpc/call [{:method "wakuext_getRevealedAccounts"
|
||||
:params [community-id pub-key]
|
||||
:js-response true
|
||||
:on-success [:communities/get-revealed-accounts-success
|
||||
community-id on-success]
|
||||
:on-error fn?}]}]
|
||||
(is (match? expected actual))))))
|
||||
|
||||
(deftest handle-community
|
||||
(let [community {:id community-id :clock 2}]
|
||||
|
@ -267,24 +195,22 @@
|
|||
(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 [: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]]]
|
||||
[[:dispatch [:communities/check-permissions-to-join-community 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]]]
|
||||
[[:dispatch [:chat.ui/spectate-community community-id]]]
|
||||
(filter some? (:fx effects))))))
|
||||
(testing "given a community with lower clock"
|
||||
(let [effects (events/handle-community {:db {:communities {community-id {:clock 3}}}} [community])]
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
|
||||
|
||||
(rf/reg-event-fx :communities/check-permissions-to-join-community-success
|
||||
(fn [{:keys [db]} [community-id based-on-client-selection? result]]
|
||||
(let [token-permissions-check (cond-> result
|
||||
|
@ -118,41 +116,19 @@
|
|||
:category-id category-id
|
||||
:collapse? collapse?})}]}))
|
||||
|
||||
(defn request-to-join-with-signatures-and-addresses
|
||||
[{:keys [db]} [community-id signatures]]
|
||||
(let [{:keys [airdrop-address selected-permission-addresses]} (get-in db [:communities community-id])]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wakuext_requestToJoinCommunity"
|
||||
:params [{:communityId community-id
|
||||
:signatures signatures
|
||||
:addressesToReveal selected-permission-addresses
|
||||
:airdropAddress airdrop-address}]
|
||||
:js-response true
|
||||
:on-success [:communities/requested-to-join]
|
||||
:on-error [:communities/requested-to-join-error community-id]}]]]}))
|
||||
|
||||
(rf/reg-event-fx :communities/request-to-join-with-signatures-and-addresses
|
||||
request-to-join-with-signatures-and-addresses)
|
||||
|
||||
(defn sign-data-with-addresses
|
||||
[_ [community-id password sign-params]]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wakuext_signData"
|
||||
:params [(map #(assoc % :password password) sign-params)]
|
||||
:on-success [:communities/request-to-join-with-signatures-and-addresses community-id]
|
||||
:on-error [:communities/requested-to-join-error community-id]}]]]})
|
||||
|
||||
(rf/reg-event-fx :communities/sign-data-with-addresses sign-data-with-addresses)
|
||||
|
||||
(defn request-to-join-with-addresses
|
||||
[{:keys [db]}
|
||||
[{:keys [community-id password]}]]
|
||||
(let [pub-key (get-in db [:profile/profile :public-key])
|
||||
addresses-to-reveal (get-in db [:communities community-id :selected-permission-addresses])]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wakuext_generateJoiningCommunityRequestsForSigning"
|
||||
:params [pub-key community-id addresses-to-reveal]
|
||||
:on-success [:communities/sign-data-with-addresses community-id password]
|
||||
:on-error [:communities/requested-to-join-error community-id]}]]]}))
|
||||
addresses-to-reveal (get-in db [:communities/all-addresses-to-reveal community-id])
|
||||
airdrop-address (get-in db [:communities/all-airdrop-addresses community-id])]
|
||||
{:fx [[:effects.community/request-to-join
|
||||
{:community-id community-id
|
||||
:password password
|
||||
:pub-key pub-key
|
||||
:addresses-to-reveal addresses-to-reveal
|
||||
:airdrop-address airdrop-address
|
||||
:on-success [:communities/requested-to-join]
|
||||
:on-error [:communities/requested-to-join-error community-id]}]]}))
|
||||
|
||||
(rf/reg-event-fx :communities/request-to-join-with-addresses request-to-join-with-addresses)
|
||||
|
|
|
@ -120,7 +120,7 @@
|
|||
[id color]
|
||||
[quo/button
|
||||
{:on-press (if config/community-accounts-selection-enabled?
|
||||
#(rf/dispatch [:open-modal :community-account-selection
|
||||
#(rf/dispatch [:open-modal :community-account-selection-sheet
|
||||
{:community-id id}])
|
||||
#(rf/dispatch [:open-modal :community-requests-to-join {:id id}]))
|
||||
:accessibility-label :show-request-to-join-screen-button
|
||||
|
@ -168,7 +168,7 @@
|
|||
:padding? true}]
|
||||
[quo/button
|
||||
{:on-press (if config/community-accounts-selection-enabled?
|
||||
#(rf/dispatch [:open-modal :community-account-selection
|
||||
#(rf/dispatch [:open-modal :community-account-selection-sheet
|
||||
{:community-id id}])
|
||||
#(rf/dispatch [:open-modal :community-requests-to-join {:id id}]))
|
||||
:accessibility-label :join-community-button
|
||||
|
|
|
@ -63,6 +63,10 @@
|
|||
{:key :admin}
|
||||
{:key :member}]})
|
||||
|
||||
(def description-top-descriptor
|
||||
{:key :description-top-text
|
||||
:type :text})
|
||||
|
||||
(def description-descriptor
|
||||
{:key :description-text
|
||||
:type :text})
|
||||
|
@ -73,28 +77,32 @@
|
|||
|
||||
(defn view
|
||||
[]
|
||||
(let [state (reagent/atom {:actions :two-actions
|
||||
:description :bottom
|
||||
:description-text description
|
||||
:error-message "Error message"
|
||||
:button-one-label button-one
|
||||
:button-two-label button-two
|
||||
:button-one-props {:on-press (button-press 1)
|
||||
:type :primary}
|
||||
:button-two-props {:on-press (button-press 2)
|
||||
:type :grey}
|
||||
:blur? false
|
||||
:role :owner
|
||||
:scroll? false})]
|
||||
(let [state (reagent/atom {:actions :two-actions
|
||||
:description :bottom
|
||||
:description-text description
|
||||
:description-top-text "Eligible to join as"
|
||||
:error-message "Error message"
|
||||
:button-one-label button-one
|
||||
:button-two-label button-two
|
||||
:button-one-props {:on-press (button-press 1)
|
||||
:type :primary}
|
||||
:button-two-props {:on-press (button-press 2)
|
||||
:type :grey}
|
||||
:blur? false
|
||||
:role :owner
|
||||
:scroll? false})]
|
||||
(fn []
|
||||
[preview/preview-container
|
||||
{:state state
|
||||
:descriptor (merge descriptor
|
||||
(case (:description @state)
|
||||
:top role-descriptor
|
||||
:bottom description-descriptor
|
||||
:top-error error-descriptor
|
||||
nil))
|
||||
:descriptor (cond-> descriptor
|
||||
(= (:description @state) :top)
|
||||
(conj role-descriptor description-top-descriptor)
|
||||
|
||||
(= (:description @state) :bottom)
|
||||
(conj description-descriptor)
|
||||
|
||||
(= (:description @state) :top-error)
|
||||
(conj error-descriptor))
|
||||
:blur? (:blur? @state)
|
||||
:show-blur-background? true
|
||||
:blur-dark-only? true
|
||||
|
|
|
@ -10,10 +10,12 @@
|
|||
|
||||
(defonce ^:private feature-flags-config
|
||||
(reagent/atom
|
||||
{::wallet.edit-default-keypair true
|
||||
::wallet.bridge-token (enabled-in-env? :FLAG_BRIDGE_TOKEN_ENABLED)
|
||||
::wallet.network-filter (enabled-in-env? :FLAG_NETWORK_FILTER_ENABLED)
|
||||
::profile.new-contact-ui (enabled-in-env? :FLAG_NEW_CONTACT_UI_ENABLED)}))
|
||||
{::wallet.edit-default-keypair true
|
||||
::wallet.bridge-token (enabled-in-env? :FLAG_BRIDGE_TOKEN_ENABLED)
|
||||
::wallet.remove-account (enabled-in-env? :FLAG_REMOVE_ACCOUNT_ENABLED)
|
||||
::wallet.network-filter (enabled-in-env? :FLAG_NETWORK_FILTER_ENABLED)
|
||||
::profile.new-contact-ui (enabled-in-env? :FLAG_NEW_CONTACT_UI_ENABLED)
|
||||
::community.edit-account-selection (enabled-in-env? :FLAG_EDIT_ACCOUNT_SELECTION_ENABLED)}))
|
||||
|
||||
(defn feature-flags [] @feature-flags-config)
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
[status-im.contexts.chat.messenger.messages.view :as chat]
|
||||
[status-im.contexts.chat.messenger.photo-selector.view :as photo-selector]
|
||||
[status-im.contexts.communities.actions.accounts-selection.view :as communities.accounts-selection]
|
||||
[status-im.contexts.communities.actions.addresses-for-permissions.view :as addresses-for-permissions]
|
||||
[status-im.contexts.communities.actions.airdrop-addresses.view :as airdrop-addresses]
|
||||
[status-im.contexts.communities.actions.request-to-join.view :as join-menu]
|
||||
[status-im.contexts.communities.actions.share-community-channel.view :as share-community-channel]
|
||||
[status-im.contexts.communities.discover.view :as communities.discover]
|
||||
|
@ -122,9 +124,23 @@
|
|||
:options options/transparent-screen-options
|
||||
:component share-community-channel/view}
|
||||
|
||||
{:name :community-account-selection
|
||||
;; Note: the sheet screen is used when selecting addresses to share when
|
||||
;; joining a community. The non-sheet screen is used when editing shared
|
||||
;; addresses after the join request was sent.
|
||||
{:name :community-account-selection-sheet
|
||||
:options {:sheet? true}
|
||||
:component communities.accounts-selection/view}
|
||||
{:name :community-account-selection
|
||||
:options {:insets {:top? true}}
|
||||
:component communities.accounts-selection/view}
|
||||
|
||||
{:name :addresses-for-permissions
|
||||
:options {:insets {:top? true}}
|
||||
:component addresses-for-permissions/view}
|
||||
|
||||
{:name :address-for-airdrop
|
||||
:options {:insets {:top? true}}
|
||||
:component airdrop-addresses/view}
|
||||
|
||||
{:name :lightbox
|
||||
:options options/lightbox
|
||||
|
|
|
@ -350,57 +350,6 @@
|
|||
(fn [communities [_ community-id]]
|
||||
(get-in communities [community-id :intro-message])))
|
||||
|
||||
(re-frame/reg-sub :communities/permissioned-balances-by-address
|
||||
:<- [:communities/permissioned-balances]
|
||||
(fn [balances [_ community-id account-address]]
|
||||
(get-in balances [community-id (keyword account-address)])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:communities/selected-permission-addresses
|
||||
(fn [[_ community-id]]
|
||||
[(re-frame/subscribe [:communities/community community-id])])
|
||||
(fn [[{:keys [selected-permission-addresses]}] _]
|
||||
selected-permission-addresses))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:communities/share-all-addresses?
|
||||
(fn [[_ community-id]]
|
||||
[(re-frame/subscribe [:communities/community community-id])])
|
||||
(fn [[{:keys [share-all-addresses?]}] _]
|
||||
share-all-addresses?))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:communities/unsaved-address-changes?
|
||||
(fn [[_ community-id]]
|
||||
[(re-frame/subscribe [:communities/community community-id])])
|
||||
(fn [[{:keys [share-all-addresses? previous-share-all-addresses?
|
||||
selected-permission-addresses previous-permission-addresses]}] _]
|
||||
(or (not= share-all-addresses? previous-share-all-addresses?)
|
||||
(not= selected-permission-addresses previous-permission-addresses))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:communities/selected-permission-accounts
|
||||
(fn [[_ community-id]]
|
||||
[(re-frame/subscribe [:wallet/accounts-without-watched-accounts])
|
||||
(re-frame/subscribe [:communities/selected-permission-addresses community-id])])
|
||||
(fn [[accounts selected-permission-addresses]]
|
||||
(filter #(contains? selected-permission-addresses (:address %)) accounts)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:communities/airdrop-address
|
||||
(fn [[_ community-id]]
|
||||
[(re-frame/subscribe [:communities/community community-id])])
|
||||
(fn [[{:keys [airdrop-address]}] _]
|
||||
airdrop-address))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:communities/airdrop-account
|
||||
(fn [[_ community-id]]
|
||||
[(re-frame/subscribe [:wallet/accounts-with-customization-color])
|
||||
(re-frame/subscribe [:communities/airdrop-address community-id])])
|
||||
(fn [[accounts airdrop-address]]
|
||||
(first (filter #(= (:address %) airdrop-address) accounts))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:communities/token-images-by-symbol
|
||||
(fn [[_ community-id]]
|
||||
|
|
|
@ -358,48 +358,6 @@
|
|||
:img-src token-image-eth}]]}
|
||||
(rf/sub [sub-name community-id])))))
|
||||
|
||||
(h/deftest-sub :communities/airdrop-account
|
||||
[sub-name]
|
||||
(testing "returns airdrop account"
|
||||
(swap! rf-db/app-db assoc-in [:communities community-id :airdrop-address] "0x1")
|
||||
(swap! rf-db/app-db assoc
|
||||
:wallet
|
||||
{:accounts {"0x1" {:address "0x1"
|
||||
:color :blue
|
||||
:name "account1"}
|
||||
"0x2" {:address "0x2"
|
||||
:color :orange
|
||||
:name "account2"}}})
|
||||
(is (match? {:address "0x1"
|
||||
:network-preferences-names #{}
|
||||
:name "account1"
|
||||
:color :blue
|
||||
:customization-color :blue}
|
||||
(rf/sub [sub-name community-id])))))
|
||||
|
||||
(h/deftest-sub :communities/selected-permission-accounts
|
||||
[sub-name]
|
||||
(testing "returns selected permission accounts"
|
||||
(swap! rf-db/app-db assoc-in
|
||||
[:communities community-id :selected-permission-addresses]
|
||||
#{"0x1" "0x3"})
|
||||
(swap! rf-db/app-db assoc
|
||||
:wallet
|
||||
{:accounts {"0x1" {:address "0x1" :color :blue :name "account1"}
|
||||
"0x2" {:address "0x2" :color :orange :name "account2"}
|
||||
"0x3" {:address "0x3" :color :purple :name "account3"}}})
|
||||
(is (match? [{:address "0x1"
|
||||
:color :blue
|
||||
:customization-color :blue
|
||||
:network-preferences-names #{}
|
||||
:name "account1"}
|
||||
{:address "0x3"
|
||||
:color :purple
|
||||
:customization-color :purple
|
||||
:network-preferences-names #{}
|
||||
:name "account3"}]
|
||||
(rf/sub [sub-name community-id])))))
|
||||
|
||||
(h/deftest-sub :communities/community-color
|
||||
[sub-name]
|
||||
(testing "returns the community color"
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
(ns status-im.subs.community.account-selection
|
||||
(:require
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
;; This sub is particularly useful in context tags in page-nav or drawer-top
|
||||
;; components. It should be preferred instead of subscribing to the whole
|
||||
;; community.
|
||||
(re-frame/reg-sub :communities/for-context-tag
|
||||
(fn [[_ community-id]]
|
||||
[(re-frame/subscribe [:communities/community community-id])])
|
||||
(fn [[{:keys [name images color]}]]
|
||||
{:name name
|
||||
:logo (get-in images [:thumbnail :uri])
|
||||
:color color}))
|
||||
|
||||
(re-frame/reg-sub :communities/addresses-to-reveal
|
||||
:<- [:communities/all-addresses-to-reveal]
|
||||
(fn [addresses-by-id [_ community-id]]
|
||||
(get addresses-by-id community-id)))
|
||||
|
||||
(re-frame/reg-sub :communities/airdrop-address
|
||||
:<- [:communities/all-airdrop-addresses]
|
||||
(fn [addresses-by-id [_ community-id]]
|
||||
(get addresses-by-id community-id)))
|
||||
|
||||
(re-frame/reg-sub :communities/share-all-addresses?
|
||||
:<- [:communities/selected-share-all-addresses]
|
||||
(fn [flags-by-id [_ community-id]]
|
||||
(get flags-by-id community-id)))
|
||||
|
||||
(re-frame/reg-sub :communities/can-edit-shared-addresses?
|
||||
(fn [[_ community-id]]
|
||||
[(re-frame/subscribe [:communities/community community-id])
|
||||
(re-frame/subscribe [:communities/my-pending-request-to-join community-id])])
|
||||
(fn [[{:keys [joined]} pending-requests]]
|
||||
(boolean (or joined (seq pending-requests)))))
|
||||
|
||||
(re-frame/reg-sub :communities/permissions-check-for-selection
|
||||
:<- [:communities/permissions-checks-for-selection]
|
||||
(fn [permissions [_ id]]
|
||||
(get permissions id)))
|
||||
|
||||
(re-frame/reg-sub :communities/highest-role-for-selection
|
||||
(fn [[_ community-id]]
|
||||
[(re-frame/subscribe [:communities/permissions-check-for-selection community-id])])
|
||||
(fn [[permissions-check] _]
|
||||
(get-in permissions-check [:check :highestRole :type])))
|
||||
|
||||
(re-frame/reg-sub :communities/accounts-to-reveal
|
||||
(fn [[_ community-id]]
|
||||
[(re-frame/subscribe [:wallet/accounts-without-watched-accounts])
|
||||
(re-frame/subscribe [:communities/addresses-to-reveal community-id])])
|
||||
(fn [[accounts addresses] _]
|
||||
(filter #(contains? addresses (:address %))
|
||||
accounts)))
|
||||
|
||||
(re-frame/reg-sub :communities/airdrop-account
|
||||
(fn [[_ community-id]]
|
||||
[(re-frame/subscribe [:wallet/accounts-without-watched-accounts])
|
||||
(re-frame/subscribe [:communities/airdrop-address community-id])])
|
||||
(fn [[accounts airdrop-address] _]
|
||||
(->> accounts
|
||||
(filter #(= (:address %) airdrop-address))
|
||||
first)))
|
||||
|
||||
(re-frame/reg-sub :communities/permissioned-balances-by-address
|
||||
:<- [:communities/permissioned-balances]
|
||||
(fn [balances [_ community-id account-address]]
|
||||
(get-in balances [community-id (keyword account-address)])))
|
|
@ -0,0 +1,75 @@
|
|||
(ns status-im.subs.community.account-selection-test
|
||||
(:require
|
||||
[cljs.test :refer [is testing]]
|
||||
matcher-combinators.test
|
||||
[re-frame.db :as rf-db]
|
||||
status-im.subs.communities
|
||||
[test-helpers.unit :as h]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def community-id "0x1")
|
||||
|
||||
(h/deftest-sub :communities/for-context-tag
|
||||
[sub-name]
|
||||
(reset! rf-db/app-db
|
||||
{:communities
|
||||
{community-id {:name "foo"
|
||||
:images {:thumbnail {:uri "data:image/png;"}}
|
||||
:color :orange}}})
|
||||
|
||||
(is (match? {:name "foo"
|
||||
:logo "data:image/png;"
|
||||
:color :orange}
|
||||
(rf/sub [sub-name community-id]))))
|
||||
|
||||
(h/deftest-sub :communities/can-edit-shared-addresses?
|
||||
[sub-name]
|
||||
(testing "joined community and there are pending requests"
|
||||
(reset! rf-db/app-db
|
||||
{:communities {community-id {:id community-id :joined true}}
|
||||
:communities/my-pending-request-to-join {community-id {:id :request-id-1}}})
|
||||
|
||||
(is (true? (rf/sub [sub-name community-id]))))
|
||||
|
||||
(testing "joined community and there are no pending requests"
|
||||
(reset! rf-db/app-db
|
||||
{:communities {community-id {:id community-id :joined true}}
|
||||
:communities/my-pending-request-to-join {community-id {}}})
|
||||
|
||||
(is (true? (rf/sub [sub-name community-id]))))
|
||||
|
||||
(testing "not joined community and there are pending requests"
|
||||
(reset! rf-db/app-db
|
||||
{:communities {community-id {:id community-id :joined false}}
|
||||
:communities/my-pending-request-to-join {community-id {:id :request-id-1}}})
|
||||
|
||||
(is (false? (rf/sub [sub-name community-id]))))
|
||||
|
||||
(testing "not joined community and there are no pending requests"
|
||||
(reset! rf-db/app-db
|
||||
{:communities {community-id {:id community-id :joined false}}
|
||||
:communities/my-pending-request-to-join {community-id {}}})
|
||||
|
||||
(is (false? (rf/sub [sub-name community-id])))))
|
||||
|
||||
(h/deftest-sub :communities/airdrop-account
|
||||
[sub-name]
|
||||
(let [airdrop-account {:address "0xA" :position 1}]
|
||||
(reset! rf-db/app-db
|
||||
{:communities/all-airdrop-addresses {community-id "0xA"}
|
||||
:wallet {:accounts {"0xB" {:address "0xB" :position 0}
|
||||
"0xA" airdrop-account}}})
|
||||
|
||||
(is (match? airdrop-account (rf/sub [sub-name community-id])))))
|
||||
|
||||
(h/deftest-sub :communities/accounts-to-reveal
|
||||
[sub-name]
|
||||
(reset! rf-db/app-db
|
||||
{:communities/all-addresses-to-reveal {community-id #{"0xC" "0xB"}}
|
||||
:wallet {:accounts {"0xB" {:address "0xB" :position 0}
|
||||
"0xA" {:address "0xA" :position 1}
|
||||
"0xC" {:address "0xC" :position 2}}}})
|
||||
|
||||
(is (match? [{:address "0xB" :position 0}
|
||||
{:address "0xC" :position 2}]
|
||||
(rf/sub [sub-name community-id]))))
|
|
@ -6,6 +6,7 @@
|
|||
status-im.subs.biometrics
|
||||
status-im.subs.chats
|
||||
status-im.subs.communities
|
||||
status-im.subs.community.account-selection
|
||||
status-im.subs.contact
|
||||
status-im.subs.general
|
||||
status-im.subs.messages
|
||||
|
@ -150,6 +151,11 @@
|
|||
(reg-root-key-sub :contract-communities :contract-communities)
|
||||
(reg-root-key-sub :communities/permissioned-balances :communities/permissioned-balances)
|
||||
(reg-root-key-sub :communities/permissions-check :communities/permissions-check)
|
||||
(reg-root-key-sub :communities/all-addresses-to-reveal :communities/all-addresses-to-reveal)
|
||||
(reg-root-key-sub :communities/all-airdrop-addresses :communities/all-airdrop-addresses)
|
||||
(reg-root-key-sub :communities/selected-share-all-addresses :communities/selected-share-all-addresses)
|
||||
(reg-root-key-sub :communities/permissions-checks-for-selection
|
||||
:communities/permissions-checks-for-selection)
|
||||
(reg-root-key-sub :communities/channel-permissions-check :communities/channel-permissions-check)
|
||||
|
||||
;;activity center
|
||||
|
|
|
@ -2279,6 +2279,19 @@
|
|||
"sync-devices-complete-title": "Device sync complete!",
|
||||
"sync-devices-complete-sub-title": "Your devices are now in sync",
|
||||
"synced-with": "Synced with",
|
||||
"confirm-and-leave": "Confirm and leave",
|
||||
"membership-requirements-not-met": "Membership requirements not met",
|
||||
"edit-shared-addresses": "Edit shared addresses",
|
||||
"leave-community-farewell": "We’ll be sad to see you go but remember, you can come back at any time! All shared addresses will be unshared.",
|
||||
"pending-join-request-farewell": "We’ll be sad to see you go but remember, you can request to join this community at any point. All shared addresses will be unshared.",
|
||||
"all-changes-will-be-discarded": "All changes in shared addresses for permissions will be discarded.",
|
||||
"cancel-request": "Cancel request",
|
||||
"discard": "Discard",
|
||||
"discard-changes?": "Discard changes?",
|
||||
"confirm-and-cancel": "Confirm and cancel",
|
||||
"you-will-be-a": "You’ll be a",
|
||||
"you-are-a": "You’re a",
|
||||
"you-are-a-role": "You’re a {{role}}",
|
||||
"you-eligible-to-join": "You’re eligible to join",
|
||||
"you-eligible-to-join-as": "You’re eligible to join as {{role}}",
|
||||
"eligible-to-join-as": "Eligible to join as",
|
||||
|
|
Loading…
Reference in New Issue