chat messages UI refresh

This commit is contained in:
Gustavo Nunes 2017-03-08 23:28:21 -03:00 committed by Roman Volosovskyi
parent 9d21285c10
commit b54c9f337f
13 changed files with 163 additions and 195 deletions

View File

@ -141,10 +141,6 @@
:height 56
:align-items :center
:justify-content :center}
:toolbar-last-activity {:color styles/text2-color
:background-color :transparent
:top 0
:font-size 12}
:text-field-focus-line-height 2})
(def fonts

View File

@ -77,13 +77,14 @@
(list-item [chat-datemark value]))
(defmethod message-row :default
[{:keys [contact-by-identity group-chat messages-count row index]}]
[{:keys [contact-by-identity group-chat messages-count row index last-outgoing?]}]
(let [message (-> row
(add-message-color contact-by-identity)
(assoc :group-chat group-chat)
(assoc :messages-count messages-count)
(assoc :index index)
(assoc :last-message (= (js/parseInt index) (dec messages-count))))]
(assoc :last-message (= (js/parseInt index) (dec messages-count)))
(assoc :last-outgoing? last-outgoing?))]
(list-item [chat-message message])))
(defn toolbar-action []
@ -152,7 +153,9 @@
[messages [:chat :messages]
contacts [:chat :contacts]
message-extras [:get :message-extras]
loaded? [:all-messages-loaded?]]
loaded? [:all-messages-loaded?]
current-chat-id [:get-current-chat-id]
last-outgoing-message [:get-chat-last-outgoing-message @current-chat-id]]
(let [contacts' (contacts-by-identity contacts)
messages (messages-with-timemarks messages message-extras)]
[list-view {:renderRow (fn [row _ index]
@ -160,7 +163,8 @@
:group-chat group-chat
:messages-count (count messages)
:row row
:index index}))
:index index
:last-outgoing? (= (:message-id last-outgoing-message) (:message-id row))}))
:renderScrollComponent #(invertible-scroll-view (js->clj %))
:onEndReached (when-not loaded? #(dispatch [:load-more-messages]))
:enableEmptySections true

View File

@ -1,19 +1,15 @@
(ns status-im.chat.styles.datemark)
(ns status-im.chat.styles.datemark
(:require [status-im.components.styles :as st]))
(def datemark-wrapper
{:flex 1
:align-items :center})
(def datemark
{:background-color "#bbc4cb33"
:padding-left 12
:padding-right 12
:margin-top 8
:margin-bottom 8
:border-radius 12
:height 24})
{:opacity 0.5
:margin-top 20
:height 20})
(def datemark-text
{:color "#838c93"
:top 4
:font-size 12})
{:color st/color-gray4
:font-size 15})

View File

