feat: pinned messages new ui (#14147)

* feat: pinned messages new ui
This commit is contained in:
Omar Basem 2022-10-13 22:27:56 +04:00 committed by GitHub
parent 5492d502fc
commit af3ba74e30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 114 additions and 77 deletions

View File

@ -4,6 +4,7 @@
[status-im.data-store.pin-messages :as data-store.pin-messages] [status-im.data-store.pin-messages :as data-store.pin-messages]
[status-im.utils.fx :as fx] [status-im.utils.fx :as fx]
[taoensso.timbre :as log] [taoensso.timbre :as log]
[status-im.transport.message.protocol :as protocol]
[re-frame.core :as re-frame])) [re-frame.core :as re-frame]))
(fx/defn handle-failed-loading-pin-messages (fx/defn handle-failed-loading-pin-messages
@ -73,7 +74,8 @@
{:events [::send-pin-message]} {:events [::send-pin-message]}
[{:keys [db] :as cofx} {:keys [chat-id message-id pinned] :as 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]) (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 (fx/merge cofx
{:db (cond-> db {:db (cond-> db
pinned pinned
@ -86,7 +88,12 @@
(update-in [:pin-messages chat-id] dissoc message-id)))} (update-in [:pin-messages chat-id] dissoc message-id)))}
(data-store.pin-messages/send-pin-message {:chat-id (pin-message :chat-id) (data-store.pin-messages/send-pin-message {:chat-id (pin-message :chat-id)
:message_id (pin-message :message-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 (fx/defn load-pin-messages
{:events [::load-pin-messages]} {:events [::load-pin-messages]}

View File

@ -14,6 +14,7 @@
(def ^:const content-type-community 9) (def ^:const content-type-community 9)
(def ^:const content-type-gap 10) (def ^:const content-type-gap 10)
(def ^:const content-type-contact-request 11) ;; TODO: temp, will be removed (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-none 0)
(def ^:const contact-request-state-mutual 1) (def ^:const contact-request-state-mutual 1)

View File

@ -31,7 +31,7 @@
(defn edit-message [] (defn edit-message []
[rn/view {:style {:flex-direction :row :height 24}} [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) [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}}] :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}} [rn/view {:style {:position :absolute :left 36 :right 54 :top 3 :flex-direction :row :align-items :center}}

View File

@ -81,15 +81,16 @@
[icons/icon :main-icons/close-circle {:container-style (styles/close-button) [icons/icon :main-icons/close-circle {:container-style (styles/close-button)
:color (:icon-02 @quo.colors/theme)}]]]])) :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]) (let [contact-name @(re-frame/subscribe [:contacts/contact-name-by-identity from])
current-public-key @(re-frame/subscribe [:multiaccount/public-key]) current-public-key @(re-frame/subscribe [:multiaccount/public-key])
content-type (or content-type contentType)] content-type (or content-type contentType)]
[rn/view {:style {:flex-direction :row :height 24}} [rn/view {:style {:flex-direction :row :height (when-not pin? 24)}}
[rn/view {:style (styles/reply-content)} [rn/view {:style (styles/reply-content pin?)}
[icons/icon :main-icons/connector {:color (theme-colors quo2.colors/neutral-40 quo2.colors/neutral-60) (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}}] :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 (styles/quoted-message pin?)}
[photos/member-photo from identicon 16] [photos/member-photo from identicon 16]
[quo2.text/text {:weight :semi-bold [quo2.text/text {:weight :semi-bold
:size :paragraph-2 :size :paragraph-2
@ -125,7 +126,7 @@
(defn send-image [images] (defn send-image [images]
[rn/view {:style (styles/reply-container-image)} [rn/view {:style (styles/reply-container-image)}
[rn/scroll-view {:horizontal true [rn/scroll-view {:horizontal true
:style (styles/reply-content)} :style (styles/reply-content false)}
(for [{:keys [uri]} (vals images)] (for [{:keys [uri]} (vals images)]
^{:key uri} ^{:key uri}
[rn/image {:source {:uri uri} [rn/image {:source {:uri uri}

View File

@ -108,11 +108,19 @@
:padding-horizontal 10 :padding-horizontal 10
:flex 1}) :flex 1})
(defn reply-content [] (defn reply-content [pin?]
{:padding-horizontal 10 {:padding-horizontal (when-not pin? 10)
:flex 1 :flex 1
:flex-direction :row}) :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 [] (defn contact-request-content []
{:flex 1 {:flex 1
:flex-direction :row :flex-direction :row

View File

@ -12,9 +12,6 @@
[status-im.react-native.resources :as resources] [status-im.react-native.resources :as resources]
[status-im.ui.components.animation :as animation] [status-im.ui.components.animation :as animation]
[status-im.ui.components.fast-image :as fast-image] [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.icons.icons :as icons]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.ui.screens.chat.bottom-sheets.context-drawer :as message-context-drawer] [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.sheets :as sheets]
[status-im.ui.screens.chat.styles.message.message :as style] [status-im.ui.screens.chat.styles.message.message :as style]
[status-im.ui.screens.chat.utils :as chat.utils] [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.ui.screens.communities.icon :as communities.icon]
[status-im.utils.handlers :refer [>evt]]
[status-im.utils.config :as config] [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]])) (:require-macros [status-im.utils.views :refer [defview letsubs]]))
(defn message-timestamp-anim (defn message-timestamp-anim
@ -93,9 +95,12 @@
timestamp-str]]))) timestamp-str]])))
(defview quoted-message (defview quoted-message
[_ reply] [_ reply pin?]
[react/view {:style (style/quoted-message-container)} [react/view {:style (when-not pin? (style/quoted-message-container))}
[components.reply/reply-message reply false]]) [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]}] (defn render-inline [message-text content-type acc {:keys [type literal destination]}]
(case type (case type
@ -137,9 +142,9 @@
(conj acc (conj acc
[react/view {:style {:background-color quo2.colors/primary-50-opa-10 :border-radius 6 :padding-horizontal 3}} [react/view {:style {:background-color quo2.colors/primary-50-opa-10 :border-radius 6 :padding-horizontal 3}}
[react/text-class [react/text-class
{:style (merge {:color (if (= content-type constants/content-type-system-text) colors/black (:text-04 @colors/theme))} {:style (merge {:color (if (system-text? content-type) colors/black quo2.colors/primary-50)}
(if (= content-type constants/content-type-system-text) typography/font-regular typography/font-medium)) (if (system-text? content-type) typography/font-regular typography/font-medium))
:on-press (when-not (= content-type constants/content-type-system-text) :on-press (when-not (system-text? content-type)
#(>evt [:chat.ui/show-profile literal]))} #(>evt [:chat.ui/show-profile literal]))}
[mention-element literal]]]) [mention-element literal]]])
"status-tag" "status-tag"
@ -224,28 +229,22 @@
(let [user-contact @(re-frame/subscribe [:multiaccount/contact]) (let [user-contact @(re-frame/subscribe [:multiaccount/contact])
contact-names @(re-frame/subscribe [:contacts/contact-two-names-by-identity pinned-by])] 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 ;; 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) (def pin-icon-height 15)
(defn pinned-by-indicator [display-photo? pinned-by] (defn pin-icon []
[react/view {:style (style/pin-indicator display-photo?) [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} :accessibility-label :pinned-by}
[react/view {:style (style/pinned-by-text-icon-container)} [pin-icon]
[react/view {:style (style/pin-icon-container)} [quo/text {:size :small
[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
:color :main :color :main
:style (style/pin-author-text)} :style (style/pin-author-text)}
(pin-author-name pinned-by)]]) (pin-author-name pinned-by)]])
@ -300,7 +299,7 @@
[{:keys [last-in-group? [{:keys [last-in-group?
identicon identicon
from in-popover? timestamp-str from in-popover? timestamp-str
deleted-for-me?] deleted-for-me? pinned]
:as message} content {:keys [modal close-modal]}] :as message} content {:keys [modal close-modal]}]
(let [response-to (:response-to (:content message))] (let [response-to (:response-to (:content message))]
[react/view {:style (style/message-wrapper message) [react/view {:style (style/message-wrapper message)
@ -311,12 +310,12 @@
[react/view {:style (style/message-body) [react/view {:style (style/message-body)
:pointer-events :box-none} :pointer-events :box-none}
[react/view (style/message-author-userpic) [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)) [react/touchable-highlight {:on-press #(do (when modal (close-modal))
(re-frame/dispatch [:chat.ui/show-profile from]))} (re-frame/dispatch [:chat.ui/show-profile from]))}
[photos/member-photo from identicon]])] [photos/member-photo from identicon]])]
[react/view {:style (style/message-author-wrapper)} [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/view {:style {:flex-direction :row :align-items :center}}
[react/touchable-opacity {:style style/message-author-touchable [react/touchable-opacity {:style style/message-author-touchable
:disabled in-popover? :disabled in-popover?
@ -492,6 +491,34 @@
[collapsible-text-message message on-long-press modal ref] [collapsible-text-message message on-long-press modal ref]
reaction-picker]) 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 (defmethod ->message constants/content-type-community
[message] [message]
[community-content message]) [community-content message])
@ -710,7 +737,7 @@
[message-content-wrapper message [message-content-wrapper message
[unknown-content-type 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)]) (let [reactions @(re-frame/subscribe [:chats/message-reactions (:message-id message) (:chat-id message)])
own-reactions (reduce (fn [acc {:keys [emoji-id own]}] own-reactions (reduce (fn [acc {:keys [emoji-id own]}]
(if own (conj acc emoji-id) acc)) (if own (conj acc emoji-id) acc))
@ -737,11 +764,12 @@
(into #{} (js->clj own-reactions)) (into #{} (js->clj own-reactions))
#(on-emoji-press %))}])) #(on-emoji-press %))}]))
on-long-press (atom nil)] 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 [->message message {:ref on-long-press
:modal false :modal false
:on-long-press on-open-drawer}] :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 [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]])]))

View File

@ -92,6 +92,7 @@
(defn reactions-row [timeline margin-top] (defn reactions-row [timeline margin-top]
{:flex-direction :row {:flex-direction :row
:padding-right 8 :padding-right 8
:padding-bottom 8
:justify-content :flex-start :justify-content :flex-start
:margin-top margin-top :margin-top margin-top
:flex-wrap :wrap :flex-wrap :wrap

View File

@ -3,7 +3,8 @@
[quo.design-system.colors :as colors] [quo.design-system.colors :as colors]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.ui.screens.chat.styles.photos :as photos] [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 (defn style-message-text
[] []
@ -71,30 +72,15 @@
{:align-self :flex-start {:align-self :flex-start
:padding-left 8}) :padding-left 8})
(defn pin-indicator [display-photo?] (defn pin-indicator []
(merge (merge {:flex-direction :row}))
{: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-container [] (defn pin-indicator-container []
{:margin-top 2 {:margin-top 8
:margin-left 68
:justify-content :center :justify-content :center
:align-self :flex-start :align-self :flex-start
:align-items :flex-start :align-items :flex-start})
:padding-left 8})
(defn pinned-by-text-icon-container [] (defn pinned-by-text-icon-container []
{:flex-direction :row {:flex-direction :row
@ -108,14 +94,9 @@
:margin-top 1}) :margin-top 1})
(defn pin-author-text [] (defn pin-author-text []
{:margin-left 2 (merge typography/font-medium
:margin-right 12 {:color quo2.colors/primary-50
:padding-right 0 :bottom 2}))
:left 12
:flex-direction :row
:flex-shrink 1
:align-self :flex-start
:overflow :hidden})
(defn pinned-by-text [] (defn pinned-by-text []
{:margin-left 5}) {:margin-left 5})
@ -171,8 +152,18 @@
:flex-direction :row-reverse}) :flex-direction :row-reverse})
(defn message-view (defn message-view
[{:keys [content-type]}] [{:keys [content-type mentioned]}]
(merge (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) (when (= content-type constants/content-type-emoji)
{:flex-direction :row}))) {:flex-direction :row})))