Merge with 'develop'

This commit is contained in:
virvar 2016-05-10 09:45:59 +03:00
commit ee4a4a6f65
26 changed files with 1039 additions and 888 deletions

View File

@ -4,22 +4,14 @@
[syng-im.components.react :refer [view
text
image
icon
navigator
touchable-highlight
toolbar-android
list-view
list-item
android?]]
[syng-im.components.styles :refer [font
title-font
color-white
chat-background
online-color
selected-message-color
separator-color
text1-color
text2-color
toolbar-background1]]
[syng-im.components.chat-styles :as st]
[syng-im.utils.logging :as log]
[syng-im.resources :as res]
[syng-im.constants :refer [content-type-status]]
@ -29,7 +21,6 @@
[syng-im.components.chat.chat-message :refer [chat-message]]
[syng-im.components.chat.chat-message-new :refer [chat-message-new]]))
(defn contacts-by-identity [contacts]
(->> contacts
(map (fn [{:keys [identity] :as contact}]
@ -50,123 +41,33 @@
[image {:source (if (s/blank? photo-path)
res/user-no-photo
{:uri photo-path})
:style {:borderRadius 50
:width 36
:height 36}}]])
:style st/chat-photo}]])
(defn contact-online [{:keys [online]}]
(when online
[view {:position "absolute"
:top 30
:left 30
:width 20
:height 20
:borderRadius 50
:backgroundColor online-color
:borderWidth 2
:borderColor color-white}
[view {:position "absolute"
:top 6
:left 3
:width 4
:height 4
:borderRadius 50
:backgroundColor color-white}]
[view {:position "absolute"
:top 6
:left 9
:width 4
:height 4
:borderRadius 50
:backgroundColor color-white}]]))
[view st/online-view
[view st/online-dot-left]
[view st/online-dot-right]]))
(defn typing [member]
[view {:style {:width 260
:marginTop 10
:paddingLeft 8
:paddingRight 8
:alignItems "flex-start"
:alignSelf "flex-start"}}
[view {:style {:borderRadius 14
:padding 12
:height 38
:backgroundColor selected-message-color}}
[text {:style {:marginTop -2
:fontSize 12
:fontFamily font
:color text2-color}}
[view st/typing-view
[view st/typing-background
[text {:style st/typing-text}
(str member " is typing")]]])
(defn typing-all []
[view {:style {:marginBottom 20}}
[view st/typing-all
(for [member ["Geoff" "Justas"]]
^{:key member} [typing member])])
(defn toolbar-content-chat [group-chat]
(let
[contacts (subscribe [:chat :contacts])
name (subscribe [:chat :name])]
(fn [group-chat]
[view {:style {:flex 1
:flexDirection "row"
:backgroundColor "transparent"}}
[view {:style {:flex 1
:alignItems "flex-start"
:justifyContent "center"
:marginRight 112}}
[text {:style {:marginTop -2.5
:color text1-color
:fontSize 16
:fontFamily font}}
(or @name "Chat name")]
(if group-chat
[view {:style {:flexDirection "row"}}
[image {:source {:uri :icon_group}
:style {:marginTop 4
:width 14
:height 9}}]
[text {:style {:marginTop -0.5
:marginLeft 4
:fontFamily font
:fontSize 12
:color text2-color}}
(let [cnt (count @contacts)]
(str cnt
(if (< 1 cnt)
;; TODO https://github.com/r0man/inflections-clj
" members"
" member")
", " cnt " active"))]]
[text {:style {:marginTop 1
:color text2-color
:fontSize 12
:fontFamily font}}
"Active a minute ago"])]
(when-not group-chat
[view {:style {:position "absolute"
:top 10
:right 66}}
[chat-photo {}]
[contact-online {:online true}]])])))
(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]))))
(def group-caht-actions
[{:title "Add Contact to chat"
:icon res/add-icon
:showWithText true}
{:title "Remove Contact from chat"
:icon res/trash-icon
:showWithText true}
{:title "Leave Chat"
:icon res/leave-icon
:showWithText true}])
(defn on-action-selected [position]
(case position
0 (dispatch [:show-add-participants #_navigator])
@ -174,43 +75,24 @@
2 (dispatch [:leave-group-chat #_navigator])))
(defn overlay [{:keys [on-click-outside]} items]
[view {:position :absolute
:top 0
:bottom 0
:left 0
:right 0}
[touchable-highlight {:on-press on-click-outside
:underlay-color :transparent
:style {:flex 1}}
[view st/actions-overlay
[touchable-highlight {:on-press on-click-outside
:style st/overlay-highlight}
[view nil]]
items])
(defn action-view [action]
(defn action-view [{:keys [icon-style handler title subtitle]
icon-name :icon}]
[touchable-highlight {:on-press (fn []
(dispatch [:set-show-actions false])
((:handler action)))
:underlay-color :transparent}
[view {:style {:flexDirection "row"
:height 56}}
[view {:width 56
:height 56
:alignItems "center"
:justifyContent "center"}
[image {:source {:uri (:icon action)}
:style (:icon-style action)}]]
[view {:style {:flex 1
:alignItems "flex-start"
:justifyContent "center"}}
[text {:style {:marginTop -2.5
:color text1-color
:fontSize 14
:fontFamily font}}
(:title action)]
(when-let [subtitle (:subtitle action)]
[text {:style {:marginTop 1
:color text2-color
:fontSize 12
:fontFamily font}}
(handler))}
[view st/action-icon-row
[view st/action-icon-view
[icon icon-name icon-style]]
[view st/action-view
[text {:style st/action-title} title]
(when-let [subtitle subtitle]
[text {:style st/action-subtitle}
subtitle])]]])
(defn actions-list-view []
@ -218,27 +100,27 @@
(subscribe [:chat-properties [:group-chat :chat-id]])]
(when-let [actions (if @group-chat
[{:title "Add Contact to chat"
:icon :icon_menu_group
:icon :menu_group
:icon-style {:width 25
:height 19}
:handler nil #_#(dispatch [:show-add-participants
navigator])}
{:title "Remove Contact from chat"
:subtitle "Alex, John"
:icon :icon_search_gray_copy
:icon :search_gray_copy
:icon-style {:width 17
:height 17}
:handler nil #_#(dispatch
[:show-remove-participants navigator])}
{:title "Leave Chat"
:icon :icon_muted
:icon :muted
:icon-style {:width 18
:height 21}
:handler nil #_#(dispatch [:leave-group-chat
navigator])}
{:title "Settings"
:subtitle "Not implemented"
:icon :icon_settings
:icon :settings
:icon-style {:width 20
:height 13}
:handler (fn [])}]
@ -247,16 +129,9 @@
:icon-style {:width 25
:height 19}
:handler #(dispatch [:show-profile @chat-id])}])]
[view {:style {:backgroundColor toolbar-background1
:elevation 2
:position :absolute
:top 56
:left 0
:right 0}}
[view {:style {:marginLeft 16
:height 1.5
:backgroundColor separator-color}}]
[view {:style {:marginVertical 10}}
[view st/actions-wrapper
[view st/actions-separator]
[view st/actions-view
(for [action actions]
^{:key action} [action-view action])]])))
@ -269,67 +144,33 @@
(subscribe [:chat-properties [:group-chat :name :contacts]])
show-actions (subscribe [:show-actions])]
(fn []
[view {:style {:flexDirection "row"
:height 56
:backgroundColor toolbar-background1
:elevation 2}}
[view st/toolbar-view
(when (not @show-actions)
[touchable-highlight {:on-press #(dispatch [:navigate-back])
:underlay-color :transparent}
[view {:width 56
:height 56}
[image {:source {:uri "icon_back"}
:style {:marginTop 21
:marginLeft 23
:width 8
:height 14}}]]])
[view {:style {:flex 1
:marginLeft (if @show-actions 16 0)
:alignItems "flex-start"
:justifyContent "center"}}
[text {:style {:marginTop -2.5
:color text1-color
:fontSize 16
:fontFamily font}}
[touchable-highlight {:on-press #(dispatch [:navigate-back])}
[view st/icon-view
[icon :back st/back-icon]]])
[view (st/chat-name-view @show-actions)
[text {:style st/chat-name-text}
(or @name "Chat name")]
(if @group-chat
[view {:style {:flexDirection :row}}
[image {:source {:uri :icon_group}
:style {:marginTop 4
:width 14
:height 9}}]
[text {:style {:marginTop -0.5
:marginLeft 4
:fontFamily font
:fontSize 12
:color text2-color}}
[view {:flexDirection :row}
[icon :group st/group-icon]
[text {:style st/members}
(let [cnt (count @contacts)]
(str cnt
(if (< 1 cnt)
" members"
" member")
", " cnt " active"))]]
[text {:style {:marginTop 1
:color text2-color
:fontSize 12
:fontFamily font}}
"Active a minute ago"])]
[text {:style st/last-activity} "Active a minute ago"])]
(if @show-actions
[touchable-highlight
{:on-press #(dispatch [:set-show-actions false])
:underlay-color :transparent}
[view {:style {:width 56
:height 56}}
[image {:source {:uri :icon_up}
:style {:marginTop 23
:marginLeft 21
:width 14
:height 8}}]]]
{:on-press #(dispatch [:set-show-actions false])}
[view st/icon-view
[icon :up st/up-icon]]]
[touchable-highlight
{:on-press #(dispatch [:set-show-actions true])
:underlay-color :transparent}
[view {:style {:width 56
:height 56}}
{:on-press #(dispatch [:set-show-actions true])}
[view st/icon-view
[chat-photo {}]
[contact-online {:online true}]]])])))
@ -348,8 +189,7 @@
group-chat (subscribe [:chat :group-chat])
show-actions-atom (subscribe [:show-actions])]
(fn []
[view {:style {:flex 1
:backgroundColor chat-background}}
[view st/chat-view
[toolbar]
[messages-view @group-chat]
(when @group-chat [typing-all])

View File

@ -1,149 +1,54 @@
(ns syng-im.components.chat.chat-message
(:require [clojure.string :as s]
[re-frame.core :refer [subscribe dispatch dispatch-sync]]
[syng-im.components.react :refer [android?
view
[re-frame.core :refer [subscribe dispatch]]
[syng-im.components.react :refer [view
text
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]]
touchable-highlight]]
[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]
[syng-im.navigation :refer [nav-pop]]
parse-command-request]]
[syng-im.resources :as res]
[syng-im.constants :refer [text-content-type
content-type-status
content-type-command
content-type-command-request]]))
(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-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}]])
(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}}
"03:39"]]])
: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])]
@ -151,27 +56,14 @@
(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/content-command-view
[view st/command-container
[view (st/command-view command)
[text {:style st/command-name}
(: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}
;; TODO isn't smart
(if (= (:command command) :keypair-password)
"******"
@ -180,99 +72,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)
:underlay-color :transparent}
[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 message)
#_(when incoming-group
[text {:style message-author-text}
"Justas"])
content])
@ -284,14 +110,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 message)}
content]])
(defmethod message-content text-content-type
@ -315,21 +136,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"
@ -337,85 +151,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 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

@ -1,23 +1,15 @@
(ns syng-im.components.chat.chat-message-new
(:require
[re-frame.core :refer [subscribe dispatch dispatch-sync]]
[syng-im.components.react :refer [android?
view
image
text
text-input]]
[syng-im.components.styles :refer [color-white]]
[syng-im.components.chat.plain-message-input :refer [plain-message-input-view]]
[syng-im.components.chat.input.simple-command :refer [simple-command-input-view]]
[syng-im.components.chat.input.phone :refer [phone-input-view]]
[syng-im.components.chat.input.password :refer [password-input-view]]
[syng-im.components.chat.input.confirmation-code :refer [confirmation-code-input-view]]
[syng-im.components.chat.input.money :refer [money-input-view]]
[syng-im.components.chat.input.simple-command-staged :refer [simple-command-staged-view]]
[syng-im.utils.utils :refer [log toast http-post]]
[syng-im.utils.logging :as log]
[syng-im.resources :as res]
[reagent.core :as r]))
[re-frame.core :refer [subscribe]]
[syng-im.components.react :refer [view]]
[syng-im.components.chat.plain-message-input :refer [plain-message-input-view]]
[syng-im.components.chat.input.simple-command :refer [simple-command-input-view]]
[syng-im.components.chat.input.phone :refer [phone-input-view]]
[syng-im.components.chat.input.password :refer [password-input-view]]
[syng-im.components.chat.input.confirmation-code :refer [confirmation-code-input-view]]
[syng-im.components.chat.input.money :refer [money-input-view]]
[syng-im.components.chat.input.simple-command-staged :refer [simple-command-staged-view]]
[syng-im.components.chat.chat-message-styles :as st]))
(defn staged-command-view [stage-command]
[simple-command-staged-view stage-command])
@ -40,13 +32,12 @@
[default-command-input-view command]))
(defn chat-message-new []
(let [command-atom (subscribe [:get-chat-command])
(let [command-atom (subscribe [:get-chat-command])
staged-commands-atom (subscribe [:get-chat-staged-commands])]
(fn []
(let [command @command-atom
(let [command @command-atom
staged-commands @staged-commands-atom]
[view {:style {:backgroundColor color-white
:elevation 4}}
[view st/new-message-container
(when (and staged-commands (pos? (count staged-commands)))
[staged-commands-view staged-commands])
(if command

View File

@ -0,0 +1,329 @@
(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
[{: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
[{: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
[{: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 content-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-name
{:fontSize 12
:fontFamily font
:color color-white})
(def command-image
{:position :absolute
:top 4
:right 0
:width 12
:height 13})
(def command-text
(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
{: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))
(def new-message-container
{:backgroundColor color-white
:elevation 4})
(def participants-container
{:flex 1
:backgroundColor :white})
(def participants-list
{:backgroundColor :white})
(def new-participant-image
{:width 20
:height 18})
(def remove-participants-image
{:width 22
:height 30})

View File

@ -1,9 +1,7 @@
(ns syng-im.components.chat.input.confirmation-code
(:require
[re-frame.core :refer [subscribe dispatch dispatch-sync]]
[syng-im.components.chat.input.simple-command :refer [simple-command-input-view]]
[syng-im.utils.utils :refer [log toast http-post]]
[syng-im.utils.logging :as log]))
[syng-im.components.chat.input.simple-command
:refer [simple-command-input-view]]))
(defn confirmation-code-input-view [command]
[simple-command-input-view command {:keyboardType "numeric"}])
[simple-command-input-view command {:keyboardType :numeric}])

View File

@ -0,0 +1,123 @@
(ns syng-im.components.chat.input.input-styles
(:require [syng-im.components.styles :refer [font
color-white
color-blue
text1-color
text2-color
chat-background
color-black]]))
(def money-input
{:flex 1
:marginLeft 8
:lineHeight 42
:fontSize 32
:fontFamily font
:color :black})
(def command-input-and-suggestions-container
{:flexDirection :column})
(def command-input-container
{:flexDirection :row
:height 56
:backgroundColor color-white
:elevation 4})
(defn command-text-container
[{:keys [color]}]
{:flexDirection :column
:marginTop 16
:marginBottom 16
:marginLeft 16
:marginRight 0
:backgroundColor color
:height 24
:borderRadius 50})
(def command-text
{:marginTop 3
:marginHorizontal 12
:fontSize 12
:fontFamily font
:color color-white})
(def command-input
{:flex 1
:marginLeft 8
:marginTop 7
:fontSize 14
:fontFamily font
:color text1-color})
(def send-container
{:marginTop 10
:marginRight 10
:width 36
:height 36
:borderRadius 50
:backgroundColor color-blue})
(def send-icon
{:marginTop 10.5
:marginLeft 12
:width 15
:height 15})
(def cancel-container
{:marginTop 10
:marginRight 10
:width 36
:height 36})
(def cancel-icon
{:marginTop 10.5
:marginLeft 12
:width 12
:height 12})
(def staged-command-container
{:flex 1
:alignItems :flex-start
:flexDirection :column
:backgroundColor color-white})
(def staged-command-background
{:flexDirection :column
:margin 16
:padding 12
:backgroundColor chat-background
:borderRadius 14})
(def staged-command-info-container
{:flexDirection :row})
(defn staged-command-text-container
[{:keys [color]}]
{:backgroundColor color
:height 24
:borderRadius 50
:marginRight 32
:paddingTop 3
:paddingHorizontal 12})
(def staged-command-text
{:fontSize 12
:fontFamily font
:color color-white})
(def staged-command-cancel
{:position :absolute
:top 7
:right 4})
(def staged-command-cancel-icon
{:width 10
:height 10})
(def staged-command-content
{:marginTop 5
:marginHorizontal 0
:fontSize 14
:fontFamily font
:color color-black})

View File

@ -1,16 +1,10 @@
(ns syng-im.components.chat.input.money
(:require
[re-frame.core :refer [subscribe dispatch dispatch-sync]]
[syng-im.components.styles :refer [font]]
[syng-im.components.chat.input.simple-command :refer [simple-command-input-view]]
[syng-im.utils.utils :refer [log toast http-post]]
[syng-im.utils.logging :as log]))
[syng-im.components.chat.input.simple-command
:refer [simple-command-input-view]]
[syng-im.components.chat.input.input-styles :as st]))
(defn money-input-view [command]
[simple-command-input-view command {:keyboardType "numeric"
:style {:flex 1
:marginLeft 8
:lineHeight 42
:fontSize 32
:fontFamily font
:color "black"}}])
[simple-command-input-view command
{:keyboardType :numeric
:style st/money-input}])

View File

@ -1,9 +1,7 @@
(ns syng-im.components.chat.input.password
(:require
[re-frame.core :refer [subscribe dispatch dispatch-sync]]
[syng-im.components.chat.input.simple-command :refer [simple-command-input-view]]
[syng-im.utils.utils :refer [log toast http-post]]
[syng-im.utils.logging :as log]))
[syng-im.components.chat.input.simple-command
:refer [simple-command-input-view]]))
(defn password-input-view [command]
[simple-command-input-view command {:secureTextEntry true}])

View File

@ -1,12 +1,10 @@
(ns syng-im.components.chat.input.phone
(:require
[re-frame.core :refer [subscribe dispatch dispatch-sync]]
[syng-im.components.chat.input.simple-command :refer [simple-command-input-view]]
[syng-im.utils.phone-number :refer [valid-mobile-number?]]
[syng-im.utils.utils :refer [log toast http-post]]
[syng-im.utils.logging :as log]))
[syng-im.components.chat.input.simple-command
:refer [simple-command-input-view]]
[syng-im.utils.phone-number :refer [valid-mobile-number?]]))
(defn phone-input-view [command]
[simple-command-input-view command {:keyboardType "phone-pad"}
[simple-command-input-view command {:keyboardType :phone-pad}
:validator (fn [message]
(valid-mobile-number? message))])

View File

@ -1,19 +1,14 @@
(ns syng-im.components.chat.input.simple-command
(:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
[syng-im.components.react :refer [android?
view
[syng-im.components.react :refer [view
image
icon
text
text-input
touchable-highlight]]
[syng-im.resources :as res]
[syng-im.components.chat.content-suggestions :refer [content-suggestions-view]]
[syng-im.components.styles :refer [font
color-white
color-blue
text1-color
text2-color]]
[syng-im.utils.utils :refer [log toast http-post]]
[syng-im.resources :as res]))
[syng-im.components.chat.input.input-styles :as st]))
(defn cancel-command-input []
(dispatch [:cancel-command]))
@ -34,65 +29,23 @@
(let [message-atom (subscribe [:get-chat-command-content])]
(fn [command input-options & {:keys [validator]}]
(let [message @message-atom]
[view {:style {:flexDirection :column}}
[view st/command-input-and-suggestions-container
[content-suggestions-view]
[view {:style {:flexDirection :row
:height 56
:backgroundColor color-white
:elevation 4}}
[view {:style {:flexDirection :column
:marginTop 16
:marginBottom 16
:marginLeft 16
:marginRight 0
:backgroundColor (:color command)
:height 24
:borderRadius 50}}
[text {:style {:marginTop 3
:marginHorizontal 12
:fontSize 12
:fontFamily font
:color color-white}}
(:text command)]]
[text-input (merge {:underlineColorAndroid :transparent
:style {:flex 1
:marginLeft 8
:marginTop 7
:fontSize 14
:fontFamily font
:color text1-color}
:autoFocus true
:placeholder "Type"
:placeholderTextColor text2-color
:onChangeText set-input-message
:onSubmitEditing (fn []
(when (valid? message validator)
(send-command)))}
[view st/command-input-container
[view (st/command-text-container command)
[text {:style st/command-text} (:text command)]]
[text-input (merge {:style st/command-input
:autoFocus true
:onChangeText set-input-message
:onSubmitEditing (fn []
(when (valid? message validator)
(send-command)))}
input-options)
message]
(if (valid? message validator)
[touchable-highlight
{:on-press send-command
:underlay-color :transparent}
[view {:style {:marginTop 10
:marginRight 10
:width 36
:height 36
:borderRadius 50
:backgroundColor color-blue}}
[image {:source {:uri :icon_send}
:style {:marginTop 10.5
:marginLeft 12
:width 15
:height 15}}]]]
[touchable-highlight {:on-press cancel-command-input
:underlay-color :transparent}
[view {:style {:marginTop 10
:marginRight 10
:width 36
:height 36}}
[touchable-highlight {:on-press send-command}
[view st/send-container [icon :send st/send-icon]]]
[touchable-highlight {:on-press cancel-command-input}
[view st/cancel-container
[image {:source res/icon-close-gray
:style {:marginTop 10.5
:marginLeft 12
:width 12
:height 12}}]]])]]))))
:style st/cancel-icon}]]])]]))))

View File

@ -1,63 +1,28 @@
(ns syng-im.components.chat.input.simple-command-staged
(:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
[syng-im.components.react :refer [android?
view
(:require [re-frame.core :refer [subscribe dispatch]]
[syng-im.components.react :refer [view
image
text
text-input
touchable-highlight]]
[syng-im.components.styles :refer [font
color-black
color-white
chat-background]]
[syng-im.utils.utils :refer [log toast http-post]]
[syng-im.utils.logging :as log]
[syng-im.resources :as res]
[reagent.core :as r]))
[syng-im.components.chat.input.input-styles :as st]))
(defn cancel-command-input [staged-command]
(dispatch [:unstage-command staged-command]))
(defn simple-command-staged-view [staged-command]
(let [chat-id-atom (subscribe [:get-current-chat-id])]
(fn [staged-command]
(let [chat-id @chat-id-atom
command (:command staged-command)]
[view {:style {:flex 1
:alignItems "flex-start"
:flexDirection "column"
:backgroundColor color-white}}
[view {:style {:flexDirection "column"
:margin 16
:padding 12
:backgroundColor chat-background
:borderRadius 14}}
[view {:style {:flexDirection "row"}}
[view {:style {:backgroundColor (:color command)
:height 24
:borderRadius 50
:marginRight 32
:paddingTop 3
:paddingHorizontal 12}}
[text {:style {:fontSize 12
:fontFamily font
:color color-white}}
(:text command)]]
[touchable-highlight {:style {:position "absolute"
:top 7
:right 4}
:onPress #(cancel-command-input
staged-command)
:underlay-color :transparent}
[image {:source res/icon-close-gray
:style {:width 10
:height 10}}]]]
[text {:style {:marginTop 5
:marginHorizontal 0
:fontSize 14
:fontFamily font
:color color-black}}
;; TODO isn't smart
(if (= (:command command) :keypair-password)
"******"
(:content staged-command))]]]))))
(let [command (:command staged-command)]
[view st/staged-command-container
[view st/staged-command-background
[view st/staged-command-info-container
[view (st/staged-command-text-container command)
[text {:style st/staged-command-text} (:text command)]]
[touchable-highlight {:style st/staged-command-cancel
:onPress #(cancel-command-input staged-command)}
[image {:source res/icon-close-gray
:style st/staged-command-cancel-icon}]]]
[text {:style st/staged-command-content}
;; TODO isn't smart
(if (= (:command command) :keypair-password)
"******"
(:content staged-command))]]]))

View File

@ -1,41 +1,35 @@
(ns syng-im.components.chat.new-participants
(:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
(:require [re-frame.core :refer [subscribe dispatch]]
[syng-im.resources :as res]
[syng-im.components.react :refer [view android? text-input text image
touchable-highlight]]
[syng-im.components.react :refer [view]]
[syng-im.components.realm :refer [list-view]]
[syng-im.components.styles :refer [font
title-font
color-white
color-black
color-blue
text1-color
text2-color
toolbar-background1]]
[syng-im.components.toolbar :refer [toolbar]]
[syng-im.utils.listview :refer [to-realm-datasource]]
[syng-im.components.chats.new-participant-contact :refer [new-participant-contact]]
[syng-im.components.chats.new-participant-contact
:refer [new-participant-contact]]
[reagent.core :as r]
[syng-im.navigation :refer [nav-pop]]))
[syng-im.components.chat.chat-message-styles :as st]))
(defn new-participants-toolbar [navigator]
[toolbar {:navigator navigator
:title "Add Participants"
:action {:image {:source res/v ;; {:uri "icon_search"}
:style {:width 20
:height 18}}
:handler (fn []
(dispatch [:add-new-participants navigator]))}}])
[toolbar
{:navigator navigator
:title "Add Participants"
:action {:image {:source res/v ;; {:uri "icon_search"}
:style st/new-participant-image}
:handler #(dispatch [:add-new-participants navigator])}}])
(defn new-participants-row [navigator]
(fn [row _ _]
(r/as-element
[new-participant-contact (js->clj row :keywordize-keys true) navigator])))
(defn new-participants [{:keys [navigator]}]
(let [contacts (subscribe [:all-new-contacts])]
(fn []
(let [contacts-ds (to-realm-datasource @contacts)]
[view {:style {:flex 1
:backgroundColor "white"}}
[view st/participants-container
[new-participants-toolbar navigator]
[list-view {:dataSource contacts-ds
:enableEmptySections true
:renderRow (fn [row section-id row-id]
(r/as-element [new-participant-contact (js->clj row :keywordize-keys true) navigator]))
:style {:backgroundColor "white"}}]]))))
:renderRow (new-participants-row navigator)
:style st/participants-list}]]))))

