220 lines
8.7 KiB
Plaintext
Raw Normal View History

(ns status-im.chat.screen
(:require-macros [status-im.utils.views :refer [defview]])
(:require [re-frame.core :refer [subscribe dispatch]]
[status-im.components.react :refer [view
text
image
icon
touchable-highlight
list-view
list-item]]
[status-im.components.chat-icon.screen :refer [chat-icon-view-action
chat-icon-view-menu-item]]
[status-im.chat.styles.screen :as st]
[status-im.utils.listview :refer [to-datasource]]
[status-im.components.invertible-scroll-view :refer [invertible-scroll-view]]
[status-im.components.toolbar :refer [toolbar]]
[status-im.chat.views.message :refer [chat-message]]
[status-im.chat.views.new-message :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))))
(defview chat-icon []
[chat-id [:chat :chat-id]
group-chat [:chat :group-chat]
name [:chat :name]
color [:chat :color]]
;; TODO stub data ('online' property)
[chat-icon-view-action chat-id group-chat name color true])
(defn typing [member]
[view st/typing-view
[view st/typing-background
[text {:style st/typing-text}
(str member " is typing")]]])
(defn typing-all []
[view st/typing-all
;; TODO stub data
(for [member ["Geoff" "Justas"]]
^{:key member} [typing member])])
(defn message-row [contact-by-identity group-chat]
(fn [row _ idx]
(let [msg (-> row
(add-msg-color contact-by-identity)
(assoc :group-chat group-chat)
(assoc :last-msg (zero? (js/parseInt idx))))]
(list-item [chat-message msg]))))
(defn on-action-selected [position]
(case position
0 (dispatch [:show-add-participants])
1 (dispatch [:show-remove-participants])
2 (dispatch [:leave-group-chat])))
(defn overlay [{:keys [on-click-outside]} items]
[view st/actions-overlay
[touchable-highlight {:on-press on-click-outside
:style st/overlay-highlight}
[view nil]]
items])
(defn action-view [{:keys [icon-style custom-icon handler title subtitle]
icon-name :icon}]
[touchable-highlight {:on-press (fn []
(dispatch [:set-show-actions false])
(when handler
(handler)))}
[view st/action-icon-row
[view st/action-icon-view
(or custom-icon
[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])]]])
(defview menu-item-icon-profile []
[chat-id [:chat :chat-id]
group-chat [:chat :group-chat]
name [:chat :name]
color [:chat :color]]
;; TODO stub data ('online' property)
[chat-icon-view-menu-item chat-id group-chat name color true])
(defn actions-list-view []
(let [{:keys [group-chat chat-id]}
(subscribe [:chat-properties [:group-chat :chat-id]])]
(when-let [actions (if @group-chat
[{:title "Add Contact to chat"
:icon :menu_group
:icon-style {:width 25
:height 19}
:handler #(dispatch [:show-add-participants])}
{:title "Remove Contact from chat"
:subtitle "Alex, John"
:icon :search_gray_copy
:icon-style {:width 17
:height 17}
:handler #(dispatch [:show-remove-participants])}
{:title "Leave Chat"
:icon :muted
:icon-style {:width 18
:height 21}
:handler #(dispatch [:leave-group-chat])}
{:title "Settings"
:icon :settings
:icon-style {:width 20
:height 13}
:handler #(dispatch [:show-group-settings])}]
[{:title "Profile"
:custom-icon [menu-item-icon-profile]
:icon :menu_group
:icon-style {:width 25
:height 19}
:handler #(dispatch [:show-profile @chat-id])}
{:title "Search chat"
:subtitle "!not implemented"
:icon :search_gray_copy
:icon-style {:width 17
:height 17}
:handler nil}
{:title "Notifications and sounds"
:subtitle "!not implemented"
:icon :muted
:icon-style {:width 18
:height 21}
:handler nil}
{:title "Settings"
:subtitle "!not implemented"
:icon :settings
:icon-style {:width 20
:height 13}
:handler (fn [])}])]
[view st/actions-wrapper
[view st/actions-separator]
[view st/actions-view
(for [action actions]
^{:key action} [action-view action])]])))
(defn actions-view []
[overlay {:on-click-outside #(dispatch [:set-show-actions false])}
[actions-list-view]])
(defn toolbar-content []
(let [{:keys [group-chat name contacts]}
(subscribe [:chat-properties [:group-chat :name :contacts]])
show-actions (subscribe [:show-actions])]
(fn []
[view (st/chat-name-view @show-actions)
[text {:style st/chat-name-text}
(or @name "Chat name")]
(if @group-chat
[view {:flexDirection :row}
[icon :group st/group-icon]
[text {:style st/members}
(let [cnt (inc (count @contacts))]
(str cnt
(if (< 1 cnt)
" members"
" member")
", " cnt " active"))]]
[text {:style st/last-activity} "Active a minute ago"])])))
(defn toolbar-action []
(let [show-actions (subscribe [:show-actions])]
(fn []
(if @show-actions
[touchable-highlight
{:on-press #(dispatch [:set-show-actions false])}
[view st/action
[icon :up st/up-icon]]]
[touchable-highlight
{:on-press #(dispatch [:set-show-actions true])}
[view st/action
[chat-icon]]]))))
(defn chat-toolbar []
(let [{:keys [group-chat name contacts]}
(subscribe [:chat-properties [:group-chat :name :contacts]])
show-actions (subscribe [:show-actions])]
(fn []
[toolbar {:hide-nav? @show-actions
:custom-content [toolbar-content]
:custom-action [toolbar-action]}])))
(defview messages-view [group-chat]
[messages [:chat :messages]
contacts [:chat :contacts]]
(let [contacts' (contacts-by-identity contacts)]
[list-view {:renderRow (message-row contacts' group-chat)
:renderScrollComponent #(invertible-scroll-view (js->clj %))
:onEndReached #(dispatch [:load-more-messages])
:enableEmptySections true
:dataSource (to-datasource messages)}]))
(defview chat []
[group-chat [:chat :group-chat]
show-actions-atom [:show-actions]]
[view st/chat-view
[chat-toolbar]
[messages-view group-chat]
(when group-chat [typing-all])
[chat-message-new]
(when show-actions-atom [actions-view])])