From 4633fc22ed02f6f08188b91aaeb36524a74be21d Mon Sep 17 00:00:00 2001 From: Ajay Sivan Date: Thu, 1 Feb 2024 05:33:54 +0530 Subject: [PATCH] Show token permissions only for role permissions (#18549) Token requirements that are not role permissions (currently channel permissions) should not be displayed to the user while they see permissions to join. Admin, Master, Owner or minted token permissions are not membership permissions, but they still should be displayed so the user understand the role they will assume after joining. Co-authored-by: Icaro Motta --- .../status_im/data_store/communities.cljs | 52 ++-- src/status_im/config.cljs | 2 +- src/status_im/constants.cljs | 5 + .../actions/request_to_join/view.cljs | 6 +- .../contexts/communities/overview/view.cljs | 241 ++++++++---------- .../components/floating_screens/view.cljs | 2 +- src/status_im/navigation/screens.cljs | 2 +- src/status_im/subs/communities.cljs | 11 +- src/status_im/subs/communities_test.cljs | 6 +- 9 files changed, 160 insertions(+), 167 deletions(-) diff --git a/src/legacy/status_im/data_store/communities.cljs b/src/legacy/status_im/data_store/communities.cljs index 80ca8268c7..4ff93d44c5 100644 --- a/src/legacy/status_im/data_store/communities.cljs +++ b/src/legacy/status_im/data_store/communities.cljs @@ -44,22 +44,37 @@ [categ] (reduce-kv #(assoc %1 (name %2) %3) {} categ)) +(defn role-permission? + [token-permission] + (contains? constants/community-role-permissions (:type token-permission))) + +(defn membership-permission? + [token-permission] + (= (:type token-permission) constants/community-token-permission-become-member)) + (defn <-rpc [c] (-> c - (set/rename-keys {:canRequestAccess :can-request-access? - :canManageUsers :can-manage-users? - :canDeleteMessageForEveryone :can-delete-message-for-everyone? - :canJoin :can-join? - :requestedToJoinAt :requested-to-join-at - :isMember :is-member? - :adminSettings :admin-settings - :tokenPermissions :token-permissions - :communityTokensMetadata :tokens-metadata - :introMessage :intro-message - :muteTill :muted-till - :lastOpenedAt :last-opened-at - :joinedAt :joined-at}) + (set/rename-keys + {:canRequestAccess :can-request-access? + :canManageUsers :can-manage-users? + :canDeleteMessageForEveryone :can-delete-message-for-everyone? + ;; This flag is misleading based on its name alone + ;; because it should not be used to decide if the user + ;; is *allowed* to join. Allowance is based on token + ;; permissions. Still, the flag can be used to know + ;; whether or not the user will have to wait until an + ;; admin approves a join request. + :canJoin :can-join? + :requestedToJoinAt :requested-to-join-at + :isMember :is-member? + :adminSettings :admin-settings + :tokenPermissions :token-permissions + :communityTokensMetadata :tokens-metadata + :introMessage :intro-message + :muteTill :muted-till + :lastOpenedAt :last-opened-at + :joinedAt :joined-at}) (update :admin-settings set/rename-keys {:pinMessageAllMembersEnabled :pin-message-all-members-enabled?}) @@ -67,9 +82,16 @@ (update :chats <-chats-rpc) (update :token-permissions seq) (update :categories <-categories-rpc) + (assoc :role-permissions? + (->> c + :tokenPermissions + vals + (some role-permission?))) (assoc :membership-permissions? - (some #(= (:type %) constants/community-token-permission-become-member) - (vals (:tokenPermissions c)))) + (->> c + :tokenPermissions + vals + (some membership-permission?))) (assoc :token-images (reduce (fn [acc {sym :symbol image :image}] (assoc acc sym image)) diff --git a/src/status_im/config.cljs b/src/status_im/config.cljs index bf8560833a..b50d6bdbb9 100644 --- a/src/status_im/config.cljs +++ b/src/status_im/config.cljs @@ -160,7 +160,7 @@ (def default-kdf-iterations 3200) -(def community-accounts-selection-enabled? false) +(def community-accounts-selection-enabled? (enabled? (get-config :ACCOUNT_SELECTION_ENABLED "1"))) (def fetch-messages-enabled? (enabled? (get-config :FETCH_MESSAGES_ENABLED "1"))) (def wallet-feature-flags diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs index fd24ef35f0..dbf1719451 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -153,6 +153,11 @@ (def ^:const community-token-permission-can-view-and-post-channel 4) (def ^:const community-token-permission-become-token-master 5) (def ^:const community-token-permission-become-token-owner 6) +(def ^:const community-role-permissions + #{community-token-permission-become-admin + community-token-permission-become-member + community-token-permission-become-token-master + community-token-permission-become-token-owner}) ;; Community rules for joining (def ^:const community-rule-ens-only "ens-only") diff --git a/src/status_im/contexts/communities/actions/request_to_join/view.cljs b/src/status_im/contexts/communities/actions/request_to_join/view.cljs index 3dfde1dc90..414554377a 100644 --- a/src/status_im/contexts/communities/actions/request_to_join/view.cljs +++ b/src/status_im/contexts/communities/actions/request_to_join/view.cljs @@ -23,10 +23,8 @@ (defn- view-internal [{:keys [theme]}] (fn [] - (let [{:keys [name - id - images]} (rf/sub [:get-screen-params]) - {:keys [color]} (rf/sub [:communities/community id])] + (let [{:keys [id]} (rf/sub [:get-screen-params]) + {:keys [color name images]} (rf/sub [:communities/community id])] [rn/safe-area-view {:flex 1} [gesture/scroll-view {:style style/container} [rn/view style/page-container diff --git a/src/status_im/contexts/communities/overview/view.cljs b/src/status_im/contexts/communities/overview/view.cljs index 3dbbf3a4be..25e2d4ac94 100644 --- a/src/status_im/contexts/communities/overview/view.cljs +++ b/src/status_im/contexts/communities/overview/view.cljs @@ -7,7 +7,6 @@ [react-native.core :as rn] [reagent.core :as reagent] [status-im.common.home.actions.view :as actions] - [status-im.common.password-authentication.view :as password-authentication] [status-im.common.scroll-page.style :as scroll-page.style] [status-im.common.scroll-page.view :as scroll-page] [status-im.config :as config] @@ -15,38 +14,20 @@ [status-im.contexts.communities.actions.chat.view :as chat-actions] [status-im.contexts.communities.actions.community-options.view :as options] [status-im.contexts.communities.overview.style :as style] - [status-im.contexts.communities.overview.utils :as utils] [status-im.contexts.communities.utils :as communities.utils] [utils.debounce :as debounce] [utils.i18n :as i18n] [utils.re-frame :as rf])) -(defn preview-user-list - [user-list] - (when (seq user-list) - [rn/view style/preview-user - [quo/preview-list - {:type :user - :number (count user-list) - :size :size-24} - user-list] - [quo/text - {:accessibility-label :communities-screen-title - :style {:margin-left 8} - :size :label} - (utils/join-existing-users-string user-list)]])) - -(defn add-category-height +(defn- add-category-height [categories-heights category height] - (swap! categories-heights - (fn [heights] - (assoc heights category height)))) + (swap! categories-heights assoc category height)) -(defn collapse-category +(defn- collapse-category [community-id category-id collapsed?] (rf/dispatch [:communities/toggle-collapsed-category community-id category-id (not collapsed?)])) -(defn layout-y +(defn- layout-y [event] (oops/oget event "nativeEvent.layout.y")) @@ -77,7 +58,7 @@ {:on-press on-press :on-long-press #(rf/dispatch [:show-bottom-sheet channel-sheet-data])})]])) -(defn channel-list-component +(defn- channel-list-component [{:keys [on-category-layout community-id community-color on-first-channel-height-changed]} channels-list] [rn/view @@ -104,7 +85,7 @@ ^{:key (:id chat)} [channel-chat-item community-id community-color chat])])])]) -(defn get-access-type +(defn- get-access-type [access] (condp = access constants/community-no-membership-access :open @@ -112,17 +93,9 @@ constants/community-on-request-access :request-access :unknown-access)) -(defn join-gated-community - [id] - (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 - {:community-id id :password %}])}])) - -(defn info-button +(defn- info-button [] - [rn/touchable-without-feedback + [rn/pressable {:on-press #(rf/dispatch [:show-bottom-sheet @@ -137,119 +110,116 @@ [rn/view [quo/icon :i/info {:no-color true}]]]) -(defn token-gates - [] - (fn [{:keys [id color]}] - (let [{:keys [can-request-access? - number-of-hold-tokens tokens - highest-permission-role]} (rf/sub [:community/token-gated-overview id]) - highest-role-text - (i18n/label - (communities.utils/role->translation-key highest-permission-role :t/member))] - [rn/view {:style (style/token-gated-container)} - [rn/view - {:style {:padding-horizontal 12 - :flex-direction :row - :align-items :center - :justify-content :space-between - :flex 1}} - [quo/text {:weight :medium} - (if can-request-access? - (i18n/label :t/you-eligible-to-join-as {:role highest-role-text}) - (i18n/label :t/you-not-eligible-to-join))] - [info-button]] - (when (pos? number-of-hold-tokens) - [quo/text {:style {:padding-horizontal 12 :padding-bottom 18} :size :paragraph-2} - (if can-request-access? - (i18n/label :t/you-hold-number-of-hold-tokens-of-these - {:number-of-hold-tokens number-of-hold-tokens}) - (i18n/label :t/you-must-hold))]) - [quo/token-requirement-list - {:tokens tokens - :padding? true}] - [quo/button - {:on-press - (if config/community-accounts-selection-enabled? - #(rf/dispatch [:open-modal :community-account-selection {:community-id id}]) - #(join-gated-community id)) - :accessibility-label :join-community-button - :customization-color color - :container-style {:margin-horizontal 12 :margin-top 12 :margin-bottom 12} - :disabled? (not can-request-access?) - :icon-left (if can-request-access? :i/unlocked :i/locked)} - (i18n/label :t/join-open-community)]]))) +(defn- token-requirements + [{:keys [id color]}] + (let [{:keys [can-request-access? + number-of-hold-tokens tokens + highest-permission-role]} (rf/sub [:community/token-gated-overview id]) + highest-role-text + (i18n/label + (communities.utils/role->translation-key highest-permission-role :t/member))] + [rn/view {:style (style/token-gated-container)} + [rn/view + {:style {:padding-horizontal 12 + :flex-direction :row + :align-items :center + :justify-content :space-between + :flex 1}} + [quo/text {:weight :medium} + (if can-request-access? + (i18n/label :t/you-eligible-to-join-as {:role highest-role-text}) + (i18n/label :t/you-not-eligible-to-join))] + [info-button]] + (when (pos? number-of-hold-tokens) + [quo/text {:style {:padding-horizontal 12 :padding-bottom 18} :size :paragraph-2} + (if can-request-access? + (i18n/label :t/you-hold-number-of-hold-tokens-of-these + {:number-of-hold-tokens number-of-hold-tokens}) + (i18n/label :t/you-must-hold))]) + [quo/token-requirement-list + {:tokens tokens + :padding? true}] + [quo/button + {:on-press (if config/community-accounts-selection-enabled? + #(rf/dispatch [:open-modal :community-account-selection + {:community-id id}]) + #(rf/dispatch [:open-modal :community-requests-to-join {:id id}])) + :accessibility-label :join-community-button + :customization-color color + :container-style {:margin-horizontal 12 :margin-top 12 :margin-bottom 12} + :disabled? (not can-request-access?) + :icon-left (if can-request-access? :i/unlocked :i/locked)} + (i18n/label :t/join-open-community)]])) -(defn join-community - [{:keys [joined color permissions token-permissions membership-permissions? id] :as community} - pending?] - (let [access-type (get-access-type (:access permissions)) +(defn- join-community + [{:keys [id color joined permissions role-permissions? can-join?] :as community}] + (let [pending? (rf/sub [:communities/my-pending-request-to-join id]) + access-type (get-access-type (:access permissions)) unknown-access? (= access-type :unknown-access) invite-only? (= access-type :invite-only)] [:<> (when-not (or joined pending? invite-only? unknown-access?) - (if membership-permissions? - [token-gates community] + (if role-permissions? + [token-requirements community] [quo/button - {:on-press - (if config/community-accounts-selection-enabled? - #(rf/dispatch [:open-modal :community-account-selection {:community-id id}]) - #(rf/dispatch [:open-modal :community-requests-to-join community])) - + {:on-press (if config/community-accounts-selection-enabled? + #(rf/dispatch [:open-modal :community-account-selection + {:community-id id}]) + #(rf/dispatch [:open-modal :community-requests-to-join {:id id}])) :accessibility-label :show-request-to-join-screen-button :customization-color color - :icon-left :i/communities} + :icon-left :i/communities} (i18n/label :t/request-to-join)])) - - (when (not (or joined pending? token-permissions)) + (when (not (or pending? role-permissions? can-join?)) [quo/text {:size :paragraph-2 :weight :regular :style style/review-notice} (i18n/label :t/community-admins-will-review-your-request)])])) -(defn status-tag - [pending? joined] - (when (or pending? joined) - [rn/view {:style {:position :absolute :top 12 :right 12}} - [quo/status-tag - {:status {:type (if joined :positive :pending)} - :label (if joined - (i18n/label :t/joined) - (i18n/label :t/pending))}]])) +(defn- status-tag + [community-id joined] + (let [pending? (rf/sub [:communities/my-pending-request-to-join community-id])] + (when (or pending? joined) + [rn/view {:style {:position :absolute :top 12 :right 12}} + [quo/status-tag + {:status {:type (if joined :positive :pending)} + :label (if joined + (i18n/label :t/joined) + (i18n/label :t/pending))}]]))) -(defn add-handlers +(defn- add-handlers [community-id joined-or-spectated {:keys [id locked?] :or {locked? false} :as chat}] - (merge - chat - (when (and (not locked?) id) - {:on-press (when joined-or-spectated - (fn [] - (rf/dispatch [:dismiss-keyboard]) - (debounce/dispatch-and-chill - [:communities/navigate-to-community-chat (str community-id id)] - 1000))) - :on-long-press #(rf/dispatch - [:show-bottom-sheet - {:content (fn [] - [chat-actions/actions chat false])}]) - :community-id community-id}))) + (cond-> chat + (and (not locked?) id) + (assoc :on-press (when joined-or-spectated + (fn [] + (rf/dispatch [:dismiss-keyboard]) + (debounce/dispatch-and-chill + [:communities/navigate-to-community-chat (str community-id id)] + 1000))) + :on-long-press #(rf/dispatch + [:show-bottom-sheet + {:content (fn [] + [chat-actions/actions chat false])}]) + :community-id community-id))) -(defn add-handlers-to-chats +(defn- add-handlers-to-chats [community-id joined-or-spectated chats] (mapv (partial add-handlers community-id joined-or-spectated) chats)) -(defn add-handlers-to-categorized-chats +(defn- add-handlers-to-categorized-chats [community-id categorized-chats joined-or-spectated] (let [add-on-press (partial add-handlers-to-chats community-id joined-or-spectated)] (map (fn [[category v]] [category (update v :chats add-on-press)]) categorized-chats))) -(defn community-header +(defn- community-header [title logo description] [quo/text-combinations {:container-style @@ -266,11 +236,11 @@ :title-accessibility-label :community-title :description-accessibility-label :community-description}]) -(defn community-content - [community] - (rf/dispatch [:communities/check-all-community-channels-permissions (:id community)]) - (fn [{:keys [name description joined spectated images tags color id token-permissions] :as community} - pending? +(defn- community-content + [{:keys [id]}] + (rf/dispatch [:communities/check-all-community-channels-permissions id]) + (fn [{:keys [name description joined spectated images tags color id membership-permissions?] + :as community} {:keys [on-category-layout collapsed? on-first-channel-height-changed]}] @@ -279,7 +249,7 @@ [:<> [rn/view {:style style/community-content-container} (when-not collapsed? - [status-tag pending? joined]) + [status-tag id joined]) [community-header name (when collapsed? (get-in images [:thumbnail :uri])) (when-not collapsed? description)] (when (and (seq tags) (not collapsed?)) @@ -287,9 +257,8 @@ {:tags tags :last-item-style style/last-community-tag :container-style style/community-tag-container}]) - [join-community community pending?]] - (when (or (and (seq token-permissions) joined) - (empty? token-permissions)) + [join-community community]] + (when (or joined (not membership-permissions?)) [channel-list-component {:on-category-layout on-category-layout :community-id id @@ -297,7 +266,7 @@ :on-first-channel-height-changed on-first-channel-height-changed} (add-handlers-to-categorized-chats id chats-by-category joined-or-spectated)])]))) -(defn sticky-category-header +(defn- sticky-category-header [_] (fn [{:keys [enabled label]}] (when enabled @@ -310,7 +279,7 @@ {:chevron :left} label]]))) -(defn page-nav-right-section-buttons +(defn- page-nav-right-section-buttons [id] [{:icon-name :i/options :accessibility-label :community-options-for-community @@ -318,7 +287,7 @@ [:show-bottom-sheet {:content (fn [] [options/community-options-bottom-sheet id])}])}]) -(defn pick-first-category-by-height +(defn- pick-first-category-by-height [scroll-height first-channel-height categories-heights] (->> categories-heights (sort-by (comp - second)) @@ -326,7 +295,7 @@ (and (>= scroll-height (+ height first-channel-height)) category))))) -(defn community-scroll-page +(defn- community-scroll-page [{:keys [joined]}] (let [scroll-height (reagent/atom 0) categories-heights (reagent/atom {}) @@ -336,7 +305,7 @@ ;; from not collapsed to collapsed if the ;; user is on this page initial-joined? joined] - (fn [{:keys [id name images] :as community} pending?] + (fn [{:keys [id name images] :as community}] (let [cover {:uri (get-in images [:banner :uri])} logo {:uri (get-in images [:thumbnail :uri])} collapsed? (and initial-joined? (:joined community)) @@ -363,7 +332,6 @@ @categories-heights)}]} [community-content community - pending? {:on-category-layout (partial add-category-height categories-heights) :collapsed? collapsed? :on-first-channel-height-changed @@ -373,17 +341,16 @@ (swap! categories-heights select-keys categories) (reset! first-channel-height height))}]])))) -(defn community-card-page-view +(defn- community-card-page-view [id] (let [{:keys [id joined] - :as community} (rf/sub [:communities/community id]) - pending? (rf/sub [:communities/my-pending-request-to-join id])] + :as community} (rf/sub [:communities/community id])] (when community (when joined (rf/dispatch [:activity-center.notifications/dismiss-community-overview id])) - [community-scroll-page community pending?]))) + [community-scroll-page community]))) -(defn overview +(defn view [id] (let [id (or id (rf/sub [:get-screen-params :community-overview])) customization-color (rf/sub [:profile/customization-color])] diff --git a/src/status_im/contexts/shell/jump_to/components/floating_screens/view.cljs b/src/status_im/contexts/shell/jump_to/components/floating_screens/view.cljs index d2ab8e402f..33ba142ba9 100644 --- a/src/status_im/contexts/shell/jump_to/components/floating_screens/view.cljs +++ b/src/status_im/contexts/shell/jump_to/components/floating_screens/view.cljs @@ -15,7 +15,7 @@ (def screens-map {shell.constants/chat-screen chat/chat - shell.constants/community-screen communities.overview/overview + shell.constants/community-screen communities.overview/view shell.constants/discover-communities-screen communities.discover/view}) (defn f-screen diff --git a/src/status_im/navigation/screens.cljs b/src/status_im/navigation/screens.cljs index d3a4f948ce..3c3deb756c 100644 --- a/src/status_im/navigation/screens.cljs +++ b/src/status_im/navigation/screens.cljs @@ -143,7 +143,7 @@ :component communities.discover/view} {:name :community-overview - :component communities.overview/overview} + :component communities.overview/view} {:name :settings :options options/transparent-screen-options diff --git a/src/status_im/subs/communities.cljs b/src/status_im/subs/communities.cljs index a45c1dde83..da7ab63559 100644 --- a/src/status_im/subs/communities.cljs +++ b/src/status_im/subs/communities.cljs @@ -1,6 +1,7 @@ (ns status-im.subs.communities (:require [clojure.string :as string] + [legacy.status-im.data-store.communities :as data-store] [legacy.status-im.ui.screens.profile.visibility-status.utils :as visibility-status-utils] [re-frame.core :as re-frame] [status-im.constants :as constants] @@ -307,10 +308,6 @@ [(re-frame/subscribe [:communities/community community-id])]) (fn [[{:keys [token-permissions-check token-permissions checking-permissions? token-images]}] _] (let [can-request-access? (:satisfied token-permissions-check) - role-permissions #{constants/community-token-permission-become-admin - constants/community-token-permission-become-member - constants/community-token-permission-become-token-master - constants/community-token-permission-become-token-owner} highest-permission-role (when can-request-access? (->> token-permissions-check @@ -321,7 +318,7 @@ (and (first criteria) (some #{(:type (permission-id->permission-value token-permissions permission-id))} - role-permissions))] + constants/community-role-permissions))] (if highest-permission-role (min highest-permission-role permission-type) permission-type) @@ -339,8 +336,8 @@ (:permissions token-permissions-check)) :tokens (->> token-permissions - (filter (fn [[_ {:keys [type]}]] - (= type constants/community-token-permission-become-member))) + (filter (fn [[_ permission]] + (data-store/role-permission? permission))) (map (fn [[perm-key {:keys [token_criteria]}]] (let [check-criteria (get-in token-permissions-check [:permissions perm-key :criteria])] diff --git a/src/status_im/subs/communities_test.cljs b/src/status_im/subs/communities_test.cljs index 56239baf4b..59078d9d10 100644 --- a/src/status_im/subs/communities_test.cljs +++ b/src/status_im/subs/communities_test.cljs @@ -455,7 +455,11 @@ (swap! rf-db/app-db assoc-in [:communities community-id] community) (is (match? {:can-request-access? true :number-of-hold-tokens 2 - :tokens [[{:symbol "ETH" + :tokens [[{:symbol "DAI" + :amount "5.0" + :sufficient? nil + :loading? checking-permissions?}] + [{:symbol "ETH" :amount "0.001" :sufficient? nil :loading? checking-permissions?