From dfa30fd14fd6af2e2882455bd877fb92557c34bf Mon Sep 17 00:00:00 2001 From: Ajay Sivan Date: Mon, 4 Sep 2023 08:39:23 -0700 Subject: [PATCH] quo channel component refactor (#17070) --- .../components/counter/counter/style.cljs | 21 +++--- src/quo2/components/list_items/channel.cljs | 68 ------------------- .../list_items/channel/component_spec.cljs | 44 ++++++++++++ .../components/list_items/channel/style.cljs | 46 +++++++++++++ .../components/list_items/channel/view.cljs | 61 +++++++++++++++++ src/quo2/core.cljs | 4 +- src/quo2/core_spec.cljs | 1 + src/quo2/foundations/colors.cljs | 8 ++- .../contexts/communities/overview/view.cljs | 28 +++++--- .../quo_preview/list_items/channel.cljs | 53 +++++++-------- 10 files changed, 216 insertions(+), 118 deletions(-) delete mode 100644 src/quo2/components/list_items/channel.cljs create mode 100644 src/quo2/components/list_items/channel/component_spec.cljs create mode 100644 src/quo2/components/list_items/channel/style.cljs create mode 100644 src/quo2/components/list_items/channel/view.cljs diff --git a/src/quo2/components/counter/counter/style.cljs b/src/quo2/components/counter/counter/style.cljs index 4751d1868f..dfda5e1d3c 100644 --- a/src/quo2/components/counter/counter/style.cljs +++ b/src/quo2/components/counter/counter/style.cljs @@ -12,16 +12,19 @@ (defn container [{:keys [type label container-style customization-color theme value max-value]}] - (let [width (case (count label) - 1 16 - 2 20 - 28)] + (let [label-length (count label) + width (case label-length + 1 16 + 2 20 + 28)] (cond-> (merge - {:align-items :center - :justify-content :center - :border-radius 6 - :width width - :height 16} + {:align-items :center + :justify-content :center + :border-radius 6 + :width width + :margin-vertical 2 + :margin-horizontal (if (= label-length 1) 2 0) + :height 16} container-style) (= type :outline) (merge {:border-width 1 diff --git a/src/quo2/components/list_items/channel.cljs b/src/quo2/components/list_items/channel.cljs deleted file mode 100644 index 63df2c2487..0000000000 --- a/src/quo2/components/list_items/channel.cljs +++ /dev/null @@ -1,68 +0,0 @@ -(ns quo2.components.list-items.channel - (:require [quo2.components.avatars.channel-avatar.view :as channel-avatar] - [quo2.components.common.unread-grey-dot.view :as unread-grey-dot] - [quo2.components.counter.counter.view :as counter] - [quo2.components.icon :as quo2.icons] - [quo2.components.markdown.text :as quo2.text] - [quo2.foundations.colors :as colors] - [react-native.core :as rn])) - -(def ^:private custom-props - [:name :locked? :mentions-count :unread-messages? - :muted? :is-active-channel? :emoji :channel-color]) - -(defn list-item - [{:keys [locked? mentions-count unread-messages? - muted? is-active-channel? emoji channel-color - default-color] - :as props}] - (let [channel-color (or channel-color default-color) - standard-props (apply dissoc props custom-props) - name-text (:name props)] - [rn/touchable-opacity standard-props - [rn/view - {:style (cond-> {:height 48 - :border-radius 12 - :flex-direction :row - :justify-content :space-between - :align-items :center - :width "100%" - :padding-left 12 - :padding-right 12} - is-active-channel? (assoc :background-color - (colors/theme-alpha channel-color 0.05 0.05)))} - [rn/view - {:style {:flex-direction :row - :justify-content :flex-start - :align-items :center} - :accessible true - :accessibility-label :chat-name-text} - [channel-avatar/view - {:size :size/l - :locked? locked? - :full-name (:name props) - :customization-color channel-color - :emoji emoji}] - [quo2.text/text - {:style (cond-> {:margin-left 12} - (and (not locked?) muted?) - (assoc :color (colors/theme-colors colors/neutral-40 colors/neutral-60))) - :weight :medium - :size :paragraph-1} - (str "# " name-text)]] - (when-not locked? - [rn/view {:style {:height 20 :justify-content :center}} - (cond - muted? - [quo2.icons/icon :i/muted - {:size 20 - :color colors/neutral-40 - :container-style {:margin-right 1 :margin-top 2}}] - - (pos? (int mentions-count)) - [rn/view {:style {:margin-right 2 :margin-top 2}} - [counter/view {:customization-color channel-color} - mentions-count]] - - unread-messages? - [unread-grey-dot/unread-grey-dot :unviewed-messages-public])])]])) diff --git a/src/quo2/components/list_items/channel/component_spec.cljs b/src/quo2/components/list_items/channel/component_spec.cljs new file mode 100644 index 0000000000..881b701206 --- /dev/null +++ b/src/quo2/components/list_items/channel/component_spec.cljs @@ -0,0 +1,44 @@ +(ns quo2.components.list-items.channel.component-spec + (:require [test-helpers.component :as h] + [quo2.components.list-items.channel.view :as channel])) + +(h/describe "list-items/channel Component" + (h/test "default render" + (h/render [channel/view {:name "general"}]) + (h/is-truthy (h/query-by-label-text :channel-list-item))) + + (h/test "with name & emoji" + (h/render [channel/view + {:name "general" + :emoji "👋"}]) + (h/is-truthy (h/query-by-text "# general")) + (h/is-truthy (h/query-by-text "👋"))) + + (h/test "notification & mentions count" + (h/render [channel/view + {:name "general" + :mentions-count 10 + :notification :mention}]) + (h/is-truthy (h/query-by-text "10"))) + + (h/test "unread indicator" + (h/render [channel/view + {:name "general" + :notification :notification}]) + (h/is-truthy (h/query-by-label-text :unviewed-messages-public))) + + (h/test "on-press event" + (let [on-press (h/mock-fn)] + (h/render [channel/view + {:name "general" + :on-press on-press}]) + (h/fire-event :press (h/query-by-label-text :channel-list-item)) + (h/was-called on-press))) + + (h/test "on-long-press event" + (let [on-long-press (h/mock-fn)] + (h/render [channel/view + {:name "general" + :on-long-press on-long-press}]) + (h/fire-event :long-press (h/query-by-label-text :channel-list-item)) + (h/was-called on-long-press)))) diff --git a/src/quo2/components/list_items/channel/style.cljs b/src/quo2/components/list_items/channel/style.cljs new file mode 100644 index 0000000000..637ac4a008 --- /dev/null +++ b/src/quo2/components/list_items/channel/style.cljs @@ -0,0 +1,46 @@ +(ns quo2.components.list-items.channel.style + (:require [quo2.foundations.colors :as colors])) + +(defn- get-label-color + [notification theme] + (let [colors {:notification (colors/theme-colors colors/neutral-100 + colors/white + theme) + :mention (colors/theme-colors colors/neutral-100 + colors/white + theme) + :mute (colors/theme-colors colors/neutral-40 + colors/neutral-60 + theme) + :default (colors/theme-colors colors/neutral-50 + colors/neutral-40 + theme)}] + (colors (or notification :default)))) + +(defn mute-notification-icon-color + [theme] + (colors/theme-colors colors/neutral-40 + colors/neutral-60 + theme)) + +(defn container + [pressed? customization-color theme] + {:height 48 + :border-radius 12 + :padding-horizontal 12 + :padding-vertical 8 + :align-items :center + :overflow :hidden + :background-color (if pressed? + (colors/theme-colors + (colors/custom-color customization-color 50 5) + (colors/custom-color customization-color 60 5) + theme) + :transparent) + :flex-direction :row}) + +(defn label + [notification theme] + {:margin-horizontal 12 + :color (get-label-color notification theme) + :flex 1}) diff --git a/src/quo2/components/list_items/channel/view.cljs b/src/quo2/components/list_items/channel/view.cljs new file mode 100644 index 0000000000..9669eb63bd --- /dev/null +++ b/src/quo2/components/list_items/channel/view.cljs @@ -0,0 +1,61 @@ +(ns quo2.components.list-items.channel.view + (:require [quo2.components.list-items.channel.style :as style] + [quo2.theme :as theme] + [react-native.core :as rn] + [quo2.components.avatars.channel-avatar.view :as channel-avatar] + [quo2.components.markdown.text :as quo.text] + [quo2.components.icon :as quo2.icons] + [quo2.components.counter.counter.view :as counter] + [reagent.core :as reagent])) + +(defn- view-internal + "Options: + - notification - (nil/:notification/:mention/:mute, default: nil): + - :notification - Display a grey dot. + - :mention - Display a counter. + - :mute - Display a mute icon. + - locked? - (nil/boolean, default: nil): + - When true, display a locked icon. + - When false, display an unlocked icon. + - mentions-count - (default: nil) - Number of mentions to display in the counter with :mention notification. + - customization-color - (default: nil) - Community color. + - emoji - (string, default: nil): + - Emoji to be displayed on the channel avatar. + - If blank, initials of the channel name are displayed. + - name - (string, default: nil) - Channel name. + - on-press - (function, default: nil) - Function called when the component is pressed. + - on-long-press - (function, default: nil) - Function called when the component is long pressed. + - theme - Theme value from with-theme HOC" + [] + (let [pressed? (reagent/atom false)] + (fn [{:keys [notification locked? mentions-count customization-color emoji name on-press + on-long-press theme]}] + [rn/pressable + {:style (style/container @pressed? customization-color theme) + :accessibility-label :channel-list-item + :on-press on-press + :on-long-press on-long-press + :on-press-in #(reset! pressed? true) + :on-press-out #(reset! pressed? false)} + [channel-avatar/view + {:size :size/l + :locked? locked? + :full-name name + :customization-color customization-color + :emoji emoji}] + [quo.text/text + {:style (style/label notification theme) + :weight :medium + :size :paragraph-1} (str "# " name)] + (when-not locked? + (condp = notification + :mute [quo2.icons/icon :i/muted + {:color (style/mute-notification-icon-color theme)}] + :mention [counter/view {:customization-color customization-color} + mentions-count] + :notification [quo2.icons/icon :i/notification + {:color (style/mute-notification-icon-color theme) + :accessibility-label :unviewed-messages-public}] + nil))]))) + +(def view (theme/with-theme view-internal)) diff --git a/src/quo2/core.cljs b/src/quo2/core.cljs index be88eb5798..e27c0ff3a3 100644 --- a/src/quo2/core.cljs +++ b/src/quo2/core.cljs @@ -60,7 +60,7 @@ quo2.components.links.url-preview-list.view quo2.components.links.url-preview.view quo2.components.list-items.account-list-card.view - quo2.components.list-items.channel + quo2.components.list-items.channel.view quo2.components.list-items.community.view quo2.components.list-items.dapp.view quo2.components.list-items.menu-item @@ -244,7 +244,7 @@ ;;;; List items (def account-list-card quo2.components.list-items.account-list-card.view/view) -(def channel-list-item quo2.components.list-items.channel/list-item) +(def channel quo2.components.list-items.channel.view/view) (def dapp quo2.components.list-items.dapp.view/view) (def menu-item quo2.components.list-items.menu-item/menu-item) (def preview-list quo2.components.list-items.preview-list.view/view) diff --git a/src/quo2/core_spec.cljs b/src/quo2/core_spec.cljs index bfb629bb71..8072390bd6 100644 --- a/src/quo2/core_spec.cljs +++ b/src/quo2/core_spec.cljs @@ -35,6 +35,7 @@ [quo2.components.links.link-preview.component-spec] [quo2.components.links.url-preview-list.component-spec] [quo2.components.links.url-preview.component-spec] + [quo2.components.list-items.channel.component-spec] [quo2.components.list-items.community.component-spec] [quo2.components.list-items.dapp.component-spec] [quo2.components.list-items.token-value.component-spec] diff --git a/src/quo2/foundations/colors.cljs b/src/quo2/foundations/colors.cljs index 9e1e84a021..45bac2dad7 100644 --- a/src/quo2/foundations/colors.cljs +++ b/src/quo2/foundations/colors.cljs @@ -257,9 +257,11 @@ color-keyword (keyword color) base-color (get-in colors-map [color-keyword suffix])] - (if hex? - color - (if opacity (alpha base-color (/ opacity 100)) base-color))))))) + (cond + (and opacity hex?) (alpha color (/ opacity 100)) + opacity (alpha base-color (/ opacity 100)) + hex? color + :else base-color)))))) (defn custom-color-by-theme "(custom-color-by-theme color suffix-light suffix-dark opacity-light opacity-dark) diff --git a/src/status_im2/contexts/communities/overview/view.cljs b/src/status_im2/contexts/communities/overview/view.cljs index f953e0e878..6b0f0d5c27 100644 --- a/src/status_im2/contexts/communities/overview/view.cljs +++ b/src/status_im2/contexts/communities/overview/view.cljs @@ -47,21 +47,31 @@ (oops/oget event "nativeEvent.layout.y")) (defn- channel-chat-item - [community-id community-color {:keys [:muted? id] :as chat}] + [community-id community-color + {:keys [name emoji muted? id mentions-count unread-messages? on-press locked?] :as chat}] (let [sheet-content [actions/chat-actions (assoc chat :chat-type constants/community-chat-type :chat-id (str community-id id)) false] - channel-sheet-data {:selected-item (fn [] [quo/channel-list-item chat]) + notification (cond + muted? :mute + (> mentions-count 0) :mention + unread-messages? :notification + :else nil) + channel-options {:name name + :emoji emoji + :customization-color community-color + :mentions-count mentions-count + :locked? locked? + :notification notification} + channel-sheet-data {:selected-item (fn [] [quo/channel channel-options]) :content (fn [] sheet-content)}] - [rn/view {:key id :style {:margin-top 4}} - [quo/channel-list-item - (assoc chat - :default-color community-color - :on-long-press #(rf/dispatch [:show-bottom-sheet channel-sheet-data]) - :muted? (or muted? - (rf/sub [:chat/check-channel-muted? community-id id])))]])) + [rn/view {:key id} + [quo/channel + (merge channel-options + {:on-press on-press + :on-long-press #(rf/dispatch [:show-bottom-sheet channel-sheet-data])})]])) (defn channel-list-component [{:keys [on-category-layout community-id community-color on-first-channel-height-changed]} diff --git a/src/status_im2/contexts/quo_preview/list_items/channel.cljs b/src/status_im2/contexts/quo_preview/list_items/channel.cljs index e84885d7e8..8d15062d3d 100644 --- a/src/status_im2/contexts/quo_preview/list_items/channel.cljs +++ b/src/status_im2/contexts/quo_preview/list_items/channel.cljs @@ -1,19 +1,27 @@ (ns status-im2.contexts.quo-preview.list-items.channel (:require [quo2.core :as quo] [reagent.core :as reagent] - [status-im2.contexts.quo-preview.preview :as preview])) + [status-im2.contexts.quo-preview.preview :as preview] + [quo2.foundations.colors :as colors])) (def descriptor - [{:key :muted? - :type :boolean} - {:key :name + [{:key :name :type :text} + {:key :notification + :type :select + :options [{:key nil + :value "None"} + {:key :notification + :value :notification} + {:key :mute + :value :mute} + {:key :mention + :value :mention}]} {:key :mentions-count :type :text} - {:key :unread-messages? - :type :boolean} {:key :emoji :type :text} + (preview/customization-color-option) {:key :locked? :type :select :options [{:key nil @@ -21,28 +29,19 @@ {:key false :value "Unlocked"} {:key true - :value "Locked"}]} - {:key :is-active-channel? - :type :boolean} - {:key :channel-color - :type :select - :options [{:key "#00FFFF" - :value "Blue"} - {:key "#FF00FF" - :value "Pink"} - {:key "#FFFF00" - :value "Yellow"}]}]) + :value "Locked"}]}]) (defn view [] - (let [state (reagent/atom {:is-active-channel? false - :muted? false - :unread-messages? false - :emoji "🍑" - :channel-color "#4360DF" - :mentions-count "5" - :name "channel" - :locked? true})] + (let [state (reagent/atom {:name "channel" + :notification nil + :mentions-count "5" + :emoji "🍑" + :customization-color :blue + :locked? nil})] (fn [] - [preview/preview-container {:state state :descriptor descriptor} - [quo/channel-list-item @state]]))) + (let [customization-color (colors/custom-color-by-theme (:customization-color @state) 50 60)] + [preview/preview-container + {:state state + :descriptor descriptor} + [quo/channel (assoc @state :customization-color customization-color)]]))))