Reply component in chat input & quoted message redesign
Signed-off-by: Brian Sztamfater <brian@status.im>
This commit is contained in:
parent
a08c7ff22e
commit
647dfc7e21
Binary file not shown.
After Width: | Height: | Size: 335 B |
Binary file not shown.
After Width: | Height: | Size: 468 B |
Binary file not shown.
After Width: | Height: | Size: 628 B |
Binary file not shown.
After Width: | Height: | Size: 897 B |
|
@ -16,7 +16,7 @@
|
|||
[rn/view {:style {:flex-direction :row}}
|
||||
[rn/view {}
|
||||
[icons/icon :tiny-icons/tiny-edit {:container-style {:margin-top 5}}]]
|
||||
[rn/view {:style (styles/reply-content)}
|
||||
[rn/view {:style (styles/reply-content-old)}
|
||||
[quo/text {:weight :medium
|
||||
:number-of-lines 1}
|
||||
(i18n/label :t/editing-message)]]
|
||||
|
|
|
@ -9,14 +9,19 @@
|
|||
[status-im.ethereum.stateofus :as stateofus]
|
||||
[status-im.ui.screens.chat.components.style :as styles]
|
||||
[re-frame.core :as re-frame]
|
||||
[clojure.string :as string]))
|
||||
[clojure.string :as string]
|
||||
[quo2.foundations.colors :as quo2.colors :refer [theme-colors]]
|
||||
[quo2.components.button :as quo2.button]
|
||||
[quo2.components.text :as quo2.text]
|
||||
[status-im.ui.screens.chat.photos :as photos]
|
||||
[status-im.constants :as constants]))
|
||||
|
||||
(def ^:private reply-symbol "↪ ")
|
||||
|
||||
(defn input-focus [text-input-ref]
|
||||
(some-> ^js (quo.react/current-ref text-input-ref) .focus))
|
||||
|
||||
(defn format-author [contact-name]
|
||||
(defn format-author-old [contact-name]
|
||||
(let [author (if (or (= (aget contact-name 0) "@")
|
||||
;; in case of replies
|
||||
(= (aget contact-name 1) "@"))
|
||||
|
@ -25,10 +30,24 @@
|
|||
contact-name)]
|
||||
(i18n/label :replying-to {:author author})))
|
||||
|
||||
(defn format-reply-author [from username current-public-key]
|
||||
(defn format-author [contact-name]
|
||||
(let [author (if (or (= (aget contact-name 0) "@")
|
||||
;; in case of replies
|
||||
(= (aget contact-name 1) "@"))
|
||||
(or (stateofus/username contact-name)
|
||||
(subs contact-name 0 81))
|
||||
contact-name)]
|
||||
author))
|
||||
|
||||
(defn format-reply-author-old [from username current-public-key]
|
||||
(or (and (= from current-public-key)
|
||||
(str reply-symbol (i18n/label :t/You)))
|
||||
(str reply-symbol (format-author username))))
|
||||
(str reply-symbol (format-author-old username))))
|
||||
|
||||
(defn format-reply-author [from username current-public-key]
|
||||
(or (and (= from current-public-key)
|
||||
(i18n/label :t/You))
|
||||
(format-author username)))
|
||||
|
||||
(defn get-quoted-text-with-mentions [parsed-text]
|
||||
(string/join
|
||||
|
@ -47,21 +66,62 @@
|
|||
literal))
|
||||
parsed-text)))
|
||||
|
||||
(defn reply-message [{:keys [from]}]
|
||||
(defn reply-message-old [{:keys [from]}]
|
||||
(let [contact-name @(re-frame/subscribe [:contacts/contact-name-by-identity from])
|
||||
current-public-key @(re-frame/subscribe [:multiaccount/public-key])]
|
||||
[rn/view {:style {:flex-direction :row}}
|
||||
[rn/view {:style (styles/reply-content)}
|
||||
[rn/view {:style (styles/reply-content-old)}
|
||||
[quo/text {:weight :medium
|
||||
:number-of-lines 1
|
||||
:style {:line-height 18}}
|
||||
(format-reply-author from contact-name current-public-key)]]
|
||||
(format-reply-author-old from contact-name current-public-key)]]
|
||||
[rn/view
|
||||
[pressable/pressable {:on-press #(re-frame/dispatch [:chat.ui/cancel-message-reply])
|
||||
:accessibility-label :cancel-message-reply}
|
||||
[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?]
|
||||
(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 :right 54 :top 3 :flex-direction :row :align-items :center}}
|
||||
[photos/member-photo from identicon 16]
|
||||
[quo2.text/text {:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:number-of-lines 1
|
||||
:style {:margin-left 4}}
|
||||
(format-reply-author from contact-name current-public-key)]
|
||||
[quo2.text/text {:number-of-lines 1
|
||||
:size :label
|
||||
:weight :regular
|
||||
:style (merge {:ellipsize-mode :tail
|
||||
:text-transform :none
|
||||
:margin-left 4
|
||||
:margin-top 2}
|
||||
(when (or (= constants/content-type-image content-type)
|
||||
(= constants/content-type-sticker content-type)
|
||||
(= constants/content-type-audio content-type))
|
||||
{:color (theme-colors quo2.colors/neutral-50 quo2.colors/neutral-40)}))}
|
||||
(case (or content-type contentType)
|
||||
constants/content-type-image "Image"
|
||||
constants/content-type-sticker "Sticker"
|
||||
constants/content-type-audio "Audio"
|
||||
(get-quoted-text-with-mentions (or parsed-text (:parsed-text content))))]]]
|
||||
(when in-chat-input?
|
||||
[quo2.button/button {:width 24
|
||||
:size 24
|
||||
:type :outline
|
||||
:accessibility-label :reply-cancel-button
|
||||
:on-press #(re-frame/dispatch [:chat.ui/cancel-message-reply])}
|
||||
[icons/icon :main-icons/close {:width 16
|
||||
:height 16
|
||||
:color (theme-colors quo2.colors/black quo2.colors/neutral-40)}]])]))
|
||||
|
||||
(defn send-image [images]
|
||||
[rn/view {:style (styles/reply-container-image)}
|
||||
[rn/scroll-view {:horizontal true
|
||||
|
@ -86,12 +146,27 @@
|
|||
(when reply
|
||||
(js/setTimeout #(input-focus text-input-ref) 250))))
|
||||
|
||||
(defn reply-message-wrapper-old [reply]
|
||||
[rn/view {:style {:padding-horizontal 15
|
||||
:border-top-width 1
|
||||
:border-top-color (:ui-01 @quo.colors/theme)
|
||||
:padding-vertical 8}}
|
||||
[reply-message-old reply]])
|
||||
|
||||
(defn reply-message-wrapper [reply]
|
||||
[rn/view {:style {:padding-horizontal 15
|
||||
:border-top-width 1
|
||||
:border-top-color (:ui-01 @quo.colors/theme)
|
||||
:padding-vertical 8}}
|
||||
[reply-message reply]])
|
||||
[reply-message reply true]])
|
||||
|
||||
(defn reply-message-auto-focus-wrapper-old [text-input-ref]
|
||||
(let [had-reply (atom nil)]
|
||||
(fn []
|
||||
(let [reply @(re-frame/subscribe [:chats/reply-message])]
|
||||
(focus-input-on-reply reply had-reply text-input-ref)
|
||||
(when reply
|
||||
[reply-message-wrapper-old reply])))))
|
||||
|
||||
(defn reply-message-auto-focus-wrapper [text-input-ref]
|
||||
(let [had-reply (atom nil)]
|
||||
|
|
|
@ -87,11 +87,16 @@
|
|||
(defn reply-container []
|
||||
{:flex-direction :row})
|
||||
|
||||
(defn reply-content []
|
||||
(defn reply-content-old []
|
||||
{:padding-vertical 6
|
||||
:padding-horizontal 10
|
||||
:flex 1})
|
||||
|
||||
(defn reply-content []
|
||||
{:padding-horizontal 10
|
||||
:flex 1
|
||||
:flex-direction :row})
|
||||
|
||||
(defn contact-request-content []
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
|
|
|
@ -87,27 +87,9 @@
|
|||
timestamp-str]])))
|
||||
|
||||
(defview quoted-message
|
||||
[_ {:keys [from parsed-text image]} current-public-key public? pinned]
|
||||
(letsubs [contact-name [:contacts/contact-name-by-identity from]]
|
||||
[react/view {:style (style/quoted-message-container)}
|
||||
[react/view {:style style/quoted-message-author-container}
|
||||
[chat.utils/format-reply-author
|
||||
from
|
||||
contact-name
|
||||
current-public-key
|
||||
(partial style/quoted-message-author (not pinned))
|
||||
false]]
|
||||
(if (and image
|
||||
;; Disabling images for public-chats
|
||||
(not public?))
|
||||
[fast-image/fast-image {:style {:width 56
|
||||
:height 56
|
||||
:background-color :black
|
||||
:border-radius 4}
|
||||
:source {:uri image}}]
|
||||
[react/text {:style (style/quoted-message-text)
|
||||
:number-of-lines 5}
|
||||
(components.reply/get-quoted-text-with-mentions parsed-text)])]))
|
||||
[_ reply]
|
||||
[react/view {:style (style/quoted-message-container)}
|
||||
[components.reply/reply-message reply false]])
|
||||
|
||||
(defn render-inline [message-text content-type acc {:keys [type literal destination]}]
|
||||
(case type
|
||||
|
@ -312,37 +294,40 @@
|
|||
identicon
|
||||
from in-popover? timestamp-str]
|
||||
:as message} content {:keys [modal close-modal]}]
|
||||
[react/view {:style (style/message-wrapper message)
|
||||
:pointer-events :box-none
|
||||
:accessibility-label :chat-item}
|
||||
[react/view {:style (style/message-body)
|
||||
:pointer-events :box-none}
|
||||
[react/view (style/message-author-userpic)
|
||||
(when last-in-group?
|
||||
[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 last-in-group?
|
||||
[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 (merge
|
||||
{:padding-left 5
|
||||
:margin-top 2}
|
||||
(style/message-timestamp-text))
|
||||
:accessibility-label :message-timestamp}
|
||||
timestamp-str]])
|
||||
(let [response-to (:response-to (:content message))]
|
||||
[react/view {:style (style/message-wrapper message)
|
||||
:pointer-events :box-none
|
||||
:accessibility-label :chat-item}
|
||||
(when (and (seq response-to) (:quoted-message message))
|
||||
[quoted-message response-to (:quoted-message message)])
|
||||
[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?)
|
||||
[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?)
|
||||
[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 (merge
|
||||
{:padding-left 5
|
||||
:margin-top 2}
|
||||
(style/message-timestamp-text))
|
||||
:accessibility-label :message-timestamp}
|
||||
timestamp-str]])
|
||||
;;MESSAGE CONTENT
|
||||
content
|
||||
[link-preview/link-preview-wrapper (:links (:content message)) false false]]]
|
||||
content
|
||||
[link-preview/link-preview-wrapper (:links (:content message)) false false]]]
|
||||
; delivery status
|
||||
[react/view (style/delivery-status)
|
||||
[message-delivery-status message]]])
|
||||
[react/view (style/delivery-status)
|
||||
[message-delivery-status message]]]))
|
||||
|
||||
(def image-max-width 260)
|
||||
(def image-max-height 192)
|
||||
|
@ -449,7 +434,7 @@
|
|||
(defn collapsible-text-message [_ _]
|
||||
(let [collapsed? (reagent/atom false)
|
||||
show-timestamp? (reagent/atom false)]
|
||||
(fn [{:keys [content current-public-key public? pinned in-popover?] :as message} on-long-press modal]
|
||||
(fn [{:keys [content in-popover?] :as message} on-long-press modal]
|
||||
[react/touchable-highlight
|
||||
(when-not modal
|
||||
{:on-press (fn [_]
|
||||
|
@ -466,11 +451,8 @@
|
|||
[message-timestamp message show-timestamp?]
|
||||
[react/view {:style (style/message-view message)}
|
||||
[react/view {:style (style/message-view-content)}
|
||||
(let [response-to (:response-to content)]
|
||||
[react/view
|
||||
(when (and (seq response-to) (:quoted-message message))
|
||||
[quoted-message response-to (:quoted-message message) current-public-key public? pinned])
|
||||
[render-parsed-text-with-message-status message (:parsed-text content)]])]]]])))
|
||||
[react/view
|
||||
[render-parsed-text-with-message-status message (:parsed-text content)]]]]]])))
|
||||
|
||||
(defmethod ->message constants/content-type-text
|
||||
[message {:keys [on-long-press modal] :as reaction-picker}]
|
||||
|
@ -494,39 +476,36 @@
|
|||
|
||||
(defmethod ->message constants/content-type-emoji []
|
||||
(let [show-timestamp? (reagent/atom false)]
|
||||
(fn [{:keys [content current-public-key outgoing public? pinned in-popover? message-pin-enabled] :as message}
|
||||
(fn [{:keys [content pinned in-popover? message-pin-enabled] :as message}
|
||||
{:keys [on-long-press modal]
|
||||
:as reaction-picker}]
|
||||
(let [response-to (:response-to content)]
|
||||
[message-content-wrapper message
|
||||
[react/touchable-highlight (when-not modal
|
||||
{:disabled in-popover?
|
||||
:on-press (fn []
|
||||
(react/dismiss-keyboard!)
|
||||
(reset! show-timestamp? true))
|
||||
:delay-long-press 100
|
||||
:on-long-press (fn []
|
||||
(on-long-press
|
||||
(concat
|
||||
[{:on-press #(re-frame/dispatch [:chat.ui/reply-to-message message])
|
||||
:id :reply
|
||||
:label (i18n/label :t/message-reply)}
|
||||
{:on-press #(react/copy-to-clipboard (get content :text))
|
||||
:id :copy
|
||||
:label (i18n/label :t/sharing-copy-to-clipboard)}]
|
||||
(when message-pin-enabled [{:on-press #(pin-message message)
|
||||
:label (if pinned (i18n/label :t/unpin) (i18n/label :t/pin))}]))))})
|
||||
[react/view style/message-view-wrapper
|
||||
[message-timestamp message show-timestamp?]
|
||||
[react/view (style/message-view message)
|
||||
[react/view {:style (style/message-view-content)}
|
||||
[react/view {:style (style/style-message-text)}
|
||||
(when (and (seq response-to) (:quoted-message message))
|
||||
[quoted-message response-to (:quoted-message message) outgoing current-public-key public? pinned])
|
||||
[react/text {:style (style/emoji-message message)}
|
||||
(:text content)]]
|
||||
[message-status message]]]]]
|
||||
reaction-picker]))))
|
||||
[message-content-wrapper message
|
||||
[react/touchable-highlight (when-not modal
|
||||
{:disabled in-popover?
|
||||
:on-press (fn []
|
||||
(react/dismiss-keyboard!)
|
||||
(reset! show-timestamp? true))
|
||||
:delay-long-press 100
|
||||
:on-long-press (fn []
|
||||
(on-long-press
|
||||
(concat
|
||||
[{:on-press #(re-frame/dispatch [:chat.ui/reply-to-message message])
|
||||
:id :reply
|
||||
:label (i18n/label :t/message-reply)}
|
||||
{:on-press #(react/copy-to-clipboard (get content :text))
|
||||
:id :copy
|
||||
:label (i18n/label :t/sharing-copy-to-clipboard)}]
|
||||
(when message-pin-enabled [{:on-press #(pin-message message)
|
||||
:label (if pinned (i18n/label :t/unpin) (i18n/label :t/pin))}]))))})
|
||||
[react/view style/message-view-wrapper
|
||||
[message-timestamp message show-timestamp?]
|
||||
[react/view (style/message-view message)
|
||||
[react/view {:style (style/message-view-content)}
|
||||
[react/view {:style (style/style-message-text)}
|
||||
[react/text {:style (style/emoji-message message)}
|
||||
(:text content)]]
|
||||
[message-status message]]]]]
|
||||
reaction-picker])))
|
||||
|
||||
(defmethod ->message constants/content-type-sticker
|
||||
[{:keys [content from outgoing in-popover?]
|
||||
|
|
|
@ -24,10 +24,15 @@
|
|||
[memo-photo-rend photo-path size accessibility-label (colors/dark?)])
|
||||
|
||||
;; We optionally pass identicon for perfomance reason, so it does not have to be calculated for each message
|
||||
(defn member-photo [pub-key identicon]
|
||||
(let [path @(re-frame/subscribe [:chats/photo-path pub-key identicon])]
|
||||
[photo path {:size style/default-size
|
||||
:accessibility-label :member-photo}]))
|
||||
(defn member-photo
|
||||
([pub-key]
|
||||
(member-photo pub-key nil))
|
||||
([pub-key identicon]
|
||||
(member-photo pub-key identicon style/default-size))
|
||||
([pub-key identicon size]
|
||||
(let [path @(re-frame/subscribe [:chats/photo-path pub-key identicon])]
|
||||
[photo path {:size size
|
||||
:accessibility-label :member-photo}])))
|
||||
|
||||
(defn account-photo [account]
|
||||
(let [path (multiaccounts/displayed-photo account)]
|
||||
|
|
|
@ -209,12 +209,9 @@
|
|||
:text-align-vertical :center})
|
||||
|
||||
(defn quoted-message-container []
|
||||
{:margin-bottom 6
|
||||
:padding-bottom 6
|
||||
:border-bottom-color colors/black-transparent
|
||||
:border-bottom-width 2
|
||||
:border-bottom-left-radius 2
|
||||
:border-bottom-right-radius 2})
|
||||
{:margin-bottom 6
|
||||
:margin-top 5
|
||||
:padding-horizontal 15})
|
||||
|
||||
(def quoted-message-author-container
|
||||
{:flex-direction :row
|
||||
|
|
|
@ -588,7 +588,7 @@
|
|||
:on-update-inset on-update}
|
||||
[react/view
|
||||
[edit/edit-message-auto-focus-wrapper text-input-ref]
|
||||
[reply/reply-message-auto-focus-wrapper text-input-ref]
|
||||
[reply/reply-message-auto-focus-wrapper-old text-input-ref]
|
||||
;; We set the key so we can force a re-render as
|
||||
;; it does not rely on ratom but just atoms
|
||||
^{:key (str @components/chat-input-key "chat-input")}
|
||||
|
|
Loading…
Reference in New Issue