mirror of
https://github.com/status-im/status-mobile.git
synced 2025-01-26 16:39:24 +00:00
Show timestamp inside bubble for text messages
Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
This commit is contained in:
parent
3b4d7a6a62
commit
4aaecf792b
@ -1,10 +1,10 @@
|
||||
(ns status-im.chat.styles.message.message
|
||||
(:require-macros [status-im.utils.styles :refer [defstyle defnstyle]])
|
||||
(:require [status-im.ui.components.styles :as styles]
|
||||
[status-im.chat.styles.photos :as photos]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.constants :as constants]))
|
||||
|
||||
(def photo-size 36)
|
||||
|
||||
(defstyle style-message-text
|
||||
{:font-size 15
|
||||
@ -48,13 +48,18 @@
|
||||
:align-self align
|
||||
:align-items align})))
|
||||
|
||||
(def message-timestamp
|
||||
{:margin-left 5
|
||||
:margin-right 5
|
||||
:margin-bottom -2
|
||||
:color colors/gray
|
||||
:opacity 0.5
|
||||
:align-self :flex-end})
|
||||
(defn message-timestamp [justify-timestamp?]
|
||||
(merge {:color colors/gray
|
||||
:font-size 10
|
||||
:align-self :flex-end
|
||||
:opacity 0.5}
|
||||
(when justify-timestamp? {:position :absolute
|
||||
:bottom 10
|
||||
:right 12})))
|
||||
|
||||
(def message-timestamp-placeholder
|
||||
(assoc (message-timestamp false)
|
||||
:color styles/color-white))
|
||||
|
||||
(def selected-message
|
||||
{:margin-top 18
|
||||
@ -83,14 +88,9 @@
|
||||
:padding-right 22})
|
||||
|
||||
(def message-author
|
||||
{:width photo-size
|
||||
{:width photos/photo-size
|
||||
:align-self :flex-end})
|
||||
|
||||
(def photo
|
||||
{:border-radius (/ photo-size 2)
|
||||
:width photo-size
|
||||
:height photo-size})
|
||||
|
||||
(def delivery-view
|
||||
{:flex-direction :row
|
||||
:margin-top 2
|
||||
@ -136,8 +136,10 @@
|
||||
|
||||
(defn message-view
|
||||
[{:keys [content-type outgoing group-chat selected]}]
|
||||
(merge {:padding 12
|
||||
:border-radius 8}
|
||||
(merge {:padding-top 6
|
||||
:padding-horizontal 12
|
||||
:padding-bottom 8
|
||||
:border-radius 8}
|
||||
(when-not (= content-type constants/content-type-emoji)
|
||||
{:background-color styles/color-white})
|
||||
(when (= content-type constants/content-type-command)
|
||||
|
8
src/status_im/chat/styles/photos.cljs
Normal file
8
src/status_im/chat/styles/photos.cljs
Normal file
@ -0,0 +1,8 @@
|
||||
(ns status-im.chat.styles.photos)
|
||||
|
||||
(def photo-size 36)
|
||||
|
||||
(def photo
|
||||
{:border-radius (/ photo-size 2)
|
||||
:width photo-size
|
||||
:height photo-size})
|
@ -12,7 +12,8 @@
|
||||
:background-color component.styles/chat-background})
|
||||
|
||||
(def toolbar-container
|
||||
{})
|
||||
{:flex 1
|
||||
:flex-direction :row})
|
||||
|
||||
(def messages-container
|
||||
{:flex 1
|
||||
|
@ -13,6 +13,7 @@
|
||||
[status-im.chat.styles.message.message :as style]
|
||||
[status-im.chat.styles.message.command-pill :as pill-style]
|
||||
[status-im.chat.views.message.request-message :as request-message]
|
||||
[status-im.chat.views.photos :as photos]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
|
||||
[status-im.utils.core :as utils]
|
||||
@ -22,8 +23,7 @@
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[clojure.string :as string]
|
||||
[status-im.chat.events.console :as console]
|
||||
[status-im.react-native.resources :as resources]))
|
||||
[status-im.chat.events.console :as console]))
|
||||
|
||||
(def window-width (:width (react/get-dimensions "window")))
|
||||
|
||||
@ -81,10 +81,14 @@
|
||||
:font :default}
|
||||
(or preview (str params))])])))
|
||||
|
||||
(defview message-timestamp [t justify-timestamp?]
|
||||
[react/text {:style (style/message-timestamp justify-timestamp?)} t])
|
||||
|
||||
(defn message-view
|
||||
[{:keys [group-chat] :as message} content]
|
||||
[{:keys [timestamp-str] :as message} content {:keys [justify-timestamp?]}]
|
||||
[react/view (style/message-view message)
|
||||
content])
|
||||
content
|
||||
[message-timestamp timestamp-str justify-timestamp?]])
|
||||
|
||||
(def replacements
|
||||
{"\\*[^*]+\\*" {:font-weight :bold}
|
||||
@ -162,18 +166,22 @@
|
||||
(autolink string event-on-press)))
|
||||
text-seq))))
|
||||
|
||||
; We can't use CSS as nested Text element don't accept margins nor padding
|
||||
; so we pad the invisible placeholder with some spaces to avoid having too
|
||||
; close to the text.
|
||||
(defn timestamp-with-padding [t]
|
||||
(str " " t))
|
||||
|
||||
(def cached-parse-text (memoize parse-text))
|
||||
|
||||
(defn text-message
|
||||
[{:keys [content] :as message}]
|
||||
[{:keys [content timestamp-str] :as message}]
|
||||
[message-view message
|
||||
(let [parsed-text (cached-parse-text content :browse-link-from-message)]
|
||||
[react/text {:style (style/text-message message)} parsed-text])])
|
||||
|
||||
(defn placeholder-message
|
||||
[{:keys [content] :as message}]
|
||||
[message-view message
|
||||
[react/text {:style (style/text-message message)} content]])
|
||||
[react/text {:style (style/text-message message)}
|
||||
parsed-text
|
||||
[react/text {:style style/message-timestamp-placeholder} (timestamp-with-padding timestamp-str)]])
|
||||
{:justify-timestamp? true}])
|
||||
|
||||
(defn emoji-message
|
||||
[{:keys [content] :as message}]
|
||||
@ -204,10 +212,6 @@
|
||||
[wrapper message
|
||||
[message-view message [message-content-command message]]])
|
||||
|
||||
(defmethod message-content constants/content-type-placeholder
|
||||
[wrapper message]
|
||||
[wrapper message [placeholder-message message]])
|
||||
|
||||
(defmethod message-content constants/content-type-emoji
|
||||
[wrapper message]
|
||||
[wrapper message [emoji-message message]])
|
||||
@ -293,29 +297,6 @@
|
||||
(when outgoing
|
||||
[text-status status]))))))
|
||||
|
||||
(defn- photo [from photo-path]
|
||||
[react/view
|
||||
[react/image {:source (if (and (not (string/blank? photo-path))
|
||||
(string/starts-with? photo-path "contacts://"))
|
||||
(->> (string/replace photo-path #"contacts://" "")
|
||||
(keyword)
|
||||
(get resources/contacts))
|
||||
{:uri photo-path})
|
||||
:style style/photo}]])
|
||||
|
||||
(defview member-photo [from]
|
||||
(letsubs [photo-path [:get-photo-path from]]
|
||||
(photo from (if (string/blank? photo-path)
|
||||
(identicon/identicon from)
|
||||
photo-path))))
|
||||
|
||||
(defview my-photo [from]
|
||||
(letsubs [{:keys [photo-path]} [:get-current-account]]
|
||||
(photo from photo-path)))
|
||||
|
||||
(defview message-timestamp [t]
|
||||
[react/text {:style style/message-timestamp} t])
|
||||
|
||||
(defview message-author-name [from message-username]
|
||||
(letsubs [username [:get-contact-name-by-identity from]]
|
||||
[react/text {:style style/message-author-name} (or username
|
||||
@ -323,21 +304,21 @@
|
||||
(gfycat/generate-gfy from))])) ; TODO: We defensively generate the name for now, to be revisited when new protocol is defined
|
||||
|
||||
(defn message-body
|
||||
[{:keys [timestamp-str last-in-group? first-in-group? from outgoing username] :as message} content]
|
||||
[{:keys [last-in-group? first-in-group? group-chat from outgoing username] :as message} content]
|
||||
[react/view (style/group-message-wrapper message)
|
||||
[react/view (style/message-body message)
|
||||
(when (not outgoing)
|
||||
(when (and (not outgoing)
|
||||
group-chat)
|
||||
[react/view style/message-author
|
||||
(when last-in-group?
|
||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:show-profile from])}
|
||||
[react/view
|
||||
[member-photo from]]])])
|
||||
[photos/member-photo from]]])])
|
||||
[react/view (style/group-message-view outgoing)
|
||||
(when first-in-group?
|
||||
[message-author-name from username])
|
||||
[react/view {:style (style/timestamp-content-wrapper message)}
|
||||
content
|
||||
[message-timestamp timestamp-str]]]]
|
||||
content]]]
|
||||
[react/view style/delivery-status
|
||||
[message-delivery-status message]]])
|
||||
|
||||
|
23
src/status_im/chat/views/photos.cljs
Normal file
23
src/status_im/chat/views/photos.cljs
Normal file
@ -0,0 +1,23 @@
|
||||
(ns status-im.chat.views.photos
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [status-im.ui.components.react :as react]
|
||||
[status-im.chat.styles.photos :as style]
|
||||
[status-im.utils.identicon :as identicon]
|
||||
[clojure.string :as string]
|
||||
[status-im.react-native.resources :as resources]))
|
||||
|
||||
(defn- photo [from photo-path]
|
||||
[react/view
|
||||
[react/image {:source (if (and (not (string/blank? photo-path))
|
||||
(string/starts-with? photo-path "contacts://"))
|
||||
(->> (string/replace photo-path #"contacts://" "")
|
||||
(keyword)
|
||||
(get resources/contacts))
|
||||
{:uri photo-path})
|
||||
:style style/photo}]])
|
||||
|
||||
(defview member-photo [from]
|
||||
(letsubs [photo-path [:get-photo-path from]]
|
||||
(photo from (if (string/blank? photo-path)
|
||||
(identicon/identicon from)
|
||||
photo-path))))
|
@ -5,6 +5,7 @@
|
||||
[status-im.ui.components.react :as react]
|
||||
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.chat.views.photos :as photos]
|
||||
[status-im.chat.styles.screen :as st]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.utils.platform :refer [platform-specific]]
|
||||
@ -60,17 +61,19 @@
|
||||
(i18n/label-pluralize cnt :t/members-active)))]])))
|
||||
|
||||
(defview toolbar-content-view []
|
||||
(letsubs [{:keys [group-chat name chat-id
|
||||
contacts public? public-key]} [:get-current-chat]
|
||||
(letsubs [{:keys [group-chat name contacts
|
||||
public? chat-id]} [:get-current-chat]
|
||||
show-actions? [:get-current-chat-ui-prop :show-actions?]
|
||||
accounts [:get-accounts]
|
||||
contact [:get-current-chat-contact]
|
||||
contact [:get-current-chat-contact]
|
||||
sync-state [:sync-state]]
|
||||
[react/view common.styles/flex
|
||||
[react/view {:style st/toolbar-container}
|
||||
|
||||
[react/view (when-not group-chat [photos/member-photo chat-id])]
|
||||
[react/view (st/chat-name-view (or (empty? accounts)
|
||||
show-actions?))
|
||||
(let [chat-name (if (string/blank? name)
|
||||
(generate-gfy public-key)
|
||||
(generate-gfy chat-id)
|
||||
(or (i18n/get-contact-translated chat-id :name name)
|
||||
(i18n/label :t/chat-name)))]
|
||||
[react/text {:style st/chat-name-text
|
||||
|
Loading…
x
Reference in New Issue
Block a user