@ -1,18 +1,22 @@
(ns status-im.chat.styles.message
(:require-macros [status-im.utils.styles :refer [defstyle defnstyle]])
(:require [status-im.components.styles :refer [color-white
color-black
color-blue
color-light-blue
selected-message-color
text1-color
text2-color
color-gray]]
color-gray
color-gray4]]
[status-im.constants :refer [text-content-type
content-type-command]]))
(def style-message-text
{:fontSize 14
:lineHeight 21
:color text1-color})
(defstyle style-message-text
{:fontSize 15
:color text1-color
:android {:line-height 22}
:ios {:line-height 23}})
(def style-sub-text
{:top -2
@ -22,17 +26,17 @@
:height 16})
(defn message-padding-top
[{:keys [new-day same-author same-direction]}]
[{:keys [first-in-date? same-author same-direction]}]
(cond
new-day 0
same-author 4
same-direction 20
:else 10))
first-in-date? 20
same-author 8
same-direction 16
:else 24))
(defn last-message-padding
[{:keys [last-message typing]}]
(when (and last-message (not typing))
{:paddingBottom 20}))
{:paddingBottom 16}))
(def message-datemark
{:margin-top 10
@ -42,30 +46,21 @@
{:height 16})
(def message-body-base
{:padding-right 8
:padding-left 8})
{:padding-right 10
:padding-left 10})
(defn message-body
[{:keys [outgoing] :as message}]
(let [align (if outgoing :flex-end :flex-start)]
(let [align (if outgoing :flex-end :flex-start)
direction (if outgoing :row-reverse :row)]
(merge message-body-base
{:flexDirection :column
{:flexDirection direction
:width 260
:paddingTop (message-padding-top message)
:alignSelf align
:alignItems align}
(last-message-padding message))))
(defn incoming-group-message-body-st
[message]
(merge message-body-base
{:flexDirection :row
:alignSelf :flex-start
:marginTop (message-padding-top message)
:paddingRight 8
:paddingLeft 8}
(last-message-padding message)))
(def selected-message
{:marginTop 18
:marginLeft 40
@ -75,75 +70,72 @@
(def group-message-wrapper
{:flexDirection :column})
(def group-message-view
{:flexDirection :column
:width 260
:paddingLeft 8
:alignItems :flex-start})
(defn group-message-view
[{:keys [outgoing] :as message}]
(let [align (if outgoing :flex-end :flex-start)]
{:flexDirection :column
:width 260
:padding-left 10
:padding-right 10
:alignItems align}))
(def message-author {:width 24})
(def message-author
{:width 36
:alignSelf :flex-start})
(def photo-view {:borderRadius 12})
(def photo
{:borderRadius 12
:width 24
:height 24})
:width 36
:height 36})
(def delivery-view
{:flexDirection :row
:marginTop 2})
:marginTop 2
:opacity 0.5})
(def delivery-image
{:marginTop 6
:width 9
:height 7})
(def delivery-text
{:fontSize 12
:color text2-color
:marginLeft 5})
(defstyle delivery-text
{:color color-gray4
:marginLeft 5
:android {:font-size 13}
:ios {:font-size 14}})
(defn text-message
[{:keys [outgoing group-chat incoming-group]}]
(merge style-message-text
{:marginTop (if incoming-group
4
0)}
(when (and outgoing group-chat)
{:color color-white})))
{:marginTop (if incoming-group 4 0)}))
(defn message-view
(defnstyle message-view
[{:keys [content-type outgoing group-chat selected]}]
(merge {:borderRadius 14
:padding 12
:backgroundColor color-white}
(merge {:padding 12
:backgroundColor color-white
:android {:border-radius 4}
:ios {:border-radius 8}}
(when (= content-type content-type-command)
{:paddingTop 10
:paddingBottom 14})
(if outgoing
(when (and group-chat (= content-type text-content-type))
{:backgroundColor color-blue})
(when selected
{:backgroundColor selected-message-color}))))
:paddingBottom 14})))
(def author
{:color color-gray})
(defstyle author
{:color color-gray4
:margin-bottom 5
:android {:font-size 13}
:ios {:font-size 14}})
(def comand-request-view
{:paddingRight 16})
(def command-request-message-view
{:borderRadius 14
:padding 12
:paddingRight 28
:backgroundColor color-white})
{:borderRadius 14
:padding-vertical 10
:paddingRight 28
:backgroundColor color-white})
(def command-request-from-text
(merge style-sub-text {:marginBottom 2}))
(defn command-request-image-touchable [top-offset?]
(defn command-request-image-touchable []
{:position :absolute
:top (if top-offset? 4 -1)
:top 0
:right -8
:alignItems :center
:justifyContent :center
@ -177,14 +169,16 @@
:height 14})
(def content-command-view
{:flexDirection :column})
{:flexDirection :column
:alignItems :flex-start})
(def command-container
{:flexDirection :row
:margin-top 4
:marginRight 32})
(def command-image
{:margin-top 5
{:margin-top 9
:width 12
:height 13
:tint-color :#a9a9a9cc})

View File

@ -1,9 +1,12 @@
(ns status-im.chat.styles.screen
(:require-macros [status-im.utils.styles :refer [defstyle defnstyle]])
(:require [status-im.components.styles :refer [chat-background
selected-message-color
separator-color
text1-color
text2-color]]
text2-color
text4-color
color-gray6]]
[status-im.components.toolbar.styles :refer [toolbar-background1]]))
(def chat-view
@ -41,16 +44,15 @@
:width 8
:height 14})
(defn chat-name-view [show-actions]
(defnstyle chat-name-view [show-actions]
{:flex 1
:margin-bottom 2
:margin-left (if show-actions 16 0)
:align-items :flex-start
:justify-content :center})
:justify-content :center
:android {:align-items :flex-start}
:ios {:align-items :center}})
(def chat-name-text
{:color text1-color
:margin-top 2
{:color color-gray6
:fontSize 16})
(def group-icon
@ -63,14 +65,17 @@
{:width 14
:height 8})
(def members
{:marginTop -0.5
:marginLeft 4
:fontSize 12
:color text2-color})
(defstyle members
{:color text4-color
:ios {:font-size 14
:margin-top 4}
:android {:font-size 13}})
(def last-activity
{:height 18})
(defstyle last-activity-text
{:color text4-color
:ios {:font-size 14
:margin-top 4}
:android {:font-size 13}})
(defn actions-wrapper [status-bar-height]
{:backgroundColor toolbar-background1

View File

@ -275,3 +275,11 @@
(let [last-message (subscribe [:get-last-message chat-id])]
(reaction
(get-in @db [:message-data :short-preview (:message-id @last-message)])))))
(register-sub :get-chat-last-outgoing-message
(fn [db [_ chat-id]]
(reaction
(->> (:messages (get-in @db [:chats chat-id]))
(filter :outgoing)
(sort-by :clock-value >)
(first)))))

View File

@ -1,7 +1,6 @@
(ns status-im.chat.views.message
(:require-macros [status-im.utils.views :refer [defview]])
(:require [clojure.string :as s]
[re-frame.core :refer [subscribe dispatch]]
(:require [re-frame.core :refer [subscribe dispatch]]
[reagent.core :as r]
[status-im.i18n :refer [message-status-label]]
[status-im.components.react :refer [view
@ -41,6 +40,14 @@
(def window-width (:width (get-dimensions "window")))
(defview message-author-name [{:keys [outgoing from] :as message}]
[current-account [:get-current-account]
incoming-name [:contact-name-by-identity from]]
(if-let [name (if outgoing
(:name current-account)
(or incoming-name "Unknown contact"))]
[text {:style st/author} name]))
(defn message-content-status [_]
(let [{:keys [chat-id group-chat name color]} (subscribe [:chat-properties [:chat-id :group-chat :name :color]])
members (subscribe [:current-chat-contacts])]
@ -143,28 +150,16 @@
:current-chat-id current-chat-id}]]))
(defn message-view
[{:keys [username same-author index] :as message} content]
[{:keys [same-author index group-chat] :as message} content]
[view (st/message-view message)
(when (and username (or (= 1 index) (not same-author)))
[text {:style st/author} username])
(when group-chat [message-author-name message])
content])
(defmulti message-content (fn [_ message _]
(message :content-type)))
(defmethod message-content content-type-command-request
[wrapper message]
[wrapper message [message-content-command-request message]])
(defmethod message-content c/content-type-wallet-request
[wrapper message]
[wrapper message [message-content-command-request message]])
(def replacements
{"\\*[^*]+\\*" {:font-weight :bold}
"~[^~]+~" {:font-style :italic}})
(def regx (re-pattern (s/join "|" (map first replacements))))
(def regx (re-pattern (str/join "|" (map first replacements))))
(defn get-style [string]
(->> replacements
@ -179,7 +174,7 @@
;; todo rewrite this, naive implementation
(defn- parse-text [string]
(if (string? string)
(let [general-text (s/split string regx)
(let [general-text (str/split string regx)
general-text' (if (zero? (count general-text))
[nil]
general-text)
@ -205,13 +200,23 @@
simple-text? (= (count parsed-text) 2)]
(if simple-text?
[autolink {:style (st/text-message message)
:font :default
:text (apply str parsed-text)
:onPress #(browse %)}]
[text {:style (st/text-message message)
:font :default}
[text {:style (st/text-message message)}
(parse-text content)]))])
(defmulti message-content (fn [_ message _] (message :content-type)))
(defmethod message-content content-type-command-request
[wrapper message]
[wrapper message
[message-view message [message-content-command-request message]]])
(defmethod message-content c/content-type-wallet-request
[wrapper message]
[wrapper message
[message-view message [message-content-command-request message]]])
(defmethod message-content text-content-type
[wrapper message]
[wrapper message [text-message message]])
@ -251,11 +256,6 @@
(if (or (zero? (count user-statuses))
seen-by-everyone?)
[view st/delivery-view
[image {:source (case status
:seen {:uri :icon_ok_small_copy_2}
:failed res/delivery-failed-icon
nil)
:style st/delivery-image}]
[text {:style st/delivery-text
:font :default}
(message-status-label
@ -295,11 +295,6 @@
:else
(or delivery-status message-status app-db-message-status-value :sending))]
[view st/delivery-view
[image {:source (case status
:seen {:uri :icon_ok_small_copy_2}
:failed res/delivery-failed-icon
nil)
:style st/delivery-image}]
[text {:style st/delivery-text
:font :default}
(message-status-label status)]]))
@ -307,37 +302,26 @@
(defview member-photo [from]
[photo-path [:photo-path from]]
[view st/photo-view
[image {:source {:uri (if (s/blank? photo-path)
[image {:source {:uri (if (str/blank? photo-path)
(identicon from)
photo-path)}
:style st/photo}]])
(defn incoming-group-message-body
[{:keys [selected same-author from index] :as message} content]
(defn message-body
[{:keys [last-outgoing? message-type same-author from index] :as message} content]
(let [delivery-status :seen-by-everyone]
[view st/group-message-wrapper
(when selected
[text {:style st/selected-message
:font :default}
"Mar 7th, 15:22"])
[view (st/incoming-group-message-body-st message)
[view (st/message-body message)
[view st/message-author
(when (or (= index 1)
(not same-author)) [member-photo from])]
[view st/group-message-view
(when (and (or (= index 1) (not same-author))
(not= from "me"))
[member-photo from])]
[view (st/group-message-view message)
content
;; TODO show for last or selected
(when (and selected delivery-status)
[message-delivery-status message])]]]))
(defn message-body
[{:keys [outgoing message-type] :as message} content]
[view (st/message-body message)
content
(when outgoing
(if (= (keyword message-type) :group-user-message)
[group-message-delivery-status message]
[message-delivery-status message]))])
(when last-outgoing?
(if (= (keyword message-type) :group-user-message)
[group-message-delivery-status message]
[message-delivery-status message]))]]]))
(defn message-container-animation-logic [{:keys [to-value val callback]}]
(fn [_]
@ -399,8 +383,5 @@
#(share content (label :t/message)))}
[view
(let [incoming-group (and group-chat (not outgoing))]
[message-content
(if incoming-group
incoming-group-message-body
message-body)
(merge message {:incoming-group incoming-group})])]]])})))
[message-content message-body (merge message
{:incoming-group incoming-group})])]]])})))

