ISSUE #3083] Adapted chat menu to latest mockups

Signed-off-by: Julien Eluard <julien.eluard@gmail.com>
This commit is contained in:
Julien Eluard 2018-02-13 15:41:45 +01:00
parent b228883de5
commit 058e6c5412
No known key found for this signature in database
GPG Key ID: 6FD7DB5437FCBEF6
8 changed files with 78 additions and 224 deletions

View File

@ -2,9 +2,7 @@
(:require [clojure.set :as set] (:require [clojure.set :as set]
[cljs.core.async :as async] [cljs.core.async :as async]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[taoensso.timbre :as log]
[status-im.utils.handlers :as handlers] [status-im.utils.handlers :as handlers]
[status-im.utils.gfycat.core :as gfycat]
[status-im.utils.async :as async-utils] [status-im.utils.async :as async-utils]
[status-im.chat.models :as model] [status-im.chat.models :as model]
[status-im.chat.console :as console-chat] [status-im.chat.console :as console-chat]
@ -13,14 +11,12 @@
[status-im.data-store.contacts :as contacts-store] [status-im.data-store.contacts :as contacts-store]
[status-im.data-store.chats :as chats-store] [status-im.data-store.chats :as chats-store]
[status-im.data-store.contacts :as contacts-store] [status-im.data-store.contacts :as contacts-store]
[status-im.data-store.requests :as requests-store]
[status-im.data-store.messages :as messages-store] [status-im.data-store.messages :as messages-store]
[status-im.data-store.pending-messages :as pending-messages-store] [status-im.data-store.pending-messages :as pending-messages-store]
[status-im.ui.screens.navigation :as navigation] [status-im.ui.screens.navigation :as navigation]
[status-im.protocol.core :as protocol] [status-im.protocol.core :as protocol]
[status-im.constants :as const] [status-im.constants :as const]
[status-im.ui.components.list-selection :as list-selection] [status-im.ui.components.list-selection :as list-selection]
[status-im.chat.events.input :as input-events]
status-im.chat.events.commands status-im.chat.events.commands
status-im.chat.events.requests status-im.chat.events.requests
status-im.chat.events.animation status-im.chat.events.animation
@ -119,12 +115,6 @@
;;;; Handlers ;;;; Handlers
(handlers/register-handler-db
:set-layout-height
[re-frame/trim-v]
(fn [db [height]]
(assoc db :layout-height height)))
(handlers/register-handler-db (handlers/register-handler-db
:set-chat-ui-props :set-chat-ui-props
[re-frame/trim-v] [re-frame/trim-v]

View File

@ -2,37 +2,22 @@
(:require-macros [status-im.utils.views :refer [defview letsubs]]) (:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [clojure.string :as string] (:require [clojure.string :as string]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[status-im.i18n :as i18n]
[status-im.chat.styles.screen :as style] [status-im.chat.styles.screen :as style]
[status-im.utils.datetime :as time]
[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.actions :as actions]
[status-im.chat.views.bottom-info :as bottom-info] [status-im.chat.views.bottom-info :as bottom-info]
[status-im.i18n :as i18n] [status-im.chat.views.message.datemark :as message-datemark]
[status-im.ui.components.react :as react] [status-im.chat.views.message.message :as message]
[status-im.chat.views.input.input :as input]
[status-im.chat.views.toolbar-content :as toolbar-content]
[status-im.ui.components.animation :as animation]
[status-im.ui.components.list.views :as list] [status-im.ui.components.list.views :as list]
[status-im.ui.components.icons.vector-icons :as vector-icons] [status-im.ui.components.list-selection :as list-selection]
[status-im.ui.components.react :as react]
[status-im.ui.components.status-bar.view :as status-bar] [status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.components.chat-icon.screen :as chat-icon-screen]
[status-im.ui.components.sync-state.offline :as offline] [status-im.ui.components.sync-state.offline :as offline]
[status-im.ui.components.toolbar.view :as toolbar] [status-im.ui.components.toolbar.view :as toolbar]
[status-im.ui.components.animation :as animation])) [status-im.utils.platform :as platform]))
(defview chat-icon []
(letsubs [{:keys [chat-id group-chat name]} [:get-current-chat]]
[chat-icon-screen/chat-icon-view-action chat-id group-chat name true]))
(defn- toolbar-action [show-actions?]
[react/touchable-highlight
{:on-press #(re-frame/dispatch [:set-chat-ui-props {:show-actions? (not show-actions?)}])
:accessibility-label :chat-menu}
[react/view style/action
(if show-actions?
[vector-icons/icon :icons/dropdown-up]
[chat-icon])]])
(defview add-contact-bar [] (defview add-contact-bar []
(letsubs [chat-id [:get-current-chat-id] (letsubs [chat-id [:get-current-chat-id]
@ -44,20 +29,26 @@
[react/text {:style style/add-contact-text} [react/text {:style style/add-contact-text}
(i18n/label :t/add-to-contacts)]]]))) (i18n/label :t/add-to-contacts)]]])))
(defn- on-options [chat-id chat-name group-chat?]
(list-selection/show {:title chat-name
:options (actions/actions group-chat? chat-id)}))
(defview chat-toolbar [] (defview chat-toolbar []
(letsubs [show-actions? [:get-current-chat-ui-prop :show-actions?] (letsubs [accounts [:get-accounts]
accounts [:get-accounts] creating? [:get :accounts/creating-account?]
creating? [:get :accounts/creating-account?]] {:keys [group-chat name chat-id]} [:get-current-chat]]
[react/view [react/view
[status-bar/status-bar] [status-bar/status-bar]
[toolbar/toolbar {} [toolbar/toolbar {}
(when-not (or show-actions? creating?) (when-not creating?
(if (empty? accounts) (if (empty? accounts)
[toolbar/nav-clear-text {:handler #(re-frame/dispatch [:navigate-to-modal :recover-modal])} [toolbar/nav-clear-text {:handler #(re-frame/dispatch [:navigate-to-modal :recover-modal])}
(i18n/label :t/recover)] (i18n/label :t/recover)]
toolbar/default-nav-back)) toolbar/default-nav-back))
[toolbar-content/toolbar-content-view] [toolbar-content/toolbar-content-view]
[toolbar-action show-actions?]] [toolbar/actions [{:icon :icons/options
:icon-opts {:color :black}
:handler #(on-options chat-id name group-chat)}]]]
[add-contact-bar]])) [add-contact-bar]]))
(defmulti message-row (fn [{{:keys [type]} :row}] type)) (defmulti message-row (fn [{{:keys [type]} :row}] type))
@ -72,13 +63,12 @@
:group-chat group-chat :group-chat group-chat
:current-public-key current-public-key)]) :current-public-key current-public-key)])
(defview messages-view-animation [message-view] (defview messages-view-animation [message-view]
;; smooths out appearance of message-view ;; smooths out appearance of message-view
(letsubs [opacity (animation/create-value 0) (letsubs [opacity (animation/create-value 0)
duration (if platform/android? 100 200) duration (if platform/android? 100 200)
timeout (if platform/android? 50 0)] timeout (if platform/android? 50 0)]
{:component-did-mount (fn [component] {:component-did-mount (fn [_]
(animation/start (animation/start
(animation/anim-sequence (animation/anim-sequence
[(animation/anim-delay timeout) [(animation/anim-delay timeout)
@ -106,24 +96,16 @@
(defview chat [] (defview chat []
(letsubs [{:keys [group-chat input-text]} [:get-current-chat] (letsubs [{:keys [group-chat input-text]} [:get-current-chat]
show-actions? [:get-current-chat-ui-prop :show-actions?]
show-bottom-info? [:get-current-chat-ui-prop :show-bottom-info?] show-bottom-info? [:get-current-chat-ui-prop :show-bottom-info?]
show-emoji? [:get-current-chat-ui-prop :show-emoji?] show-emoji? [:get-current-chat-ui-prop :show-emoji?]
layout-height [:get :layout-height]
current-view [:get :view-id]] current-view [:get :view-id]]
{:component-will-unmount #(re-frame/dispatch [:set-chat-ui-props {:show-emoji? false}])} {:component-will-unmount #(re-frame/dispatch [:set-chat-ui-props {:show-emoji? false}])}
[react/view {:style style/chat-view [react/view {:style style/chat-view}
:on-layout (fn [event]
(let [height (.. event -nativeEvent -layout -height)]
(when (not= height layout-height)
(re-frame/dispatch [:set-layout-height height]))))}
[chat-toolbar] [chat-toolbar]
(when (= :chat current-view) (when (= :chat current-view)
[messages-view-animation [messages-view-animation
[messages-view group-chat]]) [messages-view group-chat]])
[input/container {:text-empty? (string/blank? input-text)}] [input/container {:text-empty? (string/blank? input-text)}]
(when show-actions?
[actions/actions-view])
(when show-bottom-info? (when show-bottom-info?
[bottom-info/bottom-info-view]) [bottom-info/bottom-info-view])
[offline/offline-view {:top (get platform/platform-specific :status-bar-default-height)}]])) [offline/offline-view {:top (get platform/platform-specific :status-bar-default-height)}]]))

View File

@ -111,13 +111,6 @@
:color component.styles/text2-color :color component.styles/text2-color
:font-size 12}) :font-size 12})
(def actions-overlay
{:position :absolute
:top 0
:bottom 0
:left 0
:right 0})
(def typing-all (def typing-all
{:marginBottom 20}) {:marginBottom 20})
@ -129,12 +122,6 @@
:alignItems :flex-start :alignItems :flex-start
:alignSelf :flex-start}) :alignSelf :flex-start})
(def typing-background
{:borderRadius 14
:padding 12
:height 38
:backgroundColor component.styles/selected-message-color})
(def typing-text (def typing-text
{:marginTop -2 {:marginTop -2
:fontSize 12 :fontSize 12

View File

@ -1,133 +1,30 @@
(ns status-im.chat.views.actions (ns status-im.chat.views.actions
(:require [clojure.string :as string] (:require [re-frame.core :as re-frame]
[re-frame.core :as re-frame] [status-im.i18n :as i18n]))
[status-im.chat.styles.screen :as styles]
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[status-im.ui.components.react :as react]
[status-im.i18n :as i18n]
[status-im.utils.platform :as platform])
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
(defview menu-item-icon-profile [] (defn view-profile [chat-id group?]
[chat-id [:chat :chat-id] {:label (i18n/label :t/view-profile)
group-chat [:chat :group-chat] :action #(re-frame/dispatch [ (if group? :show-group-chat-profile :show-profile) chat-id])})
name [:chat :name]
color [:chat :color]]
;; TODO stub data ('online' property)
[chat-icon.screen/chat-icon-view-menu-item chat-id group-chat name color true])
(defn- members-text [members] (defn delete-chat [chat-id]
(str (string/join ", " (map :name members)) {:label (i18n/label :t/delete-chat)
" "
(i18n/label :t/and-you)))
(defn item-members [members]
{:title (i18n/label :t/members-title)
:subtitle (members-text members)
:icon :menu_group
:icon-opts {:width 25
:height 19}
;; TODO not implemented: action Members
:handler nil})
(defn item-user [chat-id]
{:title (i18n/label :t/profile)
:custom-icon [menu-item-icon-profile]
:icon :menu_group
:icon-style {:width 25
:height 19}
:handler #(re-frame/dispatch [:show-profile chat-id])})
(defn item-delete [chat-id]
{:title (i18n/label :t/delete-chat)
:icon :search_gray_copy
:icon-style {:width 17
:height 17}
;; TODO(jeluard) Refactor this or Jan will have an heart attack ;; TODO(jeluard) Refactor this or Jan will have an heart attack
:handler #(do (re-frame/dispatch [:remove-chat chat-id]) :action #(do (re-frame/dispatch [:remove-chat chat-id])
(re-frame/dispatch [:navigation-replace :home]))}) (re-frame/dispatch [:navigation-replace :home]))})
(def item-notifications (defn leave-group-chat [chat-id]
{:title (i18n/label :t/notifications-title) {:label (i18n/label :t/leave-group-chat)
:subtitle (i18n/label :t/not-implemented) :action #(re-frame/dispatch [:leave-group-chat chat-id])})
;;:subtitle "Chat muted"
:icon :muted
:icon-style {:width 18
:height 21}
;; TODO not implemented: action Notifications
:handler nil})
(def item-settings (defn- user-chat-actions [chat-id group?]
{:title (i18n/label :t/settings) [(view-profile chat-id group?)
:icon :settings (delete-chat chat-id)])
:icon-style {:width 20
:height 13}
:accessibility-label :settings
:handler #(re-frame/dispatch [:show-group-chat-settings])})
(defn group-chat-items [members public?] (defn- group-chat-actions [chat-id]
(into (if public? [] [(item-members members)]) (into (user-chat-actions chat-id true)
[item-notifications [(leave-group-chat chat-id)]))
item-settings]))
(defn user-chat-items [chat-id] (defn actions [group-chat? chat-id]
[(item-user chat-id) (if group-chat?
(item-delete chat-id) (group-chat-actions chat-id)
item-notifications]) (user-chat-actions chat-id false)))
(defn overlay [{:keys [on-click-outside]} items]
[react/view styles/actions-overlay
[react/touchable-highlight {:on-press on-click-outside
:style styles/overlay-highlight}
[react/view nil]]
items])
(defn action-view [{:keys [react/icon-style
icon
custom-icon
handler
title
subtitle
accessibility-label]
:or {accessibility-label :action}}]
[react/touchable-highlight {:on-press (fn []
(re-frame/dispatch [:set-chat-ui-props {:show-actions? false}])
(when handler
(handler)))}
[react/view {:accessibility-label accessibility-label
:style styles/action-icon-row}
[react/view styles/action-icon-view
(or custom-icon
[react/icon icon icon-style])]
[react/view styles/action-view
[react/text {:style styles/action-title
:number-of-lines 1
:font :medium}
title]
(when-let [subtitle subtitle]
[react/text {:style styles/action-subtitle
:number-of-lines 1
:font :default}
subtitle])]]])
(defview actions-list-view []
(letsubs [group-chat [:chat :group-chat]
chat-id [:chat :chat-id]
public? [:chat :public?]
members [:current-chat-contacts]
status-bar-height (get platform/platform-specific :status-bar-default-height)]
(when-let [actions (if group-chat
(group-chat-items members public?)
(user-chat-items chat-id))]
[react/view (merge
(styles/actions-wrapper status-bar-height)
styles/actions-list-view)
[react/view styles/actions-separator]
[react/view styles/actions-view
(for [action actions]
(if action
^{:key action} [action-view action]))]])))
(defn actions-view []
[overlay {:on-click-outside #(re-frame/dispatch [:set-chat-ui-props {:show-actions? false}])}
[actions-list-view]])

View File

@ -1,33 +1,29 @@
(ns status-im.chat.views.toolbar-content (ns status-im.chat.views.toolbar-content
(:require-macros [status-im.utils.views :refer [defview letsubs]]) (:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [re-frame.core :refer [subscribe dispatch]] (:require [clojure.string :as string]
[clojure.string :as str]
[cljs-time.core :as t] [cljs-time.core :as t]
[status-im.ui.components.react :refer [view [status-im.ui.components.react :as react]
text
icon]] [status-im.i18n :as i18n]
[status-im.i18n :refer [get-contact-translated
label
label-pluralize]]
[status-im.chat.styles.screen :as st] [status-im.chat.styles.screen :as st]
[status-im.utils.datetime :as time] [status-im.utils.datetime :as time]
[status-im.utils.platform :refer [platform-specific]] [status-im.utils.platform :refer [platform-specific]]
[status-im.utils.gfycat.core :refer [generate-gfy]] [status-im.utils.gfycat.core :refer [generate-gfy]]
[status-im.constants :refer [console-chat-id]])) [status-im.constants :refer [console-chat-id]]))
(defn online-text [contact chat-id] (defn- online-text [contact chat-id]
(cond (cond
(= console-chat-id chat-id) (label :t/available) (= console-chat-id chat-id) (i18n/label :t/available)
contact (let [last-online (get contact :last-online) contact (let [last-online (get contact :last-online)
last-online-date (time/to-date last-online) last-online-date (time/to-date last-online)
now-date (t/now)] now-date (t/now)]
(if (and (pos? last-online) (if (and (pos? last-online)
(<= last-online-date now-date)) (<= last-online-date now-date))
(time/time-ago last-online-date) (time/time-ago last-online-date)
(label :t/active-unknown))) (i18n/label :t/active-unknown)))
:else (label :t/active-unknown))) :else (i18n/label :t/active-unknown)))
(defn in-progress-text [{:keys [highestBlock currentBlock startBlock]}] (defn- in-progress-text [{:keys [highestBlock currentBlock startBlock]}]
(let [total (- highestBlock startBlock) (let [total (- highestBlock startBlock)
ready (- currentBlock startBlock) ready (- currentBlock startBlock)
percentage (if (zero? ready) percentage (if (zero? ready)
@ -36,29 +32,29 @@
(* 100) (* 100)
(.round js/Math)))] (.round js/Math)))]
(str (label :t/sync-in-progress) " " percentage "% " currentBlock))) (str (i18n/label :t/sync-in-progress) " " percentage "% " currentBlock)))
(defview last-activity [{:keys [online-text sync-state]}] (defview last-activity [{:keys [online-text sync-state]}]
[state [:get :sync-data]] [state [:get :sync-data]]
[text {:style st/last-activity-text} [react/text {:style st/last-activity-text}
(case sync-state (case sync-state
:in-progress (in-progress-text state) :in-progress (in-progress-text state)
:synced (label :t/sync-synced) :synced (i18n/label :t/sync-synced)
online-text)]) online-text)])
(defn group-last-activity [{:keys [contacts sync-state public?]}] (defn- group-last-activity [{:keys [contacts sync-state public?]}]
(if (or (= sync-state :in-progress) (if (or (= sync-state :in-progress)
(= sync-state :synced)) (= sync-state :synced))
[last-activity {:sync-state sync-state}] [last-activity {:sync-state sync-state}]
(if public? (if public?
[view {:flex-direction :row} [react/view {:flex-direction :row}
[text (label :t/public-group-status)]] [react/text (i18n/label :t/public-group-status)]]
[view {:flex-direction :row} [react/view {:flex-direction :row}
[text {:style st/members} [react/text {:style st/members}
(if public? (if public?
(label :t/public-group-status) (i18n/label :t/public-group-status)
(let [cnt (inc (count contacts))] (let [cnt (inc (count contacts))]
(label-pluralize cnt :t/members-active)))]]))) (i18n/label-pluralize cnt :t/members-active)))]])))
(defview toolbar-content-view [] (defview toolbar-content-view []
(letsubs [group-chat [:chat :group-chat] (letsubs [group-chat [:chat :group-chat]
@ -72,14 +68,14 @@
contact [:get-in [:contacts/contacts @chat-id]] contact [:get-in [:contacts/contacts @chat-id]]
sync-state [:sync-state] sync-state [:sync-state]
creating? [:get :accounts/creating-account?]] creating? [:get :accounts/creating-account?]]
[view (st/chat-name-view (or (empty? accounts) [react/view (st/chat-name-view (or (empty? accounts)
show-actions? show-actions?
creating?)) creating?))
(let [chat-name (if (str/blank? name) (let [chat-name (if (string/blank? name)
(generate-gfy public-key) (generate-gfy public-key)
(or (get-contact-translated chat-id :name name) (or (i18n/get-contact-translated chat-id :name name)
(label :t/chat-name)))] (i18n/label :t/chat-name)))]
[text {:style st/chat-name-text [react/text {:style st/chat-name-text
:number-of-lines 1 :number-of-lines 1
:font :toolbar-title} :font :toolbar-title}
(if public? (if public?

View File

@ -86,6 +86,7 @@
;;profile ;;profile
:profile "Profile" :profile "Profile"
:view-profile "View profile"
:edit-profile "Edit profile" :edit-profile "Edit profile"
:main-currency "Main currency" :main-currency "Main currency"
:message "Message" :message "Message"
@ -203,6 +204,7 @@
:clear-history "Clear history" :clear-history "Clear history"
:mute-notifications "Mute notifications" :mute-notifications "Mute notifications"
:leave-chat "Leave chat" :leave-chat "Leave chat"
:leave-group-chat "Leave group chat"
:chat-settings "Chat settings" :chat-settings "Chat settings"
:edit "Edit" :edit "Edit"
:add-members "Add members" :add-members "Add members"

View File

@ -132,9 +132,9 @@
;;;; Handlers ;;;; Handlers
(register-handler-fx (register-handler-fx
:show-group-chat-settings :show-group-chat-profile
(fn [{{:keys [current-chat-id] :as db} :db} _] (fn [{db :db} [_ chat-id]]
{:db (assoc db :new-chat-name (get-in db [:chats current-chat-id :name]) {:db (assoc db :new-chat-name (get-in db [:chats chat-id :name])
:group/group-type :chat-group) :group/group-type :chat-group)
:dispatch [:navigate-to :chat-group-settings]})) :dispatch [:navigate-to :chat-group-settings]}))