View File

@ -1,16 +1,11 @@
(ns syng-im.components.chat.plain-message-input
(:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
[syng-im.components.react :refer [android?
view
image
[syng-im.components.react :refer [view
icon
touchable-highlight
text-input]]
[syng-im.components.styles :refer [font
text2-color
color-white
color-blue]]
[syng-im.components.chat.suggestions :refer [suggestions-view]]
[syng-im.utils.utils :refer [log toast http-post]]))
[syng-im.components.chat.plain-message-input-styles :as st]))
(defn set-input-message [message]
(dispatch [:set-chat-input-text message]))
@ -29,49 +24,18 @@
staged-commands-atom (subscribe [:get-chat-staged-commands])]
(fn []
(let [input-message @input-message-atom]
[view {:style {:flexDirection :column}}
[view st/input-container
[suggestions-view]
[view {:style {:flexDirection :row
:height 56
:backgroundColor color-white}}
[image {:source {:uri :icon_list}
:style {:marginTop 22
:marginRight 6
:marginBottom 6
:marginLeft 21
:width 13
:height 12}}]
[text-input {:underlineColorAndroid :transparent
:style {:flex 1
:marginLeft 16
:marginTop -2
:padding 0
:fontSize 14
:fontFamily font
:color text2-color}
:autoFocus (pos? (count @staged-commands-atom))
:placeholder "Type"
:placeholderTextColor text2-color
:onChangeText set-input-message
:onSubmitEditing #(send @chat input-message)}
[view st/input-view
[icon :list st/list-icon]
[text-input {:style st/message-input
:autoFocus (pos? (count @staged-commands-atom))
:onChangeText set-input-message
:onSubmitEditing #(send @chat input-message)}
input-message]
[image {:source {:uri :icon_smile}
:style {:marginTop 18
:marginRight 18
:width 20
:height 20}}]
[icon :smile st/smile-icon]
(when (or (pos? (count input-message))
(pos? (count @staged-commands-atom)))
[touchable-highlight {:on-press #(send @chat input-message)
:underlay-color :transparent}
[view {:style {:marginTop 10
:marginRight 10
:width 36
:height 36
:borderRadius 50
:backgroundColor color-blue}}
[image {:source {:uri :icon_send}
:style {:marginTop 10.5
:marginLeft 12
:width 15
:height 15}}]]])]]))))
[touchable-highlight {:on-press #(send @chat input-message)}
[view st/send-container
[icon :send st/send-icon]]])]]))))

