chat message styles

This commit is contained in:
Roman Volosovskyi 2016-05-08 23:06:38 +03:00
parent 1ce4c1d459
commit 27302d9027
6 changed files with 430 additions and 337 deletions

View File

@ -61,10 +61,11 @@
^{:key member} [typing member])])
(defn message-row [contact-by-identity group-chat]
(fn [row _ _]
(fn [row _ idx]
(let [msg (-> row
(add-msg-color contact-by-identity)
(assoc :group-chat group-chat))]
(assoc :group-chat group-chat)
(assoc :last-msg (zero? (js/parseInt idx))))]
(list-item [chat-message msg]))))
(defn on-action-selected [position]

View File

@ -7,18 +7,9 @@
image
touchable-highlight
navigator]]
[syng-im.components.styles :refer [font
color-light-blue-transparent
color-white
color-black
color-blue
selected-message-color
online-color
text1-color
text2-color]]
[syng-im.components.chat.chat-message-styles :as st]
[syng-im.models.commands :refer [parse-command-msg-content
parse-command-request-msg-content]]
[syng-im.utils.logging :as log]
parse-command-request]]
[syng-im.navigation :refer [nav-pop]]
[syng-im.resources :as res]
[syng-im.constants :refer [text-content-type
@ -26,152 +17,64 @@
content-type-command
content-type-command-request]]))
(def style-message-text {:fontSize 14
:fontFamily font
:lineHeight 21
:color text1-color})
;-------------------------------------------------------------------------------
;styles
(def style-sub-text {:top -2
:fontFamily font
:fontSize 12
:color text2-color
:lineHeight 14
:height 16})
;-------------------------------------------------------------------------------
;components
(defn message-date [{:keys [date]}]
[view {}
[view {:style {:backgroundColor color-light-blue-transparent
:height 24
:borderRadius 50
:alignSelf :center
:marginTop 20
:marginBottom 20
:paddingTop 5
:paddingHorizontal 12}}
[text {:style (assoc style-sub-text :textAlign :center)}
date]]])
[view st/message-date-container
[text {:style st/message-date-text} date]]])
(defn contact-photo [{:keys [photo-path]}]
[view {:borderRadius 50}
[view st/contact-photo-container
[image {:source (if (s/blank? photo-path)
res/user-no-photo
{:uri photo-path})
:style {:borderRadius 50
:width 64
:height 64}}]])
:style st/contact-photo-st}]])
(defn contact-online [{:keys [online]}]
(when online
[view {:position :absolute
:top 44
:left 44
:width 24
:height 24
:borderRadius 50
:backgroundColor online-color
:borderWidth 2
:borderColor color-white}
[view {:position :absolute
:top 8
:left 5
:width 4
:height 4
:borderRadius 50
:backgroundColor color-white}]
[view {:position :absolute
:top 8
:left 11
:width 4
:height 4
:borderRadius 50
:backgroundColor color-white}]]))
[view st/online-container
[view st/online-dot-left]
[view st/online-dot-right]]))
(defn message-content-status [{:keys [from content]}]
[view {:style {:flex 1
:alignSelf :center
:alignItems :center
:width 249}}
[view {:style {:marginTop 20}}
[view st/status-container
[view st/status-image-view
[contact-photo {}]
[contact-online {:online true}]]
[text {:style {:marginTop 20
:fontSize 18
:fontFamily font
:color text1-color}}
from]
[text {:style {:marginTop 10
:fontFamily font
:fontSize 14
:lineHeight 20
:textAlign :center
:color text2-color}}
content]])
[text {:style st/status-from} from]
[text {:style st/status-text} content]])
(defn message-content-audio [_]
[view {:style {:flexDirection :row
:alignItems :center}}
[view {:style {:width 33
:height 33
:borderRadius 50
:elevation 1}}
[view st/audio-container
[view st/play-view
[image {:source res/play
:style {:width 33
:height 33}}]]
[view {:style {:marginTop 10
:marginLeft 10
:width 120
:height 26
:elevation 1}}
[view {:style {:position :absolute
:top 4
:width 120
:height 2
:backgroundColor "#EC7262"}}]
[view {:style {:position :absolute
:left 0
:top 0
:width 2
:height 10
:backgroundColor "#4A5258"}}]
[text {:style {:position :absolute
:left 1
:top 11
:fontFamily font
:fontSize 11
:color "#4A5258"
:letterSpacing 1
:lineHeight 15}}
:style st/play-image}]]
[view st/track-container
[view st/track]
[view st/track-mark]
[text {:style st/track-duration-text}
"03:39"]]])
(defn message-content-command [content]
(let [commands-atom (subscribe [:get-commands])]
(fn [content]
(let [commands @commands-atom
{:keys [command content]}
(parse-command-msg-content commands content)]
[view {:style {:flexDirection :column}}
[view {:style {:flexDirection :row
:marginRight 32}}
[view {:style {:backgroundColor (:color command)
:height 24
:borderRadius 50
:paddingTop 3
:paddingHorizontal 12}}
[text {:style {:fontSize 12
:fontFamily font
:color color-white}}
[view st/conetent-command-view
[view st/command-container
[view (st/command-view command)
[text {:style st/command-text}
(:text command)]]]
[image {:source (:icon command)
:style {:position :absolute
:top 4
:right 0
:width 12
:height 13}}]
[text {:style (merge style-message-text
{:marginTop 8
:marginHorizontal 0})}
:style st/command-image}]
[text {:style st/command-text-st}
;; TODO isn't smart
(if (= (:command command) :keypair-password)
"******"
@ -180,98 +83,33 @@
(defn set-chat-command [msg-id command]
(dispatch [:set-response-chat-command msg-id (:command command)]))
(defn message-content-command-request
[{:keys [msg-id content outgoing group-chat from]}]
[{:keys [msg-id content from incoming-group]}]
(let [commands-atom (subscribe [:get-commands])]
(fn [{:keys [msg-id content outgoing group-chat from]}]
(fn [{:keys [msg-id content from incoming-group]}]
(let [commands @commands-atom
{:keys [command content]} (parse-command-request-msg-content commands content)]
[touchable-highlight {:onPress #(set-chat-command msg-id command)}
[view {:style {:paddingRight 16}}
[view {:style (merge {:borderRadius 14
:padding 12
:backgroundColor color-white})}
(when (and group-chat (not outgoing))
[text {:style (merge style-sub-text
{:marginBottom 2})}
{:keys [command content]} (parse-command-request commands content)]
[touchable-highlight {:onPress #(set-chat-command msg-id command)}
[view st/comand-request-view
[view st/command-request-message-view
(when incoming-group
[text {:style st/command-request-from-text}
from])
[text {:style style-message-text}
[text {:style st/style-message-text}
content]]
[view {:style {:position :absolute
:top 12
:right 0
:width 32
:height 32
:borderRadius 50
:backgroundColor (:color command)}}
[view (st/command-request-image-view command)
[image {:source (:request-icon command)
:style {:position :absolute
:top 9
:left 10
:width 12
:height 13}}]]
:style st/command-request-image}]]
(when (:request-text command)
[view {:style {:marginTop 4
:height 14}}
[text {:style style-sub-text}
[view st/command-request-text-view
[text {:style st/style-sub-text}
(:request-text command)]])]]))))
(defn message-content-plain [content outgoing group-chat]
[text {:style (merge style-message-text
{:marginTop (if (and group-chat (not outgoing))
4
0)}
(when (and outgoing group-chat)
{:color color-white}))}
content])
#_(defn message-content [{:keys [msg-id from content-type content outgoing
group-chat selected]}]
(if (= content-type content-type-command-request)
[message-content-command-request msg-id from content outgoing group-chat]
[view {:style (merge {:borderRadius 14
:padding 12
:backgroundColor color-white}
(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})))}
(when (and group-chat (not outgoing))
[text {:style (merge style-sub-text
{:marginBottom 2})}
from])
(cond
(or (= content-type text-content-type)
(= content-type content-type-status))
[message-content-plain content outgoing group-chat]
(= content-type content-type-command)
[message-content-command content]
:else [message-content-audio {:content content
:content-type content-type}])]))
(defn message-view
[{:keys [content-type outgoing background-color group-chat selected]} content]
[view {:style (merge {:borderRadius 14
:padding 12
:backgroundColor color-white}
(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})))}
#_(when (and group-chat (not outgoing))
[text {:style {:marginTop 0
:fontSize 12
:fontFamily font}}
[message content]
[view (st/message-view-st message)
#_(when incoming-group
[text {:style message-author-text}
"Justas"])
content])
@ -283,14 +121,9 @@
[wrapper message [message-content-command-request message]])
(defn text-message
[{:keys [content outgoing group-chat] :as message}]
[{:keys [content] :as message}]
[message-view message
[text {:style (merge style-message-text
{:marginTop (if (and group-chat (not outgoing))
4
0)}
(when (and outgoing group-chat)
{:color color-white}))}
[text {:style (st/text-message-st message)}
content]])
(defmethod message-content text-content-type
@ -314,21 +147,14 @@
:content-type content-type}]]])
(defn message-delivery-status [{:keys [delivery-status]}]
[view {:style {:flexDirection :row
:marginTop 2}}
[view st/delivery-view
[image {:source (case delivery-status
:delivered {:uri :icon_ok_small}
:seen {:uri :icon_ok_small}
:seen-by-everyone {:uri :icon_ok_small}
:failed res/delivery-failed-icon)
:style {:marginTop 6
:width 9
:height 7}}]
[text {:style {:fontFamily font
:fontSize 12
:color text2-color
:marginLeft 5}}
:style st/delivery-image}]
[text {:style st/delivery-text}
(case delivery-status
:delivered "Delivered"
:seen "Seen"
@ -336,85 +162,46 @@
:failed "Failed")]])
(defn member-photo [{:keys [photo-path]}]
[view {:borderRadius 50}
[view st/photo-view
[image {:source (if (s/blank? photo-path)
res/user-no-photo
{:uri photo-path})
:style {:borderRadius 50
:width 24
:height 24}}]])
:style st/photo}]])
(defn incoming-group-message-body
[{:keys [selected new-day same-author same-direction last-msg typing]}
content]
[{:keys [selected same-author] :as message} content]
(let [delivery-status :seen-by-everyone]
[view {:style {:flexDirection :column}}
[view st/group-message-wrapper
(when selected
[text {:style {:marginTop 18
:marginLeft 40
:fontFamily font
:fontSize 12
:color text2-color}}
[text {:style st/selected-message}
"Mar 7th, 15:22"])
[view {:style (merge {:flexDirection :row
:alignSelf :flex-start
:marginTop (cond
new-day 0
same-author 4
same-direction 20
:else 10)
:paddingRight 8
:paddingLeft 8}
(when (and last-msg (not typing))
{:paddingBottom 20}))}
[view {:style {:width 24}}
(when (not same-author)
[member-photo {}])]
[view {:style {:flexDirection :column
:width 260
:paddingLeft 8
:alignItems :flex-start}}
[view (st/incoming-group-message-body-st message)
[view st/message-author
(when (not same-author) [member-photo {}])]
[view st/group-message-view
content
;; TODO show for last or selected
(when (and selected delivery-status)
[message-delivery-status {:delivery-status delivery-status}])]]]))
(defn message-body
[{:keys [outgoing new-day same-author same-direction last-msg typing]}
content]
(let [delivery-status :seen
align (if outgoing :flex-end :flex-start)]
[view {:style (merge {:flexDirection :column
:width 260
:paddingTop (cond
new-day 0
same-author 4
same-direction 20
:else 10)
:paddingRight 8
:paddingLeft 8
:alignSelf align
:alignItems align}
(when (and last-msg (not typing))
{:paddingBottom 20}))}
[{:keys [outgoing] :as message} content]
(let [delivery-status :seen]
[view (st/message-body-st message)
content
(when (and outgoing delivery-status)
[message-delivery-status {:delivery-status delivery-status}])]))
(defn chat-message
[{:keys [msg-id outgoing delivery-status date new-day group-chat]
:as message}
last-msg-id]
[{:keys [outgoing delivery-status date new-day group-chat]
:as message}]
[view {}
(when new-day
[message-date {:date date}])
(let [msg-data
(merge message {:delivery-status (keyword delivery-status)
:last-msg (= last-msg-id msg-id)})]
[view {}
(when new-day [message-date {:date date}])
[view {}
(let [incoming-group (and group-chat (not outgoing))]
[message-content
(if (and group-chat (not outgoing))
(if incoming-group
incoming-group-message-body
message-body)
msg-data]])])
(merge message {:delivery-status (keyword delivery-status)
:incoming-group incoming-group})])]])

View File

@ -0,0 +1,311 @@
(ns syng-im.components.chat.chat-message-styles
(:require [syng-im.components.styles :refer [font
color-light-blue-transparent
color-white
color-black
color-blue
selected-message-color
online-color
text1-color
text2-color]]
[syng-im.constants :refer [text-content-type
content-type-command]]))
(def style-message-text
{:fontSize 14
:fontFamily font
:lineHeight 21
:color text1-color})
(def style-sub-text
{:top -2
:fontFamily font
:fontSize 12
:color text2-color
:lineHeight 14
:height 16})
(defn message-padding-top
[{:keys [new-day same-author same-direction]}]
(cond
new-day 0
same-author 4
same-direction 20
:else 10))
(defn last-message-padding
[{:keys [last-msg typing]}]
(when (and last-msg (not typing))
{:paddingBottom 20}))
(def message-body-base
{:paddingRight 8
:paddingLeft 8})
(defn message-body-st
[{:keys [outgoing] :as message}]
(let [align (if outgoing :flex-end :flex-start)]
(merge message-body-base
{:flexDirection :column
: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
:fontFamily font
:fontSize 12
:color text2-color})
(def group-message-wrapper
{:flexDirection :column})
(def group-message-view
{:flexDirection :column
:width 260
:paddingLeft 8
:alignItems :flex-start})
(def message-author {:width 24})
(def photo-view {:borderRadius 50})
(def photo
{:borderRadius 50
:width 24
:height 24})
(def delivery-view
{:flexDirection :row
:marginTop 2})
(def delivery-image
{:marginTop 6
:width 9
:height 7})
(def delivery-text
{:fontFamily font
:fontSize 12
:color text2-color
:marginLeft 5})
(defn text-message-st
[{:keys [outgoing group-chat incoming-group]}]
(merge style-message-text
{:marginTop (if incoming-group
4
0)}
(when (and outgoing group-chat)
{:color color-white})))
(defn message-view-st
[{:keys [content-type outgoing group-chat selected]}]
(merge {:borderRadius 14
:padding 12
:backgroundColor color-white}
(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}))))
(def comand-request-view
{:paddingRight 16})
(def command-request-message-view
{:borderRadius 14
:padding 12
:backgroundColor color-white})
(def command-request-from-text
(merge style-sub-text {:marginBottom 2}))
(defn command-request-image-view
[command]
{:position :absolute
:top 12
:right 0
:width 32
:height 32
:borderRadius 50
:backgroundColor (:color command)})
(def command-request-image
{:position :absolute
:top 9
:left 10
:width 12
:height 13})
(def command-request-text-view
{:marginTop 4
:height 14})
(def conetent-command-view
{:flexDirection :column})
(def command-container
{:flexDirection :row
:marginRight 32})
(defn command-view [command]
{:backgroundColor (:color command)
:height 24
:borderRadius 50
:paddingTop 3
:paddingHorizontal 12})
(def command-text
{:fontSize 12
:fontFamily font
:color color-white})
(def command-image
{:position :absolute
:top 4
:right 0
:width 12
:height 13})
(def command-text-st
(merge style-message-text
{:marginTop 8
:marginHorizontal 0}))
(def message-author-text
{:marginTop 0
:fontSize 12
:fontFamily font})
(def audio-container
{:flexDirection :row
:alignItems :center})
(def play-view
{:width 33
:height 33
:borderRadius 50
:elevation 1})
(def play-image
{:width 33
:height 33})
(def track-container
{:marginTop 10
:marginLeft 10
:width 120
:height 26
:elevation 1})
(def track
{:position :absolute
:top 4
:width 120
:height 2
:backgroundColor "#EC7262"})
(def track-mark
{:position :absolute
:left 0
:top 0
:width 2
:height 10
:backgroundColor "#4A5258"})
(def track-duration-text
{:position :absolute
:left 1
:top 11
:fontFamily font
:fontSize 11
:color "#4A5258"
:letterSpacing 1
:lineHeight 15})
(def status-container
{:flex 1
:alignSelf :center
:alignItems :center
:width 249})
(def status-image-view
{:marginTop 20})
(def status-from
{:marginTop 20
:fontSize 18
:fontFamily font
:color text1-color})
(def status-text
{:marginTop 10
:fontFamily font
:fontSize 14
:lineHeight 20
:textAlign :center
:color text2-color})
(def online-container
{:position :absolute
:top 44
:left 44
:width 24
:height 24
:borderRadius 50
:backgroundColor online-color
:borderWidth 2
:borderColor color-white})
(def online-dot
{:position :absolute
:top 8
:width 4
:height 4
:borderRadius 50
:backgroundColor color-white})
(def online-dot-left
(assoc online-dot :left 5))
(def online-dot-right
(assoc online-dot :left 11))
(def contact-photo-container
{:borderRadius 50})
(def contact-photo-st
{:borderRadius 50
:width 64
:height 64})
(def message-date-container
{:backgroundColor color-light-blue-transparent
:height 24
:borderRadius 50
:alignSelf :center
:marginTop 20
:marginBottom 20
:paddingTop 5
:paddingHorizontal 12})
(def message-date-text
(assoc style-sub-text :textAlign :center))

View File

@ -144,35 +144,31 @@
:to "me"})) (range n)))
(defn store-message!
[db [_ {chat-id :from
outgoing :outgoing
:as msg}]]
(let [previous-message (first (get-in db [:chats chat-id :messages]))
msg (merge msg
{:same-author (if previous-message
(= (:from previous-message) outgoing)
true)
:same-direction (if previous-message
(= (:outgoing previous-message) outgoing)
true)})]
(save-message chat-id msg)))
[{:keys [new-message]} [_ {chat-id :from}]]
(save-message chat-id new-message))
(defn add-message-to-db
[db chat-id {:keys [from outgoing] :as message}]
(let [messages [:chats chat-id :messages]
previous-message (first (get-in db [:chats chat-id :messages]))
message (merge message
{:same-author (if previous-message
(= (:from previous-message) from)
true)
:same-direction (if previous-message
(= (:outgoing previous-message) outgoing)
true)})]
[db chat-id message]
(let [messages [:chats chat-id :messages]]
(update-in db messages conj message)))
(defn check-author-direction
[db chat-id {:keys [from outgoing] :as message}]
(let [previous-message (first (get-in db [:chats chat-id :messages]))]
(merge message
{:same-author (if previous-message
(= (:from previous-message) from)
true)
:same-direction (if previous-message
(= (:outgoing previous-message) outgoing)
true)})))
(defn receive-message
[db [_ {chat-id :from :as msg}]]
(add-message-to-db db chat-id msg))
[db [_ {chat-id :from :as message}]]
(let [message' (check-author-direction db chat-id message)]
(-> db
(add-message-to-db chat-id message')
(assoc :new-message message'))))
(register-handler :received-msg
(-> receive-message
@ -295,41 +291,40 @@
(defn prepare-message
[{:keys [identity current-chat-id] :as db} _]
(let [text (get-in db [:chats current-chat-id :input-text])
{:keys [command]} (check-suggestion db (str text " "))]
(let [text (get-in db [:chats current-chat-id :input-text])
{:keys [command]} (check-suggestion db (str text " "))
message (check-author-direction
db current-chat-id
{:msg-id (random/id)
:chat-id current-chat-id
:content text
:to current-chat-id
:from identity
:content-type text-content-type
:outgoing true})]
(if command
(set-chat-command db command)
(assoc db :new-message (when-not (str/blank? text)
{:msg-id (random/id)
:chat-id current-chat-id
:content text
:to current-chat-id
:from identity
:content-type text-content-type
:outgoing true
;; todo should be refactored
:same-author false
:same-direction false})))))
(assoc db :new-message (when-not (str/blank? text) message)))))
(defn prepare-command [identity chat-id staged-command]
(let [command-key (get-in staged-command [:command :command])
content {:command (name command-key)
:content (:content staged-command)}]
{:msg-id (random/id)
:from identity
:to chat-id
:content content
:content-type content-type-command
:outgoing true
:handler (:handler staged-command)
:same-author false
:same-direction false}))
{:msg-id (random/id)
:from identity
:to chat-id
:content content
:content-type content-type-command
:outgoing true
:handler (:handler staged-command)}))
(defn prepare-staged-commans
[{:keys [current-chat-id identity] :as db} _]
(let [staged-commands (get-in db [:chats current-chat-id :staged-commands])]
(->> staged-commands
(map #(prepare-command identity current-chat-id %))
;todo this is wrong :(
(map #(check-author-direction db current-chat-id %))
(assoc db :new-commands))))
(defn add-message
@ -373,7 +368,6 @@
(defn handle-commands
[{:keys [new-commands]}]
(println new-commands)
(doseq [{{content :content} :content
handler :handler} new-commands]
(when handler

View File

@ -130,5 +130,5 @@
(defn parse-command-msg-content [commands content]
(update content :command #(find-command commands (keyword %))))
(defn parse-command-request-msg-content [commands content]
(defn parse-command-request [commands content]
(update content :command #(find-command commands (keyword %))))

View File

@ -15,7 +15,7 @@
get-chat-command
get-chat-command-content
get-chat-command-request
parse-command-request-msg-content]]
parse-command-request]]
[syng-im.handlers.suggestions :refer [get-suggestions]]))
;; -- Chat --------------------------------------------------------------