From 27e177f18b16acff81a445237cbe61230a78d303 Mon Sep 17 00:00:00 2001 From: Icaro Motta Date: Mon, 4 Mar 2024 09:23:30 -0300 Subject: [PATCH] Account selection: Use bottom sheet component (#18919) Use bottom sheet component as designed in Figma https://www.figma.com/file/h9wo4GipgZURbqqr1vShFN/Communities-for-Mobile?type=design&node-id=16409-98076&mode=design&t=jrVNb3JnWNurJwP8-0 - Fixes no animation when closing Addresses For Permissions modal: https://github.com/status-im/status-mobile/issues/18617 - Fixes drawer is always expanded: https://github.com/status-im/status-mobile/issues/18619 Additionally: - Fixed incorrect code passing a function instance to a style prop, which leads to incorrect appearance for settings.category.reorder.view/view. - Optimized Reagent a little bit by extracting functions that need to close over the community ID to the mount phase. That way, we avoid regenerating function instances on every re-render and Reagent can avoid a bit of re-work. The challenge was to make the scrollable content work inside a bottom sheet, while supporting the designs for a fixed (always visible) header and footer. --- .../settings/category/reorder/view.cljs | 4 +- src/status_im/common/bottom_sheet/style.cljs | 23 +-- src/status_im/common/bottom_sheet/view.cljs | 25 ++- .../actions/accounts_selection/view.cljs | 153 ++++++++++-------- .../addresses_for_permissions/style.cljs | 3 - .../addresses_for_permissions/view.cljs | 58 ++++--- .../actions/airdrop_addresses/view.cljs | 6 +- src/status_im/navigation/screens.cljs | 11 -- 8 files changed, 143 insertions(+), 140 deletions(-) delete mode 100644 src/status_im/contexts/communities/actions/addresses_for_permissions/style.cljs diff --git a/src/quo/components/settings/category/reorder/view.cljs b/src/quo/components/settings/category/reorder/view.cljs index 2b2a3db7a9..bc1f8a0636 100644 --- a/src/quo/components/settings/category/reorder/view.cljs +++ b/src/quo/components/settings/category/reorder/view.cljs @@ -16,9 +16,9 @@ (reagent/flush)) (defn- reorder-category-internal - [{:keys [label data blur? theme]}] + [{:keys [label data blur? theme container-style]}] (reagent/with-let [atom-data (reagent/atom data)] - [rn/view {:style style/container} + [rn/view {:style (merge (style/container label) container-style)} [text/text {:weight :medium :size :paragraph-2 diff --git a/src/status_im/common/bottom_sheet/style.cljs b/src/status_im/common/bottom_sheet/style.cljs index 57d32ad859..b2f61b31c5 100644 --- a/src/status_im/common/bottom_sheet/style.cljs +++ b/src/status_im/common/bottom_sheet/style.cljs @@ -3,18 +3,18 @@ [quo.foundations.colors :as colors] [react-native.platform :as platform])) +(def ^:private sheet-border-radius 20) + (defn sheet - [{:keys [top]} window-height selected-item] + [{:keys [max-height]}] {:position :absolute - :max-height (- window-height top) - :z-index 1 :bottom 0 :left 0 :right 0 - :border-top-left-radius 20 - :border-top-right-radius 20 - :overflow (when-not selected-item :hidden) - :flex 1}) + :z-index 1 + :max-height max-height + :border-top-left-radius sheet-border-radius + :border-top-right-radius sheet-border-radius}) (def gradient-bg {:position :absolute @@ -31,10 +31,11 @@ :bottom 0}) (defn sheet-content - [theme padding-bottom-override {:keys [bottom]} shell? bottom-margin] - {:border-top-left-radius 20 - :border-top-right-radius 20 - :padding-bottom (or padding-bottom-override (+ bottom bottom-margin)) + [{:keys [theme padding-bottom shell?]}] + {:overflow :scroll + :padding-bottom padding-bottom + :border-top-left-radius sheet-border-radius + :border-top-right-radius sheet-border-radius :background-color (if shell? :transparent (colors/theme-colors colors/white colors/neutral-95 theme))}) diff --git a/src/status_im/common/bottom_sheet/view.cljs b/src/status_im/common/bottom_sheet/view.cljs index 31188c6766..e9063f5dab 100644 --- a/src/status_im/common/bottom_sheet/view.cljs +++ b/src/status_im/common/bottom_sheet/view.cljs @@ -56,6 +56,10 @@ (show translate-y bg-opacity) (hide translate-y bg-opacity window-height on-close)))))) +(defn- get-layout-height + [event] + (oops/oget event "nativeEvent.layout.height")) + (defn view [{:keys [hide? insets]} {:keys [content selected-item padding-bottom-override border-radius on-close shell? @@ -64,6 +68,8 @@ (let [theme (quo.theme/use-theme-value) sheet-height (rn/use-ref-atom 0) item-height (rn/use-ref-atom 0) + set-sheet-height (rn/use-callback #(reset! sheet-height (get-layout-height %))) + set-item-height (rn/use-callback #(reset! item-height (get-layout-height %))) {window-height :height} (rn/get-window) bg-opacity (reanimated/use-shared-value 0) translate-y (reanimated/use-shared-value window-height) @@ -80,7 +86,10 @@ top (- window-height (:top insets) @sheet-height) bottom (if selected-item-smaller-than-sheet? (+ @sheet-height bottom-margin) - (:bottom insets))] + (:bottom insets)) + sheet-max-height (- window-height (:top insets)) + content-padding-bottom (or padding-bottom-override + (+ (:bottom insets) bottom-margin))] (rn/use-effect #(if hide? (hide translate-y bg-opacity window-height on-close) @@ -105,7 +114,7 @@ [reanimated/view {:style (reanimated/apply-animations-to-style {:transform [{:translateY translate-y}]} - (style/sheet insets window-height selected-item))} + (style/sheet {:max-height sheet-max-height}))} (when shell? [blur/ios-view {:style style/shell-bg @@ -114,14 +123,14 @@ :overlay-color :transparent}]) (when selected-item [rn/view - {:on-layout #(reset! item-height (.-nativeEvent.layout.height ^js %)) - :style - (style/selected-item theme top bottom selected-item-smaller-than-sheet? border-radius)} + {:on-layout set-item-height + :style (style/selected-item theme top bottom selected-item-smaller-than-sheet? border-radius)} [selected-item]]) - [rn/view - {:style (style/sheet-content theme padding-bottom-override insets shell? bottom-margin) - :on-layout #(reset! sheet-height (.-nativeEvent.layout.height ^js %))} + {:on-layout set-sheet-height + :style (style/sheet-content {:theme theme + :shell? shell? + :padding-bottom content-padding-bottom})} (when (and gradient-cover? customization-color) [rn/view {:style style/gradient-bg} [quo/gradient-cover diff --git a/src/status_im/contexts/communities/actions/accounts_selection/view.cljs b/src/status_im/contexts/communities/actions/accounts_selection/view.cljs index 853e11c347..713d5ef455 100644 --- a/src/status_im/contexts/communities/actions/accounts_selection/view.cljs +++ b/src/status_im/contexts/communities/actions/accounts_selection/view.cljs @@ -5,81 +5,92 @@ [react-native.gesture :as gesture] [status-im.common.password-authentication.view :as password-authentication] [status-im.contexts.communities.actions.accounts-selection.style :as style] + [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.community-rules.view :as community-rules] [status-im.contexts.communities.utils :as communities.utils] [utils.i18n :as i18n] [utils.re-frame :as rf])) -(defn- join-community-and-navigate-back - [id] - (rf/dispatch [:password-authentication/show {:content (fn [] [password-authentication/view])} - {:label (i18n/label :t/join-open-community) - :on-press #(rf/dispatch [:communities/request-to-join-with-addresses - {:community-id id :password %}])}]) - (rf/dispatch [:navigate-back])) - (defn view [] - (let [{id :community-id} (rf/sub [:get-screen-params]) - {:keys [name color images]} (rf/sub [:communities/community id]) - airdrop-account (rf/sub [:communities/airdrop-account id]) - selected-accounts (rf/sub [:communities/selected-permission-accounts id]) - {:keys [highest-permission-role]} (rf/sub [:community/token-gated-overview id]) - highest-role-text (i18n/label (communities.utils/role->translation-key - highest-permission-role - :t/member))] - [rn/safe-area-view {:style style/container} - [quo/page-nav - {:text-align :left - :icon-name :i/close - :on-press #(rf/dispatch [: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 #(rf/dispatch [:open-modal :addresses-for-permissions - {:community-id id}]) - :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 #(rf/dispatch [:open-modal :airdrop-addresses - {:community-id id}]) - :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-community-and-navigate-back id)}]]])) + (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}]]])))) diff --git a/src/status_im/contexts/communities/actions/addresses_for_permissions/style.cljs b/src/status_im/contexts/communities/actions/addresses_for_permissions/style.cljs deleted file mode 100644 index 1f0b2ab126..0000000000 --- a/src/status_im/contexts/communities/actions/addresses_for_permissions/style.cljs +++ /dev/null @@ -1,3 +0,0 @@ -(ns status-im.contexts.communities.actions.addresses-for-permissions.style) - -(def container {:flex 1}) diff --git a/src/status_im/contexts/communities/actions/addresses_for_permissions/view.cljs b/src/status_im/contexts/communities/actions/addresses_for_permissions/view.cljs index d793a221a9..16100f54c6 100644 --- a/src/status_im/contexts/communities/actions/addresses_for_permissions/view.cljs +++ b/src/status_im/contexts/communities/actions/addresses_for_permissions/view.cljs @@ -1,11 +1,9 @@ (ns status-im.contexts.communities.actions.addresses-for-permissions.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.resources :as resources] [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])) @@ -56,8 +54,15 @@ :customization-color community-color}])) (defn view - [{:keys [scroll-enabled? on-scroll]}] - (let [{id :community-id} (rf/sub [:get-screen-params])] + [] + (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]) @@ -67,7 +72,7 @@ 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])] - [rn/safe-area-view {:style style/container} + [:<> [quo/drawer-top {:type :context-tag :title (i18n/label :t/addresses-for-permissions) @@ -79,26 +84,24 @@ :community-logo (get-in images [:thumbnail :uri]) :customization-color color}] - [quo/category - {:list-type :settings - :data [{:title (i18n/label :t/share-all-current-and-future-addresses) - :action :selector - :action-props {:on-change #(rf/dispatch - [:communities/toggle-share-all-addresses - id]) - :customization-color color - :checked? share-all-addresses?}}] - :container-style {:padding-bottom 16}}] - [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} - :scroll-enabled @scroll-enabled? - :on-scroll on-scroll :key-fn :address :data accounts}] @@ -110,25 +113,18 @@ (empty? selected-addresses) (not highest-permission-role) (not unsaved-address-changes?)) - :on-press (fn [] - (rf/dispatch - [:communities/update-previous-permission-addresses - id]) - (rf/dispatch [:navigate-back]))} + :on-press update-previous-addresses} :button-two-label (i18n/label :t/cancel) :button-two-props {:type :grey - :on-press (fn [] - (rf/dispatch - [:communities/reset-selected-permission-addresses id]) - (rf/dispatch [:navigate-back]))} + :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) - (not highest-permission-role) (i18n/label - :t/addresses-dont-contain-tokens-needed) - :else nil)}]])))) + (empty? selected-addresses) + (i18n/label :t/no-addresses-selected) + (not highest-permission-role) + (i18n/label :t/addresses-dont-contain-tokens-needed))}]])))) diff --git a/src/status_im/contexts/communities/actions/airdrop_addresses/view.cljs b/src/status_im/contexts/communities/actions/airdrop_addresses/view.cljs index b479742998..6bfaa95e8b 100644 --- a/src/status_im/contexts/communities/actions/airdrop_addresses/view.cljs +++ b/src/status_im/contexts/communities/actions/airdrop_addresses/view.cljs @@ -1,7 +1,7 @@ (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.contexts.communities.actions.airdrop-addresses.style :as style] [utils.i18n :as i18n] @@ -14,7 +14,7 @@ :state (when (= airdrop-address (:address item)) :selected) :on-press (fn [] (rf/dispatch [:communities/set-airdrop-address (:address item) community-id]) - (rf/dispatch [:navigate-back])) + (rf/dispatch [:hide-bottom-sheet])) :emoji (:emoji item)}]) (defn view @@ -33,7 +33,7 @@ :on-button-press not-implemented/alert :community-logo (get-in images [:thumbnail :uri]) :customization-color color}] - [rn/flat-list + [gesture/flat-list {:data selected-accounts :render-fn render-item :render-data [airdrop-address id] diff --git a/src/status_im/navigation/screens.cljs b/src/status_im/navigation/screens.cljs index 9b68b5e42e..12a2f7b686 100644 --- a/src/status_im/navigation/screens.cljs +++ b/src/status_im/navigation/screens.cljs @@ -13,9 +13,6 @@ [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] @@ -126,14 +123,6 @@ :options {:sheet? true} :component communities.accounts-selection/view} - {:name :addresses-for-permissions - :options {:sheet? true} - :component addresses-for-permissions/view} - - {:name :airdrop-addresses - :options {:sheet? true} - :component airdrop-addresses/view} - {:name :lightbox :options options/lightbox :component lightbox/lightbox}