View File

@ -0,0 +1,50 @@
(ns syng-im.components.chat.plain-message-input-styles
(:require [syng-im.components.styles :refer [font
text2-color
color-white
color-blue]]))
(def input-container
{:flexDirection :column})
(def input-view
{:flexDirection :row
:height 56
:backgroundColor color-white})
(def list-icon
{:marginTop 22
:marginRight 6
:marginBottom 6
:marginLeft 21
:width 13
:height 12})
(def message-input
{:flex 1
:marginLeft 16
:marginTop -2
:padding 0
:fontSize 14
:fontFamily font
:color text2-color})
(def smile-icon
{:marginTop 18
:marginRight 18
:width 20
:height 20})
(def send-icon
{:marginTop 10.5
:marginLeft 12
:width 15
:height 15})
(def send-container
{:marginTop 10
:marginRight 10
:width 36
:height 36
:borderRadius 50
:backgroundColor color-blue})

View File

@ -1,41 +1,36 @@
(ns syng-im.components.chat.remove-participants
(:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
(:require [re-frame.core :refer [subscribe dispatch]]
[syng-im.resources :as res]
[syng-im.components.react :refer [view text-input text image
touchable-highlight]]
[syng-im.components.realm :refer [list-view]]
[syng-im.components.styles :refer [font
title-font
color-white
color-black
color-blue
text1-color
text2-color
toolbar-background1]]
[syng-im.components.toolbar :refer [toolbar]]
[syng-im.utils.listview :refer [to-realm-datasource]]
[syng-im.components.chats.new-participant-contact :refer [new-participant-contact]]
[syng-im.components.chats.new-participant-contact
:refer [new-participant-contact]]
[reagent.core :as r]
[syng-im.navigation :refer [nav-pop]]))
[syng-im.components.chat.chat-message-styles :as st]))
(defn remove-participants-toolbar [navigator]
[toolbar {:navigator navigator
:title "Remove Participants"
:action {:image {:source res/trash-icon ;; {:uri "icon_search"}
:style {:width 22
:height 30}}
:handler (fn []
(dispatch [:remove-selected-participants navigator]))}}])
[toolbar
{:navigator navigator
:title "Remove Participants"
:action {:handler #(dispatch [:remove-selected-participants navigator])
:image {:source res/trash-icon ;; {:uri "icon_search"}
:style st/remove-participants-image}}}])
(defn remove-participants-row [navigator]
(fn [row _ _]
(r/as-element
[new-participant-contact (js->clj row :keywordize-keys true) navigator])))
(defn remove-participants [{:keys [navigator]}]
(let [contacts (subscribe [:current-chat-contacts])]
(fn []
(let [contacts-ds (to-realm-datasource @contacts)]
[view {:style {:flex 1
:backgroundColor "white"}}
[view st/participants-container
[remove-participants-toolbar navigator]
[list-view {:dataSource contacts-ds
:enableEmptySections true
:renderRow (fn [row section-id row-id]
(r/as-element [new-participant-contact (js->clj row :keywordize-keys true) navigator]))
:style {:backgroundColor "white"}}]]))))
:renderRow (remove-participants-row navigator)
:style st/participants-list}]]))))