View File

@ -41,7 +41,7 @@
(anim/start
(button-animation val min-scale loop? answered?)))))
(defn request-button [message-id _ _ top-offset?]
(defn request-button [message-id _ _]
(let [scale-anim-val (anim/create-value min-scale)
answered? (subscribe [:is-request-answered? message-id])
loop? (r/atom true)
@ -60,7 +60,7 @@
[touchable-highlight
{:on-press (when (and (not @answered?) status-initialized?)
#(set-chat-command message-id command))
:style (st/command-request-image-touchable top-offset?)
:style (st/command-request-image-touchable)
:accessibility-label (id/chat-request-message-button (:name command))}
[animated-view {:style (st/command-request-image-view command scale-anim-val)}
(when command-icon
@ -68,8 +68,7 @@
(defn message-content-command-request
[{:keys [message-id _ _ _]}]
(let [top-offset (r/atom {:specified? false})
commands-atom (subscribe [:get-responses])
(let [commands-atom (subscribe [:get-responses])
answered? (subscribe [:is-request-answered? message-id])
status-initialized? (subscribe [:get :status-module-initialized?])
preview (subscribe [:get-in [:message-data :preview message-id]])]
@ -85,19 +84,10 @@
{:on-press (when (and (not @answered?) @status-initialized?)
#(set-chat-command message-id command))}
[view st/command-request-message-view
(when incoming-group
[text {:style st/command-request-from-text
:font :default}
from])
(if (and @preview
(not (string? @preview)))
[view @preview]
[text {:style st/style-message-text
:on-layout #(reset! top-offset {:specified? true
:value (-> (.-nativeEvent %)
(.-layout)
(.-height)
(> 25))})
:font :default}
(or @preview content)])]]
(when (:request-text command)
@ -105,5 +95,4 @@
[text {:style st/style-sub-text
:font :default}
(:request-text command)]])
(when (:specified? @top-offset)
[request-button message-id command @status-initialized? (:value @top-offset)])]))))
[request-button message-id command @status-initialized?]]))))

