From 7aa209d9f38f9b17991e2b4ced7e7c987480fe64 Mon Sep 17 00:00:00 2001 From: virvar Date: Mon, 6 Jun 2016 18:47:11 +0300 Subject: [PATCH] Message input refactoring Former-commit-id: 89051ce50b1ecb78b0b994287d6649097a981585 --- src/status_im/chat/handlers/animation.cljs | 2 +- src/status_im/chat/styles/message_input.cljs | 32 ++++ src/status_im/chat/styles/plain_input.cljs | 63 ------ src/status_im/chat/styles/plain_message.cljs | 32 ++++ src/status_im/chat/styles/response.cljs | 2 +- src/status_im/chat/views/command.cljs | 8 + src/status_im/chat/views/message_input.cljs | 127 ++++++++++++ src/status_im/chat/views/new_message.cljs | 2 +- src/status_im/chat/views/plain_input.cljs | 192 ------------------- src/status_im/chat/views/plain_message.cljs | 94 +++++++++ src/status_im/chat/views/response.cljs | 2 +- 11 files changed, 297 insertions(+), 259 deletions(-) create mode 100644 src/status_im/chat/styles/message_input.cljs delete mode 100644 src/status_im/chat/styles/plain_input.cljs create mode 100644 src/status_im/chat/styles/plain_message.cljs create mode 100644 src/status_im/chat/views/message_input.cljs delete mode 100644 src/status_im/chat/views/plain_input.cljs create mode 100644 src/status_im/chat/views/plain_message.cljs diff --git a/src/status_im/chat/handlers/animation.cljs b/src/status_im/chat/handlers/animation.cljs index b3f540282a..a7526ec19f 100644 --- a/src/status_im/chat/handlers/animation.cljs +++ b/src/status_im/chat/handlers/animation.cljs @@ -3,7 +3,7 @@ [re-frame.middleware :refer [path]] [status-im.models.commands :as commands] [status-im.handlers.content-suggestions :refer [get-content-suggestions]] - [status-im.chat.styles.plain-input :refer [input-height]] + [status-im.chat.styles.message-input :refer [input-height]] [status-im.chat.styles.response :refer [request-info-height response-height-normal]] [status-im.chat.styles.response-suggestions :as response-suggestions-styles] [status-im.constants :refer [response-input-hiding-duration]])) diff --git a/src/status_im/chat/styles/message_input.cljs b/src/status_im/chat/styles/message_input.cljs new file mode 100644 index 0000000000..9cbcc4e27f --- /dev/null +++ b/src/status_im/chat/styles/message_input.cljs @@ -0,0 +1,32 @@ +(ns status-im.chat.styles.message-input + (:require [status-im.components.styles :refer [color-white + color-blue]])) + +(def input-height 56) + +(defn message-input-container [offset] + {:flex 1 + :transform [{:translateX offset}] + :marginRight offset}) + +(def input-container + {:flexDirection :column}) + +(def input-view + {:flexDirection :row + :height input-height + :backgroundColor color-white}) + +(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}) diff --git a/src/status_im/chat/styles/plain_input.cljs b/src/status_im/chat/styles/plain_input.cljs deleted file mode 100644 index da4168fae8..0000000000 --- a/src/status_im/chat/styles/plain_input.cljs +++ /dev/null @@ -1,63 +0,0 @@ -(ns status-im.chat.styles.plain-input - (:require [status-im.components.styles :refer [font - text2-color - color-white - color-blue]])) - -(def input-height 56) - -(def input-container - {:flexDirection :column}) - -(def input-view - {:flexDirection :row - :height input-height - :backgroundColor color-white}) - -(def message-input-button-touchable - {:width 56 - :height 56 - :alignItems :center - :justifyContent :center}) - -(defn message-input-button [scale] - {:transform [{:scale scale}]}) - -(defn message-input-container [offset] - {:flex 1 - :transform [{:translateX offset}] - :marginRight offset}) - -(def list-icon - {:width 13 - :height 12}) - -(def close-icon - {:width 12 - :height 12}) - -(def message-input - {:flex 1 - :marginTop -2 - :padding 0 - :fontSize 14 - :fontFamily font - :color text2-color}) - -(def smile-icon - {: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}) diff --git a/src/status_im/chat/styles/plain_message.cljs b/src/status_im/chat/styles/plain_message.cljs new file mode 100644 index 0000000000..d52ae4d257 --- /dev/null +++ b/src/status_im/chat/styles/plain_message.cljs @@ -0,0 +1,32 @@ +(ns status-im.chat.styles.plain-message + (:require [status-im.components.styles :refer [font + text2-color]])) + +(def message-input-button-touchable + {:width 56 + :height 56 + :alignItems :center + :justifyContent :center}) + +(defn message-input-button [scale] + {:transform [{:scale scale}]}) + +(def list-icon + {:width 13 + :height 12}) + +(def close-icon + {:width 12 + :height 12}) + +(def message-input + {:flex 1 + :marginTop -2 + :padding 0 + :fontSize 14 + :fontFamily font + :color text2-color}) + +(def smile-icon + {:width 20 + :height 20}) diff --git a/src/status_im/chat/styles/response.cljs b/src/status_im/chat/styles/response.cljs index c9612e3e35..029ca2ed86 100644 --- a/src/status_im/chat/styles/response.cljs +++ b/src/status_im/chat/styles/response.cljs @@ -6,7 +6,7 @@ text2-color chat-background color-black]] - [status-im.chat.styles.plain-input :refer [input-height]])) + [status-im.chat.styles.message-input :refer [input-height]])) (def response-height-normal 211) (def request-info-height 61) diff --git a/src/status_im/chat/views/command.cljs b/src/status_im/chat/views/command.cljs index 70cd1b5841..7ed7faafc3 100644 --- a/src/status_im/chat/views/command.cljs +++ b/src/status_im/chat/views/command.cljs @@ -1,4 +1,5 @@ (ns status-im.chat.views.command + (:require-macros [status-im.utils.views :refer [defview]]) (:require [re-frame.core :refer [subscribe dispatch]] [status-im.components.react :refer [view icon @@ -29,3 +30,10 @@ (defn command-icon [command] [view (st/command-text-container command) [text {:style st/command-text} (:text command)]]) + +(defview cancel-button [] + [commands-input-is-switching? [:get-in [:animations :commands-input-is-switching?]]] + [touchable-highlight {:disabled commands-input-is-switching? + :on-press cancel-command-input} + [view st/cancel-container + [icon :close-gray st/cancel-icon]]]) diff --git a/src/status_im/chat/views/message_input.cljs b/src/status_im/chat/views/message_input.cljs new file mode 100644 index 0000000000..0d170c83d3 --- /dev/null +++ b/src/status_im/chat/views/message_input.cljs @@ -0,0 +1,127 @@ +(ns status-im.chat.views.message-input + (:require-macros [status-im.utils.views :refer [defview]]) + (:require [re-frame.core :refer [subscribe dispatch]] + [reagent.core :as r] + [status-im.components.react :refer [view + animated-view + icon + touchable-highlight + text-input + dismiss-keyboard!]] + [status-im.components.animation :as anim] + [status-im.chat.views.plain-message :as plain-message] + [status-im.chat.views.command :as command] + [status-im.chat.views.response :as response] + [status-im.chat.styles.message-input :as st] + [status-im.chat.styles.plain-message :as st-message] + [status-im.chat.styles.input :as st-command] + [status-im.chat.styles.response :as st-response] + [status-im.constants :refer [response-input-hiding-duration]])) + +(defview send-button [{:keys [on-press accessibility-label]}] + [commands-input-is-switching? [:get-in [:animations :commands-input-is-switching?]]] + [touchable-highlight {:disabled commands-input-is-switching? + :on-press on-press + :accessibility-label accessibility-label} + [view st/send-container + [icon :send st/send-icon]]]) + +(defn message-input-container-animation-logic [{:keys [to-value val]}] + (fn [_] + (let [to-value @to-value] + (anim/start (anim/timing val {:toValue to-value + :duration response-input-hiding-duration}) + (fn [arg] + (when (.-finished arg) + (dispatch [:set-in [:animations ::message-input-offset-current] to-value]))))))) + +(defn message-input-container [input] + (let [to-message-input-offset (subscribe [:get-in [:animations :message-input-offset]]) + cur-message-input-offset (subscribe [:get-in [:animations ::message-input-offset-current]]) + message-input-offset (anim/create-value (or @cur-message-input-offset 0)) + context {:to-value to-message-input-offset + :val message-input-offset} + on-update (message-input-container-animation-logic context)] + (r/create-class + {:component-did-mount + on-update + :component-did-update + on-update + :reagent-render + (fn [input] + @to-message-input-offset + [animated-view {:style (st/message-input-container message-input-offset)} + input])}))) + +(defview message-input [] + [input-message [:get-chat-input-text] + command [:get-chat-command] + to-msg-id [:get-chat-command-to-msg-id] + input-command [:get-chat-command-content] + staged-commands [:get-chat-staged-commands] + typing-command? [:typing-command?] + commands-input-is-switching? [:get-in [:animations :commands-input-is-switching?]]] + (let [dismiss-keyboard (not (or command typing-command?)) + response? (and command to-msg-id) + message-input? (or (not command) commands-input-is-switching?) + animation? commands-input-is-switching?] + [text-input (merge {:style (cond + message-input? st-message/message-input + response? st-response/command-input + command st-command/command-input) + :ref (fn [input] + (dispatch [:set-message-input input])) + :autoFocus false + :blurOnSubmit dismiss-keyboard + :onChangeText (fn [text] + (when-not animation? + ((if message-input? + plain-message/set-input-message + command/set-input-message) + text))) + :onSubmitEditing #(when-not animation? + (if message-input? + (plain-message/try-send staged-commands + input-message + dismiss-keyboard) + (command/try-send input-command validator)))} + (when command + {:accessibility-label :command-input}) + input-options) + (if message-input? + input-message + input-command)])) + +(defview plain-message-input-view [{:keys [input-options validator]}] + [input-message [:get-chat-input-text] + command [:get-chat-command] + to-msg-id [:get-chat-command-to-msg-id] + input-command [:get-chat-command-content] + staged-commands [:get-chat-staged-commands] + typing-command? [:typing-command?] + commands-input-is-switching? [:get-in [:animations :commands-input-is-switching?]]] + (let [dismiss-keyboard (not (or command typing-command?)) + response? (and command to-msg-id) + message-input? (or (not command) commands-input-is-switching?)] + [view st/input-container + [view st/input-view + (if message-input? + [plain-message/commands-button] + (when (and command (not response?)) + [command/command-icon command response?])) + [message-input-container + [message-input]] + ;; TODO emoticons: not implemented + (when message-input? + [plain-message/smile-button]) + (if message-input? + (when (plain-message/message-valid? staged-commands input-message) + [send-button {:on-press #(plain-message/try-send staged-commands + input-message + dismiss-keyboard) + :accessibility-label :send-message}]) + (if (command/valid? input-command validator) + [send-button {:on-press command/send-command + :accessibility-label :stage-command}] + (when-not response? + [command/cancel-button])))]])) diff --git a/src/status_im/chat/views/new_message.cljs b/src/status_im/chat/views/new_message.cljs index fa8b5ab74b..be01687c74 100644 --- a/src/status_im/chat/views/new_message.cljs +++ b/src/status_im/chat/views/new_message.cljs @@ -3,7 +3,7 @@ (:require [re-frame.core :refer [subscribe]] [status-im.components.react :refer [view]] - [status-im.chat.views.plain-input :refer [plain-message-input-view]] + [status-im.chat.views.message-input :refer [plain-message-input-view]] [status-im.chat.views.staged-command :refer [simple-command-staged-view]] [status-im.utils.phone-number :refer [valid-mobile-number?]] [status-im.chat.styles.message :as st])) diff --git a/src/status_im/chat/views/plain_input.cljs b/src/status_im/chat/views/plain_input.cljs deleted file mode 100644 index da0e88648d..0000000000 --- a/src/status_im/chat/views/plain_input.cljs +++ /dev/null @@ -1,192 +0,0 @@ -(ns status-im.chat.views.plain-input - (:require-macros [status-im.utils.views :refer [defview]]) - (:require [re-frame.core :refer [subscribe dispatch]] - [reagent.core :as r] - [status-im.components.react :refer [view - animated-view - icon - touchable-highlight - text-input - dismiss-keyboard!]] - [status-im.components.animation :as anim] - [status-im.chat.views.command :as command] - [status-im.chat.views.response :as response] - [status-im.chat.styles.plain-input :as st] - [status-im.chat.styles.input :as st-command] - [status-im.chat.styles.response :as st-response] - [status-im.constants :refer [response-input-hiding-duration]])) - -(defn set-input-message [message] - (dispatch [:set-chat-input-text message])) - -(defn send [dismiss-keyboard] - (when dismiss-keyboard - (dismiss-keyboard!)) - (dispatch [:send-chat-msg])) - -(defn message-valid? [staged-commands message] - (or (and (pos? (count message)) - (not= "!" message)) - (pos? (count staged-commands)))) - -(defn try-send [staged-commands message dismiss-keyboard] - (when (message-valid? staged-commands message) - (send dismiss-keyboard))) - -(defn commands-button-animation-logic [{:keys [to-value val]}] - (fn [_] - (let [to-scale @to-value - minimum 0.1 - scale (cond (< 1 to-scale) 1 - (< to-scale minimum) minimum - :else to-scale)] - (anim/start (anim/timing val {:toValue scale - :duration response-input-hiding-duration}) - (fn [arg] - (when (.-finished arg) - (dispatch [:set-in [:animations ::message-input-buttons-scale-current] scale]) - (when (= to-scale minimum) - (dispatch [:finish-show-response])))))))) - -(defn commands-button [animation?] - (let [typing-command? (subscribe [:typing-command?]) - to-scale (subscribe [:get-in [:animations :message-input-buttons-scale]]) - cur-scale (subscribe [:get-in [:animations ::message-input-buttons-scale-current]]) - buttons-scale (anim/create-value (or @cur-scale 1)) - context {:to-value to-scale - :val buttons-scale} - on-update (commands-button-animation-logic context)] - (r/create-class - {:component-did-mount - on-update - :component-did-update - on-update - :reagent-render - (fn [animation?] - (let [typing-command? @typing-command?] - @to-scale - [touchable-highlight {:disabled animation? - :on-press #(dispatch [:switch-command-suggestions]) - :style st/message-input-button-touchable} - [animated-view {:style (st/message-input-button buttons-scale)} - (if typing-command? - [icon :close-gray st/close-icon] - [icon :list st/list-icon])]]))}))) - -(defn smile-button [animation?] - (let [to-scale (subscribe [:get-in [:animations :message-input-buttons-scale]]) - cur-scale (subscribe [:get-in [:animations ::message-input-buttons-scale-current]]) - buttons-scale (anim/create-value (or @cur-scale 1)) - context {:to-value to-scale - :val buttons-scale} - on-update (commands-button-animation-logic context)] - (r/create-class - {:component-did-mount - on-update - :component-did-update - on-update - :reagent-render - (fn [animation?] - @to-scale - [touchable-highlight {:disabled animation? - :on-press (fn [] - ;; TODO emoticons: not implemented - ) - :style st/message-input-button-touchable} - [animated-view {:style (st/message-input-button buttons-scale)} - [icon :smile st/smile-icon]]])}))) - -(defn message-input-container-animation-logic [{:keys [to-value val]}] - (fn [_] - (let [to-value @to-value] - (anim/start (anim/timing val {:toValue to-value - :duration response-input-hiding-duration}) - (fn [arg] - (when (.-finished arg) - (dispatch [:set-in [:animations ::message-input-offset-current] to-value]))))))) - -(defn message-input-container [input] - (let [to-message-input-offset (subscribe [:get-in [:animations :message-input-offset]]) - cur-message-input-offset (subscribe [:get-in [:animations ::message-input-offset-current]]) - message-input-offset (anim/create-value (or @cur-message-input-offset 0)) - context {:to-value to-message-input-offset - :val message-input-offset} - on-update (message-input-container-animation-logic context)] - (r/create-class - {:component-did-mount - on-update - :component-did-update - on-update - :reagent-render - (fn [input] - @to-message-input-offset - [animated-view {:style (st/message-input-container message-input-offset)} - input])}))) - -(defview plain-message-input-view [{:keys [input-options validator]}] - [input-message [:get-chat-input-text] - command [:get-chat-command] - to-msg-id [:get-chat-command-to-msg-id] - input-command [:get-chat-command-content] - staged-commands [:get-chat-staged-commands] - typing-command? [:typing-command?] - commands-button-is-switching? [:get-in [:animations :commands-input-is-switching?]]] - (let [dismiss-keyboard (not (or command typing-command?)) - response? (and command to-msg-id) - message-input? (or (not command) commands-button-is-switching?) - animation? commands-button-is-switching?] - [view st/input-container - [view st/input-view - (if message-input? - [commands-button animation?] - (when (and command (not response?)) - [command/command-icon command response?])) - [message-input-container - [text-input (merge {:style (cond - message-input? st/message-input - response? st-response/command-input - command st-command/command-input) - :ref (fn [input] - (dispatch [:set-message-input input])) - :autoFocus false - :blurOnSubmit dismiss-keyboard - :onChangeText (fn [text] - (when-not animation? - ((if message-input? - set-input-message - command/set-input-message) - text))) - :onSubmitEditing #(when-not animation? - (if message-input? - (try-send staged-commands - input-message - dismiss-keyboard) - (command/try-send input-command validator)))} - (when command - {:accessibility-label :command-input}) - input-options) - (if message-input? - input-message - input-command)]] - ;; TODO emoticons: not implemented - (when message-input? - [smile-button animation?]) - (if message-input? - (when (message-valid? staged-commands input-message) - [touchable-highlight {:disabled animation? - :on-press #(try-send staged-commands - input-message - dismiss-keyboard) - :accessibility-label :send-message} - [view st/send-container - [icon :send st/send-icon]]]) - (if (command/valid? input-command validator) - [touchable-highlight {:disabled animation? - :on-press command/send-command - :accessibility-label :stage-command} - [view st/send-container [icon :send st/send-icon]]] - (when-not response? - [touchable-highlight {:disabled animation? - :on-press command/cancel-command-input} - [view st-command/cancel-container - [icon :close-gray st-command/cancel-icon]]])))]])) diff --git a/src/status_im/chat/views/plain_message.cljs b/src/status_im/chat/views/plain_message.cljs new file mode 100644 index 0000000000..b516c64dc9 --- /dev/null +++ b/src/status_im/chat/views/plain_message.cljs @@ -0,0 +1,94 @@ +(ns status-im.chat.views.plain-message + (:require-macros [status-im.utils.views :refer [defview]]) + (:require [re-frame.core :refer [subscribe dispatch]] + [reagent.core :as r] + [status-im.components.react :refer [view + animated-view + icon + touchable-highlight + dismiss-keyboard!]] + [status-im.components.animation :as anim] + [status-im.chat.styles.plain-message :as st] + [status-im.constants :refer [response-input-hiding-duration]])) + +(defn set-input-message [message] + (dispatch [:set-chat-input-text message])) + +(defn send [dismiss-keyboard] + (when dismiss-keyboard + (dismiss-keyboard!)) + (dispatch [:send-chat-msg])) + +(defn message-valid? [staged-commands message] + (or (and (pos? (count message)) + (not= "!" message)) + (pos? (count staged-commands)))) + +(defn try-send [staged-commands message dismiss-keyboard] + (when (message-valid? staged-commands message) + (send dismiss-keyboard))) + +(defn commands-button-animation-logic [{:keys [to-value val]}] + (fn [_] + (let [to-scale @to-value + minimum 0.1 + scale (cond (< 1 to-scale) 1 + (< to-scale minimum) minimum + :else to-scale)] + (anim/start (anim/timing val {:toValue scale + :duration response-input-hiding-duration}) + (fn [arg] + (when (.-finished arg) + (dispatch [:set-in [:animations ::message-input-buttons-scale-current] scale]) + (when (= to-scale minimum) + (dispatch [:finish-show-response])))))))) + +(defn commands-button [] + (let [typing-command? (subscribe [:typing-command?]) + animation? (subscribe [:get-in [:animations :commands-input-is-switching?]]) + to-scale (subscribe [:get-in [:animations :message-input-buttons-scale]]) + cur-scale (subscribe [:get-in [:animations ::message-input-buttons-scale-current]]) + buttons-scale (anim/create-value (or @cur-scale 1)) + context {:to-value to-scale + :val buttons-scale} + on-update (commands-button-animation-logic context)] + (r/create-class + {:component-did-mount + on-update + :component-did-update + on-update + :reagent-render + (fn [] + (let [typing-command? @typing-command?] + @to-scale + [touchable-highlight {:disabled @animation? + :on-press #(dispatch [:switch-command-suggestions]) + :style st/message-input-button-touchable} + [animated-view {:style (st/message-input-button buttons-scale)} + (if typing-command? + [icon :close-gray st/close-icon] + [icon :list st/list-icon])]]))}))) + +(defn smile-button [] + (let [animation? (subscribe [:get-in [:animations :commands-input-is-switching?]]) + to-scale (subscribe [:get-in [:animations :message-input-buttons-scale]]) + cur-scale (subscribe [:get-in [:animations ::message-input-buttons-scale-current]]) + buttons-scale (anim/create-value (or @cur-scale 1)) + context {:to-value to-scale + :val buttons-scale} + on-update (commands-button-animation-logic context)] + (r/create-class + {:component-did-mount + on-update + :component-did-update + on-update + :reagent-render + (fn [] + @to-scale + [touchable-highlight {:disabled @animation? + :on-press (fn [] + ;; TODO emoticons: not implemented + ) + :style st/message-input-button-touchable} + [animated-view {:style (st/message-input-button buttons-scale)} + [icon :smile st/smile-icon]]])}))) diff --git a/src/status_im/chat/views/response.cljs b/src/status_im/chat/views/response.cljs index 9d2b84a490..061403ca3a 100644 --- a/src/status_im/chat/views/response.cljs +++ b/src/status_im/chat/views/response.cljs @@ -13,7 +13,7 @@ [status-im.components.drag-drop :as drag] [status-im.chat.views.response-suggestions :refer [response-suggestions-view]] [status-im.chat.styles.response :as st] - [status-im.chat.styles.plain-input :refer [input-height]] + [status-im.chat.styles.message-input :refer [input-height]] [status-im.components.animation :as anim])) (defn drag-icon []