196 lines
8.6 KiB
Plaintext
Raw Normal View History

(ns syng-im.components.chat
(:require [clojure.string :as s]
[re-frame.core :refer [subscribe dispatch dispatch-sync]]
[syng-im.components.react :refer [android?
view
text
image
navigator
toolbar-android]]
[syng-im.components.realm :refer [list-view]]
[syng-im.components.styles :refer [font
title-font
color-white
chat-background
online-color
selected-message-color
text1-color
text2-color]]
[syng-im.utils.logging :as log]
[syng-im.navigation :refer [nav-pop]]
[syng-im.resources :as res]
[syng-im.utils.listview :refer [to-realm-datasource]]
[syng-im.components.invertible-scroll-view :refer [invertible-scroll-view]]
[reagent.core :as r]
[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}]
[identity contact]))
(into {})))
(defn add-msg-color [{:keys [from] :as msg} contact-by-identity]
(if (= "system" from)
(assoc msg :text-color "#4A5258"
:background-color "#D3EEEF")
(let [{:keys [text-color background-color]} (get contact-by-identity from)]
(assoc msg :text-color text-color
:background-color background-color))))
(defn chat-photo [{:keys [photo-path]}]
[view {:borderRadius 50}
[image {:source (if (s/blank? photo-path)
res/user-no-photo
{:uri photo-path})
:style {:borderRadius 50
:width 36
:height 36}}]])
(defn contact-online [{:keys [online]}]
(when online
[view {:position "absolute"
:top 20
:left 20
: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}]]))
(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}}
(str member " is typing")]]])
(defn typing-all []
[view {:style {:marginBottom 20}}
(for [member ["Geoff" "Justas"]]
^{:key member} [typing member])])
(defn toolbar-content-chat [chat]
(let [group? (:group-chat 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 (chat :name)
"Chat name")]
(if group?
[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}}
(str (count (:contacts chat))
(if (< 1 (count (:contacts chat)))
" members"
" member")
", " (count (:contacts chat)) " active")]]
[text {:style {:marginTop 1
:color text2-color
:fontSize 12
:fontFamily font}}
"Active a minute ago"])]
(when-not group?
[view {:style {:position "absolute"
:top 10
:right 66}}
[chat-photo {}]
[contact-online {:online true}]])]))
(defn chat [{:keys [navigator]}]
(let [messages (subscribe [:get-chat-messages])
chat (subscribe [:get-current-chat])]
(fn []
(let [msgs @messages
;_ (log/debug "messages=" msgs)
;; temp
typing (:group-chat @chat)
;; end temp
datasource (to-realm-datasource msgs)
contacts (:contacts @chat)
contact-by-identity (contacts-by-identity contacts)]
[view {:style {:flex 1
:backgroundColor chat-background}}
(when android?
;; TODO add IOS version
[toolbar-android {:navIcon {:uri "icon_back"}
:style {:backgroundColor color-white
:height 56
:elevation 2}
:actions (when (and (:group-chat @chat)
(:is-active @chat))
[{: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}])
:onActionSelected (fn [position]
(case position
0 (dispatch [:show-add-participants navigator])
1 (dispatch [:show-remove-participants navigator])
2 (dispatch [:leave-group-chat navigator])))
:onIconClicked (fn []
(nav-pop navigator))}
[toolbar-content-chat @chat]])
(let [last-msg-id (:last-msg-id @chat)]
[list-view {:dataSource datasource
:renderScrollComponent (fn [props]
(invertible-scroll-view (js->clj props)))
:renderRow (fn [row section-id row-id]
(let [msg (-> (js->clj row :keywordize-keys true)
(add-msg-color contact-by-identity)
(assoc :group-chat (:group-chat @chat))
(assoc :typing typing))]
(r/as-element [chat-message msg last-msg-id])))}])
(when (:group-chat @chat)
[typing-all])
(when (:is-active @chat)
[chat-message-new])]))))