View File

@ -1,56 +1,29 @@
(ns syng-im.components.chat.suggestions
(:require-macros
[natal-shell.core :refer [with-error-view]])
(:require [clojure.string :as cstr]
[reagent.core :as r]
[re-frame.core :refer [subscribe dispatch dispatch-sync]]
(:require [re-frame.core :refer [subscribe dispatch]]
[syng-im.components.react :refer [view
image
text
touchable-highlight
list-view
list-item]]
[syng-im.components.styles :refer [font
color-white]]
[syng-im.utils.listview :refer [to-datasource]]
[syng-im.utils.utils :refer [log toast http-post]]
[syng-im.utils.logging :as log]))
[syng-im.components.chat.suggestions-styles :as st]))
(defn set-command-input [command]
(dispatch [:set-chat-command command]))
(defn suggestion-list-item [suggestion]
[touchable-highlight {:onPress (fn []
(set-command-input (keyword (:command suggestion))))
:underlay-color :transparent}
[view {:style {:flexDirection "row"
:marginVertical 1
:marginHorizontal 0
:height 40
:backgroundColor color-white}}
[view {:style {:flexDirection "column"
:position "absolute"
:top 10
:left 60
:backgroundColor (:color suggestion)
:borderRadius 10}}
[text {:style {:marginTop -2
:marginHorizontal 10
:fontSize 14
:fontFamily font
:color color-white}}
[touchable-highlight
{:onPress #(set-command-input (keyword (:command suggestion)))}
[view st/suggestion-item-container
[view (st/suggestion-background suggestion)
[text {:style st/suggestion-text}
(:text suggestion)]]
[text {:style {:flex 1
:position "absolute"
:top 7
:left 190
:lineHeight 18
:fontSize 14
:fontFamily font
:color "black"}}
[text {:style st/suggestion-description}
(:description suggestion)]]])
(defn render-row [row section-id row-id]
(defn render-row [row _ _]
(list-item [suggestion-list-item (js->clj row :keywordize-keys true)]))
(defn suggestions-view []
@ -58,12 +31,7 @@
(fn []
(let [suggestions @suggestions-atom]
(when (seq suggestions)
[view {:style {:flexDirection "row"
:marginVertical 1
:marginHorizontal 0
:height (min 105 (* 42 (count suggestions)))
:backgroundColor color-white
:borderRadius 5}}
[view (st/suggestions-container suggestions)
[list-view {:dataSource (to-datasource suggestions)
:enableEmptySections true
:renderRow render-row

View File

@ -0,0 +1,44 @@
(ns syng-im.components.chat.suggestions-styles
(:require [syng-im.components.styles :refer [font color-white]]))
(def suggestion-item-container
{:flexDirection :row
:marginVertical 1
:marginHorizontal 0
:height 40
:backgroundColor color-white})
(defn suggestion-background
[{:keys [color]}]
{:flexDirection :column
:position :absolute
:top 10
:left 60
:backgroundColor color
:borderRadius 10})
(def suggestion-text
{:marginTop -2
:marginHorizontal 10
:fontSize 14
:fontFamily font
:color color-white})
(def suggestion-description
{:flex 1
:position :absolute
:top 7
:left 190
:lineHeight 18
:fontSize 14
:fontFamily font
:color :black})
(defn suggestions-container
[suggestions]
{:flexDirection :row
:marginVertical 1
:marginHorizontal 0
:height (min 105 (* 42 (count suggestions)))
:backgroundColor color-white
:borderRadius 5})

View File

@ -0,0 +1,169 @@
(ns syng-im.components.chat-styles
(:require [syng-im.components.styles :refer [font
title-font
color-white
chat-background
online-color
selected-message-color
separator-color
text1-color
text2-color
toolbar-background1]]))
(def chat-view
{:flex 1
:backgroundColor chat-background})
(def toolbar-view
{:flexDirection :row
:height 56
:backgroundColor toolbar-background1
:elevation 2})
(def icon-view
{:width 56
:height 56})
(def back-icon
{:marginTop 21
:marginLeft 23
:width 8
:height 14})
(defn chat-name-view [show-actions]
{:flex 1
:marginLeft (if show-actions 16 0)
:alignItems :flex-start
:justifyContent :center})
(def chat-name-text
{:marginTop -2.5
:color text1-color
:fontSize 16
:fontFamily font})
(def group-icon
{:marginTop 4
:width 14
:height 9})
(def up-icon
{:marginTop 23
:marginLeft 21
:width 14
:height 8})
(def members
{:marginTop -0.5
:marginLeft 4
:fontFamily font
:fontSize 12
:color text2-color})
(def last-activity
{:marginTop 1
:color text2-color
:fontSize 12
:fontFamily font})
(def actions-wrapper
{:backgroundColor toolbar-background1
:elevation 2
:position :absolute
:top 56
:left 0
:right 0})
(def actions-separator
{:marginLeft 16
:height 1.5
:backgroundColor separator-color})
(def actions-view
{:marginVertical 10})
(def action-icon-row
{:flexDirection :row
:height 56})
(def action-icon-view
(merge icon-view
{:alignItems :center
:justifyContent :center}))
(def action-view
{:flex 1
:alignItems :flex-start
:justifyContent :center})
(def action-title
{:marginTop -2.5
:color text1-color
:fontSize 14
:fontFamily font})
(def action-subtitle
{:marginTop 1
:color text2-color
:fontSize 12
:fontFamily font})
(def online-view
{:position :absolute
:top 30
:left 30
:width 20
:height 20
:borderRadius 50
:backgroundColor online-color
:borderWidth 2
:borderColor color-white})
(def online-dot
{:position :absolute
:top 6
:width 4
:height 4
:borderRadius 50
:backgroundColor color-white})
(def online-dot-left (merge online-dot {:left 3}))
(def online-dot-right (merge online-dot {:left 9}))
(def typing-all
{:marginBottom 20})
(def typing-view
{:width 260
:marginTop 10
:paddingLeft 8
:paddingRight 8
:alignItems :flex-start
:alignSelf :flex-start})
(def typing-background
{:borderRadius 14
:padding 12
:height 38
:backgroundColor selected-message-color})
(def typing-text
{:marginTop -2
:fontSize 12
:fontFamily font
:color text2-color})
(def chat-photo
{:borderRadius 50
:width 36
:height 36})
(def actions-overlay
{:position :absolute
:top 0
:bottom 0
:left 0
:right 0})
(def overlay-highlight
{:flex 1})

View File

@ -10,9 +10,8 @@
[syng-im.resources :as res]))
(defn chat-list-item [chat-obj navigator]
[touchable-highlight {:on-press (fn []
(dispatch [:show-chat (aget chat-obj "chat-id") navigator :push]))
:underlay-color :transparent}
[touchable-highlight
{:on-press #(dispatch [:show-chat (aget chat-obj "chat-id") navigator :push])}
;; TODO add [photo-path delivery-status new-messages-count online] values to chat-obj
;; TODO should chat-obj be clj-map?
[view {} [chat-list-item-inner-view (merge (js->clj chat-obj :keywordize-keys true)

View File

@ -68,8 +68,7 @@
:fontSize 14
:lineHeight 20}}
"Members"]
[touchable-highlight {:on-press (fn [])
:underlay-color :transparent}
[touchable-highlight {:on-press (fn [])}
[view {:style {:flexDirection "row"
:marginBottom 16}}
[image {:source {:uri "icon_add_gray"}

View File

@ -9,7 +9,5 @@
(defn contact-view [{:keys [navigator contact]}]
(let [{:keys [whisper-identity]} contact]
[touchable-highlight {:onPress (fn []
(show-chat navigator whisper-identity))
:underlay-color :transparent}
[touchable-highlight {:onPress #(show-chat navigator whisper-identity)}
[view {} [contact-inner-view contact]]]))

View File

@ -1,5 +1,6 @@
(ns syng-im.components.react
(:require [reagent.core :as r]))
(:require [reagent.core :as r]
[syng-im.components.styles :as st]))
(set! js/window.React (js/require "react-native"))
@ -8,14 +9,30 @@
(def text (r/adapt-react-class (.-Text js/React)))
(def view (r/adapt-react-class (.-View js/React)))
(def image (r/adapt-react-class (.-Image js/React)))
(def touchable-highlight (r/adapt-react-class (.-TouchableHighlight js/React)))
(def touchable-highlight-class (r/adapt-react-class (.-TouchableHighlight js/React)))
(defn touchable-highlight [props content]
[touchable-highlight-class
(merge {:underlay-color :transparent} props)
content])
(def toolbar-android (r/adapt-react-class (.-ToolbarAndroid js/React)))
(def list-view (r/adapt-react-class (.-ListView js/React)))
(def scroll-view (r/adapt-react-class (.-ScrollView js/React)))
(def text-input (r/adapt-react-class (.-TextInput js/React)))
(def text-input-class (r/adapt-react-class (.-TextInput js/React)))
(defn text-input [props text]
[text-input-class (merge
{:underlineColorAndroid :transparent
:placeholderTextColor st/text2-color
:placeholder "Type"}
props)
text])
(def drawer-layout-android (r/adapt-react-class (.-DrawerLayoutAndroid js/React)))
(def touchable-opacity (r/adapt-react-class (.-TouchableOpacity js/React)))
(defn icon [n style]
[image {:source {:uri (keyword (str "icon_" (name n)))}
:style style}])
(def platform (.. js/React -Platform -OS))
(def android? (= platform "android"))

View File

@ -24,16 +24,13 @@
:height 56
:elevation 2}}
(if nav-action
[touchable-highlight {:on-press (:handler nav-action)
:underlay-color :transparent}
[touchable-highlight {:on-press (:handler nav-action)}
[view {:width 56
:height 56
:alignItems "center"
:justifyContent "center"}
[image (:image nav-action)]]]
[touchable-highlight {:on-press (fn []
(nav-pop navigator))
:underlay-color :transparent}
[touchable-highlight {:on-press #(nav-pop navigator)}
[view {:width 56
:height 56}
[image {:source {:uri "icon_back"}
@ -41,16 +38,15 @@
:marginLeft 23
:width 8
:height 14}}]]])
[view {:style {:flex 1
:alignItems "center"
[view {:style {:flex 1
:alignItems "center"
:justifyContent "center"}}
[text {:style {:marginTop -2.5
:color text1-color
:fontSize 16
:fontFamily font}}
title]]
[touchable-highlight {:on-press (:handler action)
:underlay-color :transparent}
[touchable-highlight {:on-press (:handler action)}
[view {:width 56
:height 56
:alignItems "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

@ -17,7 +17,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]]
[syng-im.handlers.content-suggestions :refer [get-content-suggestions]]))
@ -111,9 +111,9 @@
(get @db :signed-up))))
(register-sub
:show-actions
(fn [db _]
(reaction (get-in @db db/show-actions-path))))
:show-actions
(fn [db _]
(reaction (get-in @db db/show-actions-path))))
(register-sub
:get-contacts
@ -167,16 +167,16 @@
(register-sub :navigation-stack
(fn [db _]
(:navigation-stack @db)))
(reaction (:navigation-stack @db))))
(register-sub :db
(fn [db _] (reaction @db)))
(register-sub :chat-properties
(fn [{:keys [current-chat-id] :as db} [_ properties]]
(fn [db [_ properties]]
(->> properties
(map (fn [k]
[k (-> @db
(get-in [:cgats current-chat-id k])
(get-in [:chats (:current-chat-id @db) k])
(reaction))]))
(into {}))))