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 {:style {:flex-direction :row}}
|
||||||
[rn/view {}
|
[rn/view {}
|
||||||
[icons/icon :tiny-icons/tiny-edit {:container-style {:margin-top 5}}]]
|
[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
|
[quo/text {:weight :medium
|
||||||
:number-of-lines 1}
|
:number-of-lines 1}
|
||||||
(i18n/label :t/editing-message)]]
|
(i18n/label :t/editing-message)]]
|
||||||
|
|
|
@ -9,14 +9,19 @@
|
||||||
[status-im.ethereum.stateofus :as stateofus]
|
[status-im.ethereum.stateofus :as stateofus]
|
||||||
[status-im.ui.screens.chat.components.style :as styles]
|
[status-im.ui.screens.chat.components.style :as styles]
|
||||||
[re-frame.core :as re-frame]
|
[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 "↪ ")
|
(def ^:private reply-symbol "↪ ")
|
||||||
|
|
||||||
(defn input-focus [text-input-ref]
|
(defn input-focus [text-input-ref]
|
||||||
(some-> ^js (quo.react/current-ref text-input-ref) .focus))
|
(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) "@")
|
(let [author (if (or (= (aget contact-name 0) "@")
|
||||||
;; in case of replies
|
;; in case of replies
|
||||||
(= (aget contact-name 1) "@"))
|
(= (aget contact-name 1) "@"))
|
||||||
|
@ -25,10 +30,24 @@
|
||||||
contact-name)]
|
contact-name)]
|
||||||
(i18n/label :replying-to {:author author})))
|
(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)
|
(or (and (= from current-public-key)
|
||||||
(str reply-symbol (i18n/label :t/You)))
|
(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]
|
(defn get-quoted-text-with-mentions [parsed-text]
|
||||||
(string/join
|
(string/join
|
||||||
|
@ -47,21 +66,62 @@
|
||||||
literal))
|
literal))
|
||||||
parsed-text)))
|
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])
|
(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])]
|
||||||
[rn/view {:style {:flex-direction :row}}
|
[rn/view {:style {:flex-direction :row}}
|
||||||
[rn/view {:style (styles/reply-content)}
|
[rn/view {:style (styles/reply-content-old)}
|
||||||
[quo/text {:weight :medium
|
[quo/text {:weight :medium
|
||||||
:number-of-lines 1
|
:number-of-lines 1
|
||||||
:style {:line-height 18}}
|
: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
|
[rn/view
|
||||||
[pressable/pressable {:on-press #(re-frame/dispatch [:chat.ui/cancel-message-reply])
|
[pressable/pressable {:on-press #(re-frame/dispatch [:chat.ui/cancel-message-reply])
|
||||||
:accessibility-label :cancel-message-reply}
|
:accessibility-label :cancel-message-reply}
|
||||||
[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?]
|
||||||
|
(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]
|
(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
|
||||||
|
@ -86,12 +146,27 @@
|
||||||
(when reply
|
(when reply
|
||||||
(js/setTimeout #(input-focus text-input-ref) 250))))
|
(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]
|
(defn reply-message-wrapper [reply]
|
||||||
[rn/view {:style {:padding-horizontal 15
|
[rn/view {:style {:padding-horizontal 15
|
||||||
:border-top-width 1
|
:border-top-width 1
|
||||||
:border-top-color (:ui-01 @quo.colors/theme)
|
:border-top-color (:ui-01 @quo.colors/theme)
|
||||||
:padding-vertical 8}}
|
: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]
|
(defn reply-message-auto-focus-wrapper [text-input-ref]
|
||||||
(let [had-reply (atom nil)]
|
(let [had-reply (atom nil)]
|
||||||
|
|
|
@ -87,11 +87,16 @@
|
||||||
(defn reply-container []
|
(defn reply-container []
|
||||||
{:flex-direction :row})
|
{:flex-direction :row})
|
||||||
|
|
||||||
(defn reply-content []
|
(defn reply-content-old []
|
||||||
{:padding-vertical 6
|
{:padding-vertical 6
|
||||||
:padding-horizontal 10
|
:padding-horizontal 10
|
||||||
:flex 1})
|
:flex 1})
|
||||||
|
|
||||||
|
(defn reply-content []
|
||||||
|
{:padding-horizontal 10
|
||||||
|
:flex 1
|
||||||
|
:flex-direction :row})
|
||||||
|
|
||||||
(defn contact-request-content []
|
(defn contact-request-content []
|
||||||
{:flex 1
|
{:flex 1
|
||||||
:flex-direction :row
|
:flex-direction :row
|
||||||
|
|
|
@ -87,27 +87,9 @@
|
||||||
timestamp-str]])))
|
timestamp-str]])))
|
||||||
|
|
||||||
(defview quoted-message
|
(defview quoted-message
|
||||||
[_ {:keys [from parsed-text image]} current-public-key public? pinned]
|
[_ reply]
|
||||||
(letsubs [contact-name [:contacts/contact-name-by-identity from]]
|
|
||||||
[react/view {:style (style/quoted-message-container)}
|
[react/view {:style (style/quoted-message-container)}
|
||||||
[react/view {:style style/quoted-message-author-container}
|
[components.reply/reply-message reply false]])
|
||||||
[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)])]))
|
|
||||||
|
|
||||||
(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
|
||||||
|
@ -312,18 +294,21 @@
|
||||||
identicon
|
identicon
|
||||||
from in-popover? timestamp-str]
|
from in-popover? timestamp-str]
|
||||||
:as message} content {:keys [modal close-modal]}]
|
:as message} content {:keys [modal close-modal]}]
|
||||||
|
(let [response-to (:response-to (:content message))]
|
||||||
[react/view {:style (style/message-wrapper message)
|
[react/view {:style (style/message-wrapper message)
|
||||||
:pointer-events :box-none
|
:pointer-events :box-none
|
||||||
:accessibility-label :chat-item}
|
: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)
|
[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 last-in-group?
|
(when (or (and (seq response-to) (:quoted-message message)) last-in-group?)
|
||||||
[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 last-in-group?
|
(when (or (and (seq response-to) (:quoted-message message)) last-in-group?)
|
||||||
[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?
|
||||||
|
@ -342,7 +327,7 @@
|
||||||
[link-preview/link-preview-wrapper (:links (:content message)) false false]]]
|
[link-preview/link-preview-wrapper (:links (:content message)) false false]]]
|
||||||
; delivery status
|
; delivery status
|
||||||
[react/view (style/delivery-status)
|
[react/view (style/delivery-status)
|
||||||
[message-delivery-status message]]])
|
[message-delivery-status message]]]))
|
||||||
|
|
||||||
(def image-max-width 260)
|
(def image-max-width 260)
|
||||||
(def image-max-height 192)
|
(def image-max-height 192)
|
||||||
|
@ -449,7 +434,7 @@
|
||||||
(defn collapsible-text-message [_ _]
|
(defn collapsible-text-message [_ _]
|
||||||
(let [collapsed? (reagent/atom false)
|
(let [collapsed? (reagent/atom false)
|
||||||
show-timestamp? (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
|
[react/touchable-highlight
|
||||||
(when-not modal
|
(when-not modal
|
||||||
{:on-press (fn [_]
|
{:on-press (fn [_]
|
||||||
|
@ -466,11 +451,8 @@
|
||||||
[message-timestamp message show-timestamp?]
|
[message-timestamp message show-timestamp?]
|
||||||
[react/view {:style (style/message-view message)}
|
[react/view {:style (style/message-view message)}
|
||||||
[react/view {:style (style/message-view-content)}
|
[react/view {:style (style/message-view-content)}
|
||||||
(let [response-to (:response-to content)]
|
|
||||||
[react/view
|
[react/view
|
||||||
(when (and (seq response-to) (:quoted-message message))
|
[render-parsed-text-with-message-status message (:parsed-text content)]]]]]])))
|
||||||
[quoted-message response-to (:quoted-message message) current-public-key public? pinned])
|
|
||||||
[render-parsed-text-with-message-status message (:parsed-text content)]])]]]])))
|
|
||||||
|
|
||||||
(defmethod ->message constants/content-type-text
|
(defmethod ->message constants/content-type-text
|
||||||
[message {:keys [on-long-press modal] :as reaction-picker}]
|
[message {:keys [on-long-press modal] :as reaction-picker}]
|
||||||
|
@ -494,10 +476,9 @@
|
||||||
|
|
||||||
(defmethod ->message constants/content-type-emoji []
|
(defmethod ->message constants/content-type-emoji []
|
||||||
(let [show-timestamp? (reagent/atom false)]
|
(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]
|
{:keys [on-long-press modal]
|
||||||
:as reaction-picker}]
|
:as reaction-picker}]
|
||||||
(let [response-to (:response-to content)]
|
|
||||||
[message-content-wrapper message
|
[message-content-wrapper message
|
||||||
[react/touchable-highlight (when-not modal
|
[react/touchable-highlight (when-not modal
|
||||||
{:disabled in-popover?
|
{:disabled in-popover?
|
||||||
|
@ -521,12 +502,10 @@
|
||||||
[react/view (style/message-view message)
|
[react/view (style/message-view message)
|
||||||
[react/view {:style (style/message-view-content)}
|
[react/view {:style (style/message-view-content)}
|
||||||
[react/view {:style (style/style-message-text)}
|
[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)}
|
[react/text {:style (style/emoji-message message)}
|
||||||
(:text content)]]
|
(:text content)]]
|
||||||
[message-status message]]]]]
|
[message-status message]]]]]
|
||||||
reaction-picker]))))
|
reaction-picker])))
|
||||||
|
|
||||||
(defmethod ->message constants/content-type-sticker
|
(defmethod ->message constants/content-type-sticker
|
||||||
[{:keys [content from outgoing in-popover?]
|
[{:keys [content from outgoing in-popover?]
|
||||||
|
|
|
@ -24,10 +24,15 @@
|
||||||
[memo-photo-rend photo-path size accessibility-label (colors/dark?)])
|
[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
|
;; We optionally pass identicon for perfomance reason, so it does not have to be calculated for each message
|
||||||
(defn member-photo [pub-key identicon]
|
(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])]
|
(let [path @(re-frame/subscribe [:chats/photo-path pub-key identicon])]
|
||||||
[photo path {:size style/default-size
|
[photo path {:size size
|
||||||
:accessibility-label :member-photo}]))
|
:accessibility-label :member-photo}])))
|
||||||
|
|
||||||
(defn account-photo [account]
|
(defn account-photo [account]
|
||||||
(let [path (multiaccounts/displayed-photo account)]
|
(let [path (multiaccounts/displayed-photo account)]
|
||||||
|
|
|
@ -210,11 +210,8 @@
|
||||||
|
|
||||||
(defn quoted-message-container []
|
(defn quoted-message-container []
|
||||||
{:margin-bottom 6
|
{:margin-bottom 6
|
||||||
:padding-bottom 6
|
:margin-top 5
|
||||||
:border-bottom-color colors/black-transparent
|
:padding-horizontal 15})
|
||||||
:border-bottom-width 2
|
|
||||||
:border-bottom-left-radius 2
|
|
||||||
:border-bottom-right-radius 2})
|
|
||||||
|
|
||||||
(def quoted-message-author-container
|
(def quoted-message-author-container
|
||||||
{:flex-direction :row
|
{:flex-direction :row
|
||||||
|
|
|
@ -588,7 +588,7 @@
|
||||||
:on-update-inset on-update}
|
:on-update-inset on-update}
|
||||||
[react/view
|
[react/view
|
||||||
[edit/edit-message-auto-focus-wrapper text-input-ref]
|
[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
|
;; We set the key so we can force a re-render as
|
||||||
;; it does not rely on ratom but just atoms
|
;; it does not rely on ratom but just atoms
|
||||||
^{:key (str @components/chat-input-key "chat-input")}
|
^{:key (str @components/chat-input-key "chat-input")}
|
||||||
|
|
Loading…
Reference in New Issue