From af3ba74e301fee34dc4b6ffc63b52c69a5539638 Mon Sep 17 00:00:00 2001 From: Omar Basem Date: Thu, 13 Oct 2022 22:27:56 +0400 Subject: [PATCH] feat: pinned messages new ui (#14147) * feat: pinned messages new ui --- src/status_im/chat/models/pin_message.cljs | 11 ++- src/status_im/constants.cljs | 1 + .../ui/screens/chat/components/edit.cljs | 2 +- .../ui/screens/chat/components/reply.cljs | 15 +-- .../ui/screens/chat/components/style.cljs | 12 ++- .../ui/screens/chat/message/message.cljs | 98 ++++++++++++------- .../ui/screens/chat/message/styles.cljs | 1 + .../screens/chat/styles/message/message.cljs | 51 ++++------ 8 files changed, 114 insertions(+), 77 deletions(-) diff --git a/src/status_im/chat/models/pin_message.cljs b/src/status_im/chat/models/pin_message.cljs index f0bef34f3d..e39cf96c8d 100644 --- a/src/status_im/chat/models/pin_message.cljs +++ b/src/status_im/chat/models/pin_message.cljs @@ -4,6 +4,7 @@ [status-im.data-store.pin-messages :as data-store.pin-messages] [status-im.utils.fx :as fx] [taoensso.timbre :as log] + [status-im.transport.message.protocol :as protocol] [re-frame.core :as re-frame])) (fx/defn handle-failed-loading-pin-messages @@ -73,7 +74,8 @@ {:events [::send-pin-message]} [{:keys [db] :as cofx} {:keys [chat-id message-id pinned] :as pin-message}] (let [current-public-key (get-in db [:multiaccount :public-key]) - message (merge pin-message {:pinned-by current-public-key})] + message (merge pin-message {:pinned-by current-public-key}) + preferred-name (get-in db [:multiaccount :preferred-name])] (fx/merge cofx {:db (cond-> db pinned @@ -86,7 +88,12 @@ (update-in [:pin-messages chat-id] dissoc message-id)))} (data-store.pin-messages/send-pin-message {:chat-id (pin-message :chat-id) :message_id (pin-message :message-id) - :pinned (pin-message :pinned)})))) + :pinned (pin-message :pinned)}) + (when pinned + (protocol/send-chat-messages [{:chat-id (pin-message :chat-id) + :content-type constants/content-type-pin + :response-to (pin-message :message-id) + :ens-name preferred-name}]))))) (fx/defn load-pin-messages {:events [::load-pin-messages]} diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs index 4b44a89f04..283b287eb8 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -14,6 +14,7 @@ (def ^:const content-type-community 9) (def ^:const content-type-gap 10) (def ^:const content-type-contact-request 11) ;; TODO: temp, will be removed +(def ^:const content-type-pin 13) (def ^:const contact-request-state-none 0) (def ^:const contact-request-state-mutual 1) diff --git a/src/status_im/ui/screens/chat/components/edit.cljs b/src/status_im/ui/screens/chat/components/edit.cljs index 5158e2e4a3..9ab7566000 100644 --- a/src/status_im/ui/screens/chat/components/edit.cljs +++ b/src/status_im/ui/screens/chat/components/edit.cljs @@ -31,7 +31,7 @@ (defn edit-message [] [rn/view {:style {:flex-direction :row :height 24}} - [rn/view {:style (styles/reply-content)} + [rn/view {:style (styles/reply-content false)} [icons/icon :main-icons/edit-connector {:color (theme-colors quo2.colors/neutral-40 quo2.colors/neutral-60) :container-style {:position :absolute :left 10 :bottom -4 :width 16 :height 16}}] [rn/view {:style {:position :absolute :left 36 :right 54 :top 3 :flex-direction :row :align-items :center}} diff --git a/src/status_im/ui/screens/chat/components/reply.cljs b/src/status_im/ui/screens/chat/components/reply.cljs index 34c37489a2..524ddaf00d 100644 --- a/src/status_im/ui/screens/chat/components/reply.cljs +++ b/src/status_im/ui/screens/chat/components/reply.cljs @@ -81,15 +81,16 @@ [icons/icon :main-icons/close-circle {:container-style (styles/close-button) :color (:icon-02 @quo.colors/theme)}]]]])) -(defn reply-message [{:keys [from identicon content-type contentType parsed-text content]} in-chat-input?] +; This component is also used for quoted pinned message as the UI is very similar +(defn reply-message [{:keys [from identicon content-type contentType parsed-text content]} in-chat-input? pin?] (let [contact-name @(re-frame/subscribe [:contacts/contact-name-by-identity from]) current-public-key @(re-frame/subscribe [:multiaccount/public-key]) content-type (or content-type contentType)] - [rn/view {:style {:flex-direction :row :height 24}} - [rn/view {:style (styles/reply-content)} - [icons/icon :main-icons/connector {:color (theme-colors quo2.colors/neutral-40 quo2.colors/neutral-60) - :container-style {:position :absolute :left 10 :bottom -4 :width 16 :height 16}}] - [rn/view {:style {:position :absolute :left 34 :top 3 :flex-direction :row :align-items :center :width "45%"}} + [rn/view {:style {:flex-direction :row :height (when-not pin? 24)}} + [rn/view {:style (styles/reply-content pin?)} + (when-not pin? [icons/icon :main-icons/connector {:color (theme-colors quo2.colors/neutral-40 quo2.colors/neutral-60) + :container-style {:position :absolute :left 10 :bottom -4 :width 16 :height 16}}]) + [rn/view {:style (styles/quoted-message pin?)} [photos/member-photo from identicon 16] [quo2.text/text {:weight :semi-bold :size :paragraph-2 @@ -125,7 +126,7 @@ (defn send-image [images] [rn/view {:style (styles/reply-container-image)} [rn/scroll-view {:horizontal true - :style (styles/reply-content)} + :style (styles/reply-content false)} (for [{:keys [uri]} (vals images)] ^{:key uri} [rn/image {:source {:uri uri} diff --git a/src/status_im/ui/screens/chat/components/style.cljs b/src/status_im/ui/screens/chat/components/style.cljs index 6ffb236dec..e6b61d1405 100644 --- a/src/status_im/ui/screens/chat/components/style.cljs +++ b/src/status_im/ui/screens/chat/components/style.cljs @@ -108,11 +108,19 @@ :padding-horizontal 10 :flex 1}) -(defn reply-content [] - {:padding-horizontal 10 +(defn reply-content [pin?] + {:padding-horizontal (when-not pin? 10) :flex 1 :flex-direction :row}) +(defn quoted-message [pin?] + (merge {:flex-direction :row + :align-items :center + :width "45%"} + (when-not pin? {:position :absolute + :left 34 + :top 3}))) + (defn contact-request-content [] {:flex 1 :flex-direction :row diff --git a/src/status_im/ui/screens/chat/message/message.cljs b/src/status_im/ui/screens/chat/message/message.cljs index 51fa517e0f..3299d35bdb 100644 --- a/src/status_im/ui/screens/chat/message/message.cljs +++ b/src/status_im/ui/screens/chat/message/message.cljs @@ -12,9 +12,6 @@ [status-im.react-native.resources :as resources] [status-im.ui.components.animation :as animation] [status-im.ui.components.fast-image :as fast-image] - [status-im.utils.handlers :refer [>evt]] - [quo2.foundations.colors :as quo2.colors] - [quo2.foundations.typography :as typography] [status-im.ui.components.icons.icons :as icons] [status-im.ui.components.react :as react] [status-im.ui.screens.chat.bottom-sheets.context-drawer :as message-context-drawer] @@ -30,9 +27,14 @@ [status-im.ui.screens.chat.sheets :as sheets] [status-im.ui.screens.chat.styles.message.message :as style] [status-im.ui.screens.chat.utils :as chat.utils] + [status-im.ui.screens.chat.styles.photos :as photos.style] [status-im.ui.screens.communities.icon :as communities.icon] + [status-im.utils.handlers :refer [>evt]] [status-im.utils.config :as config] - [status-im.utils.security :as security]) + [status-im.utils.security :as security] + [quo2.foundations.typography :as typography] + [quo2.foundations.colors :as quo2.colors]) + (:require-macros [status-im.utils.views :refer [defview letsubs]])) (defn message-timestamp-anim @@ -93,9 +95,12 @@ timestamp-str]]))) (defview quoted-message - [_ reply] - [react/view {:style (style/quoted-message-container)} - [components.reply/reply-message reply false]]) + [_ reply pin?] + [react/view {:style (when-not pin? (style/quoted-message-container))} + [components.reply/reply-message reply false pin?]]) + +(defn system-text? [content-type] + (= content-type constants/content-type-system-text)) (defn render-inline [message-text content-type acc {:keys [type literal destination]}] (case type @@ -137,9 +142,9 @@ (conj acc [react/view {:style {:background-color quo2.colors/primary-50-opa-10 :border-radius 6 :padding-horizontal 3}} [react/text-class - {:style (merge {:color (if (= content-type constants/content-type-system-text) colors/black (:text-04 @colors/theme))} - (if (= content-type constants/content-type-system-text) typography/font-regular typography/font-medium)) - :on-press (when-not (= content-type constants/content-type-system-text) + {:style (merge {:color (if (system-text? content-type) colors/black quo2.colors/primary-50)} + (if (system-text? content-type) typography/font-regular typography/font-medium)) + :on-press (when-not (system-text? content-type) #(>evt [:chat.ui/show-profile literal]))} [mention-element literal]]]) "status-tag" @@ -224,28 +229,22 @@ (let [user-contact @(re-frame/subscribe [:multiaccount/contact]) contact-names @(re-frame/subscribe [:contacts/contact-two-names-by-identity pinned-by])] ;; We append empty spaces to the name as a workaround to make one-line and multi-line label components show correctly - (str " " (if (= pinned-by (user-contact :public-key)) (i18n/label :t/You) (first contact-names))))) + (str " " (if (= pinned-by (user-contact :public-key)) (i18n/label :t/You) (first contact-names))))) -(def pin-icon-width 9) +(def pin-icon-width 10) (def pin-icon-height 15) -(defn pinned-by-indicator [display-photo? pinned-by] - [react/view {:style (style/pin-indicator display-photo?) +(defn pin-icon [] + [icons/icon :main-icons/pin16 {:color (:text-04 @colors/theme) + :height pin-icon-height + :width pin-icon-width}]) + +(defn pinned-by-indicator [pinned-by] + [react/view {:style (style/pin-indicator) :accessibility-label :pinned-by} - [react/view {:style (style/pinned-by-text-icon-container)} - [react/view {:style (style/pin-icon-container)} - [icons/icon :main-icons/pin {:color colors/gray - :height pin-icon-height - :width pin-icon-width - :background-color :red}]] - [quo/text {:weight :regular - :size :small - :color :main - :style (style/pinned-by-text)} - (i18n/label :t/pinned-by)]] - [quo/text {:weight :medium - :size :small + [pin-icon] + [quo/text {:size :small :color :main :style (style/pin-author-text)} (pin-author-name pinned-by)]]) @@ -300,7 +299,7 @@ [{:keys [last-in-group? identicon from in-popover? timestamp-str - deleted-for-me?] + deleted-for-me? pinned] :as message} content {:keys [modal close-modal]}] (let [response-to (:response-to (:content message))] [react/view {:style (style/message-wrapper message) @@ -311,12 +310,12 @@ [react/view {:style (style/message-body) :pointer-events :box-none} [react/view (style/message-author-userpic) - (when (or (and (seq response-to) (:quoted-message message)) last-in-group?) + (when (or (and (seq response-to) (:quoted-message message)) last-in-group? pinned) [react/touchable-highlight {:on-press #(do (when modal (close-modal)) (re-frame/dispatch [:chat.ui/show-profile from]))} [photos/member-photo from identicon]])] [react/view {:style (style/message-author-wrapper)} - (when (or (and (seq response-to) (:quoted-message message)) last-in-group?) + (when (or (and (seq response-to) (:quoted-message message)) last-in-group? pinned) [react/view {:style {:flex-direction :row :align-items :center}} [react/touchable-opacity {:style style/message-author-touchable :disabled in-popover? @@ -492,6 +491,34 @@ [collapsible-text-message message on-long-press modal ref] reaction-picker]) +(defmethod ->message constants/content-type-pin [{:keys [from in-popover? timestamp-str] :as message} {:keys [modal close-modal]}] + (let [response-to (:response-to (:content message))] + [react/view {:style (merge {:flex-direction :row :margin-vertical 8} (style/message-wrapper message))} + [react/view {:style {:width photos.style/default-size + :height photos.style/default-size + :margin-horizontal 8 + :border-radius photos.style/default-size + :justify-content :center + :align-items :center + :background-color quo2.colors/primary-50-opa-10}} + [pin-icon]] + [react/view + [react/view {:style {:flex-direction :row :align-items :center}} + [react/touchable-opacity {:style style/message-author-touchable + :disabled in-popover? + :on-press #(do (when modal (close-modal)) + (re-frame/dispatch [:chat.ui/show-profile from]))} + [message-author-name from {:modal modal}]] + [react/text {:style {:font-size 13}} (str " " (i18n/label :pinned-a-message))] + [react/text + {:style (merge + {:padding-left 5 + :margin-top 2} + (style/message-timestamp-text)) + :accessibility-label :message-timestamp} + timestamp-str]] + [quoted-message response-to (:quoted-message message) true]]])) + (defmethod ->message constants/content-type-community [message] [community-content message]) @@ -710,7 +737,7 @@ [message-content-wrapper message [unknown-content-type message]]) -(defn chat-message [{:keys [display-photo? pinned pinned-by mentioned] :as message}] +(defn chat-message [{:keys [pinned pinned-by mentioned] :as message}] (let [reactions @(re-frame/subscribe [:chats/message-reactions (:message-id message) (:chat-id message)]) own-reactions (reduce (fn [acc {:keys [emoji-id own]}] (if own (conj acc emoji-id) acc)) @@ -737,11 +764,12 @@ (into #{} (js->clj own-reactions)) #(on-emoji-press %))}])) on-long-press (atom nil)] - [react/view {:style (merge (when mentioned {:background-color quo2.colors/primary-50-opa-5 :border-radius 16 :margin-bottom 4}) {:margin-horizontal 8})} + [react/view {:style (merge (when (or mentioned pinned) {:background-color quo2.colors/primary-50-opa-5 :border-radius 16 :margin-bottom 4}) {:margin-horizontal 8})} + (when pinned + [react/view {:style (style/pin-indicator-container)} + [pinned-by-indicator pinned-by]]) [->message message {:ref on-long-press :modal false :on-long-press on-open-drawer}] [reaction-row/message-reactions message reactions nil on-emoji-press on-long-press] ;; TODO: pass on-open-drawer function - (when pinned - [react/view {:style (style/pin-indicator-container)} - [pinned-by-indicator display-photo? pinned-by]])])) + ])) diff --git a/src/status_im/ui/screens/chat/message/styles.cljs b/src/status_im/ui/screens/chat/message/styles.cljs index 62d72b20c3..492fe1d94c 100644 --- a/src/status_im/ui/screens/chat/message/styles.cljs +++ b/src/status_im/ui/screens/chat/message/styles.cljs @@ -92,6 +92,7 @@ (defn reactions-row [timeline margin-top] {:flex-direction :row :padding-right 8 + :padding-bottom 8 :justify-content :flex-start :margin-top margin-top :flex-wrap :wrap diff --git a/src/status_im/ui/screens/chat/styles/message/message.cljs b/src/status_im/ui/screens/chat/styles/message/message.cljs index 13b778b56e..6eb6f3f892 100644 --- a/src/status_im/ui/screens/chat/styles/message/message.cljs +++ b/src/status_im/ui/screens/chat/styles/message/message.cljs @@ -3,7 +3,8 @@ [quo.design-system.colors :as colors] [status-im.ui.components.react :as react] [status-im.ui.screens.chat.styles.photos :as photos] - [quo2.foundations.colors :as quo2.colors])) + [quo2.foundations.colors :as quo2.colors] + [quo2.foundations.typography :as typography])) (defn style-message-text [] @@ -71,30 +72,15 @@ {:align-self :flex-start :padding-left 8}) -(defn pin-indicator [display-photo?] - (merge - {:flex-direction :row - :border-top-left-radius 4 - :border-top-right-radius 12 - :border-bottom-left-radius 12 - :border-bottom-right-radius 12 - :padding-left 8 - :padding-right 10 - :padding-vertical 5 - :background-color colors/gray-lighter - :justify-content :center - :max-width "80%" - :align-self :flex-start - :align-items :flex-start} - (when display-photo? - {:margin-left 44}))) +(defn pin-indicator [] + (merge {:flex-direction :row})) (defn pin-indicator-container [] - {:margin-top 2 + {:margin-top 8 + :margin-left 68 :justify-content :center :align-self :flex-start - :align-items :flex-start - :padding-left 8}) + :align-items :flex-start}) (defn pinned-by-text-icon-container [] {:flex-direction :row @@ -108,14 +94,9 @@ :margin-top 1}) (defn pin-author-text [] - {:margin-left 2 - :margin-right 12 - :padding-right 0 - :left 12 - :flex-direction :row - :flex-shrink 1 - :align-self :flex-start - :overflow :hidden}) + (merge typography/font-medium + {:color quo2.colors/primary-50 + :bottom 2})) (defn pinned-by-text [] {:margin-left 5}) @@ -171,8 +152,18 @@ :flex-direction :row-reverse}) (defn message-view - [{:keys [content-type]}] + [{:keys [content-type mentioned]}] (merge + {:border-radius 10} + (cond + (= content-type constants/content-type-system-text) nil + mentioned {:background-color colors/mentioned-background + :border-color colors/mentioned-border + :border-width 1} + (= content-type constants/content-type-audio) {:background-color colors/blue + :padding-horizontal 12 + :padding-top 6}) + (when (= content-type constants/content-type-emoji) {:flex-direction :row})))