View File

@ -10,7 +10,6 @@
label
label-pluralize]]
[status-im.chat.styles.screen :as st]
[status-im.components.refreshable-text.view :refer [refreshable-text]]
[status-im.utils.datetime :as time]
[status-im.utils.platform :refer [platform-specific]]
[status-im.utils.gfycat.core :refer [generate-gfy]]
@ -41,13 +40,11 @@
(defview last-activity [{:keys [online-text sync-state]}]
[state [:get :sync-data]]
[refreshable-text {:style st/last-activity
:text-style (get-in platform-specific [:component-styles :toolbar-last-activity])
:font :default
:value (case sync-state
:in-progress (in-progress-text state)
:synced (label :t/sync-synced)
online-text)}])
[text {:style st/last-activity-text}
(case sync-state
:in-progress (in-progress-text state)
:synced (label :t/sync-synced)
online-text)])
(defn group-last-activity [{:keys [contacts sync-state public?]}]
(if (or (= sync-state :in-progress)
@ -55,13 +52,10 @@
[last-activity {:sync-state sync-state}]
(if public?
[view {:flex-direction :row}
[text {:font :default
:style (get-in platform-specific [:component-styles :toolbar-last-activity])}
[text {:style (get-in platform-specific [:component-styles :toolbar-last-activity])}
(label :t/public-group-status)]]
[view {:flex-direction :row}
[icon :group st/group-icon]
[text {:style st/members
:font :medium}
[text {:style st/members}
(if public?
(label :t/public-group-status)
(let [cnt (inc (count contacts))]

View File

@ -10,6 +10,7 @@
(def color-gray3 "#00000040")
(def color-gray4 "#939ba1")
(def color-gray5 "#d9dae1")
(def color-gray6 "#212121")
(def color-steel "#838b91")
(def color-white "white")
(def color-light-blue "#628fe3")

View File

@ -156,6 +156,11 @@
(fn [db [_ identity]]
(reaction (get-in @db [:contacts identity]))))
(register-sub :contact-name-by-identity
(fn [db [_ identity]]
(let [contacts (subscribe [:get-contacts])]
(reaction (:name (@contacts identity))))))
(register-sub :all-new-contacts
(fn [db _]
(contacts-by-current-chat remove db)))

View File

@ -174,10 +174,6 @@
:toolbar-border {:height 1
:background-color styles/color-gray5
:opacity 0.5}
:toolbar-last-activity {:color styles/text2-color
:background-color :transparent
:top 0
:font-size 14}
:text-field-focus-line-height 1})
(def fonts
@ -223,4 +219,3 @@
:public-group-icon-container {:margin-top 2}
:private-group-icon-container {:margin-top 2}
:public-group-chat-hash-style {:top 6 :left 3}})

View File

@ -25,8 +25,8 @@
:members {:one "1 member"
:other "{{count}} members"
:zero "no members"}
:members-active {:one "1 member, 1 active"
:other "{{count}} members, {{count}} active"
:members-active {:one "1 member"
:other "{{count}} members"
:zero "no members"}
:public-group-status "Public"
:active-online "Online"