diff --git a/src/status_im/chat/events.cljs b/src/status_im/chat/events.cljs index b3a5c3627a..85cedba498 100644 --- a/src/status_im/chat/events.cljs +++ b/src/status_im/chat/events.cljs @@ -294,6 +294,7 @@ (fn [cofx [chat]] (models/update-chat cofx chat))) + (handlers/register-handler-fx :remove-chat [re-frame/trim-v] @@ -325,3 +326,24 @@ :content (i18n/label (if group? :t/delete-group-chat-confirmation :t/delete-chat-confirmation)) :confirm-button-text (i18n/label :t/delete) :on-accept #(re-frame/dispatch [:delete-chat chat-id])}})) + +(defn remove-chats [db chat-id] + (let [chat (get-in db [:chats chat-id])] + {:db (-> db + (update :chats dissoc chat-id) + (update :deleted-chats (fnil conj #{}) chat-id)) + :delete-chat chat + :delete-chat-messages chat})) + +(handlers/register-handler-fx + :remove-chat + [re-frame/trim-v] + (fn [{:keys [db]} [chat-id]] + (remove-chats db chat-id))) + +(handlers/register-handler-fx + :remove-chat-and-navigate-home + [re-frame/trim-v] + (fn [{:keys [db]} [chat-id]] + (merge (remove-chats db chat-id) + {:dispatch [:navigation-replace :home]}))) \ No newline at end of file diff --git a/src/status_im/chat/screen.cljs b/src/status_im/chat/screen.cljs index e4a9ac02f4..92223b5b71 100644 --- a/src/status_im/chat/screen.cljs +++ b/src/status_im/chat/screen.cljs @@ -4,6 +4,11 @@ [re-frame.core :as re-frame] [status-im.i18n :as i18n] [status-im.chat.styles.screen :as style] + [status-im.utils.platform :as platform] + [status-im.chat.views.toolbar-content :as toolbar-content] + [status-im.chat.views.message.message :as message] + [status-im.chat.views.message.datemark :as message-datemark] + [status-im.chat.views.input.input :as input] [status-im.chat.views.actions :as actions] [status-im.chat.views.bottom-info :as bottom-info] [status-im.chat.views.message.datemark :as message-datemark] @@ -17,7 +22,17 @@ [status-im.ui.components.status-bar.view :as status-bar] [status-im.ui.components.connectivity.view :as connectivity] [status-im.ui.components.toolbar.view :as toolbar] - [status-im.utils.platform :as platform])) + [status-im.ui.components.animation :as animation] + [status-im.ui.components.icons.vector-icons :as vector-icons] + [status-im.ui.components.colors :as colors])) + +(defn toolbar-action [chat-id chat-name group-chat public?] + [react/touchable-highlight + {:on-press #(list-selection/show {:title chat-name + :options (actions/actions chat-id group-chat public?)}) + :accessibility-label :chat-menu} + [react/view style/action + [vector-icons/icon :icons/dots-horizontal]]]) (defview add-contact-bar [] (letsubs [chat-id [:get-current-chat-id] @@ -38,7 +53,7 @@ {:keys [group-chat name chat-id]} [:get-current-chat]] [react/view [status-bar/status-bar] - [toolbar/toolbar {} + [toolbar/platform-agnostic-toolbar {} toolbar/default-nav-back [toolbar-content/toolbar-content-view] [toolbar/actions [{:icon :icons/options @@ -78,16 +93,20 @@ (defview messages-view [group-chat] (letsubs [messages [:get-current-chat-messages] current-public-key [:get-current-public-key]] - [list/flat-list {:data messages - :render-fn (fn [{:keys [message-id] :as message}] - ^{:key message-id} - [message-row {:group-chat group-chat - :current-public-key current-public-key - :row message}]) - :inverted true - :onEndReached #(re-frame/dispatch [:load-more-messages]) - :enableEmptySections true - :keyboardShouldPersistTaps (if platform/android? :always :handled)}])) + (if (empty? messages) + [react/view style/empty-chat-container + [react/text {:style style/empty-chat-text} + (i18n/label :t/empty-chat-description)]] + [list/flat-list {:data messages + :render-fn (fn [{:keys [message-id] :as message}] + ^{:key message-id} + [message-row {:group-chat group-chat + :current-public-key current-public-key + :row message}]) + :inverted true + :onEndReached #(re-frame/dispatch [:load-more-messages]) + :enableEmptySections true + :keyboardShouldPersistTaps (if platform/android? :always :handled)}]))) (defview chat [] (letsubs [{:keys [group-chat public? input-text]} [:get-current-chat] diff --git a/src/status_im/chat/styles/message/message.cljs b/src/status_im/chat/styles/message/message.cljs index 7efc641c6e..981dcc13fe 100644 --- a/src/status_im/chat/styles/message/message.cljs +++ b/src/status_im/chat/styles/message/message.cljs @@ -1,8 +1,11 @@ (ns status-im.chat.styles.message.message (:require-macros [status-im.utils.styles :refer [defstyle defnstyle]]) (:require [status-im.ui.components.styles :as styles] + [status-im.ui.components.colors :as colors] [status-im.constants :as constants])) +(def photo-size 36) + (defstyle style-message-text {:font-size 15 :color styles/text1-color @@ -24,15 +27,6 @@ same-direction? 16 :else 24)) -(defn last-message-padding - [{:keys [last? typing]}] - (when (and last? (not typing)) - {:padding-bottom 16})) - -(def message-datemark - {:margin-top 10 - :height 34}) - (def message-empty-spacing {:height 16}) @@ -40,6 +34,11 @@ {:padding-right 10 :padding-left 10}) +(defn last-message-padding + [{:keys [last? typing]}] + (when (and last? (not typing)) + {:padding-bottom 16})) + (defn message-body [{:keys [outgoing] :as message}] (let [align (if outgoing :flex-end :flex-start) @@ -49,8 +48,7 @@ :width 260 :padding-top (message-padding-top message) :align-self align - :align-items align} - (last-message-padding message)))) + :align-items align}))) (def selected-message {:margin-top 18 @@ -58,11 +56,12 @@ :font-size 12 :color styles/text2-color}) -(def group-message-wrapper - {:flex-direction :column}) +(defn group-message-wrapper [message] + (merge {:flex-direction :column} + (last-message-padding message))) (defn group-message-view - [{:keys [outgoing] :as message}] + [outgoing] (let [align (if outgoing :flex-end :flex-start)] {:flex-direction :column :width 260 @@ -70,14 +69,18 @@ :padding-right 10 :align-items align})) +(def delivery-status + {:align-self :flex-end + :padding-right 56}) + (def message-author - {:width 36 + {:width photo-size :align-self :flex-start}) (def photo - {:border-radius 18 - :width 36 - :height 36}) + {:border-radius (/ photo-size 2) + :width photo-size + :height photo-size}) (def delivery-view {:flex-direction :row @@ -255,3 +258,10 @@ {:background-color styles/color-white :margin-bottom margin :elevation (if on-top? 6 5)}) + +(def message-author-name + {:font-size 12 + :letter-spacing -0.2 + :padding-bottom 4 + :color colors/gray}) + diff --git a/src/status_im/chat/styles/screen.cljs b/src/status_im/chat/styles/screen.cljs index f3ae0c63bb..10e7772af8 100644 --- a/src/status_im/chat/styles/screen.cljs +++ b/src/status_im/chat/styles/screen.cljs @@ -1,6 +1,7 @@ (ns status-im.chat.styles.screen (:require-macros [status-im.utils.styles :refer [defstyle defnstyle]]) - (:require [status-im.ui.components.styles :as component.styles])) + (:require [status-im.ui.components.styles :as component.styles] + [status-im.ui.components.colors :as colors])) (def chat-view {:flex 1 @@ -37,6 +38,10 @@ :width 8 :height 14}) +(def chat-toolbar-contents + {:flex-direction :row + :flex 1}) + (defnstyle chat-name-view [show-actions] {:flex 1 :justify-content :center @@ -200,3 +205,17 @@ (defn message-view-animated [opacity] {:opacity opacity :flex 1}) + +(def empty-chat-container + {:flex 1 + :flex-direction :row + :justify-content :center + :align-items :center + :padding-vertical 50 + :margin-right 6}) + +(def empty-chat-text + {:color colors/gray + :font-size 14 + :line-height 20 + :letter-spacing -0.2}) \ No newline at end of file diff --git a/src/status_im/chat/subs.cljs b/src/status_im/chat/subs.cljs index d56c2ce8db..7a8c6e1825 100644 --- a/src/status_im/chat/subs.cljs +++ b/src/status_im/chat/subs.cljs @@ -130,23 +130,25 @@ (->> message-datemark-groups (mapcat (fn [[datemark messages]] (let [prepared-messages (into [] - (map (fn [{:keys [message-id] :as message} previous-message] + (map (fn [previous-message + {:keys [message-id] :as message} + next-message] (assoc message - :same-author? (= (:from message) - (:from previous-message)) - :same-direction? (= (:outgoing message) - (:outgoing previous-message)) - :last? (= message-id - last-message-id) - :last-outgoing? (= message-id - last-outgoing-message-id))) + :same-author? (= (:from message) + (:from previous-message)) + :same-direction? (= (:outgoing message) + (:outgoing previous-message)) + :last-by-same-author? (not= (:from message) + (:from next-message)) + :last? (= message-id + last-message-id) + :last-outgoing? (= message-id + last-outgoing-message-id))) + (concat (rest messages) '(nil)) messages - (concat (rest messages) '(nil))))] + (concat '(nil) (butlast messages))))] (conj prepared-messages {:type :datemark - :value datemark})))))) - ;; when no messages are in chat, we need to at least fake-out today's datemark - (list {:type :datemark - :value (i18n/label :t/datetime-today)}))) + :value datemark})))))))) (reg-sub :get-current-chat-messages diff --git a/src/status_im/chat/views/message/message.cljs b/src/status_im/chat/views/message/message.cljs index d9ccbcf496..167207ff2d 100644 --- a/src/status_im/chat/views/message/message.cljs +++ b/src/status_im/chat/views/message/message.cljs @@ -24,14 +24,6 @@ (def window-width (:width (react/get-dimensions "window"))) -(defview message-author-name [{:keys [outgoing from username] :as message}] - (letsubs [current-account [:get-current-account] - incoming-name [:contact-name-by-identity from]] - (when-let [name (if outgoing - (:name current-account) - (or incoming-name username (gfycat/generate-gfy from)))] - [react/text {:style style/author} name]))) - (defview message-content-status [] (letsubs [{:keys [chat-id group-id name color public-key]} [:get-current-chat] members [:current-chat-contacts]] @@ -89,7 +81,6 @@ (defn message-view [{:keys [group-chat] :as message} content] [react/view (style/message-view message) - (when group-chat [message-author-name message]) content]) (def replacements @@ -266,24 +257,31 @@ (letsubs [{:keys [photo-path]} [:get-current-account]] (photo from photo-path))) +(defview message-author-name [from] + (letsubs [username [:contact-name-by-identity from]] + [react/text {:style style/message-author-name} username])) + (defn message-body - [{:keys [last-outgoing? message-type same-author? from outgoing group-chat] :as message} content] - [react/view style/group-message-wrapper + [{:keys [last-outgoing? last-by-same-author? message-type same-author? from outgoing group-chat] :as message} content] + [react/view (style/group-message-wrapper message) [react/view (style/message-body message) [react/view style/message-author - (when-not same-author? + (when last-by-same-author? (if outgoing [my-photo from] [react/touchable-highlight {:on-press #(re-frame/dispatch [:show-profile from])} [react/view [member-photo from]]]))] - [react/view (style/group-message-view message) - content - (when last-outgoing? - (if (or (= (keyword message-type) :group-user-message) - group-chat) - [group-message-delivery-status message] - [message-delivery-status message]))]]]) + [react/view (style/group-message-view outgoing) + (when-not same-author? + [message-author-name from]) + content]] + (when last-outgoing? + [react/view style/delivery-status + (if (or (= (keyword message-type) :group-user-message) + group-chat) + [group-message-delivery-status message] + [message-delivery-status message])])]) (defn message-container-animation-logic [{:keys [to-value val callback]}] (fn [_] diff --git a/src/status_im/translations/en.cljs b/src/status_im/translations/en.cljs index 228841f667..fb9695753c 100644 --- a/src/status_im/translations/en.cljs +++ b/src/status_im/translations/en.cljs @@ -191,6 +191,7 @@ :topic-format "Wrong format [a-z0-9\\-]+" :public-group-topic "Topic" :set-a-topic "Set a topic" + :empty-chat-description "There are no messages \nin this chat yet" ;;discover :discover "Discover" diff --git a/src/status_im/ui/components/toolbar/view.cljs b/src/status_im/ui/components/toolbar/view.cljs index e96ca4b501..b059083c9e 100644 --- a/src/status_im/ui/components/toolbar/view.cljs +++ b/src/status_im/ui/components/toolbar/view.cljs @@ -123,6 +123,19 @@ [react/view components.styles/flex] action-items])) +(defn platform-agnostic-toolbar + ([props nav-item content-item] (platform-agnostic-toolbar props nav-item content-item [actions [{:image :blank}]])) + ([{:keys [background-color style flat?]} + nav-item + content-item + action-items] + [react/view {:style (merge (styles/toolbar background-color flat?) style)} + (when nav-item + [react/view {:style (styles/toolbar-nav-actions-container 0)} + nav-item]) + content-item + action-items])) + (defn simple-toolbar "A simple toolbar composed of a nav-back item and a single line title." ([] (simple-toolbar nil)) diff --git a/src/status_im/ui/screens/contacts/subs.cljs b/src/status_im/ui/screens/contacts/subs.cljs index 5f9c2b2ebe..02f9d315b2 100644 --- a/src/status_im/ui/screens/contacts/subs.cljs +++ b/src/status_im/ui/screens/contacts/subs.cljs @@ -114,8 +114,12 @@ (reg-sub :contact-name-by-identity :<- [:get-contacts] - (fn [contacts [_ identity]] - (:name (contacts identity)))) + :<- [:get-current-account] + (fn [[contacts current-account] [_ identity]] + (let [me? (= (:public-key current-account) identity)] + (if me? + (:name current-account) + (:name (contacts identity)))))) (defn chat-contacts [[chat contacts] [_ fn]] (when chat